]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/class-simplepie.php
Wordpress 3.1.1
[autoinstalls/wordpress.git] / wp-includes / class-simplepie.php
1 <?php
2 if ( !class_exists( 'SimplePie' ) ) :
3 /**
4  * SimplePie
5  *
6  * A PHP-Based RSS and Atom Feed Framework.
7  * Takes the hard work out of managing a complete RSS/Atom solution.
8  *
9  * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification, are
13  * permitted provided that the following conditions are met:
14  *
15  *      * Redistributions of source code must retain the above copyright notice, this list of
16  *        conditions and the following disclaimer.
17  *
18  *      * Redistributions in binary form must reproduce the above copyright notice, this list
19  *        of conditions and the following disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
23  *        to endorse or promote products derived from this software without specific prior
24  *        written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
27  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
29  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * @package SimplePie
37  * @version 1.2
38  * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
39  * @author Ryan Parman
40  * @author Geoffrey Sneddon
41  * @link http://simplepie.org/ SimplePie
42  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
43  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
44  * @todo phpDoc comments
45  */
46
47 /**
48  * SimplePie Name
49  */
50 define('SIMPLEPIE_NAME', 'SimplePie');
51
52 /**
53  * SimplePie Version
54  */
55 define('SIMPLEPIE_VERSION', '1.2');
56
57 /**
58  * SimplePie Build
59  */
60 define('SIMPLEPIE_BUILD', '20090627192103');
61
62 /**
63  * SimplePie Website URL
64  */
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
66
67 /**
68  * SimplePie Useragent
69  * @see SimplePie::set_useragent()
70  */
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
72
73 /**
74  * SimplePie Linkback
75  */
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
77
78 /**
79  * No Autodiscovery
80  * @see SimplePie::set_autodiscovery_level()
81  */
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
83
84 /**
85  * Feed Link Element Autodiscovery
86  * @see SimplePie::set_autodiscovery_level()
87  */
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
89
90 /**
91  * Local Feed Extension Autodiscovery
92  * @see SimplePie::set_autodiscovery_level()
93  */
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
95
96 /**
97  * Local Feed Body Autodiscovery
98  * @see SimplePie::set_autodiscovery_level()
99  */
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
101
102 /**
103  * Remote Feed Extension Autodiscovery
104  * @see SimplePie::set_autodiscovery_level()
105  */
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
107
108 /**
109  * Remote Feed Body Autodiscovery
110  * @see SimplePie::set_autodiscovery_level()
111  */
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
113
114 /**
115  * All Feed Autodiscovery
116  * @see SimplePie::set_autodiscovery_level()
117  */
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
119
120 /**
121  * No known feed type
122  */
123 define('SIMPLEPIE_TYPE_NONE', 0);
124
125 /**
126  * RSS 0.90
127  */
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
129
130 /**
131  * RSS 0.91 (Netscape)
132  */
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
134
135 /**
136  * RSS 0.91 (Userland)
137  */
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
139
140 /**
141  * RSS 0.91 (both Netscape and Userland)
142  */
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
144
145 /**
146  * RSS 0.92
147  */
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
149
150 /**
151  * RSS 0.93
152  */
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
154
155 /**
156  * RSS 0.94
157  */
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
159
160 /**
161  * RSS 1.0
162  */
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
164
165 /**
166  * RSS 2.0
167  */
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
169
170 /**
171  * RDF-based RSS
172  */
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
174
175 /**
176  * Non-RDF-based RSS (truly intended as syndication format)
177  */
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
179
180 /**
181  * All RSS
182  */
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
184
185 /**
186  * Atom 0.3
187  */
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
189
190 /**
191  * Atom 1.0
192  */
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
194
195 /**
196  * All Atom
197  */
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
199
200 /**
201  * All feed types
202  */
203 define('SIMPLEPIE_TYPE_ALL', 1023);
204
205 /**
206  * No construct
207  */
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
209
210 /**
211  * Text construct
212  */
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
214
215 /**
216  * HTML construct
217  */
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
219
220 /**
221  * XHTML construct
222  */
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
224
225 /**
226  * base64-encoded construct
227  */
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
229
230 /**
231  * IRI construct
232  */
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
234
235 /**
236  * A construct that might be HTML
237  */
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
239
240 /**
241  * All constructs
242  */
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
244
245 /**
246  * Don't change case
247  */
248 define('SIMPLEPIE_SAME_CASE', 1);
249
250 /**
251  * Change to lowercase
252  */
253 define('SIMPLEPIE_LOWERCASE', 2);
254
255 /**
256  * Change to uppercase
257  */
258 define('SIMPLEPIE_UPPERCASE', 4);
259
260 /**
261  * PCRE for HTML attributes
262  */
263 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]*');
264
265 /**
266  * PCRE for XML attributes
267  */
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
269
270 /**
271  * XML Namespace
272  */
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
274
275 /**
276  * Atom 1.0 Namespace
277  */
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
279
280 /**
281  * Atom 0.3 Namespace
282  */
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
284
285 /**
286  * RDF Namespace
287  */
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
289
290 /**
291  * RSS 0.90 Namespace
292  */
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
294
295 /**
296  * RSS 1.0 Namespace
297  */
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
299
300 /**
301  * RSS 1.0 Content Module Namespace
302  */
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
304
305 /**
306  * RSS 2.0 Namespace
307  * (Stupid, I know, but I'm certain it will confuse people less with support.)
308  */
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
310
311 /**
312  * DC 1.0 Namespace
313  */
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
315
316 /**
317  * DC 1.1 Namespace
318  */
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
320
321 /**
322  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
323  */
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
325
326 /**
327  * GeoRSS Namespace
328  */
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
330
331 /**
332  * Media RSS Namespace
333  */
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
335
336 /**
337  * Wrong Media RSS Namespace
338  */
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
340
341 /**
342  * iTunes RSS Namespace
343  */
344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
345
346 /**
347  * XHTML Namespace
348  */
349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
350
351 /**
352  * IANA Link Relations Registry
353  */
354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
355
356 /**
357  * Whether we're running on PHP5
358  */
359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
360
361 /**
362  * No file source
363  */
364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
365
366 /**
367  * Remote file source
368  */
369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
370
371 /**
372  * Local file source
373  */
374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
375
376 /**
377  * fsockopen() file source
378  */
379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
380
381 /**
382  * cURL file source
383  */
384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
385
386 /**
387  * file_get_contents() file source
388  */
389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
390
391 /**
392  * SimplePie
393  *
394  * @package SimplePie
395  */
396 class SimplePie
397 {
398         /**
399          * @var array Raw data
400          * @access private
401          */
402         var $data = array();
403
404         /**
405          * @var mixed Error string
406          * @access private
407          */
408         var $error;
409
410         /**
411          * @var object Instance of SimplePie_Sanitize (or other class)
412          * @see SimplePie::set_sanitize_class()
413          * @access private
414          */
415         var $sanitize;
416
417         /**
418          * @var string SimplePie Useragent
419          * @see SimplePie::set_useragent()
420          * @access private
421          */
422         var $useragent = SIMPLEPIE_USERAGENT;
423
424         /**
425          * @var string Feed URL
426          * @see SimplePie::set_feed_url()
427          * @access private
428          */
429         var $feed_url;
430
431         /**
432          * @var object Instance of SimplePie_File to use as a feed
433          * @see SimplePie::set_file()
434          * @access private
435          */
436         var $file;
437
438         /**
439          * @var string Raw feed data
440          * @see SimplePie::set_raw_data()
441          * @access private
442          */
443         var $raw_data;
444
445         /**
446          * @var int Timeout for fetching remote files
447          * @see SimplePie::set_timeout()
448          * @access private
449          */
450         var $timeout = 10;
451
452         /**
453          * @var bool Forces fsockopen() to be used for remote files instead
454          * of cURL, even if a new enough version is installed
455          * @see SimplePie::force_fsockopen()
456          * @access private
457          */
458         var $force_fsockopen = false;
459
460         /**
461          * @var bool Force the given data/URL to be treated as a feed no matter what
462          * it appears like
463          * @see SimplePie::force_feed()
464          * @access private
465          */
466         var $force_feed = false;
467
468         /**
469          * @var bool Enable/Disable XML dump
470          * @see SimplePie::enable_xml_dump()
471          * @access private
472          */
473         var $xml_dump = false;
474
475         /**
476          * @var bool Enable/Disable Caching
477          * @see SimplePie::enable_cache()
478          * @access private
479          */
480         var $cache = true;
481
482         /**
483          * @var int Cache duration (in seconds)
484          * @see SimplePie::set_cache_duration()
485          * @access private
486          */
487         var $cache_duration = 3600;
488
489         /**
490          * @var int Auto-discovery cache duration (in seconds)
491          * @see SimplePie::set_autodiscovery_cache_duration()
492          * @access private
493          */
494         var $autodiscovery_cache_duration = 604800; // 7 Days.
495
496         /**
497          * @var string Cache location (relative to executing script)
498          * @see SimplePie::set_cache_location()
499          * @access private
500          */
501         var $cache_location = './cache';
502
503         /**
504          * @var string Function that creates the cache filename
505          * @see SimplePie::set_cache_name_function()
506          * @access private
507          */
508         var $cache_name_function = 'md5';
509
510         /**
511          * @var bool Reorder feed by date descending
512          * @see SimplePie::enable_order_by_date()
513          * @access private
514          */
515         var $order_by_date = true;
516
517         /**
518          * @var mixed Force input encoding to be set to the follow value
519          * (false, or anything type-cast to false, disables this feature)
520          * @see SimplePie::set_input_encoding()
521          * @access private
522          */
523         var $input_encoding = false;
524
525         /**
526          * @var int Feed Autodiscovery Level
527          * @see SimplePie::set_autodiscovery_level()
528          * @access private
529          */
530         var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
531
532         /**
533          * @var string Class used for caching feeds
534          * @see SimplePie::set_cache_class()
535          * @access private
536          */
537         var $cache_class = 'SimplePie_Cache';
538
539         /**
540          * @var string Class used for locating feeds
541          * @see SimplePie::set_locator_class()
542          * @access private
543          */
544         var $locator_class = 'SimplePie_Locator';
545
546         /**
547          * @var string Class used for parsing feeds
548          * @see SimplePie::set_parser_class()
549          * @access private
550          */
551         var $parser_class = 'SimplePie_Parser';
552
553         /**
554          * @var string Class used for fetching feeds
555          * @see SimplePie::set_file_class()
556          * @access private
557          */
558         var $file_class = 'SimplePie_File';
559
560         /**
561          * @var string Class used for items
562          * @see SimplePie::set_item_class()
563          * @access private
564          */
565         var $item_class = 'SimplePie_Item';
566
567         /**
568          * @var string Class used for authors
569          * @see SimplePie::set_author_class()
570          * @access private
571          */
572         var $author_class = 'SimplePie_Author';
573
574         /**
575          * @var string Class used for categories
576          * @see SimplePie::set_category_class()
577          * @access private
578          */
579         var $category_class = 'SimplePie_Category';
580
581         /**
582          * @var string Class used for enclosures
583          * @see SimplePie::set_enclosures_class()
584          * @access private
585          */
586         var $enclosure_class = 'SimplePie_Enclosure';
587
588         /**
589          * @var string Class used for Media RSS <media:text> captions
590          * @see SimplePie::set_caption_class()
591          * @access private
592          */
593         var $caption_class = 'SimplePie_Caption';
594
595         /**
596          * @var string Class used for Media RSS <media:copyright>
597          * @see SimplePie::set_copyright_class()
598          * @access private
599          */
600         var $copyright_class = 'SimplePie_Copyright';
601
602         /**
603          * @var string Class used for Media RSS <media:credit>
604          * @see SimplePie::set_credit_class()
605          * @access private
606          */
607         var $credit_class = 'SimplePie_Credit';
608
609         /**
610          * @var string Class used for Media RSS <media:rating>
611          * @see SimplePie::set_rating_class()
612          * @access private
613          */
614         var $rating_class = 'SimplePie_Rating';
615
616         /**
617          * @var string Class used for Media RSS <media:restriction>
618          * @see SimplePie::set_restriction_class()
619          * @access private
620          */
621         var $restriction_class = 'SimplePie_Restriction';
622
623         /**
624          * @var string Class used for content-type sniffing
625          * @see SimplePie::set_content_type_sniffer_class()
626          * @access private
627          */
628         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
629
630         /**
631          * @var string Class used for item sources.
632          * @see SimplePie::set_source_class()
633          * @access private
634          */
635         var $source_class = 'SimplePie_Source';
636
637         /**
638          * @var mixed Set javascript query string parameter (false, or
639          * anything type-cast to false, disables this feature)
640          * @see SimplePie::set_javascript()
641          * @access private
642          */
643         var $javascript = 'js';
644
645         /**
646          * @var int Maximum number of feeds to check with autodiscovery
647          * @see SimplePie::set_max_checked_feeds()
648          * @access private
649          */
650         var $max_checked_feeds = 10;
651
652         /**
653          * @var array All the feeds found during the autodiscovery process
654          * @see SimplePie::get_all_discovered_feeds()
655          * @access private
656          */
657         var $all_discovered_feeds = array();
658
659         /**
660          * @var string Web-accessible path to the handler_favicon.php file.
661          * @see SimplePie::set_favicon_handler()
662          * @access private
663          */
664         var $favicon_handler = '';
665
666         /**
667          * @var string Web-accessible path to the handler_image.php file.
668          * @see SimplePie::set_image_handler()
669          * @access private
670          */
671         var $image_handler = '';
672
673         /**
674          * @var array Stores the URLs when multiple feeds are being initialized.
675          * @see SimplePie::set_feed_url()
676          * @access private
677          */
678         var $multifeed_url = array();
679
680         /**
681          * @var array Stores SimplePie objects when multiple feeds initialized.
682          * @access private
683          */
684         var $multifeed_objects = array();
685
686         /**
687          * @var array Stores the get_object_vars() array for use with multifeeds.
688          * @see SimplePie::set_feed_url()
689          * @access private
690          */
691         var $config_settings = null;
692
693         /**
694          * @var integer Stores the number of items to return per-feed with multifeeds.
695          * @see SimplePie::set_item_limit()
696          * @access private
697          */
698         var $item_limit = 0;
699
700         /**
701          * @var array Stores the default attributes to be stripped by strip_attributes().
702          * @see SimplePie::strip_attributes()
703          * @access private
704          */
705         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
706
707         /**
708          * @var array Stores the default tags to be stripped by strip_htmltags().
709          * @see SimplePie::strip_htmltags()
710          * @access private
711          */
712         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
713
714         /**
715          * The SimplePie class contains feed level data and options
716          *
717          * There are two ways that you can create a new SimplePie object. The first
718          * is by passing a feed URL as a parameter to the SimplePie constructor
719          * (as well as optionally setting the cache location and cache expiry). This
720          * will initialise the whole feed with all of the default settings, and you
721          * can begin accessing methods and properties immediately.
722          *
723          * The second way is to create the SimplePie object with no parameters
724          * at all. This will enable you to set configuration options. After setting
725          * them, you must initialise the feed using $feed->init(). At that point the
726          * object's methods and properties will be available to you. This format is
727          * what is used throughout this documentation.
728          *
729          * @access public
730          * @since 1.0 Preview Release
731          * @param string $feed_url This is the URL you want to parse.
732          * @param string $cache_location This is where you want the cache to be stored.
733          * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
734          */
735         function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
736         {
737                 // Other objects, instances created here so we can set options on them
738                 $this->sanitize =& new SimplePie_Sanitize;
739
740                 // Set options if they're passed to the constructor
741                 if ($cache_location !== null)
742                 {
743                         $this->set_cache_location($cache_location);
744                 }
745
746                 if ($cache_duration !== null)
747                 {
748                         $this->set_cache_duration($cache_duration);
749                 }
750
751                 // Only init the script if we're passed a feed URL
752                 if ($feed_url !== null)
753                 {
754                         $this->set_feed_url($feed_url);
755                         $this->init();
756                 }
757         }
758
759         /**
760          * Used for converting object to a string
761          */
762         function __toString()
763         {
764                 return md5(serialize($this->data));
765         }
766
767         /**
768          * Remove items that link back to this before destroying this object
769          */
770         function __destruct()
771         {
772                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
773                 {
774                         if (!empty($this->data['items']))
775                         {
776                                 foreach ($this->data['items'] as $item)
777                                 {
778                                         $item->__destruct();
779                                 }
780                                 unset($item, $this->data['items']);
781                         }
782                         if (!empty($this->data['ordered_items']))
783                         {
784                                 foreach ($this->data['ordered_items'] as $item)
785                                 {
786                                         $item->__destruct();
787                                 }
788                                 unset($item, $this->data['ordered_items']);
789                         }
790                 }
791         }
792
793         /**
794          * Force the given data/URL to be treated as a feed no matter what it
795          * appears like
796          *
797          * @access public
798          * @since 1.1
799          * @param bool $enable Force the given data/URL to be treated as a feed
800          */
801         function force_feed($enable = false)
802         {
803                 $this->force_feed = (bool) $enable;
804         }
805
806         /**
807          * This is the URL of the feed you want to parse.
808          *
809          * This allows you to enter the URL of the feed you want to parse, or the
810          * website you want to try to use auto-discovery on. This takes priority
811          * over any set raw data.
812          *
813          * You can set multiple feeds to mash together by passing an array instead
814          * of a string for the $url. Remember that with each additional feed comes
815          * additional processing and resources.
816          *
817          * @access public
818          * @since 1.0 Preview Release
819          * @param mixed $url This is the URL (or array of URLs) that you want to parse.
820          * @see SimplePie::set_raw_data()
821          */
822         function set_feed_url($url)
823         {
824                 if (is_array($url))
825                 {
826                         $this->multifeed_url = array();
827                         foreach ($url as $value)
828                         {
829                                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
830                         }
831                 }
832                 else
833                 {
834                         $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
835                 }
836         }
837
838         /**
839          * Provides an instance of SimplePie_File to use as a feed
840          *
841          * @access public
842          * @param object &$file Instance of SimplePie_File (or subclass)
843          * @return bool True on success, false on failure
844          */
845         function set_file(&$file)
846         {
847                 if (is_a($file, 'SimplePie_File'))
848                 {
849                         $this->feed_url = $file->url;
850                         $this->file =& $file;
851                         return true;
852                 }
853                 return false;
854         }
855
856         /**
857          * Allows you to use a string of RSS/Atom data instead of a remote feed.
858          *
859          * If you have a feed available as a string in PHP, you can tell SimplePie
860          * to parse that data string instead of a remote feed. Any set feed URL
861          * takes precedence.
862          *
863          * @access public
864          * @since 1.0 Beta 3
865          * @param string $data RSS or Atom data as a string.
866          * @see SimplePie::set_feed_url()
867          */
868         function set_raw_data($data)
869         {
870                 $this->raw_data = $data;
871         }
872
873         /**
874          * Allows you to override the default timeout for fetching remote feeds.
875          *
876          * This allows you to change the maximum time the feed's server to respond
877          * and send the feed back.
878          *
879          * @access public
880          * @since 1.0 Beta 3
881          * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
882          */
883         function set_timeout($timeout = 10)
884         {
885                 $this->timeout = (int) $timeout;
886         }
887
888         /**
889          * Forces SimplePie to use fsockopen() instead of the preferred cURL
890          * functions.
891          *
892          * @access public
893          * @since 1.0 Beta 3
894          * @param bool $enable Force fsockopen() to be used
895          */
896         function force_fsockopen($enable = false)
897         {
898                 $this->force_fsockopen = (bool) $enable;
899         }
900
901         /**
902          * Outputs the raw XML content of the feed, after it has gone through
903          * SimplePie's filters.
904          *
905          * Used only for debugging, this function will output the XML content as
906          * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
907          * before trying to parse it. Many parts of the feed are re-written in
908          * memory, and in the end, you have a parsable feed. XML dump shows you the
909          * actual XML that SimplePie tries to parse, which may or may not be very
910          * different from the original feed.
911          *
912          * @access public
913          * @since 1.0 Preview Release
914          * @param bool $enable Enable XML dump
915          */
916         function enable_xml_dump($enable = false)
917         {
918                 $this->xml_dump = (bool) $enable;
919         }
920
921         /**
922          * Enables/disables caching in SimplePie.
923          *
924          * This option allows you to disable caching all-together in SimplePie.
925          * However, disabling the cache can lead to longer load times.
926          *
927          * @access public
928          * @since 1.0 Preview Release
929          * @param bool $enable Enable caching
930          */
931         function enable_cache($enable = true)
932         {
933                 $this->cache = (bool) $enable;
934         }
935
936         /**
937          * Set the length of time (in seconds) that the contents of a feed
938          * will be cached.
939          *
940          * @access public
941          * @param int $seconds The feed content cache duration.
942          */
943         function set_cache_duration($seconds = 3600)
944         {
945                 $this->cache_duration = (int) $seconds;
946         }
947
948         /**
949          * Set the length of time (in seconds) that the autodiscovered feed
950          * URL will be cached.
951          *
952          * @access public
953          * @param int $seconds The autodiscovered feed URL cache duration.
954          */
955         function set_autodiscovery_cache_duration($seconds = 604800)
956         {
957                 $this->autodiscovery_cache_duration = (int) $seconds;
958         }
959
960         /**
961          * Set the file system location where the cached files should be stored.
962          *
963          * @access public
964          * @param string $location The file system location.
965          */
966         function set_cache_location($location = './cache')
967         {
968                 $this->cache_location = (string) $location;
969         }
970
971         /**
972          * Determines whether feed items should be sorted into reverse chronological order.
973          *
974          * @access public
975          * @param bool $enable Sort as reverse chronological order.
976          */
977         function enable_order_by_date($enable = true)
978         {
979                 $this->order_by_date = (bool) $enable;
980         }
981
982         /**
983          * Allows you to override the character encoding reported by the feed.
984          *
985          * @access public
986          * @param string $encoding Character encoding.
987          */
988         function set_input_encoding($encoding = false)
989         {
990                 if ($encoding)
991                 {
992                         $this->input_encoding = (string) $encoding;
993                 }
994                 else
995                 {
996                         $this->input_encoding = false;
997                 }
998         }
999
1000         /**
1001          * Set how much feed autodiscovery to do
1002          *
1003          * @access public
1004          * @see SIMPLEPIE_LOCATOR_NONE
1005          * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1006          * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1007          * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1008          * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1009          * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1010          * @see SIMPLEPIE_LOCATOR_ALL
1011          * @param int $level Feed Autodiscovery Level (level can be a
1012          * combination of the above constants, see bitwise OR operator)
1013          */
1014         function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1015         {
1016                 $this->autodiscovery = (int) $level;
1017         }
1018
1019         /**
1020          * Allows you to change which class SimplePie uses for caching.
1021          * Useful when you are overloading or extending SimplePie's default classes.
1022          *
1023          * @access public
1024          * @param string $class Name of custom class.
1025          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1026          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1027          */
1028         function set_cache_class($class = 'SimplePie_Cache')
1029         {
1030                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1031                 {
1032                         $this->cache_class = $class;
1033                         return true;
1034                 }
1035                 return false;
1036         }
1037
1038         /**
1039          * Allows you to change which class SimplePie uses for auto-discovery.
1040          * Useful when you are overloading or extending SimplePie's default classes.
1041          *
1042          * @access public
1043          * @param string $class Name of custom class.
1044          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1045          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1046          */
1047         function set_locator_class($class = 'SimplePie_Locator')
1048         {
1049                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1050                 {
1051                         $this->locator_class = $class;
1052                         return true;
1053                 }
1054                 return false;
1055         }
1056
1057         /**
1058          * Allows you to change which class SimplePie uses for XML parsing.
1059          * Useful when you are overloading or extending SimplePie's default classes.
1060          *
1061          * @access public
1062          * @param string $class Name of custom class.
1063          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1064          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1065          */
1066         function set_parser_class($class = 'SimplePie_Parser')
1067         {
1068                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1069                 {
1070                         $this->parser_class = $class;
1071                         return true;
1072                 }
1073                 return false;
1074         }
1075
1076         /**
1077          * Allows you to change which class SimplePie uses for remote file fetching.
1078          * Useful when you are overloading or extending SimplePie's default classes.
1079          *
1080          * @access public
1081          * @param string $class Name of custom class.
1082          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1083          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1084          */
1085         function set_file_class($class = 'SimplePie_File')
1086         {
1087                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1088                 {
1089                         $this->file_class = $class;
1090                         return true;
1091                 }
1092                 return false;
1093         }
1094
1095         /**
1096          * Allows you to change which class SimplePie uses for data sanitization.
1097          * Useful when you are overloading or extending SimplePie's default classes.
1098          *
1099          * @access public
1100          * @param string $class Name of custom class.
1101          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1102          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1103          */
1104         function set_sanitize_class($class = 'SimplePie_Sanitize')
1105         {
1106                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1107                 {
1108                         $this->sanitize =& new $class;
1109                         return true;
1110                 }
1111                 return false;
1112         }
1113
1114         /**
1115          * Allows you to change which class SimplePie uses for handling feed items.
1116          * Useful when you are overloading or extending SimplePie's default classes.
1117          *
1118          * @access public
1119          * @param string $class Name of custom class.
1120          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1121          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1122          */
1123         function set_item_class($class = 'SimplePie_Item')
1124         {
1125                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1126                 {
1127                         $this->item_class = $class;
1128                         return true;
1129                 }
1130                 return false;
1131         }
1132
1133         /**
1134          * Allows you to change which class SimplePie uses for handling author data.
1135          * Useful when you are overloading or extending SimplePie's default classes.
1136          *
1137          * @access public
1138          * @param string $class Name of custom class.
1139          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1140          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1141          */
1142         function set_author_class($class = 'SimplePie_Author')
1143         {
1144                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1145                 {
1146                         $this->author_class = $class;
1147                         return true;
1148                 }
1149                 return false;
1150         }
1151
1152         /**
1153          * Allows you to change which class SimplePie uses for handling category data.
1154          * Useful when you are overloading or extending SimplePie's default classes.
1155          *
1156          * @access public
1157          * @param string $class Name of custom class.
1158          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1159          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1160          */
1161         function set_category_class($class = 'SimplePie_Category')
1162         {
1163                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1164                 {
1165                         $this->category_class = $class;
1166                         return true;
1167                 }
1168                 return false;
1169         }
1170
1171         /**
1172          * Allows you to change which class SimplePie uses for feed enclosures.
1173          * Useful when you are overloading or extending SimplePie's default classes.
1174          *
1175          * @access public
1176          * @param string $class Name of custom class.
1177          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1178          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1179          */
1180         function set_enclosure_class($class = 'SimplePie_Enclosure')
1181         {
1182                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1183                 {
1184                         $this->enclosure_class = $class;
1185                         return true;
1186                 }
1187                 return false;
1188         }
1189
1190         /**
1191          * Allows you to change which class SimplePie uses for <media:text> captions
1192          * Useful when you are overloading or extending SimplePie's default classes.
1193          *
1194          * @access public
1195          * @param string $class Name of custom class.
1196          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1197          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1198          */
1199         function set_caption_class($class = 'SimplePie_Caption')
1200         {
1201                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1202                 {
1203                         $this->caption_class = $class;
1204                         return true;
1205                 }
1206                 return false;
1207         }
1208
1209         /**
1210          * Allows you to change which class SimplePie uses for <media:copyright>
1211          * Useful when you are overloading or extending SimplePie's default classes.
1212          *
1213          * @access public
1214          * @param string $class Name of custom class.
1215          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1216          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1217          */
1218         function set_copyright_class($class = 'SimplePie_Copyright')
1219         {
1220                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1221                 {
1222                         $this->copyright_class = $class;
1223                         return true;
1224                 }
1225                 return false;
1226         }
1227
1228         /**
1229          * Allows you to change which class SimplePie uses for <media:credit>
1230          * Useful when you are overloading or extending SimplePie's default classes.
1231          *
1232          * @access public
1233          * @param string $class Name of custom class.
1234          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1235          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1236          */
1237         function set_credit_class($class = 'SimplePie_Credit')
1238         {
1239                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1240                 {
1241                         $this->credit_class = $class;
1242                         return true;
1243                 }
1244                 return false;
1245         }
1246
1247         /**
1248          * Allows you to change which class SimplePie uses for <media:rating>
1249          * Useful when you are overloading or extending SimplePie's default classes.
1250          *
1251          * @access public
1252          * @param string $class Name of custom class.
1253          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1254          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1255          */
1256         function set_rating_class($class = 'SimplePie_Rating')
1257         {
1258                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1259                 {
1260                         $this->rating_class = $class;
1261                         return true;
1262                 }
1263                 return false;
1264         }
1265
1266         /**
1267          * Allows you to change which class SimplePie uses for <media:restriction>
1268          * Useful when you are overloading or extending SimplePie's default classes.
1269          *
1270          * @access public
1271          * @param string $class Name of custom class.
1272          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1273          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1274          */
1275         function set_restriction_class($class = 'SimplePie_Restriction')
1276         {
1277                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1278                 {
1279                         $this->restriction_class = $class;
1280                         return true;
1281                 }
1282                 return false;
1283         }
1284
1285         /**
1286          * Allows you to change which class SimplePie uses for content-type sniffing.
1287          * Useful when you are overloading or extending SimplePie's default classes.
1288          *
1289          * @access public
1290          * @param string $class Name of custom class.
1291          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1292          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1293          */
1294         function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1295         {
1296                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1297                 {
1298                         $this->content_type_sniffer_class = $class;
1299                         return true;
1300                 }
1301                 return false;
1302         }
1303
1304         /**
1305          * Allows you to change which class SimplePie uses item sources.
1306          * Useful when you are overloading or extending SimplePie's default classes.
1307          *
1308          * @access public
1309          * @param string $class Name of custom class.
1310          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1311          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1312          */
1313         function set_source_class($class = 'SimplePie_Source')
1314         {
1315                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1316                 {
1317                         $this->source_class = $class;
1318                         return true;
1319                 }
1320                 return false;
1321         }
1322
1323         /**
1324          * Allows you to override the default user agent string.
1325          *
1326          * @access public
1327          * @param string $ua New user agent string.
1328          */
1329         function set_useragent($ua = SIMPLEPIE_USERAGENT)
1330         {
1331                 $this->useragent = (string) $ua;
1332         }
1333
1334         /**
1335          * Set callback function to create cache filename with
1336          *
1337          * @access public
1338          * @param mixed $function Callback function
1339          */
1340         function set_cache_name_function($function = 'md5')
1341         {
1342                 if (is_callable($function))
1343                 {
1344                         $this->cache_name_function = $function;
1345                 }
1346         }
1347
1348         /**
1349          * Set javascript query string parameter
1350          *
1351          * @access public
1352          * @param mixed $get Javascript query string parameter
1353          */
1354         function set_javascript($get = 'js')
1355         {
1356                 if ($get)
1357                 {
1358                         $this->javascript = (string) $get;
1359                 }
1360                 else
1361                 {
1362                         $this->javascript = false;
1363                 }
1364         }
1365
1366         /**
1367          * Set options to make SP as fast as possible.  Forgoes a
1368          * substantial amount of data sanitization in favor of speed.
1369          *
1370          * @access public
1371          * @param bool $set Whether to set them or not
1372          */
1373         function set_stupidly_fast($set = false)
1374         {
1375                 if ($set)
1376                 {
1377                         $this->enable_order_by_date(false);
1378                         $this->remove_div(false);
1379                         $this->strip_comments(false);
1380                         $this->strip_htmltags(false);
1381                         $this->strip_attributes(false);
1382                         $this->set_image_handler(false);
1383                 }
1384         }
1385
1386         /**
1387          * Set maximum number of feeds to check with autodiscovery
1388          *
1389          * @access public
1390          * @param int $max Maximum number of feeds to check
1391          */
1392         function set_max_checked_feeds($max = 10)
1393         {
1394                 $this->max_checked_feeds = (int) $max;
1395         }
1396
1397         function remove_div($enable = true)
1398         {
1399                 $this->sanitize->remove_div($enable);
1400         }
1401
1402         function strip_htmltags($tags = '', $encode = null)
1403         {
1404                 if ($tags === '')
1405                 {
1406                         $tags = $this->strip_htmltags;
1407                 }
1408                 $this->sanitize->strip_htmltags($tags);
1409                 if ($encode !== null)
1410                 {
1411                         $this->sanitize->encode_instead_of_strip($tags);
1412                 }
1413         }
1414
1415         function encode_instead_of_strip($enable = true)
1416         {
1417                 $this->sanitize->encode_instead_of_strip($enable);
1418         }
1419
1420         function strip_attributes($attribs = '')
1421         {
1422                 if ($attribs === '')
1423                 {
1424                         $attribs = $this->strip_attributes;
1425                 }
1426                 $this->sanitize->strip_attributes($attribs);
1427         }
1428
1429         function set_output_encoding($encoding = 'UTF-8')
1430         {
1431                 $this->sanitize->set_output_encoding($encoding);
1432         }
1433
1434         function strip_comments($strip = false)
1435         {
1436                 $this->sanitize->strip_comments($strip);
1437         }
1438
1439         /**
1440          * Set element/attribute key/value pairs of HTML attributes
1441          * containing URLs that need to be resolved relative to the feed
1442          *
1443          * @access public
1444          * @since 1.0
1445          * @param array $element_attribute Element/attribute key/value pairs
1446          */
1447         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'))
1448         {
1449                 $this->sanitize->set_url_replacements($element_attribute);
1450         }
1451
1452         /**
1453          * Set the handler to enable the display of cached favicons.
1454          *
1455          * @access public
1456          * @param str $page Web-accessible path to the handler_favicon.php file.
1457          * @param str $qs The query string that the value should be passed to.
1458          */
1459         function set_favicon_handler($page = false, $qs = 'i')
1460         {
1461                 if ($page !== false)
1462                 {
1463                         $this->favicon_handler = $page . '?' . $qs . '=';
1464                 }
1465                 else
1466                 {
1467                         $this->favicon_handler = '';
1468                 }
1469         }
1470
1471         /**
1472          * Set the handler to enable the display of cached images.
1473          *
1474          * @access public
1475          * @param str $page Web-accessible path to the handler_image.php file.
1476          * @param str $qs The query string that the value should be passed to.
1477          */
1478         function set_image_handler($page = false, $qs = 'i')
1479         {
1480                 if ($page !== false)
1481                 {
1482                         $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1483                 }
1484                 else
1485                 {
1486                         $this->image_handler = '';
1487                 }
1488         }
1489
1490         /**
1491          * Set the limit for items returned per-feed with multifeeds.
1492          *
1493          * @access public
1494          * @param integer $limit The maximum number of items to return.
1495          */
1496         function set_item_limit($limit = 0)
1497         {
1498                 $this->item_limit = (int) $limit;
1499         }
1500
1501         function init()
1502         {
1503                 // Check absolute bare minimum requirements.
1504                 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1505                 {
1506                         return false;
1507                 }
1508                 // 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.
1509                 elseif (!extension_loaded('xmlreader'))
1510                 {
1511                         static $xml_is_sane = null;
1512                         if ($xml_is_sane === null)
1513                         {
1514                                 $parser_check = xml_parser_create();
1515                                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1516                                 xml_parser_free($parser_check);
1517                                 $xml_is_sane = isset($values[0]['value']);
1518                         }
1519                         if (!$xml_is_sane)
1520                         {
1521                                 return false;
1522                         }
1523                 }
1524
1525                 if (isset($_GET[$this->javascript]))
1526                 {
1527                         SimplePie_Misc::output_javascript();
1528                         exit;
1529                 }
1530
1531                 // Pass whatever was set with config options over to the sanitizer.
1532                 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1533                 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1534
1535                 if ($this->feed_url !== null || $this->raw_data !== null)
1536                 {
1537                         $this->data = array();
1538                         $this->multifeed_objects = array();
1539                         $cache = false;
1540
1541                         if ($this->feed_url !== null)
1542                         {
1543                                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1544                                 // Decide whether to enable caching
1545                                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1546                                 {
1547                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1548                                 }
1549                                 // If it's enabled and we don't want an XML dump, use the cache
1550                                 if ($cache && !$this->xml_dump)
1551                                 {
1552                                         // Load the Cache
1553                                         $this->data = $cache->load();
1554                                         if (!empty($this->data))
1555                                         {
1556                                                 // If the cache is for an outdated build of SimplePie
1557                                                 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1558                                                 {
1559                                                         $cache->unlink();
1560                                                         $this->data = array();
1561                                                 }
1562                                                 // If we've hit a collision just rerun it with caching disabled
1563                                                 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1564                                                 {
1565                                                         $cache = false;
1566                                                         $this->data = array();
1567                                                 }
1568                                                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1569                                                 elseif (isset($this->data['feed_url']))
1570                                                 {
1571                                                         // If the autodiscovery cache is still valid use it.
1572                                                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1573                                                         {
1574                                                                 // Do not need to do feed autodiscovery yet.
1575                                                                 if ($this->data['feed_url'] === $this->data['url'])
1576                                                                 {
1577                                                                         $cache->unlink();
1578                                                                         $this->data = array();
1579                                                                 }
1580                                                                 else
1581                                                                 {
1582                                                                         $this->set_feed_url($this->data['feed_url']);
1583                                                                         return $this->init();
1584                                                                 }
1585                                                         }
1586                                                 }
1587                                                 // Check if the cache has been updated
1588                                                 elseif ($cache->mtime() + $this->cache_duration < time())
1589                                                 {
1590                                                         // If we have last-modified and/or etag set
1591                                                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1592                                                         {
1593                                                                 $headers = array();
1594                                                                 if (isset($this->data['headers']['last-modified']))
1595                                                                 {
1596                                                                         $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1597                                                                 }
1598                                                                 if (isset($this->data['headers']['etag']))
1599                                                                 {
1600                                                                         $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1601                                                                 }
1602                                                                 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1603                                                                 if ($file->success)
1604                                                                 {
1605                                                                         if ($file->status_code === 304)
1606                                                                         {
1607                                                                                 $cache->touch();
1608                                                                                 return true;
1609                                                                         }
1610                                                                         else
1611                                                                         {
1612                                                                                 $headers = $file->headers;
1613                                                                         }
1614                                                                 }
1615                                                                 else
1616                                                                 {
1617                                                                         unset($file);
1618                                                                 }
1619                                                         }
1620                                                 }
1621                                                 // If the cache is still valid, just return true
1622                                                 else
1623                                                 {
1624                                                         return true;
1625                                                 }
1626                                         }
1627                                         // If the cache is empty, delete it
1628                                         else
1629                                         {
1630                                                 $cache->unlink();
1631                                                 $this->data = array();
1632                                         }
1633                                 }
1634                                 // 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.
1635                                 if (!isset($file))
1636                                 {
1637                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1638                                         {
1639                                                 $file =& $this->file;
1640                                         }
1641                                         else
1642                                         {
1643                                                 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1644                                         }
1645                                 }
1646                                 // If the file connection has an error, set SimplePie::error to that and quit
1647                                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1648                                 {
1649                                         $this->error = $file->error;
1650                                         if (!empty($this->data))
1651                                         {
1652                                                 return true;
1653                                         }
1654                                         else
1655                                         {
1656                                                 return false;
1657                                         }
1658                                 }
1659
1660                                 if (!$this->force_feed)
1661                                 {
1662                                         // Check if the supplied URL is a feed, if it isn't, look for it.
1663                                         $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1664                                         if (!$locate->is_feed($file))
1665                                         {
1666                                                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1667                                                 unset($file);
1668                                                 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1669                                                 {
1670                                                         if ($cache)
1671                                                         {
1672                                                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673                                                                 if (!$cache->save($this))
1674                                                                 {
1675                                                                         trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
1676                                                                 }
1677                                                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1678                                                         }
1679                                                         $this->feed_url = $file->url;
1680                                                 }
1681                                                 else
1682                                                 {
1683                                                         $this->error = "A feed could not be found at $this->feed_url";
1684                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1685                                                         return false;
1686                                                 }
1687                                         }
1688                                         $locate = null;
1689                                 }
1690
1691                                 $headers = $file->headers;
1692                                 $data = $file->body;
1693                                 $sniffer =& new $this->content_type_sniffer_class($file);
1694                                 $sniffed = $sniffer->get_type();
1695                         }
1696                         else
1697                         {
1698                                 $data = $this->raw_data;
1699                         }
1700
1701                         // Set up array of possible encodings
1702                         $encodings = array();
1703
1704                         // First check to see if input has been overridden.
1705                         if ($this->input_encoding !== false)
1706                         {
1707                                 $encodings[] = $this->input_encoding;
1708                         }
1709
1710                         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1711                         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1712
1713                         // RFC 3023 (only applies to sniffed content)
1714                         if (isset($sniffed))
1715                         {
1716                                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1717                                 {
1718                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1719                                         {
1720                                                 $encodings[] = strtoupper($charset[1]);
1721                                         }
1722                                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723                                         $encodings[] = 'UTF-8';
1724                                 }
1725                                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1726                                 {
1727                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1728                                         {
1729                                                 $encodings[] = $charset[1];
1730                                         }
1731                                         $encodings[] = 'US-ASCII';
1732                                 }
1733                                 // Text MIME-type default
1734                                 elseif (substr($sniffed, 0, 5) === 'text/')
1735                                 {
1736                                         $encodings[] = 'US-ASCII';
1737                                 }
1738                         }
1739
1740                         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1741                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1742                         $encodings[] = 'UTF-8';
1743                         $encodings[] = 'ISO-8859-1';
1744
1745                         // There's no point in trying an encoding twice
1746                         $encodings = array_unique($encodings);
1747
1748                         // If we want the XML, just output that with the most likely encoding and quit
1749                         if ($this->xml_dump)
1750                         {
1751                                 header('Content-type: text/xml; charset=' . $encodings[0]);
1752                                 echo $data;
1753                                 exit;
1754                         }
1755
1756                         // Loop through each possible encoding, till we return something, or run out of possibilities
1757                         foreach ($encodings as $encoding)
1758                         {
1759                                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1760                                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1761                                 {
1762                                         // Create new parser
1763                                         $parser =& new $this->parser_class();
1764
1765                                         // If it's parsed fine
1766                                         if ($parser->parse($utf8_data, 'UTF-8'))
1767                                         {
1768                                                 $this->data = $parser->get_data();
1769                                                 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1770                                                 {
1771                                                         if (isset($headers))
1772                                                         {
1773                                                                 $this->data['headers'] = $headers;
1774                                                         }
1775                                                         $this->data['build'] = SIMPLEPIE_BUILD;
1776
1777                                                         // Cache the file if caching is enabled
1778                                                         if ($cache && !$cache->save($this))
1779                                                         {
1780                                                                 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1781                                                         }
1782                                                         return true;
1783                                                 }
1784                                                 else
1785                                                 {
1786                                                         $this->error = "A feed could not be found at $this->feed_url";
1787                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1788                                                         return false;
1789                                                 }
1790                                         }
1791                                 }
1792                         }
1793                         if(isset($parser))
1794                         {
1795                                 // We have an error, just set SimplePie_Misc::error to it and quit
1796                                 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1797                         }
1798                         else
1799                         {
1800                                 $this->error = 'The data could not be converted to UTF-8';
1801                         }
1802                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1803                         return false;
1804                 }
1805                 elseif (!empty($this->multifeed_url))
1806                 {
1807                         $i = 0;
1808                         $success = 0;
1809                         $this->multifeed_objects = array();
1810                         foreach ($this->multifeed_url as $url)
1811                         {
1812                                 if (SIMPLEPIE_PHP5)
1813                                 {
1814                                         // This keyword needs to defy coding standards for PHP4 compatibility
1815                                         $this->multifeed_objects[$i] = clone($this);
1816                                 }
1817                                 else
1818                                 {
1819                                         $this->multifeed_objects[$i] = $this;
1820                                 }
1821                                 $this->multifeed_objects[$i]->set_feed_url($url);
1822                                 $success |= $this->multifeed_objects[$i]->init();
1823                                 $i++;
1824                         }
1825                         return (bool) $success;
1826                 }
1827                 else
1828                 {
1829                         return false;
1830                 }
1831         }
1832
1833         /**
1834          * Return the error message for the occurred error
1835          *
1836          * @access public
1837          * @return string Error message
1838          */
1839         function error()
1840         {
1841                 return $this->error;
1842         }
1843
1844         function get_encoding()
1845         {
1846                 return $this->sanitize->output_encoding;
1847         }
1848
1849         function handle_content_type($mime = 'text/html')
1850         {
1851                 if (!headers_sent())
1852                 {
1853                         $header = "Content-type: $mime;";
1854                         if ($this->get_encoding())
1855                         {
1856                                 $header .= ' charset=' . $this->get_encoding();
1857                         }
1858                         else
1859                         {
1860                                 $header .= ' charset=UTF-8';
1861                         }
1862                         header($header);
1863                 }
1864         }
1865
1866         function get_type()
1867         {
1868                 if (!isset($this->data['type']))
1869                 {
1870                         $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1872                         {
1873                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1874                         }
1875                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1876                         {
1877                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1878                         }
1879                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1880                         {
1881                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1882                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1883                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1884                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1885                                 {
1886                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1887                                 }
1888                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1889                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1890                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1891                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1892                                 {
1893                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1894                                 }
1895                         }
1896                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1897                         {
1898                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1900                                 {
1901                                         switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1902                                         {
1903                                                 case '0.91':
1904                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1905                                                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1906                                                         {
1907                                                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1908                                                                 {
1909                                                                         case '0':
1910                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1911                                                                                 break;
1912
1913                                                                         case '24':
1914                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1915                                                                                 break;
1916                                                                 }
1917                                                         }
1918                                                         break;
1919
1920                                                 case '0.92':
1921                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1922                                                         break;
1923
1924                                                 case '0.93':
1925                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1926                                                         break;
1927
1928                                                 case '0.94':
1929                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1930                                                         break;
1931
1932                                                 case '2.0':
1933                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1934                                                         break;
1935                                         }
1936                                 }
1937                         }
1938                         else
1939                         {
1940                                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1941                         }
1942                 }
1943                 return $this->data['type'];
1944         }
1945
1946         /**
1947          * Returns the URL for the favicon of the feed's website.
1948          *
1949          * @todo Cache atom:icon
1950          * @access public
1951          * @since 1.0
1952          */
1953         function get_favicon()
1954         {
1955                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1956                 {
1957                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1958                 }
1959                 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1960                 {
1961                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1962
1963                         if ($this->cache && $this->favicon_handler)
1964                         {
1965                                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1966                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1967
1968                                 if ($cache->load())
1969                                 {
1970                                         return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1971                                 }
1972                                 else
1973                                 {
1974                                         $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1975
1976                                         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)
1977                                         {
1978                                                 $sniffer =& new $this->content_type_sniffer_class($file);
1979                                                 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1980                                                 {
1981                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1982                                                         {
1983                                                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1984                                                         }
1985                                                         else
1986                                                         {
1987                                                                 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1988                                                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1989                                                         }
1990                                                 }
1991                                                 // not an image
1992                                                 else
1993                                                 {
1994                                                         return false;
1995                                                 }
1996                                         }
1997                                 }
1998                         }
1999                         else
2000                         {
2001                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2002                         }
2003                 }
2004                 return false;
2005         }
2006
2007         /**
2008          * @todo If we have a perm redirect we should return the new URL
2009          * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2010          * @todo Also, |atom:link|@rel=self
2011          */
2012         function subscribe_url()
2013         {
2014                 if ($this->feed_url !== null)
2015                 {
2016                         return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2017                 }
2018                 else
2019                 {
2020                         return null;
2021                 }
2022         }
2023
2024         function subscribe_feed()
2025         {
2026                 if ($this->feed_url !== null)
2027                 {
2028                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2029                 }
2030                 else
2031                 {
2032                         return null;
2033                 }
2034         }
2035
2036         function subscribe_outlook()
2037         {
2038                 if ($this->feed_url !== null)
2039                 {
2040                         return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2041                 }
2042                 else
2043                 {
2044                         return null;
2045                 }
2046         }
2047
2048         function subscribe_podcast()
2049         {
2050                 if ($this->feed_url !== null)
2051                 {
2052                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2053                 }
2054                 else
2055                 {
2056                         return null;
2057                 }
2058         }
2059
2060         function subscribe_itunes()
2061         {
2062                 if ($this->feed_url !== null)
2063                 {
2064                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2065                 }
2066                 else
2067                 {
2068                         return null;
2069                 }
2070         }
2071
2072         /**
2073          * Creates the subscribe_* methods' return data
2074          *
2075          * @access private
2076          * @param string $feed_url String to prefix to the feed URL
2077          * @param string $site_url String to prefix to the site URL (and
2078          * suffix to the feed URL)
2079          * @return mixed URL if feed exists, false otherwise
2080          */
2081         function subscribe_service($feed_url, $site_url = null)
2082         {
2083                 if ($this->subscribe_url())
2084                 {
2085                         $return = $feed_url . rawurlencode($this->feed_url);
2086                         if ($site_url !== null && $this->get_link() !== null)
2087                         {
2088                                 $return .= $site_url . rawurlencode($this->get_link());
2089                         }
2090                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2091                 }
2092                 else
2093                 {
2094                         return null;
2095                 }
2096         }
2097
2098         function subscribe_aol()
2099         {
2100                 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2101         }
2102
2103         function subscribe_bloglines()
2104         {
2105                 return $this->subscribe_service('http://www.bloglines.com/sub/');
2106         }
2107
2108         function subscribe_eskobo()
2109         {
2110                 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2111         }
2112
2113         function subscribe_feedfeeds()
2114         {
2115                 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2116         }
2117
2118         function subscribe_feedster()
2119         {
2120                 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2121         }
2122
2123         function subscribe_google()
2124         {
2125                 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2126         }
2127
2128         function subscribe_gritwire()
2129         {
2130                 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2131         }
2132
2133         function subscribe_msn()
2134         {
2135                 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2136         }
2137
2138         function subscribe_netvibes()
2139         {
2140                 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2141         }
2142
2143         function subscribe_newsburst()
2144         {
2145                 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2146         }
2147
2148         function subscribe_newsgator()
2149         {
2150                 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2151         }
2152
2153         function subscribe_odeo()
2154         {
2155                 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2156         }
2157
2158         function subscribe_podnova()
2159         {
2160                 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2161         }
2162
2163         function subscribe_rojo()
2164         {
2165                 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2166         }
2167
2168         function subscribe_yahoo()
2169         {
2170                 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2171         }
2172
2173         function get_feed_tags($namespace, $tag)
2174         {
2175                 $type = $this->get_type();
2176                 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2177                 {
2178                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2179                         {
2180                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2181                         }
2182                 }
2183                 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2184                 {
2185                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2186                         {
2187                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2188                         }
2189                 }
2190                 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2191                 {
2192                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2193                         {
2194                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2195                         }
2196                 }
2197                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2198                 {
2199                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2200                         {
2201                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2202                         }
2203                 }
2204                 return null;
2205         }
2206
2207         function get_channel_tags($namespace, $tag)
2208         {
2209                 $type = $this->get_type();
2210                 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2211                 {
2212                         if ($return = $this->get_feed_tags($namespace, $tag))
2213                         {
2214                                 return $return;
2215                         }
2216                 }
2217                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2218                 {
2219                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2220                         {
2221                                 if (isset($channel[0]['child'][$namespace][$tag]))
2222                                 {
2223                                         return $channel[0]['child'][$namespace][$tag];
2224                                 }
2225                         }
2226                 }
2227                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2228                 {
2229                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2230                         {
2231                                 if (isset($channel[0]['child'][$namespace][$tag]))
2232                                 {
2233                                         return $channel[0]['child'][$namespace][$tag];
2234                                 }
2235                         }
2236                 }
2237                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2238                 {
2239                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2240                         {
2241                                 if (isset($channel[0]['child'][$namespace][$tag]))
2242                                 {
2243                                         return $channel[0]['child'][$namespace][$tag];
2244                                 }
2245                         }
2246                 }
2247                 return null;
2248         }
2249
2250         function get_image_tags($namespace, $tag)
2251         {
2252                 $type = $this->get_type();
2253                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2254                 {
2255                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2256                         {
2257                                 if (isset($image[0]['child'][$namespace][$tag]))
2258                                 {
2259                                         return $image[0]['child'][$namespace][$tag];
2260                                 }
2261                         }
2262                 }
2263                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2264                 {
2265                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2266                         {
2267                                 if (isset($image[0]['child'][$namespace][$tag]))
2268                                 {
2269                                         return $image[0]['child'][$namespace][$tag];
2270                                 }
2271                         }
2272                 }
2273                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2274                 {
2275                         if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2276                         {
2277                                 if (isset($image[0]['child'][$namespace][$tag]))
2278                                 {
2279                                         return $image[0]['child'][$namespace][$tag];
2280                                 }
2281                         }
2282                 }
2283                 return null;
2284         }
2285
2286         function get_base($element = array())
2287         {
2288                 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2289                 {
2290                         return $element['xml_base'];
2291                 }
2292                 elseif ($this->get_link() !== null)
2293                 {
2294                         return $this->get_link();
2295                 }
2296                 else
2297                 {
2298                         return $this->subscribe_url();
2299                 }
2300         }
2301
2302         function sanitize($data, $type, $base = '')
2303         {
2304                 return $this->sanitize->sanitize($data, $type, $base);
2305         }
2306
2307         function get_title()
2308         {
2309                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2310                 {
2311                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2312                 }
2313                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2314                 {
2315                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2316                 }
2317                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2318                 {
2319                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2320                 }
2321                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2322                 {
2323                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2324                 }
2325                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2326                 {
2327                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2328                 }
2329                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2330                 {
2331                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2332                 }
2333                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2334                 {
2335                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2336                 }
2337                 else
2338                 {
2339                         return null;
2340                 }
2341         }
2342
2343         function get_category($key = 0)
2344         {
2345                 $categories = $this->get_categories();
2346                 if (isset($categories[$key]))
2347                 {
2348                         return $categories[$key];
2349                 }
2350                 else
2351                 {
2352                         return null;
2353                 }
2354         }
2355
2356         function get_categories()
2357         {
2358                 $categories = array();
2359
2360                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2361                 {
2362                         $term = null;
2363                         $scheme = null;
2364                         $label = null;
2365                         if (isset($category['attribs']['']['term']))
2366                         {
2367                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2368                         }
2369                         if (isset($category['attribs']['']['scheme']))
2370                         {
2371                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2372                         }
2373                         if (isset($category['attribs']['']['label']))
2374                         {
2375                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2376                         }
2377                         $categories[] =& new $this->category_class($term, $scheme, $label);
2378                 }
2379                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2380                 {
2381                         // This is really the label, but keep this as the term also for BC.
2382                         // Label will also work on retrieving because that falls back to term.
2383                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384                         if (isset($category['attribs']['']['domain']))
2385                         {
2386                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2387                         }
2388                         else
2389                         {
2390                                 $scheme = null;
2391                         }
2392                         $categories[] =& new $this->category_class($term, $scheme, null);
2393                 }
2394                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2395                 {
2396                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2397                 }
2398                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2399                 {
2400                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2401                 }
2402
2403                 if (!empty($categories))
2404                 {
2405                         return SimplePie_Misc::array_unique($categories);
2406                 }
2407                 else
2408                 {
2409                         return null;
2410                 }
2411         }
2412
2413         function get_author($key = 0)
2414         {
2415                 $authors = $this->get_authors();
2416                 if (isset($authors[$key]))
2417                 {
2418                         return $authors[$key];
2419                 }
2420                 else
2421                 {
2422                         return null;
2423                 }
2424         }
2425
2426         function get_authors()
2427         {
2428                 $authors = array();
2429                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2430                 {
2431                         $name = null;
2432                         $uri = null;
2433                         $email = null;
2434                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2435                         {
2436                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2437                         }
2438                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2439                         {
2440                                 $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]));
2441                         }
2442                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2443                         {
2444                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2445                         }
2446                         if ($name !== null || $email !== null || $uri !== null)
2447                         {
2448                                 $authors[] =& new $this->author_class($name, $uri, $email);
2449                         }
2450                 }
2451                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2452                 {
2453                         $name = null;
2454                         $url = null;
2455                         $email = null;
2456                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2457                         {
2458                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2459                         }
2460                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2461                         {
2462                                 $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]));
2463                         }
2464                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2465                         {
2466                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2467                         }
2468                         if ($name !== null || $email !== null || $url !== null)
2469                         {
2470                                 $authors[] =& new $this->author_class($name, $url, $email);
2471                         }
2472                 }
2473                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2474                 {
2475                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2476                 }
2477                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2478                 {
2479                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2480                 }
2481                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2482                 {
2483                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2484                 }
2485
2486                 if (!empty($authors))
2487                 {
2488                         return SimplePie_Misc::array_unique($authors);
2489                 }
2490                 else
2491                 {
2492                         return null;
2493                 }
2494         }
2495
2496         function get_contributor($key = 0)
2497         {
2498                 $contributors = $this->get_contributors();
2499                 if (isset($contributors[$key]))
2500                 {
2501                         return $contributors[$key];
2502                 }
2503                 else
2504                 {
2505                         return null;
2506                 }
2507         }
2508
2509         function get_contributors()
2510         {
2511                 $contributors = array();
2512                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2513                 {
2514                         $name = null;
2515                         $uri = null;
2516                         $email = null;
2517                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2518                         {
2519                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2520                         }
2521                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2522                         {
2523                                 $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]));
2524                         }
2525                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2526                         {
2527                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2528                         }
2529                         if ($name !== null || $email !== null || $uri !== null)
2530                         {
2531                                 $contributors[] =& new $this->author_class($name, $uri, $email);
2532                         }
2533                 }
2534                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2535                 {
2536                         $name = null;
2537                         $url = null;
2538                         $email = null;
2539                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2540                         {
2541                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2542                         }
2543                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2544                         {
2545                                 $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]));
2546                         }
2547                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2548                         {
2549                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2550                         }
2551                         if ($name !== null || $email !== null || $url !== null)
2552                         {
2553                                 $contributors[] =& new $this->author_class($name, $url, $email);
2554                         }
2555                 }
2556
2557                 if (!empty($contributors))
2558                 {
2559                         return SimplePie_Misc::array_unique($contributors);
2560                 }
2561                 else
2562                 {
2563                         return null;
2564                 }
2565         }
2566
2567         function get_link($key = 0, $rel = 'alternate')
2568         {
2569                 $links = $this->get_links($rel);
2570                 if (isset($links[$key]))
2571                 {
2572                         return $links[$key];
2573                 }
2574                 else
2575                 {
2576                         return null;
2577                 }
2578         }
2579
2580         /**
2581          * Added for parity between the parent-level and the item/entry-level.
2582          */
2583         function get_permalink()
2584         {
2585                 return $this->get_link(0);
2586         }
2587
2588         function get_links($rel = 'alternate')
2589         {
2590                 if (!isset($this->data['links']))
2591                 {
2592                         $this->data['links'] = array();
2593                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2594                         {
2595                                 foreach ($links as $link)
2596                                 {
2597                                         if (isset($link['attribs']['']['href']))
2598                                         {
2599                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2600                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2601                                         }
2602                                 }
2603                         }
2604                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2605                         {
2606                                 foreach ($links as $link)
2607                                 {
2608                                         if (isset($link['attribs']['']['href']))
2609                                         {
2610                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2611                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2612
2613                                         }
2614                                 }
2615                         }
2616                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2617                         {
2618                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2619                         }
2620                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2621                         {
2622                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2623                         }
2624                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2625                         {
2626                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2627                         }
2628
2629                         $keys = array_keys($this->data['links']);
2630                         foreach ($keys as $key)
2631                         {
2632                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2633                                 {
2634                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2635                                         {
2636                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2637                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2638                                         }
2639                                         else
2640                                         {
2641                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2642                                         }
2643                                 }
2644                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2645                                 {
2646                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2647                                 }
2648                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2649                         }
2650                 }
2651
2652                 if (isset($this->data['links'][$rel]))
2653                 {
2654                         return $this->data['links'][$rel];
2655                 }
2656                 else
2657                 {
2658                         return null;
2659                 }
2660         }
2661
2662         function get_all_discovered_feeds()
2663         {
2664                 return $this->all_discovered_feeds;
2665         }
2666
2667         function get_description()
2668         {
2669                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2670                 {
2671                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2672                 }
2673                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2674                 {
2675                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2676                 }
2677                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2678                 {
2679                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2680                 }
2681                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2682                 {
2683                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2684                 }
2685                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2686                 {
2687                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2688                 }
2689                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2690                 {
2691                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2692                 }
2693                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2694                 {
2695                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2696                 }
2697                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2698                 {
2699                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2700                 }
2701                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2702                 {
2703                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2704                 }
2705                 else
2706                 {
2707                         return null;
2708                 }
2709         }
2710
2711         function get_copyright()
2712         {
2713                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2714                 {
2715                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2716                 }
2717                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2718                 {
2719                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2720                 }
2721                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2722                 {
2723                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2724                 }
2725                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2726                 {
2727                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2728                 }
2729                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2730                 {
2731                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2732                 }
2733                 else
2734                 {
2735                         return null;
2736                 }
2737         }
2738
2739         function get_language()
2740         {
2741                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2742                 {
2743                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2744                 }
2745                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2746                 {
2747                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2748                 }
2749                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2750                 {
2751                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2752                 }
2753                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2754                 {
2755                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2756                 }
2757                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2758                 {
2759                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2760                 }
2761                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2762                 {
2763                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2764                 }
2765                 elseif (isset($this->data['headers']['content-language']))
2766                 {
2767                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2768                 }
2769                 else
2770                 {
2771                         return null;
2772                 }
2773         }
2774
2775         function get_latitude()
2776         {
2777                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2778                 {
2779                         return (float) $return[0]['data'];
2780                 }
2781                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2782                 {
2783                         return (float) $match[1];
2784                 }
2785                 else
2786                 {
2787                         return null;
2788                 }
2789         }
2790
2791         function get_longitude()
2792         {
2793                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2794                 {
2795                         return (float) $return[0]['data'];
2796                 }
2797                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2798                 {
2799                         return (float) $return[0]['data'];
2800                 }
2801                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2802                 {
2803                         return (float) $match[2];
2804                 }
2805                 else
2806                 {
2807                         return null;
2808                 }
2809         }
2810
2811         function get_image_title()
2812         {
2813                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2814                 {
2815                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2816                 }
2817                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2818                 {
2819                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2820                 }
2821                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2822                 {
2823                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2824                 }
2825                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2826                 {
2827                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2828                 }
2829                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2830                 {
2831                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2832                 }
2833                 else
2834                 {
2835                         return null;
2836                 }
2837         }
2838
2839         function get_image_url()
2840         {
2841                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2842                 {
2843                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2844                 }
2845                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2846                 {
2847                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2848                 }
2849                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2850                 {
2851                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2852                 }
2853                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2854                 {
2855                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2856                 }
2857                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2858                 {
2859                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2860                 }
2861                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2862                 {
2863                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2864                 }
2865                 else
2866                 {
2867                         return null;
2868                 }
2869         }
2870
2871         function get_image_link()
2872         {
2873                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2874                 {
2875                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2876                 }
2877                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2878                 {
2879                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2880                 }
2881                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2882                 {
2883                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2884                 }
2885                 else
2886                 {
2887                         return null;
2888                 }
2889         }
2890
2891         function get_image_width()
2892         {
2893                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2894                 {
2895                         return round($return[0]['data']);
2896                 }
2897                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2898                 {
2899                         return 88.0;
2900                 }
2901                 else
2902                 {
2903                         return null;
2904                 }
2905         }
2906
2907         function get_image_height()
2908         {
2909                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2910                 {
2911                         return round($return[0]['data']);
2912                 }
2913                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2914                 {
2915                         return 31.0;
2916                 }
2917                 else
2918                 {
2919                         return null;
2920                 }
2921         }
2922
2923         function get_item_quantity($max = 0)
2924         {
2925                 $max = (int) $max;
2926                 $qty = count($this->get_items());
2927                 if ($max === 0)
2928                 {
2929                         return $qty;
2930                 }
2931                 else
2932                 {
2933                         return ($qty > $max) ? $max : $qty;
2934                 }
2935         }
2936
2937         function get_item($key = 0)
2938         {
2939                 $items = $this->get_items();
2940                 if (isset($items[$key]))
2941                 {
2942                         return $items[$key];
2943                 }
2944                 else
2945                 {
2946                         return null;
2947                 }
2948         }
2949
2950         function get_items($start = 0, $end = 0)
2951         {
2952                 if (!isset($this->data['items']))
2953                 {
2954                         if (!empty($this->multifeed_objects))
2955                         {
2956                                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2957                         }
2958                         else
2959                         {
2960                                 $this->data['items'] = array();
2961                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2962                                 {
2963                                         $keys = array_keys($items);
2964                                         foreach ($keys as $key)
2965                                         {
2966                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2967                                         }
2968                                 }
2969                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2970                                 {
2971                                         $keys = array_keys($items);
2972                                         foreach ($keys as $key)
2973                                         {
2974                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2975                                         }
2976                                 }
2977                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2978                                 {
2979                                         $keys = array_keys($items);
2980                                         foreach ($keys as $key)
2981                                         {
2982                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2983                                         }
2984                                 }
2985                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2986                                 {
2987                                         $keys = array_keys($items);
2988                                         foreach ($keys as $key)
2989                                         {
2990                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2991                                         }
2992                                 }
2993                                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2994                                 {
2995                                         $keys = array_keys($items);
2996                                         foreach ($keys as $key)
2997                                         {
2998                                                 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2999                                         }
3000                                 }
3001                         }
3002                 }
3003
3004                 if (!empty($this->data['items']))
3005                 {
3006                         // If we want to order it by date, check if all items have a date, and then sort it
3007                         if ($this->order_by_date && empty($this->multifeed_objects))
3008                         {
3009                                 if (!isset($this->data['ordered_items']))
3010                                 {
3011                                         $do_sort = true;
3012                                         foreach ($this->data['items'] as $item)
3013                                         {
3014                                                 if (!$item->get_date('U'))
3015                                                 {
3016                                                         $do_sort = false;
3017                                                         break;
3018                                                 }
3019                                         }
3020                                         $item = null;
3021                                         $this->data['ordered_items'] = $this->data['items'];
3022                                         if ($do_sort)
3023                                         {
3024                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3025                                         }
3026                                 }
3027                                 $items = $this->data['ordered_items'];
3028                         }
3029                         else
3030                         {
3031                                 $items = $this->data['items'];
3032                         }
3033
3034                         // Slice the data as desired
3035                         if ($end === 0)
3036                         {
3037                                 return array_slice($items, $start);
3038                         }
3039                         else
3040                         {
3041                                 return array_slice($items, $start, $end);
3042                         }
3043                 }
3044                 else
3045                 {
3046                         return array();
3047                 }
3048         }
3049
3050         /**
3051          * @static
3052          */
3053         function sort_items($a, $b)
3054         {
3055                 return $a->get_date('U') <= $b->get_date('U');
3056         }
3057
3058         /**
3059          * @static
3060          */
3061         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3062         {
3063                 if (is_array($urls) && sizeof($urls) > 0)
3064                 {
3065                         $items = array();
3066                         foreach ($urls as $arg)
3067                         {
3068                                 if (is_a($arg, 'SimplePie'))
3069                                 {
3070                                         $items = array_merge($items, $arg->get_items(0, $limit));
3071                                 }
3072                                 else
3073                                 {
3074                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3075                                 }
3076                         }
3077
3078                         $do_sort = true;
3079                         foreach ($items as $item)
3080                         {
3081                                 if (!$item->get_date('U'))
3082                                 {
3083                                         $do_sort = false;
3084                                         break;
3085                                 }
3086                         }
3087                         $item = null;
3088                         if ($do_sort)
3089                         {
3090                                 usort($items, array('SimplePie', 'sort_items'));
3091                         }
3092
3093                         if ($end === 0)
3094                         {
3095                                 return array_slice($items, $start);
3096                         }
3097                         else
3098                         {
3099                                 return array_slice($items, $start, $end);
3100                         }
3101                 }
3102                 else
3103                 {
3104                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3105                         return array();
3106                 }
3107         }
3108 }
3109
3110 class SimplePie_Item
3111 {
3112         var $feed;
3113         var $data = array();
3114
3115         function SimplePie_Item($feed, $data)
3116         {
3117                 $this->feed = $feed;
3118                 $this->data = $data;
3119         }
3120
3121         function __toString()
3122         {
3123                 return md5(serialize($this->data));
3124         }
3125
3126         /**
3127          * Remove items that link back to this before destroying this object
3128          */
3129         function __destruct()
3130         {
3131                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3132                 {
3133                         unset($this->feed);
3134                 }
3135         }
3136
3137         function get_item_tags($namespace, $tag)
3138         {
3139                 if (isset($this->data['child'][$namespace][$tag]))
3140                 {
3141                         return $this->data['child'][$namespace][$tag];
3142                 }
3143                 else
3144                 {
3145                         return null;
3146                 }
3147         }
3148
3149         function get_base($element = array())
3150         {
3151                 return $this->feed->get_base($element);
3152         }
3153
3154         function sanitize($data, $type, $base = '')
3155         {
3156                 return $this->feed->sanitize($data, $type, $base);
3157         }
3158
3159         function get_feed()
3160         {
3161                 return $this->feed;
3162         }
3163
3164         function get_id($hash = false)
3165         {
3166                 if (!$hash)
3167                 {
3168                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3169                         {
3170                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3171                         }
3172                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3173                         {
3174                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3175                         }
3176                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3177                         {
3178                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3179                         }
3180                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3181                         {
3182                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3183                         }
3184                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3185                         {
3186                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3187                         }
3188                         elseif (($return = $this->get_permalink()) !== null)
3189                         {
3190                                 return $return;
3191                         }
3192                         elseif (($return = $this->get_title()) !== null)
3193                         {
3194                                 return $return;
3195                         }
3196                 }
3197                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3198                 {
3199                         return md5($this->get_permalink() . $this->get_title());
3200                 }
3201                 else
3202                 {
3203                         return md5(serialize($this->data));
3204                 }
3205         }
3206
3207         function get_title()
3208         {
3209                 if (!isset($this->data['title']))
3210                 {
3211                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3212                         {
3213                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3214                         }
3215                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3216                         {
3217                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3218                         }
3219                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3220                         {
3221                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3222                         }
3223                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3224                         {
3225                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3226                         }
3227                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3228                         {
3229                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3230                         }
3231                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3232                         {
3233                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3234                         }
3235                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3236                         {
3237                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3238                         }
3239                         else
3240                         {
3241                                 $this->data['title'] = null;
3242                         }
3243                 }
3244                 return $this->data['title'];
3245         }
3246
3247         function get_description($description_only = false)
3248         {
3249                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3250                 {
3251                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3252                 }
3253                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3254                 {
3255                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3256                 }
3257                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3258                 {
3259                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3260                 }
3261                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3262                 {
3263                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3264                 }
3265                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3266                 {
3267                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3268                 }
3269                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3270                 {
3271                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3272                 }
3273                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3274                 {
3275                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3276                 }
3277                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3278                 {
3279                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3280                 }
3281                 elseif (!$description_only)
3282                 {
3283                         return $this->get_content(true);
3284                 }
3285                 else
3286                 {
3287                         return null;
3288                 }
3289         }
3290
3291         function get_content($content_only = false)
3292         {
3293                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3294                 {
3295                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3296                 }
3297                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3298                 {
3299                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3300                 }
3301                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3302                 {
3303                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3304                 }
3305                 elseif (!$content_only)
3306                 {
3307                         return $this->get_description(true);
3308                 }
3309                 else
3310                 {
3311                         return null;
3312                 }
3313         }
3314
3315         function get_category($key = 0)
3316         {
3317                 $categories = $this->get_categories();
3318                 if (isset($categories[$key]))
3319                 {
3320                         return $categories[$key];
3321                 }
3322                 else
3323                 {
3324                         return null;
3325                 }
3326         }
3327
3328         function get_categories()
3329         {
3330                 $categories = array();
3331
3332                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3333                 {
3334                         $term = null;
3335                         $scheme = null;
3336                         $label = null;
3337                         if (isset($category['attribs']['']['term']))
3338                         {
3339                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3340                         }
3341                         if (isset($category['attribs']['']['scheme']))
3342                         {
3343                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3344                         }
3345                         if (isset($category['attribs']['']['label']))
3346                         {
3347                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3348                         }
3349                         $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3350                 }
3351                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3352                 {
3353                         // This is really the label, but keep this as the term also for BC.
3354                         // Label will also work on retrieving because that falls back to term.
3355                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3356                         if (isset($category['attribs']['']['domain']))
3357                         {
3358                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3359                         }
3360                         else
3361                         {
3362                                 $scheme = null;
3363                         }
3364                         $categories[] =& new $this->feed->category_class($term, $scheme, null);
3365                 }
3366                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3367                 {
3368                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3369                 }
3370                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3371                 {
3372                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3373                 }
3374
3375                 if (!empty($categories))
3376                 {
3377                         return SimplePie_Misc::array_unique($categories);
3378                 }
3379                 else
3380                 {
3381                         return null;
3382                 }
3383         }
3384
3385         function get_author($key = 0)
3386         {
3387                 $authors = $this->get_authors();
3388                 if (isset($authors[$key]))
3389                 {
3390                         return $authors[$key];
3391                 }
3392                 else
3393                 {
3394                         return null;
3395                 }
3396         }
3397
3398         function get_contributor($key = 0)
3399         {
3400                 $contributors = $this->get_contributors();
3401                 if (isset($contributors[$key]))
3402                 {
3403                         return $contributors[$key];
3404                 }
3405                 else
3406                 {
3407                         return null;
3408                 }
3409         }
3410
3411         function get_contributors()
3412         {
3413                 $contributors = array();
3414                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3415                 {
3416                         $name = null;
3417                         $uri = null;
3418                         $email = null;
3419                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3420                         {
3421                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3422                         }
3423                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3424                         {
3425                                 $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]));
3426                         }
3427                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3428                         {
3429                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3430                         }
3431                         if ($name !== null || $email !== null || $uri !== null)
3432                         {
3433                                 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3434                         }
3435                 }
3436                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3437                 {
3438                         $name = null;
3439                         $url = null;
3440                         $email = null;
3441                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3442                         {
3443                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3444                         }
3445                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3446                         {
3447                                 $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]));
3448                         }
3449                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3450                         {
3451                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3452                         }
3453                         if ($name !== null || $email !== null || $url !== null)
3454                         {
3455                                 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3456                         }
3457                 }
3458
3459                 if (!empty($contributors))
3460                 {
3461                         return SimplePie_Misc::array_unique($contributors);
3462                 }
3463                 else
3464                 {
3465                         return null;
3466                 }
3467         }
3468
3469         function get_authors()
3470         {
3471                 $authors = array();
3472                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3473                 {
3474                         $name = null;
3475                         $uri = null;
3476                         $email = null;
3477                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3478                         {
3479                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3480                         }
3481                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3482                         {
3483                                 $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]));
3484                         }
3485                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3486                         {
3487                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3488                         }
3489                         if ($name !== null || $email !== null || $uri !== null)
3490                         {
3491                                 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3492                         }
3493                 }
3494                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3495                 {
3496                         $name = null;
3497                         $url = null;
3498                         $email = null;
3499                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3500                         {
3501                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3502                         }
3503                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3504                         {
3505                                 $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]));
3506                         }
3507                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3508                         {
3509                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3510                         }
3511                         if ($name !== null || $email !== null || $url !== null)
3512                         {
3513                                 $authors[] =& new $this->feed->author_class($name, $url, $email);
3514                         }
3515                 }
3516                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3517                 {
3518                         $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3519                 }
3520                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3521                 {
3522                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3523                 }
3524                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3525                 {
3526                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3527                 }
3528                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3529                 {
3530                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3531                 }
3532
3533                 if (!empty($authors))
3534                 {
3535                         return SimplePie_Misc::array_unique($authors);
3536                 }
3537                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3538                 {
3539                         return $authors;
3540                 }
3541                 elseif ($authors = $this->feed->get_authors())
3542                 {
3543                         return $authors;
3544                 }
3545                 else
3546                 {
3547                         return null;
3548                 }
3549         }
3550
3551         function get_copyright()
3552         {
3553                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3554                 {
3555                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3556                 }
3557                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3558                 {
3559                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3560                 }
3561                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3562                 {
3563                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3564                 }
3565                 else
3566                 {
3567                         return null;
3568                 }
3569         }
3570
3571         function get_date($date_format = 'j F Y, g:i a')
3572         {
3573                 if (!isset($this->data['date']))
3574                 {
3575                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3576                         {
3577                                 $this->data['date']['raw'] = $return[0]['data'];
3578                         }
3579                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3580                         {
3581                                 $this->data['date']['raw'] = $return[0]['data'];
3582                         }
3583                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3584                         {
3585                                 $this->data['date']['raw'] = $return[0]['data'];
3586                         }
3587                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3588                         {
3589                                 $this->data['date']['raw'] = $return[0]['data'];
3590                         }
3591                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3592                         {
3593                                 $this->data['date']['raw'] = $return[0]['data'];
3594                         }
3595                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3596                         {
3597                                 $this->data['date']['raw'] = $return[0]['data'];
3598                         }
3599                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3600                         {
3601                                 $this->data['date']['raw'] = $return[0]['data'];
3602                         }
3603                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3604                         {
3605                                 $this->data['date']['raw'] = $return[0]['data'];
3606                         }
3607
3608                         if (!empty($this->data['date']['raw']))
3609                         {
3610                                 $parser = SimplePie_Parse_Date::get();
3611                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3612                         }
3613                         else
3614                         {
3615                                 $this->data['date'] = null;
3616                         }
3617                 }
3618                 if ($this->data['date'])
3619                 {
3620                         $date_format = (string) $date_format;
3621                         switch ($date_format)
3622                         {
3623                                 case '':
3624                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3625
3626                                 case 'U':
3627                                         return $this->data['date']['parsed'];
3628
3629                                 default:
3630                                         return date($date_format, $this->data['date']['parsed']);
3631                         }
3632                 }
3633                 else
3634                 {
3635                         return null;
3636                 }
3637         }
3638
3639         function get_local_date($date_format = '%c')
3640         {
3641                 if (!$date_format)
3642                 {
3643                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3644                 }
3645                 elseif (($date = $this->get_date('U')) !== null)
3646                 {
3647                         return strftime($date_format, $date);
3648                 }
3649                 else
3650                 {
3651                         return null;
3652                 }
3653         }
3654
3655         function get_permalink()
3656         {
3657                 $link = $this->get_link();
3658                 $enclosure = $this->get_enclosure(0);
3659                 if ($link !== null)
3660                 {
3661                         return $link;
3662                 }
3663                 elseif ($enclosure !== null)
3664                 {
3665                         return $enclosure->get_link();
3666                 }
3667                 else
3668                 {
3669                         return null;
3670                 }
3671         }
3672
3673         function get_link($key = 0, $rel = 'alternate')
3674         {
3675                 $links = $this->get_links($rel);
3676                 if ($links[$key] !== null)
3677                 {
3678                         return $links[$key];
3679                 }
3680                 else
3681                 {
3682                         return null;
3683                 }
3684         }
3685
3686         function get_links($rel = 'alternate')
3687         {
3688                 if (!isset($this->data['links']))
3689                 {
3690                         $this->data['links'] = array();
3691                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3692                         {
3693                                 if (isset($link['attribs']['']['href']))
3694                                 {
3695                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3696                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3697
3698                                 }
3699                         }
3700                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3701                         {
3702                                 if (isset($link['attribs']['']['href']))
3703                                 {
3704                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3705                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3706                                 }
3707                         }
3708                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3709                         {
3710                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3711                         }
3712                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3713                         {
3714                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3715                         }
3716                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3717                         {
3718                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3719                         }
3720                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3721                         {
3722                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3723                                 {
3724                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3725                                 }
3726                         }
3727
3728                         $keys = array_keys($this->data['links']);
3729                         foreach ($keys as $key)
3730                         {
3731                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3732                                 {
3733                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3734                                         {
3735                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3736                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3737                                         }
3738                                         else
3739                                         {
3740                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3741                                         }
3742                                 }
3743                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3744                                 {
3745                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3746                                 }
3747                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3748                         }
3749                 }
3750                 if (isset($this->data['links'][$rel]))
3751                 {
3752                         return $this->data['links'][$rel];
3753                 }
3754                 else
3755                 {
3756                         return null;
3757                 }
3758         }
3759
3760         /**
3761          * @todo Add ability to prefer one type of content over another (in a media group).
3762          */
3763         function get_enclosure($key = 0, $prefer = null)
3764         {
3765                 $enclosures = $this->get_enclosures();
3766                 if (isset($enclosures[$key]))
3767                 {
3768                         return $enclosures[$key];
3769                 }
3770                 else
3771                 {
3772                         return null;
3773                 }
3774         }
3775
3776         /**
3777          * Grabs all available enclosures (podcasts, etc.)
3778          *
3779          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3780          *
3781          * 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.
3782          *
3783          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3784          * @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).
3785          */
3786         function get_enclosures()
3787         {
3788                 if (!isset($this->data['enclosures']))
3789                 {
3790                         $this->data['enclosures'] = array();
3791
3792                         // Elements
3793                         $captions_parent = null;
3794                         $categories_parent = null;
3795                         $copyrights_parent = null;
3796                         $credits_parent = null;
3797                         $description_parent = null;
3798                         $duration_parent = null;
3799                         $hashes_parent = null;
3800                         $keywords_parent = null;
3801                         $player_parent = null;
3802                         $ratings_parent = null;
3803                         $restrictions_parent = null;
3804                         $thumbnails_parent = null;
3805                         $title_parent = null;
3806
3807                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3808                         $parent = $this->get_feed();
3809
3810                         // CAPTIONS
3811                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3812                         {
3813                                 foreach ($captions as $caption)
3814                                 {
3815                                         $caption_type = null;
3816                                         $caption_lang = null;
3817                                         $caption_startTime = null;
3818                                         $caption_endTime = null;
3819                                         $caption_text = null;
3820                                         if (isset($caption['attribs']['']['type']))
3821                                         {
3822                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3823                                         }
3824                                         if (isset($caption['attribs']['']['lang']))
3825                                         {
3826                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3827                                         }
3828                                         if (isset($caption['attribs']['']['start']))
3829                                         {
3830                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3831                                         }
3832                                         if (isset($caption['attribs']['']['end']))
3833                                         {
3834                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3835                                         }
3836                                         if (isset($caption['data']))
3837                                         {
3838                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3839                                         }
3840                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3841                                 }
3842                         }
3843                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3844                         {
3845                                 foreach ($captions as $caption)
3846                                 {
3847                                         $caption_type = null;
3848                                         $caption_lang = null;
3849                                         $caption_startTime = null;
3850                                         $caption_endTime = null;
3851                                         $caption_text = null;
3852                                         if (isset($caption['attribs']['']['type']))
3853                                         {
3854                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3855                                         }
3856                                         if (isset($caption['attribs']['']['lang']))
3857                                         {
3858                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3859                                         }
3860                                         if (isset($caption['attribs']['']['start']))
3861                                         {
3862                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3863                                         }
3864                                         if (isset($caption['attribs']['']['end']))
3865                                         {
3866                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3867                                         }
3868                                         if (isset($caption['data']))
3869                                         {
3870                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3871                                         }
3872                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3873                                 }
3874                         }
3875                         if (is_array($captions_parent))
3876                         {
3877                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3878                         }
3879
3880                         // CATEGORIES
3881                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3882                         {
3883                                 $term = null;
3884                                 $scheme = null;
3885                                 $label = null;
3886                                 if (isset($category['data']))
3887                                 {
3888                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3889                                 }
3890                                 if (isset($category['attribs']['']['scheme']))
3891                                 {
3892                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3893                                 }
3894                                 else
3895                                 {
3896                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3897                                 }
3898                                 if (isset($category['attribs']['']['label']))
3899                                 {
3900                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3901                                 }
3902                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3903                         }
3904                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3905                         {
3906                                 $term = null;
3907                                 $scheme = null;
3908                                 $label = null;
3909                                 if (isset($category['data']))
3910                                 {
3911                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3912                                 }
3913                                 if (isset($category['attribs']['']['scheme']))
3914                                 {
3915                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3916                                 }
3917                                 else
3918                                 {
3919                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3920                                 }
3921                                 if (isset($category['attribs']['']['label']))
3922                                 {
3923                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3924                                 }
3925                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3926                         }
3927                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3928                         {
3929                                 $term = null;
3930                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3931                                 $label = null;
3932                                 if (isset($category['attribs']['']['text']))
3933                                 {
3934                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3935                                 }
3936                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3937
3938                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3939                                 {
3940                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3941                                         {
3942                                                 if (isset($subcategory['attribs']['']['text']))
3943                                                 {
3944                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3945                                                 }
3946                                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3947                                         }
3948                                 }
3949                         }
3950                         if (is_array($categories_parent))
3951                         {
3952                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3953                         }
3954
3955                         // COPYRIGHT
3956                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3957                         {
3958                                 $copyright_url = null;
3959                                 $copyright_label = null;
3960                                 if (isset($copyright[0]['attribs']['']['url']))
3961                                 {
3962                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3963                                 }
3964                                 if (isset($copyright[0]['data']))
3965                                 {
3966                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3967                                 }
3968                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3969                         }
3970                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3971                         {
3972                                 $copyright_url = null;
3973                                 $copyright_label = null;
3974                                 if (isset($copyright[0]['attribs']['']['url']))
3975                                 {
3976                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3977                                 }
3978                                 if (isset($copyright[0]['data']))
3979                                 {
3980                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3981                                 }
3982                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3983                         }
3984
3985                         // CREDITS
3986                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3987                         {
3988                                 foreach ($credits as $credit)
3989                                 {
3990                                         $credit_role = null;
3991                                         $credit_scheme = null;
3992                                         $credit_name = null;
3993                                         if (isset($credit['attribs']['']['role']))
3994                                         {
3995                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3996                                         }
3997                                         if (isset($credit['attribs']['']['scheme']))
3998                                         {
3999                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4000                                         }
4001                                         else
4002                                         {
4003                                                 $credit_scheme = 'urn:ebu';
4004                                         }
4005                                         if (isset($credit['data']))
4006                                         {
4007                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4008                                         }
4009                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4010                                 }
4011                         }
4012                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4013                         {
4014                                 foreach ($credits as $credit)
4015                                 {
4016                                         $credit_role = null;
4017                                         $credit_scheme = null;
4018                                         $credit_name = null;
4019                                         if (isset($credit['attribs']['']['role']))
4020                                         {
4021                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4022                                         }
4023                                         if (isset($credit['attribs']['']['scheme']))
4024                                         {
4025                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4026                                         }
4027                                         else
4028                                         {
4029                                                 $credit_scheme = 'urn:ebu';
4030                                         }
4031                                         if (isset($credit['data']))
4032                                         {
4033                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4034                                         }
4035                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4036                                 }
4037                         }
4038                         if (is_array($credits_parent))
4039                         {
4040                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4041                         }
4042
4043                         // DESCRIPTION
4044                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4045                         {
4046                                 if (isset($description_parent[0]['data']))
4047                                 {
4048                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4049                                 }
4050                         }
4051                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4052                         {
4053                                 if (isset($description_parent[0]['data']))
4054                                 {
4055                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4056                                 }
4057                         }
4058
4059                         // DURATION
4060                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4061                         {
4062                                 $seconds = null;
4063                                 $minutes = null;
4064                                 $hours = null;
4065                                 if (isset($duration_parent[0]['data']))
4066                                 {
4067                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4068                                         if (sizeof($temp) > 0)
4069                                         {
4070                                                 $seconds = (int) array_pop($temp);
4071                                         }
4072                                         if (sizeof($temp) > 0)
4073                                         {
4074                                                 $minutes = (int) array_pop($temp);
4075                                                 $seconds += $minutes * 60;
4076                                         }
4077                                         if (sizeof($temp) > 0)
4078                                         {
4079                                                 $hours = (int) array_pop($temp);
4080                                                 $seconds += $hours * 3600;
4081                                         }
4082                                         unset($temp);
4083                                         $duration_parent = $seconds;
4084                                 }
4085                         }
4086
4087                         // HASHES
4088                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4089                         {
4090                                 foreach ($hashes_iterator as $hash)
4091                                 {
4092                                         $value = null;
4093                                         $algo = null;
4094                                         if (isset($hash['data']))
4095                                         {
4096                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4097                                         }
4098                                         if (isset($hash['attribs']['']['algo']))
4099                                         {
4100                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4101                                         }
4102                                         else
4103                                         {
4104                                                 $algo = 'md5';
4105                                         }
4106                                         $hashes_parent[] = $algo.':'.$value;
4107                                 }
4108                         }
4109                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4110                         {
4111                                 foreach ($hashes_iterator as $hash)
4112                                 {
4113                                         $value = null;
4114                                         $algo = null;
4115                                         if (isset($hash['data']))
4116                                         {
4117                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4118                                         }
4119                                         if (isset($hash['attribs']['']['algo']))
4120                                         {
4121                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4122                                         }
4123                                         else
4124                                         {
4125                                                 $algo = 'md5';
4126                                         }
4127                                         $hashes_parent[] = $algo.':'.$value;
4128                                 }
4129                         }
4130                         if (is_array($hashes_parent))
4131                         {
4132                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4133                         }
4134
4135                         // KEYWORDS
4136                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4137                         {
4138                                 if (isset($keywords[0]['data']))
4139                                 {
4140                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4141                                         foreach ($temp as $word)
4142                                         {
4143                                                 $keywords_parent[] = trim($word);
4144                                         }
4145                                 }
4146                                 unset($temp);
4147                         }
4148                         elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4149                         {
4150                                 if (isset($keywords[0]['data']))
4151                                 {
4152                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4153                                         foreach ($temp as $word)
4154                                         {
4155                                                 $keywords_parent[] = trim($word);
4156                                         }
4157                                 }
4158                                 unset($temp);
4159                         }
4160                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4161                         {
4162                                 if (isset($keywords[0]['data']))
4163                                 {
4164                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4165                                         foreach ($temp as $word)
4166                                         {
4167                                                 $keywords_parent[] = trim($word);
4168                                         }
4169                                 }
4170                                 unset($temp);
4171                         }
4172                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4173                         {
4174                                 if (isset($keywords[0]['data']))
4175                                 {
4176                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4177                                         foreach ($temp as $word)
4178                                         {
4179                                                 $keywords_parent[] = trim($word);
4180                                         }
4181                                 }
4182                                 unset($temp);
4183                         }
4184                         if (is_array($keywords_parent))
4185                         {
4186                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4187                         }
4188
4189                         // PLAYER
4190                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4191                         {
4192                                 if (isset($player_parent[0]['attribs']['']['url']))
4193                                 {
4194                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4195                                 }
4196                         }
4197                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4198                         {
4199                                 if (isset($player_parent[0]['attribs']['']['url']))
4200                                 {
4201                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4202                                 }
4203                         }
4204
4205                         // RATINGS
4206                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4207                         {
4208                                 foreach ($ratings as $rating)
4209                                 {
4210                                         $rating_scheme = null;
4211                                         $rating_value = null;
4212                                         if (isset($rating['attribs']['']['scheme']))
4213                                         {
4214                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4215                                         }
4216                                         else
4217                                         {
4218                                                 $rating_scheme = 'urn:simple';
4219                                         }
4220                                         if (isset($rating['data']))
4221                                         {
4222                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4223                                         }
4224                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4225                                 }
4226                         }
4227                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4228                         {
4229                                 foreach ($ratings as $rating)
4230                                 {
4231                                         $rating_scheme = 'urn:itunes';
4232                                         $rating_value = null;
4233                                         if (isset($rating['data']))
4234                                         {
4235                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4236                                         }
4237                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4238                                 }
4239                         }
4240                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4241                         {
4242                                 foreach ($ratings as $rating)
4243                                 {
4244                                         $rating_scheme = null;
4245                                         $rating_value = null;
4246                                         if (isset($rating['attribs']['']['scheme']))
4247                                         {
4248                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4249                                         }
4250                                         else
4251                                         {
4252                                                 $rating_scheme = 'urn:simple';
4253                                         }
4254                                         if (isset($rating['data']))
4255                                         {
4256                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4257                                         }
4258                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4259                                 }
4260                         }
4261                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4262                         {
4263                                 foreach ($ratings as $rating)
4264                                 {
4265                                         $rating_scheme = 'urn:itunes';
4266                                         $rating_value = null;
4267                                         if (isset($rating['data']))
4268                                         {
4269                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4270                                         }
4271                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4272                                 }
4273                         }
4274                         if (is_array($ratings_parent))
4275                         {
4276                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4277                         }
4278
4279                         // RESTRICTIONS
4280                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4281                         {
4282                                 foreach ($restrictions as $restriction)
4283                                 {
4284                                         $restriction_relationship = null;
4285                                         $restriction_type = null;
4286                                         $restriction_value = null;
4287                                         if (isset($restriction['attribs']['']['relationship']))
4288                                         {
4289                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4290                                         }
4291                                         if (isset($restriction['attribs']['']['type']))
4292                                         {
4293                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4294                                         }
4295                                         if (isset($restriction['data']))
4296                                         {
4297                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4298                                         }
4299                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4300                                 }
4301                         }
4302                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4303                         {
4304                                 foreach ($restrictions as $restriction)
4305                                 {
4306                                         $restriction_relationship = 'allow';
4307                                         $restriction_type = null;
4308                                         $restriction_value = 'itunes';
4309                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4310                                         {
4311                                                 $restriction_relationship = 'deny';
4312                                         }
4313                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4314                                 }
4315                         }
4316                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4317                         {
4318                                 foreach ($restrictions as $restriction)
4319                                 {
4320                                         $restriction_relationship = null;
4321                                         $restriction_type = null;
4322                                         $restriction_value = null;
4323                                         if (isset($restriction['attribs']['']['relationship']))
4324                                         {
4325                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4326                                         }
4327                                         if (isset($restriction['attribs']['']['type']))
4328                                         {
4329                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4330                                         }
4331                                         if (isset($restriction['data']))
4332                                         {
4333                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4334                                         }
4335                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4336                                 }
4337                         }
4338                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4339                         {
4340                                 foreach ($restrictions as $restriction)
4341                                 {
4342                                         $restriction_relationship = 'allow';
4343                                         $restriction_type = null;
4344                                         $restriction_value = 'itunes';
4345                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4346                                         {
4347                                                 $restriction_relationship = 'deny';
4348                                         }
4349                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4350                                 }
4351                         }
4352                         if (is_array($restrictions_parent))
4353                         {
4354                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4355                         }
4356
4357                         // THUMBNAILS
4358                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4359                         {
4360                                 foreach ($thumbnails as $thumbnail)
4361                                 {
4362                                         if (isset($thumbnail['attribs']['']['url']))
4363                                         {
4364                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4365                                         }
4366                                 }
4367                         }
4368                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4369                         {
4370                                 foreach ($thumbnails as $thumbnail)
4371                                 {
4372                                         if (isset($thumbnail['attribs']['']['url']))
4373                                         {
4374                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4375                                         }
4376                                 }
4377                         }
4378
4379                         // TITLES
4380                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4381                         {
4382                                 if (isset($title_parent[0]['data']))
4383                                 {
4384                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4385                                 }
4386                         }
4387                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4388                         {
4389                                 if (isset($title_parent[0]['data']))
4390                                 {
4391                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4392                                 }
4393                         }
4394
4395                         // Clear the memory
4396                         unset($parent);
4397
4398                         // Attributes
4399                         $bitrate = null;
4400                         $channels = null;
4401                         $duration = null;
4402                         $expression = null;
4403                         $framerate = null;
4404                         $height = null;
4405                         $javascript = null;
4406                         $lang = null;
4407                         $length = null;
4408                         $medium = null;
4409                         $samplingrate = null;
4410                         $type = null;
4411                         $url = null;
4412                         $width = null;
4413
4414                         // Elements
4415                         $captions = null;
4416                         $categories = null;
4417                         $copyrights = null;
4418                         $credits = null;
4419                         $description = null;
4420                         $hashes = null;
4421                         $keywords = null;
4422                         $player = null;
4423                         $ratings = null;
4424                         $restrictions = null;
4425                         $thumbnails = null;
4426                         $title = null;
4427
4428                         // If we have media:group tags, loop through them.
4429                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4430                         {
4431                                 // If we have media:content tags, loop through them.
4432                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4433                                 {
4434                                         if (isset($content['attribs']['']['url']))
4435                                         {
4436                                                 // Attributes
4437                                                 $bitrate = null;
4438                                                 $channels = null;
4439                                                 $duration = null;
4440                                                 $expression = null;
4441                                                 $framerate = null;
4442                                                 $height = null;
4443                                                 $javascript = null;
4444                                                 $lang = null;
4445                                                 $length = null;
4446                                                 $medium = null;
4447                                                 $samplingrate = null;
4448                                                 $type = null;
4449                                                 $url = null;
4450                                                 $width = null;
4451
4452                                                 // Elements
4453                                                 $captions = null;
4454                                                 $categories = null;
4455                                                 $copyrights = null;
4456                                                 $credits = null;
4457                                                 $description = null;
4458                                                 $hashes = null;
4459                                                 $keywords = null;
4460                                                 $player = null;
4461                                                 $ratings = null;
4462                                                 $restrictions = null;
4463                                                 $thumbnails = null;
4464                                                 $title = null;
4465
4466                                                 // Start checking the attributes of media:content
4467                                                 if (isset($content['attribs']['']['bitrate']))
4468                                                 {
4469                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4470                                                 }
4471                                                 if (isset($content['attribs']['']['channels']))
4472                                                 {
4473                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4474                                                 }
4475                                                 if (isset($content['attribs']['']['duration']))
4476                                                 {
4477                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4478                                                 }
4479                                                 else
4480                                                 {
4481                                                         $duration = $duration_parent;
4482                                                 }
4483                                                 if (isset($content['attribs']['']['expression']))
4484                                                 {
4485                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4486                                                 }
4487                                                 if (isset($content['attribs']['']['framerate']))
4488                                                 {
4489                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4490                                                 }
4491                                                 if (isset($content['attribs']['']['height']))
4492                                                 {
4493                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4494                                                 }
4495                                                 if (isset($content['attribs']['']['lang']))
4496                                                 {
4497                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4498                                                 }
4499                                                 if (isset($content['attribs']['']['fileSize']))
4500                                                 {
4501                                                         $length = ceil($content['attribs']['']['fileSize']);
4502                                                 }
4503                                                 if (isset($content['attribs']['']['medium']))
4504                                                 {
4505                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4506                                                 }
4507                                                 if (isset($content['attribs']['']['samplingrate']))
4508                                                 {
4509                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4510                                                 }
4511                                                 if (isset($content['attribs']['']['type']))
4512                                                 {
4513                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4514                                                 }
4515                                                 if (isset($content['attribs']['']['width']))
4516                                                 {
4517                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4518                                                 }
4519                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4520
4521                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4522
4523                                                 // CAPTIONS
4524                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4525                                                 {
4526                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4527                                                         {
4528                                                                 $caption_type = null;
4529                                                                 $caption_lang = null;
4530                                                                 $caption_startTime = null;
4531                                                                 $caption_endTime = null;
4532                                                                 $caption_text = null;
4533                                                                 if (isset($caption['attribs']['']['type']))
4534                                                                 {
4535                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4536                                                                 }
4537                                                                 if (isset($caption['attribs']['']['lang']))
4538                                                                 {
4539                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4540                                                                 }
4541                                                                 if (isset($caption['attribs']['']['start']))
4542                                                                 {
4543                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4544                                                                 }
4545                                                                 if (isset($caption['attribs']['']['end']))
4546                                                                 {
4547                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4548                                                                 }
4549                                                                 if (isset($caption['data']))
4550                                                                 {
4551                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4552                                                                 }
4553                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4554                                                         }
4555                                                         if (is_array($captions))
4556                                                         {
4557                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
4558                                                         }
4559                                                 }
4560                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4561                                                 {
4562                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4563                                                         {
4564                                                                 $caption_type = null;
4565                                                                 $caption_lang = null;
4566                                                                 $caption_startTime = null;
4567                                                                 $caption_endTime = null;
4568                                                                 $caption_text = null;
4569                                                                 if (isset($caption['attribs']['']['type']))
4570                                                                 {
4571                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4572                                                                 }
4573                                                                 if (isset($caption['attribs']['']['lang']))
4574                                                                 {
4575                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4576                                                                 }
4577                                                                 if (isset($caption['attribs']['']['start']))
4578                                                                 {
4579                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4580                                                                 }
4581                                                                 if (isset($caption['attribs']['']['end']))
4582                                                                 {
4583                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4584                                                                 }
4585                                                                 if (isset($caption['data']))
4586                                                                 {
4587                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4588                                                                 }
4589                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4590                                                         }
4591                                                         if (is_array($captions))
4592                                                         {
4593                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
4594                                                         }
4595                                                 }
4596                                                 else
4597                                                 {
4598                                                         $captions = $captions_parent;
4599                                                 }
4600
4601                                                 // CATEGORIES
4602                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4603                                                 {
4604                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4605                                                         {
4606                                                                 $term = null;
4607                                                                 $scheme = null;
4608                                                                 $label = null;
4609                                                                 if (isset($category['data']))
4610                                                                 {
4611                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4612                                                                 }
4613                                                                 if (isset($category['attribs']['']['scheme']))
4614                                                                 {
4615                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4616                                                                 }
4617                                                                 else
4618                                                                 {
4619                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4620                                                                 }
4621                                                                 if (isset($category['attribs']['']['label']))
4622                                                                 {
4623                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4624                                                                 }
4625                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4626                                                         }
4627                                                 }
4628                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4629                                                 {
4630                                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4631                                                         {
4632                                                                 $term = null;
4633                                                                 $scheme = null;
4634                                                                 $label = null;
4635                                                                 if (isset($category['data']))
4636                                                                 {
4637                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4638                                                                 }
4639                                                                 if (isset($category['attribs']['']['scheme']))
4640                                                                 {
4641                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4642                                                                 }
4643                                                                 else
4644                                                                 {
4645                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4646                                                                 }
4647                                                                 if (isset($category['attribs']['']['label']))
4648                                                                 {
4649                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4650                                                                 }
4651                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4652                                                         }
4653                                                 }
4654                                                 if (is_array($categories) && is_array($categories_parent))
4655                                                 {
4656                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4657                                                 }
4658                                                 elseif (is_array($categories))
4659                                                 {
4660                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
4661                                                 }
4662                                                 elseif (is_array($categories_parent))
4663                                                 {
4664                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4665                                                 }
4666
4667                                                 // COPYRIGHTS
4668                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4669                                                 {
4670                                                         $copyright_url = null;
4671                                                         $copyright_label = null;
4672                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4673                                                         {
4674                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4675                                                         }
4676                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4677                                                         {
4678                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4679                                                         }
4680                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4681                                                 }
4682                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4683                                                 {
4684                                                         $copyright_url = null;
4685                                                         $copyright_label = null;
4686                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4687                                                         {
4688                                                                 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4689                                                         }
4690                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4691                                                         {
4692                                                                 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4693                                                         }
4694                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4695                                                 }
4696                                                 else
4697                                                 {
4698                                                         $copyrights = $copyrights_parent;
4699                                                 }
4700
4701                                                 // CREDITS
4702                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4703                                                 {
4704                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4705                                                         {
4706                                                                 $credit_role = null;
4707                                                                 $credit_scheme = null;
4708                                                                 $credit_name = null;
4709                                                                 if (isset($credit['attribs']['']['role']))
4710                                                                 {
4711                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4712                                                                 }
4713                                                                 if (isset($credit['attribs']['']['scheme']))
4714                                                                 {
4715                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4716                                                                 }
4717                                                                 else
4718                                                                 {
4719                                                                         $credit_scheme = 'urn:ebu';
4720                                                                 }
4721                                                                 if (isset($credit['data']))
4722                                                                 {
4723                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4724                                                                 }
4725                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4726                                                         }
4727                                                         if (is_array($credits))
4728                                                         {
4729                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
4730                                                         }
4731                                                 }
4732                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4733                                                 {
4734                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4735                                                         {
4736                                                                 $credit_role = null;
4737                                                                 $credit_scheme = null;
4738                                                                 $credit_name = null;
4739                                                                 if (isset($credit['attribs']['']['role']))
4740                                                                 {
4741                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4742                                                                 }
4743                                                                 if (isset($credit['attribs']['']['scheme']))
4744                                                                 {
4745                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4746                                                                 }
4747                                                                 else
4748                                                                 {
4749                                                                         $credit_scheme = 'urn:ebu';
4750                                                                 }
4751                                                                 if (isset($credit['data']))
4752                                                                 {
4753                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4754                                                                 }
4755                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4756                                                         }
4757                                                         if (is_array($credits))
4758                                                         {
4759                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
4760                                                         }
4761                                                 }
4762                                                 else
4763                                                 {
4764                                                         $credits = $credits_parent;
4765                                                 }
4766
4767                                                 // DESCRIPTION
4768                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4769                                                 {
4770                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4771                                                 }
4772                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4773                                                 {
4774                                                         $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4775                                                 }
4776                                                 else
4777                                                 {
4778                                                         $description = $description_parent;
4779                                                 }
4780
4781                                                 // HASHES
4782                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4783                                                 {
4784                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4785                                                         {
4786                                                                 $value = null;
4787                                                                 $algo = null;
4788                                                                 if (isset($hash['data']))
4789                                                                 {
4790                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4791                                                                 }
4792                                                                 if (isset($hash['attribs']['']['algo']))
4793                                                                 {
4794                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4795                                                                 }
4796                                                                 else
4797                                                                 {
4798                                                                         $algo = 'md5';
4799                                                                 }
4800                                                                 $hashes[] = $algo.':'.$value;
4801                                                         }
4802                                                         if (is_array($hashes))
4803                                                         {
4804                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4805                                                         }
4806                                                 }
4807                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4808                                                 {
4809                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4810                                                         {
4811                                                                 $value = null;
4812                                                                 $algo = null;
4813                                                                 if (isset($hash['data']))
4814                                                                 {
4815                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4816                                                                 }
4817                                                                 if (isset($hash['attribs']['']['algo']))
4818                                                                 {
4819                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4820                                                                 }
4821                                                                 else
4822                                                                 {
4823                                                                         $algo = 'md5';
4824                                                                 }
4825                                                                 $hashes[] = $algo.':'.$value;
4826                                                         }
4827                                                         if (is_array($hashes))
4828                                                         {
4829                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4830                                                         }
4831                                                 }
4832                                                 else
4833                                                 {
4834                                                         $hashes = $hashes_parent;
4835                                                 }
4836
4837                                                 // KEYWORDS
4838                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4839                                                 {
4840                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4841                                                         {
4842                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4843                                                                 foreach ($temp as $word)
4844                                                                 {
4845                                                                         $keywords[] = trim($word);
4846                                                                 }
4847                                                                 unset($temp);
4848                                                         }
4849                                                         if (is_array($keywords))
4850                                                         {
4851                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4852                                                         }
4853                                                 }
4854                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4855                                                 {
4856                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4857                                                         {
4858                                                                 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4859                                                                 foreach ($temp as $word)
4860                                                                 {
4861                                                                         $keywords[] = trim($word);
4862                                                                 }
4863                                                                 unset($temp);
4864                                                         }
4865                                                         if (is_array($keywords))
4866                                                         {
4867                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4868                                                         }
4869                                                 }
4870                                                 else
4871                                                 {
4872                                                         $keywords = $keywords_parent;
4873                                                 }
4874
4875                                                 // PLAYER
4876                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4877                                                 {
4878                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4879                                                 }
4880                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4881                                                 {
4882                                                         $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4883                                                 }
4884                                                 else
4885                                                 {
4886                                                         $player = $player_parent;
4887                                                 }
4888
4889                                                 // RATINGS
4890                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4891                                                 {
4892                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4893                                                         {
4894                                                                 $rating_scheme = null;
4895                                                                 $rating_value = null;
4896                                                                 if (isset($rating['attribs']['']['scheme']))
4897                                                                 {
4898                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4899                                                                 }
4900                                                                 else
4901                                                                 {
4902                                                                         $rating_scheme = 'urn:simple';
4903                                                                 }
4904                                                                 if (isset($rating['data']))
4905                                                                 {
4906                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4907                                                                 }
4908                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4909                                                         }
4910                                                         if (is_array($ratings))
4911                                                         {
4912                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4913                                                         }
4914                                                 }
4915                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4916                                                 {
4917                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4918                                                         {
4919                                                                 $rating_scheme = null;
4920                                                                 $rating_value = null;
4921                                                                 if (isset($rating['attribs']['']['scheme']))
4922                                                                 {
4923                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4924                                                                 }
4925                                                                 else
4926                                                                 {
4927                                                                         $rating_scheme = 'urn:simple';
4928                                                                 }
4929                                                                 if (isset($rating['data']))
4930                                                                 {
4931                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4932                                                                 }
4933                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4934                                                         }
4935                                                         if (is_array($ratings))
4936                                                         {
4937                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4938                                                         }
4939                                                 }
4940                                                 else
4941                                                 {
4942                                                         $ratings = $ratings_parent;
4943                                                 }
4944
4945                                                 // RESTRICTIONS
4946                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4947                                                 {
4948                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4949                                                         {
4950                                                                 $restriction_relationship = null;
4951                                                                 $restriction_type = null;
4952                                                                 $restriction_value = null;
4953                                                                 if (isset($restriction['attribs']['']['relationship']))
4954                                                                 {
4955                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4956                                                                 }
4957                                                                 if (isset($restriction['attribs']['']['type']))
4958                                                                 {
4959                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4960                                                                 }
4961                                                                 if (isset($restriction['data']))
4962                                                                 {
4963                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4964                                                                 }
4965                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4966                                                         }
4967                                                         if (is_array($restrictions))
4968                                                         {
4969                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4970                                                         }
4971                                                 }
4972                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4973                                                 {
4974                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4975                                                         {
4976                                                                 $restriction_relationship = null;
4977                                                                 $restriction_type = null;
4978                                                                 $restriction_value = null;
4979                                                                 if (isset($restriction['attribs']['']['relationship']))
4980                                                                 {
4981                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4982                                                                 }
4983                                                                 if (isset($restriction['attribs']['']['type']))
4984                                                                 {
4985                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4986                                                                 }
4987                                                                 if (isset($restriction['data']))
4988                                                                 {
4989                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4990                                                                 }
4991                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4992                                                         }
4993                                                         if (is_array($restrictions))
4994                                                         {
4995                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4996                                                         }
4997                                                 }
4998                                                 else
4999                                                 {
5000                                                         $restrictions = $restrictions_parent;
5001                                                 }
5002
5003                                                 // THUMBNAILS
5004                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5005                                                 {
5006                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5007                                                         {
5008                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5009                                                         }
5010                                                         if (is_array($thumbnails))
5011                                                         {
5012                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5013                                                         }
5014                                                 }
5015                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5016                                                 {
5017                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5018                                                         {
5019                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5020                                                         }
5021                                                         if (is_array($thumbnails))
5022                                                         {
5023                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5024                                                         }
5025                                                 }
5026                                                 else
5027                                                 {
5028                                                         $thumbnails = $thumbnails_parent;
5029                                                 }
5030
5031                                                 // TITLES
5032                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5033                                                 {
5034                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5035                                                 }
5036                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5037                                                 {
5038                                                         $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5039                                                 }
5040                                                 else
5041                                                 {
5042                                                         $title = $title_parent;
5043                                                 }
5044
5045                                                 $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);
5046                                         }
5047                                 }
5048                         }
5049
5050                         // If we have standalone media:content tags, loop through them.
5051                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5052                         {
5053                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5054                                 {
5055                                         if (isset($content['attribs']['']['url']))
5056                                         {
5057                                                 // Attributes
5058                                                 $bitrate = null;
5059                                                 $channels = null;
5060                                                 $duration = null;
5061                                                 $expression = null;
5062                                                 $framerate = null;
5063                                                 $height = null;
5064                                                 $javascript = null;
5065                                                 $lang = null;
5066                                                 $length = null;
5067                                                 $medium = null;
5068                                                 $samplingrate = null;
5069                                                 $type = null;
5070                                                 $url = null;
5071                                                 $width = null;
5072
5073                                                 // Elements
5074                                                 $captions = null;
5075                                                 $categories = null;
5076                                                 $copyrights = null;
5077                                                 $credits = null;
5078                                                 $description = null;
5079                                                 $hashes = null;
5080                                                 $keywords = null;
5081                                                 $player = null;
5082                                                 $ratings = null;
5083                                                 $restrictions = null;
5084                                                 $thumbnails = null;
5085                                                 $title = null;
5086
5087                                                 // Start checking the attributes of media:content
5088                                                 if (isset($content['attribs']['']['bitrate']))
5089                                                 {
5090                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5091                                                 }
5092                                                 if (isset($content['attribs']['']['channels']))
5093                                                 {
5094                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5095                                                 }
5096                                                 if (isset($content['attribs']['']['duration']))
5097                                                 {
5098                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5099                                                 }
5100                                                 else
5101                                                 {
5102                                                         $duration = $duration_parent;
5103                                                 }
5104                                                 if (isset($content['attribs']['']['expression']))
5105                                                 {
5106                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5107                                                 }
5108                                                 if (isset($content['attribs']['']['framerate']))
5109                                                 {
5110                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5111                                                 }
5112                                                 if (isset($content['attribs']['']['height']))
5113                                                 {
5114                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5115                                                 }
5116                                                 if (isset($content['attribs']['']['lang']))
5117                                                 {
5118                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5119                                                 }
5120                                                 if (isset($content['attribs']['']['fileSize']))
5121                                                 {
5122                                                         $length = ceil($content['attribs']['']['fileSize']);
5123                                                 }
5124                                                 if (isset($content['attribs']['']['medium']))
5125                                                 {
5126                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5127                                                 }
5128                                                 if (isset($content['attribs']['']['samplingrate']))
5129                                                 {
5130                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5131                                                 }
5132                                                 if (isset($content['attribs']['']['type']))
5133                                                 {
5134                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5135                                                 }
5136                                                 if (isset($content['attribs']['']['width']))
5137                                                 {
5138                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5139                                                 }
5140                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5141
5142                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5143
5144                                                 // CAPTIONS
5145                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5146                                                 {
5147                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5148                                                         {
5149                                                                 $caption_type = null;
5150                                                                 $caption_lang = null;
5151                                                                 $caption_startTime = null;
5152                                                                 $caption_endTime = null;
5153                                                                 $caption_text = null;
5154                                                                 if (isset($caption['attribs']['']['type']))
5155                                                                 {
5156                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5157                                                                 }
5158                                                                 if (isset($caption['attribs']['']['lang']))
5159                                                                 {
5160                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5161                                                                 }
5162                                                                 if (isset($caption['attribs']['']['start']))
5163                                                                 {
5164                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5165                                                                 }
5166                                                                 if (isset($caption['attribs']['']['end']))
5167                                                                 {
5168                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5169                                                                 }
5170                                                                 if (isset($caption['data']))
5171                                                                 {
5172                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5173                                                                 }
5174                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5175                                                         }
5176                                                         if (is_array($captions))
5177                                                         {
5178                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5179                                                         }
5180                                                 }
5181                                                 else
5182                                                 {
5183                                                         $captions = $captions_parent;
5184                                                 }
5185
5186                                                 // CATEGORIES
5187                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5188                                                 {
5189                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5190                                                         {
5191                                                                 $term = null;
5192                                                                 $scheme = null;
5193                                                                 $label = null;
5194                                                                 if (isset($category['data']))
5195                                                                 {
5196                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5197                                                                 }
5198                                                                 if (isset($category['attribs']['']['scheme']))
5199                                                                 {
5200                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5201                                                                 }
5202                                                                 else
5203                                                                 {
5204                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5205                                                                 }
5206                                                                 if (isset($category['attribs']['']['label']))
5207                                                                 {
5208                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5209                                                                 }
5210                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5211                                                         }
5212                                                 }
5213                                                 if (is_array($categories) && is_array($categories_parent))
5214                                                 {
5215                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5216                                                 }
5217                                                 elseif (is_array($categories))
5218                                                 {
5219                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5220                                                 }
5221                                                 elseif (is_array($categories_parent))
5222                                                 {
5223                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5224                                                 }
5225                                                 else
5226                                                 {
5227                                                         $categories = null;
5228                                                 }
5229
5230                                                 // COPYRIGHTS
5231                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5232                                                 {
5233                                                         $copyright_url = null;
5234                                                         $copyright_label = null;
5235                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5236                                                         {
5237                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5238                                                         }
5239                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5240                                                         {
5241                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5242                                                         }
5243                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5244                                                 }
5245                                                 else
5246                                                 {
5247                                                         $copyrights = $copyrights_parent;
5248                                                 }
5249
5250                                                 // CREDITS
5251                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5252                                                 {
5253                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5254                                                         {
5255                                                                 $credit_role = null;
5256                                                                 $credit_scheme = null;
5257                                                                 $credit_name = null;
5258                                                                 if (isset($credit['attribs']['']['role']))
5259                                                                 {
5260                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5261                                                                 }
5262                                                                 if (isset($credit['attribs']['']['scheme']))
5263                                                                 {
5264                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5265                                                                 }
5266                                                                 else
5267                                                                 {
5268                                                                         $credit_scheme = 'urn:ebu';
5269                                                                 }
5270                                                                 if (isset($credit['data']))
5271                                                                 {
5272                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5273                                                                 }
5274                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5275                                                         }
5276                                                         if (is_array($credits))
5277                                                         {
5278                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5279                                                         }
5280                                                 }
5281                                                 else
5282                                                 {
5283                                                         $credits = $credits_parent;
5284                                                 }
5285
5286                                                 // DESCRIPTION
5287                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5288                                                 {
5289                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5290                                                 }
5291                                                 else
5292                                                 {
5293                                                         $description = $description_parent;
5294                                                 }
5295
5296                                                 // HASHES
5297                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5298                                                 {
5299                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5300                                                         {
5301                                                                 $value = null;
5302                                                                 $algo = null;
5303                                                                 if (isset($hash['data']))
5304                                                                 {
5305                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5306                                                                 }
5307                                                                 if (isset($hash['attribs']['']['algo']))
5308                                                                 {
5309                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5310                                                                 }
5311                                                                 else
5312                                                                 {
5313                                                                         $algo = 'md5';
5314                                                                 }
5315                                                                 $hashes[] = $algo.':'.$value;
5316                                                         }
5317                                                         if (is_array($hashes))
5318                                                         {
5319                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5320                                                         }
5321                                                 }
5322                                                 else
5323                                                 {
5324                                                         $hashes = $hashes_parent;
5325                                                 }
5326
5327                                                 // KEYWORDS
5328                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5329                                                 {
5330                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5331                                                         {
5332                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5333                                                                 foreach ($temp as $word)
5334                                                                 {
5335                                                                         $keywords[] = trim($word);
5336                                                                 }
5337                                                                 unset($temp);
5338                                                         }
5339                                                         if (is_array($keywords))
5340                                                         {
5341                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5342                                                         }
5343                                                 }
5344                                                 else
5345                                                 {
5346                                                         $keywords = $keywords_parent;
5347                                                 }
5348
5349                                                 // PLAYER
5350                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5351                                                 {
5352                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5353                                                 }
5354                                                 else
5355                                                 {
5356                                                         $player = $player_parent;
5357                                                 }
5358
5359                                                 // RATINGS
5360                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5361                                                 {
5362                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5363                                                         {
5364                                                                 $rating_scheme = null;
5365                                                                 $rating_value = null;
5366                                                                 if (isset($rating['attribs']['']['scheme']))
5367                                                                 {
5368                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5369                                                                 }
5370                                                                 else
5371                                                                 {
5372                                                                         $rating_scheme = 'urn:simple';
5373                                                                 }
5374                                                                 if (isset($rating['data']))
5375                                                                 {
5376                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5377                                                                 }
5378                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5379                                                         }
5380                                                         if (is_array($ratings))
5381                                                         {
5382                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5383                                                         }
5384                                                 }
5385                                                 else
5386                                                 {
5387                                                         $ratings = $ratings_parent;
5388                                                 }
5389
5390                                                 // RESTRICTIONS
5391                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5392                                                 {
5393                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5394                                                         {
5395                                                                 $restriction_relationship = null;
5396                                                                 $restriction_type = null;
5397                                                                 $restriction_value = null;
5398                                                                 if (isset($restriction['attribs']['']['relationship']))
5399                                                                 {
5400                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5401                                                                 }
5402                                                                 if (isset($restriction['attribs']['']['type']))
5403                                                                 {
5404                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5405                                                                 }
5406                                                                 if (isset($restriction['data']))
5407                                                                 {
5408                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5409                                                                 }
5410                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5411                                                         }
5412                                                         if (is_array($restrictions))
5413                                                         {
5414                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5415                                                         }
5416                                                 }
5417                                                 else
5418                                                 {
5419                                                         $restrictions = $restrictions_parent;
5420                                                 }
5421
5422                                                 // THUMBNAILS
5423                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5424                                                 {
5425                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5426                                                         {
5427                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5428                                                         }
5429                                                         if (is_array($thumbnails))
5430                                                         {
5431                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5432                                                         }
5433                                                 }
5434                                                 else
5435                                                 {
5436                                                         $thumbnails = $thumbnails_parent;
5437                                                 }
5438
5439                                                 // TITLES
5440                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5441                                                 {
5442                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5443                                                 }
5444                                                 else
5445                                                 {
5446                                                         $title = $title_parent;
5447                                                 }
5448
5449                                                 $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);
5450                                         }
5451                                 }
5452                         }
5453
5454                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5455                         {
5456                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5457                                 {
5458                                         // Attributes
5459                                         $bitrate = null;
5460                                         $channels = null;
5461                                         $duration = null;
5462                                         $expression = null;
5463                                         $framerate = null;
5464                                         $height = null;
5465                                         $javascript = null;
5466                                         $lang = null;
5467                                         $length = null;
5468                                         $medium = null;
5469                                         $samplingrate = null;
5470                                         $type = null;
5471                                         $url = null;
5472                                         $width = null;
5473
5474                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5475                                         if (isset($link['attribs']['']['type']))
5476                                         {
5477                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5478                                         }
5479                                         if (isset($link['attribs']['']['length']))
5480                                         {
5481                                                 $length = ceil($link['attribs']['']['length']);
5482                                         }
5483
5484                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5485                                         $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);
5486                                 }
5487                         }
5488
5489                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5490                         {
5491                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5492                                 {
5493                                         // Attributes
5494                                         $bitrate = null;
5495                                         $channels = null;
5496                                         $duration = null;
5497                                         $expression = null;
5498                                         $framerate = null;
5499                                         $height = null;
5500                                         $javascript = null;
5501                                         $lang = null;
5502                                         $length = null;
5503                                         $medium = null;
5504                                         $samplingrate = null;
5505                                         $type = null;
5506                                         $url = null;
5507                                         $width = null;
5508
5509                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5510                                         if (isset($link['attribs']['']['type']))
5511                                         {
5512                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5513                                         }
5514                                         if (isset($link['attribs']['']['length']))
5515                                         {
5516                                                 $length = ceil($link['attribs']['']['length']);
5517                                         }
5518
5519                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5520                                         $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);
5521                                 }
5522                         }
5523
5524                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5525                         {
5526                                 if (isset($enclosure[0]['attribs']['']['url']))
5527                                 {
5528                                         // Attributes
5529                                         $bitrate = null;
5530                                         $channels = null;
5531                                         $duration = null;
5532                                         $expression = null;
5533                                         $framerate = null;
5534                                         $height = null;
5535                                         $javascript = null;
5536                                         $lang = null;
5537                                         $length = null;
5538                                         $medium = null;
5539                                         $samplingrate = null;
5540                                         $type = null;
5541                                         $url = null;
5542                                         $width = null;
5543
5544                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5545                                         if (isset($enclosure[0]['attribs']['']['type']))
5546                                         {
5547                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5548                                         }
5549                                         if (isset($enclosure[0]['attribs']['']['length']))
5550                                         {
5551                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5552                                         }
5553
5554                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5555                                         $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);
5556                                 }
5557                         }
5558
5559                         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))
5560                         {
5561                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5562                                 $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);
5563                         }
5564
5565                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5566                 }
5567                 if (!empty($this->data['enclosures']))
5568                 {
5569                         return $this->data['enclosures'];
5570                 }
5571                 else
5572                 {
5573                         return null;
5574                 }
5575         }
5576
5577         function get_latitude()
5578         {
5579                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5580                 {
5581                         return (float) $return[0]['data'];
5582                 }
5583                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5584                 {
5585                         return (float) $match[1];
5586                 }
5587                 else
5588                 {
5589                         return null;
5590                 }
5591         }
5592
5593         function get_longitude()
5594         {
5595                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5596                 {
5597                         return (float) $return[0]['data'];
5598                 }
5599                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5600                 {
5601                         return (float) $return[0]['data'];
5602                 }
5603                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5604                 {
5605                         return (float) $match[2];
5606                 }
5607                 else
5608                 {
5609                         return null;
5610                 }
5611         }
5612
5613         function get_source()
5614         {
5615                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5616                 {
5617                         return new $this->feed->source_class($this, $return[0]);
5618                 }
5619                 else
5620                 {
5621                         return null;
5622                 }
5623         }
5624
5625         /**
5626          * Creates the add_to_* methods' return data
5627          *
5628          * @access private
5629          * @param string $item_url String to prefix to the item permalink
5630          * @param string $title_url String to prefix to the item title
5631          * (and suffix to the item permalink)
5632          * @return mixed URL if feed exists, false otherwise
5633          */
5634         function add_to_service($item_url, $title_url = null, $summary_url = null)
5635         {
5636                 if ($this->get_permalink() !== null)
5637                 {
5638                         $return = $item_url . rawurlencode($this->get_permalink());
5639                         if ($title_url !== null && $this->get_title() !== null)
5640                         {
5641                                 $return .= $title_url . rawurlencode($this->get_title());
5642                         }
5643                         if ($summary_url !== null && $this->get_description() !== null)
5644                         {
5645                                 $return .= $summary_url . rawurlencode($this->get_description());
5646                         }
5647                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5648                 }
5649                 else
5650                 {
5651                         return null;
5652                 }
5653         }
5654
5655         function add_to_blinklist()
5656         {
5657                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5658         }
5659
5660         function add_to_blogmarks()
5661         {
5662                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5663         }
5664
5665         function add_to_delicious()
5666         {
5667                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5668         }
5669
5670         function add_to_digg()
5671         {
5672                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5673         }
5674
5675         function add_to_furl()
5676         {
5677                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5678         }
5679
5680         function add_to_magnolia()
5681         {
5682                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5683         }
5684
5685         function add_to_myweb20()
5686         {
5687                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5688         }
5689
5690         function add_to_newsvine()
5691         {
5692                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5693         }
5694
5695         function add_to_reddit()
5696         {
5697                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5698         }
5699
5700         function add_to_segnalo()
5701         {
5702                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5703         }
5704
5705         function add_to_simpy()
5706         {
5707                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5708         }
5709
5710         function add_to_spurl()
5711         {
5712                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5713         }
5714
5715         function add_to_wists()
5716         {
5717                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5718         }
5719
5720         function search_technorati()
5721         {
5722                 return $this->add_to_service('http://www.technorati.com/search/');
5723         }
5724 }
5725
5726 class SimplePie_Source
5727 {
5728         var $item;
5729         var $data = array();
5730
5731         function SimplePie_Source($item, $data)
5732         {
5733                 $this->item = $item;
5734                 $this->data = $data;
5735         }
5736
5737         function __toString()
5738         {
5739                 return md5(serialize($this->data));
5740         }
5741
5742         function get_source_tags($namespace, $tag)
5743         {
5744                 if (isset($this->data['child'][$namespace][$tag]))
5745                 {
5746                         return $this->data['child'][$namespace][$tag];
5747                 }
5748                 else
5749                 {
5750                         return null;
5751                 }
5752         }
5753
5754         function get_base($element = array())
5755         {
5756                 return $this->item->get_base($element);
5757         }
5758
5759         function sanitize($data, $type, $base = '')
5760         {
5761                 return $this->item->sanitize($data, $type, $base);
5762         }
5763
5764         function get_item()
5765         {
5766                 return $this->item;
5767         }
5768
5769         function get_title()
5770         {
5771                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5772                 {
5773                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5774                 }
5775                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5776                 {
5777                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5778                 }
5779                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5780                 {
5781                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5782                 }
5783                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5784                 {
5785                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5786                 }
5787                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5788                 {
5789                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5790                 }
5791                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5792                 {
5793                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5794                 }
5795                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5796                 {
5797                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5798                 }
5799                 else
5800                 {
5801                         return null;
5802                 }
5803         }
5804
5805         function get_category($key = 0)
5806         {
5807                 $categories = $this->get_categories();
5808                 if (isset($categories[$key]))
5809                 {
5810                         return $categories[$key];
5811                 }
5812                 else
5813                 {
5814                         return null;
5815                 }
5816         }
5817
5818         function get_categories()
5819         {
5820                 $categories = array();
5821
5822                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5823                 {
5824                         $term = null;
5825                         $scheme = null;
5826                         $label = null;
5827                         if (isset($category['attribs']['']['term']))
5828                         {
5829                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5830                         }
5831                         if (isset($category['attribs']['']['scheme']))
5832                         {
5833                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5834                         }
5835                         if (isset($category['attribs']['']['label']))
5836                         {
5837                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5838                         }
5839                         $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5840                 }
5841                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5842                 {
5843                         // This is really the label, but keep this as the term also for BC.
5844                         // Label will also work on retrieving because that falls back to term.
5845                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5846                         if (isset($category['attribs']['']['domain']))
5847                         {
5848                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5849                         }
5850                         else
5851                         {
5852                                 $scheme = null;
5853                         }
5854                         $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5855                 }
5856                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5857                 {
5858                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5859                 }
5860                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5861                 {
5862                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5863                 }
5864
5865                 if (!empty($categories))
5866                 {
5867                         return SimplePie_Misc::array_unique($categories);
5868                 }
5869                 else
5870                 {
5871                         return null;
5872                 }
5873         }
5874
5875         function get_author($key = 0)
5876         {
5877                 $authors = $this->get_authors();
5878                 if (isset($authors[$key]))
5879                 {
5880                         return $authors[$key];
5881                 }
5882                 else
5883                 {
5884                         return null;
5885                 }
5886         }
5887
5888         function get_authors()
5889         {
5890                 $authors = array();
5891                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5892                 {
5893                         $name = null;
5894                         $uri = null;
5895                         $email = null;
5896                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5897                         {
5898                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5899                         }
5900                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5901                         {
5902                                 $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]));
5903                         }
5904                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5905                         {
5906                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5907                         }
5908                         if ($name !== null || $email !== null || $uri !== null)
5909                         {
5910                                 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5911                         }
5912                 }
5913                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5914                 {
5915                         $name = null;
5916                         $url = null;
5917                         $email = null;
5918                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5919                         {
5920                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5921                         }
5922                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5923                         {
5924                                 $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]));
5925                         }
5926                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5927                         {
5928                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5929                         }
5930                         if ($name !== null || $email !== null || $url !== null)
5931                         {
5932                                 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5933                         }
5934                 }
5935                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5936                 {
5937                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5938                 }
5939                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5940                 {
5941                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5942                 }
5943                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5944                 {
5945                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5946                 }
5947
5948                 if (!empty($authors))
5949                 {
5950                         return SimplePie_Misc::array_unique($authors);
5951                 }
5952                 else
5953                 {
5954                         return null;
5955                 }
5956         }
5957
5958         function get_contributor($key = 0)
5959         {
5960                 $contributors = $this->get_contributors();
5961                 if (isset($contributors[$key]))
5962                 {
5963                         return $contributors[$key];
5964                 }
5965                 else
5966                 {
5967                         return null;
5968                 }
5969         }
5970
5971         function get_contributors()
5972         {
5973                 $contributors = array();
5974                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5975                 {
5976                         $name = null;
5977                         $uri = null;
5978                         $email = null;
5979                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5980                         {
5981                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5982                         }
5983                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5984                         {
5985                                 $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]));
5986                         }
5987                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5988                         {
5989                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5990                         }
5991                         if ($name !== null || $email !== null || $uri !== null)
5992                         {
5993                                 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
5994                         }
5995                 }
5996                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
5997                 {
5998                         $name = null;
5999                         $url = null;
6000                         $email = null;
6001                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6002                         {
6003                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6004                         }
6005                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6006                         {
6007                                 $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]));
6008                         }
6009                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6010                         {
6011                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6012                         }
6013                         if ($name !== null || $email !== null || $url !== null)
6014                         {
6015                                 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6016                         }
6017                 }
6018
6019                 if (!empty($contributors))
6020                 {
6021                         return SimplePie_Misc::array_unique($contributors);
6022                 }
6023                 else
6024                 {
6025                         return null;
6026                 }
6027         }
6028
6029         function get_link($key = 0, $rel = 'alternate')
6030         {
6031                 $links = $this->get_links($rel);
6032                 if (isset($links[$key]))
6033                 {
6034                         return $links[$key];
6035                 }
6036                 else
6037                 {
6038                         return null;
6039                 }
6040         }
6041
6042         /**
6043          * Added for parity between the parent-level and the item/entry-level.
6044          */
6045         function get_permalink()
6046         {
6047                 return $this->get_link(0);
6048         }
6049
6050         function get_links($rel = 'alternate')
6051         {
6052                 if (!isset($this->data['links']))
6053                 {
6054                         $this->data['links'] = array();
6055                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6056                         {
6057                                 foreach ($links as $link)
6058                                 {
6059                                         if (isset($link['attribs']['']['href']))
6060                                         {
6061                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6062                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6063                                         }
6064                                 }
6065                         }
6066                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6067                         {
6068                                 foreach ($links as $link)
6069                                 {
6070                                         if (isset($link['attribs']['']['href']))
6071                                         {
6072                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6073                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6074
6075                                         }
6076                                 }
6077                         }
6078                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6079                         {
6080                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6081                         }
6082                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6083                         {
6084                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6085                         }
6086                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6087                         {
6088                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6089                         }
6090
6091                         $keys = array_keys($this->data['links']);
6092                         foreach ($keys as $key)
6093                         {
6094                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6095                                 {
6096                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6097                                         {
6098                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6099                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6100                                         }
6101                                         else
6102                                         {
6103                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6104                                         }
6105                                 }
6106                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6107                                 {
6108                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6109                                 }
6110                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6111                         }
6112                 }
6113
6114                 if (isset($this->data['links'][$rel]))
6115                 {
6116                         return $this->data['links'][$rel];
6117                 }
6118                 else
6119                 {
6120                         return null;
6121                 }
6122         }
6123
6124         function get_description()
6125         {
6126                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6127                 {
6128                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6129                 }
6130                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6131                 {
6132                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6133                 }
6134                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6135                 {
6136                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6137                 }
6138                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6139                 {
6140                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6141                 }
6142                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6143                 {
6144                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6145                 }
6146                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6147                 {
6148                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6149                 }
6150                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6151                 {
6152                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6153                 }
6154                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6155                 {
6156                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6157                 }
6158                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6159                 {
6160                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6161                 }
6162                 else
6163                 {
6164                         return null;
6165                 }
6166         }
6167
6168         function get_copyright()
6169         {
6170                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6171                 {
6172                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6173                 }
6174                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6175                 {
6176                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6177                 }
6178                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6179                 {
6180                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6181                 }
6182                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6183                 {
6184                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6185                 }
6186                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6187                 {
6188                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6189                 }
6190                 else
6191                 {
6192                         return null;
6193                 }
6194         }
6195
6196         function get_language()
6197         {
6198                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6199                 {
6200                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6201                 }
6202                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6203                 {
6204                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6205                 }
6206                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6207                 {
6208                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6209                 }
6210                 elseif (isset($this->data['xml_lang']))
6211                 {
6212                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6213                 }
6214                 else
6215                 {
6216                         return null;
6217                 }
6218         }
6219
6220         function get_latitude()
6221         {
6222                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6223                 {
6224                         return (float) $return[0]['data'];
6225                 }
6226                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6227                 {
6228                         return (float) $match[1];
6229                 }
6230                 else
6231                 {
6232                         return null;
6233                 }
6234         }
6235
6236         function get_longitude()
6237         {
6238                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6239                 {
6240                         return (float) $return[0]['data'];
6241                 }
6242                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6243                 {
6244                         return (float) $return[0]['data'];
6245                 }
6246                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6247                 {
6248                         return (float) $match[2];
6249                 }
6250                 else
6251                 {
6252                         return null;
6253                 }
6254         }
6255
6256         function get_image_url()
6257         {
6258                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6259                 {
6260                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6261                 }
6262                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6263                 {
6264                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6265                 }
6266                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6267                 {
6268                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6269                 }
6270                 else
6271                 {
6272                         return null;
6273                 }
6274         }
6275 }
6276
6277 class SimplePie_Author
6278 {
6279         var $name;
6280         var $link;
6281         var $email;
6282
6283         // Constructor, used to input the data
6284         function SimplePie_Author($name = null, $link = null, $email = null)
6285         {
6286                 $this->name = $name;
6287                 $this->link = $link;
6288                 $this->email = $email;
6289         }
6290
6291         function __toString()
6292         {
6293                 // There is no $this->data here
6294                 return md5(serialize($this));
6295         }
6296
6297         function get_name()
6298         {
6299                 if ($this->name !== null)
6300                 {
6301                         return $this->name;
6302                 }
6303                 else
6304                 {
6305                         return null;
6306                 }
6307         }
6308
6309         function get_link()
6310         {
6311                 if ($this->link !== null)
6312                 {
6313                         return $this->link;
6314                 }
6315                 else
6316                 {
6317                         return null;
6318                 }
6319         }
6320
6321         function get_email()
6322         {
6323                 if ($this->email !== null)
6324                 {
6325                         return $this->email;
6326                 }
6327                 else
6328                 {
6329                         return null;
6330                 }
6331         }
6332 }
6333
6334 class SimplePie_Category
6335 {
6336         var $term;
6337         var $scheme;
6338         var $label;
6339
6340         // Constructor, used to input the data
6341         function SimplePie_Category($term = null, $scheme = null, $label = null)
6342         {
6343                 $this->term = $term;
6344                 $this->scheme = $scheme;
6345                 $this->label = $label;
6346         }
6347
6348         function __toString()
6349         {
6350                 // There is no $this->data here
6351                 return md5(serialize($this));
6352         }
6353
6354         function get_term()
6355         {
6356                 if ($this->term !== null)
6357                 {
6358                         return $this->term;
6359                 }
6360                 else
6361                 {
6362                         return null;
6363                 }
6364         }
6365
6366         function get_scheme()
6367         {
6368                 if ($this->scheme !== null)
6369                 {
6370                         return $this->scheme;
6371                 }
6372                 else
6373                 {
6374                         return null;
6375                 }
6376         }
6377
6378         function get_label()
6379         {
6380                 if ($this->label !== null)
6381                 {
6382                         return $this->label;
6383                 }
6384                 else
6385                 {
6386                         return $this->get_term();
6387                 }
6388         }
6389 }
6390
6391 class SimplePie_Enclosure
6392 {
6393         var $bitrate;
6394         var $captions;
6395         var $categories;
6396         var $channels;
6397         var $copyright;
6398         var $credits;
6399         var $description;
6400         var $duration;
6401         var $expression;
6402         var $framerate;
6403         var $handler;
6404         var $hashes;
6405         var $height;
6406         var $javascript;
6407         var $keywords;
6408         var $lang;
6409         var $length;
6410         var $link;
6411         var $medium;
6412         var $player;
6413         var $ratings;
6414         var $restrictions;
6415         var $samplingrate;
6416         var $thumbnails;
6417         var $title;
6418         var $type;
6419         var $width;
6420
6421         // Constructor, used to input the data
6422         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)
6423         {
6424                 $this->bitrate = $bitrate;
6425                 $this->captions = $captions;
6426                 $this->categories = $categories;
6427                 $this->channels = $channels;
6428                 $this->copyright = $copyright;
6429                 $this->credits = $credits;
6430                 $this->description = $description;
6431                 $this->duration = $duration;
6432                 $this->expression = $expression;
6433                 $this->framerate = $framerate;
6434                 $this->hashes = $hashes;
6435                 $this->height = $height;
6436                 $this->javascript = $javascript;
6437                 $this->keywords = $keywords;
6438                 $this->lang = $lang;
6439                 $this->length = $length;
6440                 $this->link = $link;
6441                 $this->medium = $medium;
6442                 $this->player = $player;
6443                 $this->ratings = $ratings;
6444                 $this->restrictions = $restrictions;
6445                 $this->samplingrate = $samplingrate;
6446                 $this->thumbnails = $thumbnails;
6447                 $this->title = $title;
6448                 $this->type = $type;
6449                 $this->width = $width;
6450                 if (class_exists('idna_convert'))
6451                 {
6452                         $idn =& new idna_convert;
6453                         $parsed = SimplePie_Misc::parse_url($link);
6454                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6455                 }
6456                 $this->handler = $this->get_handler(); // Needs to load last
6457         }
6458
6459         function __toString()
6460         {
6461                 // There is no $this->data here
6462                 return md5(serialize($this));
6463         }
6464
6465         function get_bitrate()
6466         {
6467                 if ($this->bitrate !== null)
6468                 {
6469                         return $this->bitrate;
6470                 }
6471                 else
6472                 {
6473                         return null;
6474                 }
6475         }
6476
6477         function get_caption($key = 0)
6478         {
6479                 $captions = $this->get_captions();
6480                 if (isset($captions[$key]))
6481                 {
6482                         return $captions[$key];
6483                 }
6484                 else
6485                 {
6486                         return null;
6487                 }
6488         }
6489
6490         function get_captions()
6491         {
6492                 if ($this->captions !== null)
6493                 {
6494                         return $this->captions;
6495                 }
6496                 else
6497                 {
6498                         return null;
6499                 }
6500         }
6501
6502         function get_category($key = 0)
6503         {
6504                 $categories = $this->get_categories();
6505                 if (isset($categories[$key]))
6506                 {
6507                         return $categories[$key];
6508                 }
6509                 else
6510                 {
6511                         return null;
6512                 }
6513         }
6514
6515         function get_categories()
6516         {
6517                 if ($this->categories !== null)
6518                 {
6519                         return $this->categories;
6520                 }
6521                 else
6522                 {
6523                         return null;
6524                 }
6525         }
6526
6527         function get_channels()
6528         {
6529                 if ($this->channels !== null)
6530                 {
6531                         return $this->channels;
6532                 }
6533                 else
6534                 {
6535                         return null;
6536                 }
6537         }
6538
6539         function get_copyright()
6540         {
6541                 if ($this->copyright !== null)
6542                 {
6543                         return $this->copyright;
6544                 }
6545                 else
6546                 {
6547                         return null;
6548                 }
6549         }
6550
6551         function get_credit($key = 0)
6552         {
6553                 $credits = $this->get_credits();
6554                 if (isset($credits[$key]))
6555                 {
6556                         return $credits[$key];
6557                 }
6558                 else
6559                 {
6560                         return null;
6561                 }
6562         }
6563
6564         function get_credits()
6565         {
6566                 if ($this->credits !== null)
6567                 {
6568                         return $this->credits;
6569                 }
6570                 else
6571                 {
6572                         return null;
6573                 }
6574         }
6575
6576         function get_description()
6577         {
6578                 if ($this->description !== null)
6579                 {
6580                         return $this->description;
6581                 }
6582                 else
6583                 {
6584                         return null;
6585                 }
6586         }
6587
6588         function get_duration($convert = false)
6589         {
6590                 if ($this->duration !== null)
6591                 {
6592                         if ($convert)
6593                         {
6594                                 $time = SimplePie_Misc::time_hms($this->duration);
6595                                 return $time;
6596                         }
6597                         else
6598                         {
6599                                 return $this->duration;
6600                         }
6601                 }
6602                 else
6603                 {
6604                         return null;
6605                 }
6606         }
6607
6608         function get_expression()
6609         {
6610                 if ($this->expression !== null)
6611                 {
6612                         return $this->expression;
6613                 }
6614                 else
6615                 {
6616                         return 'full';
6617                 }
6618         }
6619
6620         function get_extension()
6621         {
6622                 if ($this->link !== null)
6623                 {
6624                         $url = SimplePie_Misc::parse_url($this->link);
6625                         if ($url['path'] !== '')
6626                         {
6627                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6628                         }
6629                 }
6630                 return null;
6631         }
6632
6633         function get_framerate()
6634         {
6635                 if ($this->framerate !== null)
6636                 {
6637                         return $this->framerate;
6638                 }
6639                 else
6640                 {
6641                         return null;
6642                 }
6643         }
6644
6645         function get_handler()
6646         {
6647                 return $this->get_real_type(true);
6648         }
6649
6650         function get_hash($key = 0)
6651         {
6652                 $hashes = $this->get_hashes();
6653                 if (isset($hashes[$key]))
6654                 {
6655                         return $hashes[$key];
6656                 }
6657                 else
6658                 {
6659                         return null;
6660                 }
6661         }
6662
6663         function get_hashes()
6664         {
6665                 if ($this->hashes !== null)
6666                 {
6667                         return $this->hashes;
6668                 }
6669                 else
6670                 {
6671                         return null;
6672                 }
6673         }
6674
6675         function get_height()
6676         {
6677                 if ($this->height !== null)
6678                 {
6679                         return $this->height;
6680                 }
6681                 else
6682                 {
6683                         return null;
6684                 }
6685         }
6686
6687         function get_language()
6688         {
6689                 if ($this->lang !== null)
6690                 {
6691                         return $this->lang;
6692                 }
6693                 else
6694                 {
6695                         return null;
6696                 }
6697         }
6698
6699         function get_keyword($key = 0)
6700         {
6701                 $keywords = $this->get_keywords();
6702                 if (isset($keywords[$key]))
6703                 {
6704                         return $keywords[$key];
6705                 }
6706                 else
6707                 {
6708                         return null;
6709                 }
6710         }
6711
6712         function get_keywords()
6713         {
6714                 if ($this->keywords !== null)
6715                 {
6716                         return $this->keywords;
6717                 }
6718                 else
6719                 {
6720                         return null;
6721                 }
6722         }
6723
6724         function get_length()
6725         {
6726                 if ($this->length !== null)
6727                 {
6728                         return $this->length;
6729                 }
6730                 else
6731                 {
6732                         return null;
6733                 }
6734         }
6735
6736         function get_link()
6737         {
6738                 if ($this->link !== null)
6739                 {
6740                         return urldecode($this->link);
6741                 }
6742                 else
6743                 {
6744                         return null;
6745                 }
6746         }
6747
6748         function get_medium()
6749         {
6750                 if ($this->medium !== null)
6751                 {
6752                         return $this->medium;
6753                 }
6754                 else
6755                 {
6756                         return null;
6757                 }
6758         }
6759
6760         function get_player()
6761         {
6762                 if ($this->player !== null)
6763                 {
6764                         return $this->player;
6765                 }
6766                 else
6767                 {
6768                         return null;
6769                 }
6770         }
6771
6772         function get_rating($key = 0)
6773         {
6774                 $ratings = $this->get_ratings();
6775                 if (isset($ratings[$key]))
6776                 {
6777                         return $ratings[$key];
6778                 }
6779                 else
6780                 {
6781                         return null;
6782                 }
6783         }
6784
6785         function get_ratings()
6786         {
6787                 if ($this->ratings !== null)
6788                 {
6789                         return $this->ratings;
6790                 }
6791                 else
6792                 {
6793                         return null;
6794                 }
6795         }
6796
6797         function get_restriction($key = 0)
6798         {
6799                 $restrictions = $this->get_restrictions();
6800                 if (isset($restrictions[$key]))
6801                 {
6802                         return $restrictions[$key];
6803                 }
6804                 else
6805                 {
6806                         return null;
6807                 }
6808         }
6809
6810         function get_restrictions()
6811         {
6812                 if ($this->restrictions !== null)
6813                 {
6814                         return $this->restrictions;
6815                 }
6816                 else
6817                 {
6818                         return null;
6819                 }
6820         }
6821
6822         function get_sampling_rate()
6823         {
6824                 if ($this->samplingrate !== null)
6825                 {
6826                         return $this->samplingrate;
6827                 }
6828                 else
6829                 {
6830                         return null;
6831                 }
6832         }
6833
6834         function get_size()
6835         {
6836                 $length = $this->get_length();
6837                 if ($length !== null)
6838                 {
6839                         return round($length/1048576, 2);
6840                 }
6841                 else
6842                 {
6843                         return null;
6844                 }
6845         }
6846
6847         function get_thumbnail($key = 0)
6848         {
6849                 $thumbnails = $this->get_thumbnails();
6850                 if (isset($thumbnails[$key]))
6851                 {
6852                         return $thumbnails[$key];
6853                 }
6854                 else
6855                 {
6856                         return null;
6857                 }
6858         }
6859
6860         function get_thumbnails()
6861         {
6862                 if ($this->thumbnails !== null)
6863                 {
6864                         return $this->thumbnails;
6865                 }
6866                 else
6867                 {
6868                         return null;
6869                 }
6870         }
6871
6872         function get_title()
6873         {
6874                 if ($this->title !== null)
6875                 {
6876                         return $this->title;
6877                 }
6878                 else
6879                 {
6880                         return null;
6881                 }
6882         }
6883
6884         function get_type()
6885         {
6886                 if ($this->type !== null)
6887                 {
6888                         return $this->type;
6889                 }
6890                 else
6891                 {
6892                         return null;
6893                 }
6894         }
6895
6896         function get_width()
6897         {
6898                 if ($this->width !== null)
6899                 {
6900                         return $this->width;
6901                 }
6902                 else
6903                 {
6904                         return null;
6905                 }
6906         }
6907
6908         function native_embed($options='')
6909         {
6910                 return $this->embed($options, true);
6911         }
6912
6913         /**
6914          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6915          */
6916         function embed($options = '', $native = false)
6917         {
6918                 // Set up defaults
6919                 $audio = '';
6920                 $video = '';
6921                 $alt = '';
6922                 $altclass = '';
6923                 $loop = 'false';
6924                 $width = 'auto';
6925                 $height = 'auto';
6926                 $bgcolor = '#ffffff';
6927                 $mediaplayer = '';
6928                 $widescreen = false;
6929                 $handler = $this->get_handler();
6930                 $type = $this->get_real_type();
6931
6932                 // Process options and reassign values as necessary
6933                 if (is_array($options))
6934                 {
6935                         extract($options);
6936                 }
6937                 else
6938                 {
6939                         $options = explode(',', $options);
6940                         foreach($options as $option)
6941                         {
6942                                 $opt = explode(':', $option, 2);
6943                                 if (isset($opt[0], $opt[1]))
6944                                 {
6945                                         $opt[0] = trim($opt[0]);
6946                                         $opt[1] = trim($opt[1]);
6947                                         switch ($opt[0])
6948                                         {
6949                                                 case 'audio':
6950                                                         $audio = $opt[1];
6951                                                         break;
6952
6953                                                 case 'video':
6954                                                         $video = $opt[1];
6955                                                         break;
6956
6957                                                 case 'alt':
6958                                                         $alt = $opt[1];
6959                                                         break;
6960
6961                                                 case 'altclass':
6962                                                         $altclass = $opt[1];
6963                                                         break;
6964
6965                                                 case 'loop':
6966                                                         $loop = $opt[1];
6967                                                         break;
6968
6969                                                 case 'width':
6970                                                         $width = $opt[1];
6971                                                         break;
6972
6973                                                 case 'height':
6974                                                         $height = $opt[1];
6975                                                         break;
6976
6977                                                 case 'bgcolor':
6978                                                         $bgcolor = $opt[1];
6979                                                         break;
6980
6981                                                 case 'mediaplayer':
6982                                                         $mediaplayer = $opt[1];
6983                                                         break;
6984
6985                                                 case 'widescreen':
6986                                                         $widescreen = $opt[1];
6987                                                         break;
6988                                         }
6989                                 }
6990                         }
6991                 }
6992
6993                 $mime = explode('/', $type, 2);
6994                 $mime = $mime[0];
6995
6996                 // Process values for 'auto'
6997                 if ($width === 'auto')
6998                 {
6999                         if ($mime === 'video')
7000                         {
7001                                 if ($height === 'auto')
7002                                 {
7003                                         $width = 480;
7004                                 }
7005                                 elseif ($widescreen)
7006                                 {
7007                                         $width = round((intval($height)/9)*16);
7008                                 }
7009                                 else
7010                                 {
7011                                         $width = round((intval($height)/3)*4);
7012                                 }
7013                         }
7014                         else
7015                         {
7016                                 $width = '100%';
7017                         }
7018                 }
7019
7020                 if ($height === 'auto')
7021                 {
7022                         if ($mime === 'audio')
7023                         {
7024                                 $height = 0;
7025                         }
7026                         elseif ($mime === 'video')
7027                         {
7028                                 if ($width === 'auto')
7029                                 {
7030                                         if ($widescreen)
7031                                         {
7032                                                 $height = 270;
7033                                         }
7034                                         else
7035                                         {
7036                                                 $height = 360;
7037                                         }
7038                                 }
7039                                 elseif ($widescreen)
7040                                 {
7041                                         $height = round((intval($width)/16)*9);
7042                                 }
7043                                 else
7044                                 {
7045                                         $height = round((intval($width)/4)*3);
7046                                 }
7047                         }
7048                         else
7049                         {
7050                                 $height = 376;
7051                         }
7052                 }
7053                 elseif ($mime === 'audio')
7054                 {
7055                         $height = 0;
7056                 }
7057
7058                 // Set proper placeholder value
7059                 if ($mime === 'audio')
7060                 {
7061                         $placeholder = $audio;
7062                 }
7063                 elseif ($mime === 'video')
7064                 {
7065                         $placeholder = $video;
7066                 }
7067
7068                 $embed = '';
7069
7070                 // Make sure the JS library is included
7071                 if (!$native)
7072                 {
7073                         static $javascript_outputted = null;
7074                         if (!$javascript_outputted && $this->javascript)
7075                         {
7076                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7077                                 $javascript_outputted = true;
7078                         }
7079                 }
7080
7081                 // Odeo Feed MP3's
7082                 if ($handler === 'odeo')
7083                 {
7084                         if ($native)
7085                         {
7086                                 $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>';
7087                         }
7088                         else
7089                         {
7090                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7091                         }
7092                 }
7093
7094                 // Flash
7095                 elseif ($handler === 'flash')
7096                 {
7097                         if ($native)
7098                         {
7099                                 $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>";
7100                         }
7101                         else
7102                         {
7103                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7104                         }
7105                 }
7106
7107                 // Flash Media Player file types.
7108                 // Preferred handler for MP3 file types.
7109                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7110                 {
7111                         $height += 20;
7112                         if ($native)
7113                         {
7114                                 $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>";
7115                         }
7116                         else
7117                         {
7118                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7119                         }
7120                 }
7121
7122                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7123                 // Only handle MP3's if the Flash Media Player is not present.
7124                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7125                 {
7126                         $height += 16;
7127                         if ($native)
7128                         {
7129                                 if ($placeholder !== '')
7130                                 {
7131                                         $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>";
7132                                 }
7133                                 else
7134                                 {
7135                                         $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>";
7136                                 }
7137                         }
7138                         else
7139                         {
7140                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7141                         }
7142                 }
7143
7144                 // Windows Media
7145                 elseif ($handler === 'wmedia')
7146                 {
7147                         $height += 45;
7148                         if ($native)
7149                         {
7150                                 $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>";
7151                         }
7152                         else
7153                         {
7154                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7155                         }
7156                 }
7157
7158                 // Everything else
7159                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7160
7161                 return $embed;
7162         }
7163
7164         function get_real_type($find_handler = false)
7165         {
7166                 // If it's Odeo, let's get it out of the way.
7167                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7168                 {
7169                         return 'odeo';
7170                 }
7171
7172                 // Mime-types by handler.
7173                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7174                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7175                 $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
7176                 $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
7177                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7178
7179                 if ($this->get_type() !== null)
7180                 {
7181                         $type = strtolower($this->type);
7182                 }
7183                 else
7184                 {
7185                         $type = null;
7186                 }
7187
7188                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7189                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7190                 {
7191                         switch (strtolower($this->get_extension()))
7192                         {
7193                                 // Audio mime-types
7194                                 case 'aac':
7195                                 case 'adts':
7196                                         $type = 'audio/acc';
7197                                         break;
7198
7199                                 case 'aif':
7200                                 case 'aifc':
7201                                 case 'aiff':
7202                                 case 'cdda':
7203                                         $type = 'audio/aiff';
7204                                         break;
7205
7206                                 case 'bwf':
7207                                         $type = 'audio/wav';
7208                                         break;
7209
7210                                 case 'kar':
7211                                 case 'mid':
7212                                 case 'midi':
7213                                 case 'smf':
7214                                         $type = 'audio/midi';
7215                                         break;
7216
7217                                 case 'm4a':
7218                                         $type = 'audio/x-m4a';
7219                                         break;
7220
7221                                 case 'mp3':
7222                                 case 'swa':
7223                                         $type = 'audio/mp3';
7224                                         break;
7225
7226                                 case 'wav':
7227                                         $type = 'audio/wav';
7228                                         break;
7229
7230                                 case 'wax':
7231                                         $type = 'audio/x-ms-wax';
7232                                         break;
7233
7234                                 case 'wma':
7235                                         $type = 'audio/x-ms-wma';
7236                                         break;
7237
7238                                 // Video mime-types
7239                                 case '3gp':
7240                                 case '3gpp':
7241                                         $type = 'video/3gpp';
7242                                         break;
7243
7244                                 case '3g2':
7245                                 case '3gp2':
7246                                         $type = 'video/3gpp2';
7247                                         break;
7248
7249                                 case 'asf':
7250                                         $type = 'video/x-ms-asf';
7251                                         break;
7252
7253                                 case 'flv':
7254                                         $type = 'video/x-flv';
7255                                         break;
7256
7257                                 case 'm1a':
7258                                 case 'm1s':
7259                                 case 'm1v':
7260                                 case 'm15':
7261                                 case 'm75':
7262                                 case 'mp2':
7263                                 case 'mpa':
7264                                 case 'mpeg':
7265                                 case 'mpg':
7266                                 case 'mpm':
7267                                 case 'mpv':
7268                                         $type = 'video/mpeg';
7269                                         break;
7270
7271                                 case 'm4v':
7272                                         $type = 'video/x-m4v';
7273                                         break;
7274
7275                                 case 'mov':
7276                                 case 'qt':
7277                                         $type = 'video/quicktime';
7278                                         break;
7279
7280                                 case 'mp4':
7281                                 case 'mpg4':
7282                                         $type = 'video/mp4';
7283                                         break;
7284
7285                                 case 'sdv':
7286                                         $type = 'video/sd-video';
7287                                         break;
7288
7289                                 case 'wm':
7290                                         $type = 'video/x-ms-wm';
7291                                         break;
7292
7293                                 case 'wmv':
7294                                         $type = 'video/x-ms-wmv';
7295                                         break;
7296
7297                                 case 'wvx':
7298                                         $type = 'video/x-ms-wvx';
7299                                         break;
7300
7301                                 // Flash mime-types
7302                                 case 'spl':
7303                                         $type = 'application/futuresplash';
7304                                         break;
7305
7306                                 case 'swf':
7307                                         $type = 'application/x-shockwave-flash';
7308                                         break;
7309                         }
7310                 }
7311
7312                 if ($find_handler)
7313                 {
7314                         if (in_array($type, $types_flash))
7315                         {
7316                                 return 'flash';
7317                         }
7318                         elseif (in_array($type, $types_fmedia))
7319                         {
7320                                 return 'fmedia';
7321                         }
7322                         elseif (in_array($type, $types_quicktime))
7323                         {
7324                                 return 'quicktime';
7325                         }
7326                         elseif (in_array($type, $types_wmedia))
7327                         {
7328                                 return 'wmedia';
7329                         }
7330                         elseif (in_array($type, $types_mp3))
7331                         {
7332                                 return 'mp3';
7333                         }
7334                         else
7335                         {
7336                                 return null;
7337                         }
7338                 }
7339                 else
7340                 {
7341                         return $type;
7342                 }
7343         }
7344 }
7345
7346 class SimplePie_Caption
7347 {
7348         var $type;
7349         var $lang;
7350         var $startTime;
7351         var $endTime;
7352         var $text;
7353
7354         // Constructor, used to input the data
7355         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7356         {
7357                 $this->type = $type;
7358                 $this->lang = $lang;
7359                 $this->startTime = $startTime;
7360                 $this->endTime = $endTime;
7361                 $this->text = $text;
7362         }
7363
7364         function __toString()
7365         {
7366                 // There is no $this->data here
7367                 return md5(serialize($this));
7368         }
7369
7370         function get_endtime()
7371         {
7372                 if ($this->endTime !== null)
7373                 {
7374                         return $this->endTime;
7375                 }
7376                 else
7377                 {
7378                         return null;
7379                 }
7380         }
7381
7382         function get_language()
7383         {
7384                 if ($this->lang !== null)
7385                 {
7386                         return $this->lang;
7387                 }
7388                 else
7389                 {
7390                         return null;
7391                 }
7392         }
7393
7394         function get_starttime()
7395         {
7396                 if ($this->startTime !== null)
7397                 {
7398                         return $this->startTime;
7399                 }
7400                 else
7401                 {
7402                         return null;
7403                 }
7404         }
7405
7406         function get_text()
7407         {
7408                 if ($this->text !== null)
7409                 {
7410                         return $this->text;
7411                 }
7412                 else
7413                 {
7414                         return null;
7415                 }
7416         }
7417
7418         function get_type()
7419         {
7420                 if ($this->type !== null)
7421                 {
7422                         return $this->type;
7423                 }
7424                 else
7425                 {
7426                         return null;
7427                 }
7428         }
7429 }
7430
7431 class SimplePie_Credit
7432 {
7433         var $role;
7434         var $scheme;
7435         var $name;
7436
7437         // Constructor, used to input the data
7438         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7439         {
7440                 $this->role = $role;
7441                 $this->scheme = $scheme;
7442                 $this->name = $name;
7443         }
7444
7445         function __toString()
7446         {
7447                 // There is no $this->data here
7448                 return md5(serialize($this));
7449         }
7450
7451         function get_role()
7452         {
7453                 if ($this->role !== null)
7454                 {
7455                         return $this->role;
7456                 }
7457                 else
7458                 {
7459                         return null;
7460                 }
7461         }
7462
7463         function get_scheme()
7464         {
7465                 if ($this->scheme !== null)
7466                 {
7467                         return $this->scheme;
7468                 }
7469                 else
7470                 {
7471                         return null;
7472                 }
7473         }
7474
7475         function get_name()
7476         {
7477                 if ($this->name !== null)
7478                 {
7479                         return $this->name;
7480                 }
7481                 else
7482                 {
7483                         return null;
7484                 }
7485         }
7486 }
7487
7488 class SimplePie_Copyright
7489 {
7490         var $url;
7491         var $label;
7492
7493         // Constructor, used to input the data
7494         function SimplePie_Copyright($url = null, $label = null)
7495         {
7496                 $this->url = $url;
7497                 $this->label = $label;
7498         }
7499
7500         function __toString()
7501         {
7502                 // There is no $this->data here
7503                 return md5(serialize($this));
7504         }
7505
7506         function get_url()
7507         {
7508                 if ($this->url !== null)
7509                 {
7510                         return $this->url;
7511                 }
7512                 else
7513                 {
7514                         return null;
7515                 }
7516         }
7517
7518         function get_attribution()
7519         {
7520                 if ($this->label !== null)
7521                 {
7522                         return $this->label;
7523                 }
7524                 else
7525                 {
7526                         return null;
7527                 }
7528         }
7529 }
7530
7531 class SimplePie_Rating
7532 {
7533         var $scheme;
7534         var $value;
7535
7536         // Constructor, used to input the data
7537         function SimplePie_Rating($scheme = null, $value = null)
7538         {
7539                 $this->scheme = $scheme;
7540                 $this->value = $value;
7541         }
7542
7543         function __toString()
7544         {
7545                 // There is no $this->data here
7546                 return md5(serialize($this));
7547         }
7548
7549         function get_scheme()
7550         {
7551                 if ($this->scheme !== null)
7552                 {
7553                         return $this->scheme;
7554                 }
7555                 else
7556                 {
7557                         return null;
7558                 }
7559         }
7560
7561         function get_value()
7562         {
7563                 if ($this->value !== null)
7564                 {
7565                         return $this->value;
7566                 }
7567                 else
7568                 {
7569                         return null;
7570                 }
7571         }
7572 }
7573
7574 class SimplePie_Restriction
7575 {
7576         var $relationship;
7577         var $type;
7578         var $value;
7579
7580         // Constructor, used to input the data
7581         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7582         {
7583                 $this->relationship = $relationship;
7584                 $this->type = $type;
7585                 $this->value = $value;
7586         }
7587
7588         function __toString()
7589         {
7590                 // There is no $this->data here
7591                 return md5(serialize($this));
7592         }
7593
7594         function get_relationship()
7595         {
7596                 if ($this->relationship !== null)
7597                 {
7598                         return $this->relationship;
7599                 }
7600                 else
7601                 {
7602                         return null;
7603                 }
7604         }
7605
7606         function get_type()
7607         {
7608                 if ($this->type !== null)
7609                 {
7610                         return $this->type;
7611                 }
7612                 else
7613                 {
7614                         return null;
7615                 }
7616         }
7617
7618         function get_value()
7619         {
7620                 if ($this->value !== null)
7621                 {
7622                         return $this->value;
7623                 }
7624                 else
7625                 {
7626                         return null;
7627                 }
7628         }
7629 }
7630
7631 /**
7632  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7633  */
7634 class SimplePie_File
7635 {
7636         var $url;
7637         var $useragent;
7638         var $success = true;
7639         var $headers = array();
7640         var $body;
7641         var $status_code;
7642         var $redirects = 0;
7643         var $error;
7644         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7645
7646         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7647         {
7648                 if (class_exists('idna_convert'))
7649                 {
7650                         $idn =& new idna_convert;
7651                         $parsed = SimplePie_Misc::parse_url($url);
7652                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7653                 }
7654                 $this->url = $url;
7655                 $this->useragent = $useragent;
7656                 if (preg_match('/^http(s)?:\/\//i', $url))
7657                 {
7658                         if ($useragent === null)
7659                         {
7660                                 $useragent = ini_get('user_agent');
7661                                 $this->useragent = $useragent;
7662                         }
7663                         if (!is_array($headers))
7664                         {
7665                                 $headers = array();
7666                         }
7667                         if (!$force_fsockopen && function_exists('curl_exec'))
7668                         {
7669                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7670                                 $fp = curl_init();
7671                                 $headers2 = array();
7672                                 foreach ($headers as $key => $value)
7673                                 {
7674                                         $headers2[] = "$key: $value";
7675                                 }
7676                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7677                                 {
7678                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7679                                 }
7680                                 curl_setopt($fp, CURLOPT_URL, $url);
7681                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7682                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7683                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7684                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7685                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7686                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7687                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7688                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7689                                 {
7690                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7691                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7692                                 }
7693
7694                                 $this->headers = curl_exec($fp);
7695                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7696                                 {
7697                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7698                                         $this->headers = curl_exec($fp);
7699                                 }
7700                                 if (curl_errno($fp))
7701                                 {
7702                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7703                                         $this->success = false;
7704                                 }
7705                                 else
7706                                 {
7707                                         $info = curl_getinfo($fp);
7708                                         curl_close($fp);
7709                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7710                                         $this->headers = array_pop($this->headers);
7711                                         $parser =& new SimplePie_HTTP_Parser($this->headers);
7712                                         if ($parser->parse())
7713                                         {
7714                                                 $this->headers = $parser->headers;
7715                                                 $this->body = $parser->body;
7716                                                 $this->status_code = $parser->status_code;
7717                                                 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)
7718                                                 {
7719                                                         $this->redirects++;
7720                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7721                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7722                                                 }
7723                                         }
7724                                 }
7725                         }
7726                         else
7727                         {
7728                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7729                                 $url_parts = parse_url($url);
7730                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7731                                 {
7732                                         $url_parts['host'] = "ssl://$url_parts[host]";
7733                                         $url_parts['port'] = 443;
7734                                 }
7735                                 if (!isset($url_parts['port']))
7736                                 {
7737                                         $url_parts['port'] = 80;
7738                                 }
7739                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7740                                 if (!$fp)
7741                                 {
7742                                         $this->error = 'fsockopen error: ' . $errstr;
7743                                         $this->success = false;
7744                                 }
7745                                 else
7746                                 {
7747                                         stream_set_timeout($fp, $timeout);
7748                                         if (isset($url_parts['path']))
7749                                         {
7750                                                 if (isset($url_parts['query']))
7751                                                 {
7752                                                         $get = "$url_parts[path]?$url_parts[query]";
7753                                                 }
7754                                                 else
7755                                                 {
7756                                                         $get = $url_parts['path'];
7757                                                 }
7758                                         }
7759                                         else
7760                                         {
7761                                                 $get = '/';
7762                                         }
7763                                         $out = "GET $get HTTP/1.0\r\n";
7764                                         $out .= "Host: $url_parts[host]\r\n";
7765                                         $out .= "User-Agent: $useragent\r\n";
7766                                         if (extension_loaded('zlib'))
7767                                         {
7768                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7769                                         }
7770
7771                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7772                                         {
7773                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7774                                         }
7775                                         foreach ($headers as $key => $value)
7776                                         {
7777                                                 $out .= "$key: $value\r\n";
7778                                         }
7779                                         $out .= "Connection: Close\r\n\r\n";
7780                                         fwrite($fp, $out);
7781
7782                                         $info = stream_get_meta_data($fp);
7783
7784                                         $this->headers = '';
7785                                         while (!$info['eof'] && !$info['timed_out'])
7786                                         {
7787                                                 $this->headers .= fread($fp, 1160);
7788                                                 $info = stream_get_meta_data($fp);
7789                                         }
7790                                         if (!$info['timed_out'])
7791                                         {
7792                                                 $parser =& new SimplePie_HTTP_Parser($this->headers);
7793                                                 if ($parser->parse())
7794                                                 {
7795                                                         $this->headers = $parser->headers;
7796                                                         $this->body = $parser->body;
7797                                                         $this->status_code = $parser->status_code;
7798                                                         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)
7799                                                         {
7800                                                                 $this->redirects++;
7801                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7802                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7803                                                         }
7804                                                         if (isset($this->headers['content-encoding']))
7805                                                         {
7806                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7807                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7808                                                                 {
7809                                                                         case 'gzip':
7810                                                                         case 'x-gzip':
7811                                                                                 $decoder =& new SimplePie_gzdecode($this->body);
7812                                                                                 if (!$decoder->parse())
7813                                                                                 {
7814                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7815                                                                                         $this->success = false;
7816                                                                                 }
7817                                                                                 else
7818                                                                                 {
7819                                                                                         $this->body = $decoder->data;
7820                                                                                 }
7821                                                                                 break;
7822
7823                                                                         case 'deflate':
7824                                                                                 if (($body = gzuncompress($this->body)) === false)
7825                                                                                 {
7826                                                                                         if (($body = gzinflate($this->body)) === false)
7827                                                                                         {
7828                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7829                                                                                                 $this->success = false;
7830                                                                                         }
7831                                                                                 }
7832                                                                                 $this->body = $body;
7833                                                                                 break;
7834
7835                                                                         default:
7836                                                                                 $this->error = 'Unknown content coding';
7837                                                                                 $this->success = false;
7838                                                                 }
7839                                                         }
7840                                                 }
7841                                         }
7842                                         else
7843                                         {
7844                                                 $this->error = 'fsocket timed out';
7845                                                 $this->success = false;
7846                                         }
7847                                         fclose($fp);
7848                                 }
7849                         }
7850                 }
7851                 else
7852                 {
7853                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7854                         if (!$this->body = file_get_contents($url))
7855                         {
7856                                 $this->error = 'file_get_contents could not read the file';
7857                                 $this->success = false;
7858                         }
7859                 }
7860         }
7861 }
7862
7863 /**
7864  * HTTP Response Parser
7865  *
7866  * @package SimplePie
7867  */
7868 class SimplePie_HTTP_Parser
7869 {
7870         /**
7871          * HTTP Version
7872          *
7873          * @access public
7874          * @var float
7875          */
7876         var $http_version = 0.0;
7877
7878         /**
7879          * Status code
7880          *
7881          * @access public
7882          * @var int
7883          */
7884         var $status_code = 0;
7885
7886         /**
7887          * Reason phrase
7888          *
7889          * @access public
7890          * @var string
7891          */
7892         var $reason = '';
7893
7894         /**
7895          * Key/value pairs of the headers
7896          *
7897          * @access public
7898          * @var array
7899          */
7900         var $headers = array();
7901
7902         /**
7903          * Body of the response
7904          *
7905          * @access public
7906          * @var string
7907          */
7908         var $body = '';
7909
7910         /**
7911          * Current state of the state machine
7912          *
7913          * @access private
7914          * @var string
7915          */
7916         var $state = 'http_version';
7917
7918         /**
7919          * Input data
7920          *
7921          * @access private
7922          * @var string
7923          */
7924         var $data = '';
7925
7926         /**
7927          * Input data length (to avoid calling strlen() everytime this is needed)
7928          *
7929          * @access private
7930          * @var int
7931          */
7932         var $data_length = 0;
7933
7934         /**
7935          * Current position of the pointer
7936          *
7937          * @var int
7938          * @access private
7939          */
7940         var $position = 0;
7941
7942         /**
7943          * Name of the hedaer currently being parsed
7944          *
7945          * @access private
7946          * @var string
7947          */
7948         var $name = '';
7949
7950         /**
7951          * Value of the hedaer currently being parsed
7952          *
7953          * @access private
7954          * @var string
7955          */
7956         var $value = '';
7957
7958         /**
7959          * Create an instance of the class with the input data
7960          *
7961          * @access public
7962          * @param string $data Input data
7963          */
7964         function SimplePie_HTTP_Parser($data)
7965         {
7966                 $this->data = $data;
7967                 $this->data_length = strlen($this->data);
7968         }
7969
7970         /**
7971          * Parse the input data
7972          *
7973          * @access public
7974          * @return bool true on success, false on failure
7975          */
7976         function parse()
7977         {
7978                 while ($this->state && $this->state !== 'emit' && $this->has_data())
7979                 {
7980                         $state = $this->state;
7981                         $this->$state();
7982                 }
7983                 $this->data = '';
7984                 if ($this->state === 'emit' || $this->state === 'body')
7985                 {
7986                         return true;
7987                 }
7988                 else
7989                 {
7990                         $this->http_version = '';
7991                         $this->status_code = '';
7992                         $this->reason = '';
7993                         $this->headers = array();
7994                         $this->body = '';
7995                         return false;
7996                 }
7997         }
7998
7999         /**
8000          * Check whether there is data beyond the pointer
8001          *
8002          * @access private
8003          * @return bool true if there is further data, false if not
8004          */
8005         function has_data()
8006         {
8007                 return (bool) ($this->position < $this->data_length);
8008         }
8009
8010         /**
8011          * See if the next character is LWS
8012          *
8013          * @access private
8014          * @return bool true if the next character is LWS, false if not
8015          */
8016         function is_linear_whitespace()
8017         {
8018                 return (bool) ($this->data[$this->position] === "\x09"
8019                         || $this->data[$this->position] === "\x20"
8020                         || ($this->data[$this->position] === "\x0A"
8021                                 && isset($this->data[$this->position + 1])
8022                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8023         }
8024
8025         /**
8026          * Parse the HTTP version
8027          *
8028          * @access private
8029          */
8030         function http_version()
8031         {
8032                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8033                 {
8034                         $len = strspn($this->data, '0123456789.', 5);
8035                         $this->http_version = substr($this->data, 5, $len);
8036                         $this->position += 5 + $len;
8037                         if (substr_count($this->http_version, '.') <= 1)
8038                         {
8039                                 $this->http_version = (float) $this->http_version;
8040                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8041                                 $this->state = 'status';
8042                         }
8043                         else
8044                         {
8045                                 $this->state = false;
8046                         }
8047                 }
8048                 else
8049                 {
8050                         $this->state = false;
8051                 }
8052         }
8053
8054         /**
8055          * Parse the status code
8056          *
8057          * @access private
8058          */
8059         function status()
8060         {
8061                 if ($len = strspn($this->data, '0123456789', $this->position))
8062                 {
8063                         $this->status_code = (int) substr($this->data, $this->position, $len);
8064                         $this->position += $len;
8065                         $this->state = 'reason';
8066                 }
8067                 else
8068                 {
8069                         $this->state = false;
8070                 }
8071         }
8072
8073         /**
8074          * Parse the reason phrase
8075          *
8076          * @access private
8077          */
8078         function reason()
8079         {
8080                 $len = strcspn($this->data, "\x0A", $this->position);
8081                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8082                 $this->position += $len + 1;
8083                 $this->state = 'new_line';
8084         }
8085
8086         /**
8087          * Deal with a new line, shifting data around as needed
8088          *
8089          * @access private
8090          */
8091         function new_line()
8092         {
8093                 $this->value = trim($this->value, "\x0D\x20");
8094                 if ($this->name !== '' && $this->value !== '')
8095                 {
8096                         $this->name = strtolower($this->name);
8097                         if (isset($this->headers[$this->name]))
8098                         {
8099                                 $this->headers[$this->name] .= ', ' . $this->value;
8100                         }
8101                         else
8102                         {
8103                                 $this->headers[$this->name] = $this->value;
8104                         }
8105                 }
8106                 $this->name = '';
8107                 $this->value = '';
8108                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8109                 {
8110                         $this->position += 2;
8111                         $this->state = 'body';
8112                 }
8113                 elseif ($this->data[$this->position] === "\x0A")
8114                 {
8115                         $this->position++;
8116                         $this->state = 'body';
8117                 }
8118                 else
8119                 {
8120                         $this->state = 'name';
8121                 }
8122         }
8123
8124         /**
8125          * Parse a header name
8126          *
8127          * @access private
8128          */
8129         function name()
8130         {
8131                 $len = strcspn($this->data, "\x0A:", $this->position);
8132                 if (isset($this->data[$this->position + $len]))
8133                 {
8134                         if ($this->data[$this->position + $len] === "\x0A")
8135                         {
8136                                 $this->position += $len;
8137                                 $this->state = 'new_line';
8138                         }
8139                         else
8140                         {
8141                                 $this->name = substr($this->data, $this->position, $len);
8142                                 $this->position += $len + 1;
8143                                 $this->state = 'value';
8144                         }
8145                 }
8146                 else
8147                 {
8148                         $this->state = false;
8149                 }
8150         }
8151
8152         /**
8153          * Parse LWS, replacing consecutive LWS characters with a single space
8154          *
8155          * @access private
8156          */
8157         function linear_whitespace()
8158         {
8159                 do
8160                 {
8161                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8162                         {
8163                                 $this->position += 2;
8164                         }
8165                         elseif ($this->data[$this->position] === "\x0A")
8166                         {
8167                                 $this->position++;
8168                         }
8169                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8170                 } while ($this->has_data() && $this->is_linear_whitespace());
8171                 $this->value .= "\x20";
8172         }
8173
8174         /**
8175          * See what state to move to while within non-quoted header values
8176          *
8177          * @access private
8178          */
8179         function value()
8180         {
8181                 if ($this->is_linear_whitespace())
8182                 {
8183                         $this->linear_whitespace();
8184                 }
8185                 else
8186                 {
8187                         switch ($this->data[$this->position])
8188                         {
8189                                 case '"':
8190                                         $this->position++;
8191                                         $this->state = 'quote';
8192                                         break;
8193
8194                                 case "\x0A":
8195                                         $this->position++;
8196                                         $this->state = 'new_line';
8197                                         break;
8198
8199                                 default:
8200                                         $this->state = 'value_char';
8201                                         break;
8202                         }
8203                 }
8204         }
8205
8206         /**
8207          * Parse a header value while outside quotes
8208          *
8209          * @access private
8210          */
8211         function value_char()
8212         {
8213                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8214                 $this->value .= substr($this->data, $this->position, $len);
8215                 $this->position += $len;
8216                 $this->state = 'value';
8217         }
8218
8219         /**
8220          * See what state to move to while within quoted header values
8221          *
8222          * @access private
8223          */
8224         function quote()
8225         {
8226                 if ($this->is_linear_whitespace())
8227                 {
8228                         $this->linear_whitespace();
8229                 }
8230                 else
8231                 {
8232                         switch ($this->data[$this->position])
8233                         {
8234                                 case '"':
8235                                         $this->position++;
8236                                         $this->state = 'value';
8237                                         break;
8238
8239                                 case "\x0A":
8240                                         $this->position++;
8241                                         $this->state = 'new_line';
8242                                         break;
8243
8244                                 case '\\':
8245                                         $this->position++;
8246                                         $this->state = 'quote_escaped';
8247                                         break;
8248
8249                                 default:
8250                                         $this->state = 'quote_char';
8251                                         break;
8252                         }
8253                 }
8254         }
8255
8256         /**
8257          * Parse a header value while within quotes
8258          *
8259          * @access private
8260          */
8261         function quote_char()
8262         {
8263                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8264                 $this->value .= substr($this->data, $this->position, $len);
8265                 $this->position += $len;
8266                 $this->state = 'value';
8267         }
8268
8269         /**
8270          * Parse an escaped character within quotes
8271          *
8272          * @access private
8273          */
8274         function quote_escaped()
8275         {
8276                 $this->value .= $this->data[$this->position];
8277                 $this->position++;
8278                 $this->state = 'quote';
8279         }
8280
8281         /**
8282          * Parse the body
8283          *
8284          * @access private
8285          */
8286         function body()
8287         {
8288                 $this->body = substr($this->data, $this->position);
8289                 $this->state = 'emit';
8290         }
8291 }
8292
8293 /**
8294  * gzdecode
8295  *
8296  * @package SimplePie
8297  */
8298 class SimplePie_gzdecode
8299 {
8300         /**
8301          * Compressed data
8302          *
8303          * @access private
8304          * @see gzdecode::$data
8305          */
8306         var $compressed_data;
8307
8308         /**
8309          * Size of compressed data
8310          *
8311          * @access private
8312          */
8313         var $compressed_size;
8314
8315         /**
8316          * Minimum size of a valid gzip string
8317          *
8318          * @access private
8319          */
8320         var $min_compressed_size = 18;
8321
8322         /**
8323          * Current position of pointer
8324          *
8325          * @access private
8326          */
8327         var $position = 0;
8328
8329         /**
8330          * Flags (FLG)
8331          *
8332          * @access private
8333          */
8334         var $flags;
8335
8336         /**
8337          * Uncompressed data
8338          *
8339          * @access public
8340          * @see gzdecode::$compressed_data
8341          */
8342         var $data;
8343
8344         /**
8345          * Modified time
8346          *
8347          * @access public
8348          */
8349         var $MTIME;
8350
8351         /**
8352          * Extra Flags
8353          *
8354          * @access public
8355          */
8356         var $XFL;
8357
8358         /**
8359          * Operating System
8360          *
8361          * @access public
8362          */
8363         var $OS;
8364
8365         /**
8366          * Subfield ID 1
8367          *
8368          * @access public
8369          * @see gzdecode::$extra_field
8370          * @see gzdecode::$SI2
8371          */
8372         var $SI1;
8373
8374         /**
8375          * Subfield ID 2
8376          *
8377          * @access public
8378          * @see gzdecode::$extra_field
8379          * @see gzdecode::$SI1
8380          */
8381         var $SI2;
8382
8383         /**
8384          * Extra field content
8385          *
8386          * @access public
8387          * @see gzdecode::$SI1
8388          * @see gzdecode::$SI2
8389          */
8390         var $extra_field;
8391
8392         /**
8393          * Original filename
8394          *
8395          * @access public
8396          */
8397         var $filename;
8398
8399         /**
8400          * Human readable comment
8401          *
8402          * @access public
8403          */
8404         var $comment;
8405
8406         /**
8407          * Don't allow anything to be set
8408          *
8409          * @access public
8410          */
8411         function __set($name, $value)
8412         {
8413                 trigger_error("Cannot write property $name", E_USER_ERROR);
8414         }
8415
8416         /**
8417          * Set the compressed string and related properties
8418          *
8419          * @access public
8420          */
8421         function SimplePie_gzdecode($data)
8422         {
8423                 $this->compressed_data = $data;
8424                 $this->compressed_size = strlen($data);
8425         }
8426
8427         /**
8428          * Decode the GZIP stream
8429          *
8430          * @access public
8431          */
8432         function parse()
8433         {
8434                 if ($this->compressed_size >= $this->min_compressed_size)
8435                 {
8436                         // Check ID1, ID2, and CM
8437                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8438                         {
8439                                 return false;
8440                         }
8441
8442                         // Get the FLG (FLaGs)
8443                         $this->flags = ord($this->compressed_data[3]);
8444
8445                         // FLG bits above (1 << 4) are reserved
8446                         if ($this->flags > 0x1F)
8447                         {
8448                                 return false;
8449                         }
8450
8451                         // Advance the pointer after the above
8452                         $this->position += 4;
8453
8454                         // MTIME
8455                         $mtime = substr($this->compressed_data, $this->position, 4);
8456                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8457                         if (current(unpack('S', "\x00\x01")) === 1)
8458                         {
8459                                 $mtime = strrev($mtime);
8460                         }
8461                         $this->MTIME = current(unpack('l', $mtime));
8462                         $this->position += 4;
8463
8464                         // Get the XFL (eXtra FLags)
8465                         $this->XFL = ord($this->compressed_data[$this->position++]);
8466
8467                         // Get the OS (Operating System)
8468                         $this->OS = ord($this->compressed_data[$this->position++]);
8469
8470                         // Parse the FEXTRA
8471                         if ($this->flags & 4)
8472                         {
8473                                 // Read subfield IDs
8474                                 $this->SI1 = $this->compressed_data[$this->position++];
8475                                 $this->SI2 = $this->compressed_data[$this->position++];
8476
8477                                 // SI2 set to zero is reserved for future use
8478                                 if ($this->SI2 === "\x00")
8479                                 {
8480                                         return false;
8481                                 }
8482
8483                                 // Get the length of the extra field
8484                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8485                                 $position += 2;
8486
8487                                 // Check the length of the string is still valid
8488                                 $this->min_compressed_size += $len + 4;
8489                                 if ($this->compressed_size >= $this->min_compressed_size)
8490                                 {
8491                                         // Set the extra field to the given data
8492                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8493                                         $this->position += $len;
8494                                 }
8495                                 else
8496                                 {
8497                                         return false;
8498                                 }
8499                         }
8500
8501                         // Parse the FNAME
8502                         if ($this->flags & 8)
8503                         {
8504                                 // Get the length of the filename
8505                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8506
8507                                 // Check the length of the string is still valid
8508                                 $this->min_compressed_size += $len + 1;
8509                                 if ($this->compressed_size >= $this->min_compressed_size)
8510                                 {
8511                                         // Set the original filename to the given string
8512                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8513                                         $this->position += $len + 1;
8514                                 }
8515                                 else
8516                                 {
8517                                         return false;
8518                                 }
8519                         }
8520
8521                         // Parse the FCOMMENT
8522                         if ($this->flags & 16)
8523                         {
8524                                 // Get the length of the comment
8525                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8526
8527                                 // Check the length of the string is still valid
8528                                 $this->min_compressed_size += $len + 1;
8529                                 if ($this->compressed_size >= $this->min_compressed_size)
8530                                 {
8531                                         // Set the original comment to the given string
8532                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8533                                         $this->position += $len + 1;
8534                                 }
8535                                 else
8536                                 {
8537                                         return false;
8538                                 }
8539                         }
8540
8541                         // Parse the FHCRC
8542                         if ($this->flags & 2)
8543                         {
8544                                 // Check the length of the string is still valid
8545                                 $this->min_compressed_size += $len + 2;
8546                                 if ($this->compressed_size >= $this->min_compressed_size)
8547                                 {
8548                                         // Read the CRC
8549                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8550
8551                                         // Check the CRC matches
8552                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8553                                         {
8554                                                 $this->position += 2;
8555                                         }
8556                                         else
8557                                         {
8558                                                 return false;
8559                                         }
8560                                 }
8561                                 else
8562                                 {
8563                                         return false;
8564                                 }
8565                         }
8566
8567                         // Decompress the actual data
8568                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8569                         {
8570                                 return false;
8571                         }
8572                         else
8573                         {
8574                                 $this->position = $this->compressed_size - 8;
8575                         }
8576
8577                         // Check CRC of data
8578                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8579                         $this->position += 4;
8580                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8581                         {
8582                                 return false;
8583                         }*/
8584
8585                         // Check ISIZE of data
8586                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8587                         $this->position += 4;
8588                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8589                         {
8590                                 return false;
8591                         }
8592
8593                         // Wow, against all odds, we've actually got a valid gzip string
8594                         return true;
8595                 }
8596                 else
8597                 {
8598                         return false;
8599                 }
8600         }
8601 }
8602
8603 class SimplePie_Cache
8604 {
8605         /**
8606          * Don't call the constructor. Please.
8607          *
8608          * @access private
8609          */
8610         function SimplePie_Cache()
8611         {
8612                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8613         }
8614
8615         /**
8616          * Create a new SimplePie_Cache object
8617          *
8618          * @static
8619          * @access public
8620          */
8621         function create($location, $filename, $extension)
8622         {
8623                 $location_iri =& new SimplePie_IRI($location);
8624                 switch ($location_iri->get_scheme())
8625                 {
8626                         case 'mysql':
8627                                 if (extension_loaded('mysql'))
8628                                 {
8629                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8630                                 }
8631                                 break;
8632
8633                         default:
8634                                 return new SimplePie_Cache_File($location, $filename, $extension);
8635                 }
8636         }
8637 }
8638
8639 class SimplePie_Cache_File
8640 {
8641         var $location;
8642         var $filename;
8643         var $extension;
8644         var $name;
8645
8646         function SimplePie_Cache_File($location, $filename, $extension)
8647         {
8648                 $this->location = $location;
8649                 $this->filename = $filename;
8650                 $this->extension = $extension;
8651                 $this->name = "$this->location/$this->filename.$this->extension";
8652         }
8653
8654         function save($data)
8655         {
8656                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8657                 {
8658                         if (is_a($data, 'SimplePie'))
8659                         {
8660                                 $data = $data->data;
8661                         }
8662
8663                         $data = serialize($data);
8664
8665                         if (function_exists('file_put_contents'))
8666                         {
8667                                 return (bool) file_put_contents($this->name, $data);
8668                         }
8669                         else
8670                         {
8671                                 $fp = fopen($this->name, 'wb');
8672                                 if ($fp)
8673                                 {
8674                                         fwrite($fp, $data);
8675                                         fclose($fp);
8676                                         return true;
8677                                 }
8678                         }
8679                 }
8680                 return false;
8681         }
8682
8683         function load()
8684         {
8685                 if (file_exists($this->name) && is_readable($this->name))
8686                 {
8687                         return unserialize(file_get_contents($this->name));
8688                 }
8689                 return false;
8690         }
8691
8692         function mtime()
8693         {
8694                 if (file_exists($this->name))
8695                 {
8696                         return filemtime($this->name);
8697                 }
8698                 return false;
8699         }
8700
8701         function touch()
8702         {
8703                 if (file_exists($this->name))
8704                 {
8705                         return touch($this->name);
8706                 }
8707                 return false;
8708         }
8709
8710         function unlink()
8711         {
8712                 if (file_exists($this->name))
8713                 {
8714                         return unlink($this->name);
8715                 }
8716                 return false;
8717         }
8718 }
8719
8720 class SimplePie_Cache_DB
8721 {
8722         function prepare_simplepie_object_for_cache($data)
8723         {
8724                 $items = $data->get_items();
8725                 $items_by_id = array();
8726
8727                 if (!empty($items))
8728                 {
8729                         foreach ($items as $item)
8730                         {
8731                                 $items_by_id[$item->get_id()] = $item;
8732                         }
8733
8734                         if (count($items_by_id) !== count($items))
8735                         {
8736                                 $items_by_id = array();
8737                                 foreach ($items as $item)
8738                                 {
8739                                         $items_by_id[$item->get_id(true)] = $item;
8740                                 }
8741                         }
8742
8743                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8744                         {
8745                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8746                         }
8747                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8748                         {
8749                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8750                         }
8751                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8752                         {
8753                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8754                         }
8755                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8756                         {
8757                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8758                         }
8759                         else
8760                         {
8761                                 $channel = null;
8762                         }
8763
8764                         if ($channel !== null)
8765                         {
8766                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8767                                 {
8768                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8769                                 }
8770                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8771                                 {
8772                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8773                                 }
8774                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8775                                 {
8776                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8777                                 }
8778                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8779                                 {
8780                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8781                                 }
8782                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8783                                 {
8784                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8785                                 }
8786                         }
8787                         if (isset($data->data['items']))
8788                         {
8789                                 unset($data->data['items']);
8790                         }
8791                         if (isset($data->data['ordered_items']))
8792                         {
8793                                 unset($data->data['ordered_items']);
8794                         }
8795                 }
8796                 return array(serialize($data->data), $items_by_id);
8797         }
8798 }
8799
8800 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8801 {
8802         var $mysql;
8803         var $options;
8804         var $id;
8805
8806         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8807         {
8808                 $host = $mysql_location->get_host();
8809                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8810                 {
8811                         $server = ':' . substr($host, 5, -1);
8812                 }
8813                 else
8814                 {
8815                         $server = $host;
8816                         if ($mysql_location->get_port() !== null)
8817                         {
8818                                 $server .= ':' . $mysql_location->get_port();
8819                         }
8820                 }
8821
8822                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8823                 {
8824                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8825                 }
8826                 else
8827                 {
8828                         $username = $mysql_location->get_userinfo();
8829                         $password = null;
8830                 }
8831
8832                 if ($this->mysql = mysql_connect($server, $username, $password))
8833                 {
8834                         $this->id = $name . $extension;
8835                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8836                         if (!isset($this->options['prefix'][0]))
8837                         {
8838                                 $this->options['prefix'][0] = '';
8839                         }
8840
8841                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8842                                 && mysql_query('SET NAMES utf8')
8843                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8844                         {
8845                                 $db = array();
8846                                 while ($row = mysql_fetch_row($query))
8847                                 {
8848                                         $db[] = $row[0];
8849                                 }
8850
8851                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8852                                 {
8853                                         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)))'))
8854                                         {
8855                                                 $this->mysql = null;
8856                                         }
8857                                 }
8858
8859                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8860                                 {
8861                                         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)))'))
8862                                         {
8863                                                 $this->mysql = null;
8864                                         }
8865                                 }
8866                         }
8867                         else
8868                         {
8869                                 $this->mysql = null;
8870                         }
8871                 }
8872         }
8873
8874         function save($data)
8875         {
8876                 if ($this->mysql)
8877                 {
8878                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8879
8880                         if (is_a($data, 'SimplePie'))
8881                         {
8882                                 if (SIMPLEPIE_PHP5)
8883                                 {
8884                                         // This keyword needs to defy coding standards for PHP4 compatibility
8885                                         $data = clone($data);
8886                                 }
8887
8888                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
8889
8890                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8891                                 {
8892                                         if (mysql_num_rows($query))
8893                                         {
8894                                                 $items = count($prepared[1]);
8895                                                 if ($items)
8896                                                 {
8897                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8898                                                 }
8899                                                 else
8900                                                 {
8901                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8902                                                 }
8903
8904                                                 if (!mysql_query($sql, $this->mysql))
8905                                                 {
8906                                                         return false;
8907                                                 }
8908                                         }
8909                                         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))
8910                                         {
8911                                                 return false;
8912                                         }
8913
8914                                         $ids = array_keys($prepared[1]);
8915                                         if (!empty($ids))
8916                                         {
8917                                                 foreach ($ids as $id)
8918                                                 {
8919                                                         $database_ids[] = mysql_real_escape_string($id);
8920                                                 }
8921
8922                                                 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))
8923                                                 {
8924                                                         $existing_ids = array();
8925                                                         while ($row = mysql_fetch_row($query))
8926                                                         {
8927                                                                 $existing_ids[] = $row[0];
8928                                                         }
8929
8930                                                         $new_ids = array_diff($ids, $existing_ids);
8931
8932                                                         foreach ($new_ids as $new_id)
8933                                                         {
8934                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
8935                                                                 {
8936                                                                         $date = time();
8937                                                                 }
8938
8939                                                                 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))
8940                                                                 {
8941                                                                         return false;
8942                                                                 }
8943                                                         }
8944                                                         return true;
8945                                                 }
8946                                         }
8947                                         else
8948                                         {
8949                                                 return true;
8950                                         }
8951                                 }
8952                         }
8953                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8954                         {
8955                                 if (mysql_num_rows($query))
8956                                 {
8957                                         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))
8958                                         {
8959                                                 return true;
8960                                         }
8961                                 }
8962                                 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))
8963                                 {
8964                                         return true;
8965                                 }
8966                         }
8967                 }
8968                 return false;
8969         }
8970
8971         function load()
8972         {
8973                 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)))
8974                 {
8975                         $data = unserialize($row[1]);
8976
8977                         if (isset($this->options['items'][0]))
8978                         {
8979                                 $items = (int) $this->options['items'][0];
8980                         }
8981                         else
8982                         {
8983                                 $items = (int) $row[0];
8984                         }
8985
8986                         if ($items !== 0)
8987                         {
8988                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8989                                 {
8990                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8991                                 }
8992                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8993                                 {
8994                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8995                                 }
8996                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8997                                 {
8998                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8999                                 }
9000                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9001                                 {
9002                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9003                                 }
9004                                 else
9005                                 {
9006                                         $feed = null;
9007                                 }
9008
9009                                 if ($feed !== null)
9010                                 {
9011                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9012                                         if ($items > 0)
9013                                         {
9014                                                 $sql .= ' LIMIT ' . $items;
9015                                         }
9016
9017                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9018                                         {
9019                                                 while ($row = mysql_fetch_row($query))
9020                                                 {
9021                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9022                                                 }
9023                                         }
9024                                         else
9025                                         {
9026                                                 return false;
9027                                         }
9028                                 }
9029                         }
9030                         return $data;
9031                 }
9032                 return false;
9033         }
9034
9035         function mtime()
9036         {
9037                 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)))
9038                 {
9039                         return $row[0];
9040                 }
9041                 else
9042                 {
9043                         return false;
9044                 }
9045         }
9046
9047         function touch()
9048         {
9049                 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))
9050                 {
9051                         return true;
9052                 }
9053                 else
9054                 {
9055                         return false;
9056                 }
9057         }
9058
9059         function unlink()
9060         {
9061                 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)))
9062                 {
9063                         return true;
9064                 }
9065                 else
9066                 {
9067                         return false;
9068                 }
9069         }
9070 }
9071
9072 class SimplePie_Misc
9073 {
9074         function time_hms($seconds)
9075         {
9076                 $time = '';
9077
9078                 $hours = floor($seconds / 3600);
9079                 $remainder = $seconds % 3600;
9080                 if ($hours > 0)
9081                 {
9082                         $time .= $hours.':';
9083                 }
9084
9085                 $minutes = floor($remainder / 60);
9086                 $seconds = $remainder % 60;
9087                 if ($minutes < 10 && $hours > 0)
9088                 {
9089                         $minutes = '0' . $minutes;
9090                 }
9091                 if ($seconds < 10)
9092                 {
9093                         $seconds = '0' . $seconds;
9094                 }
9095
9096                 $time .= $minutes.':';
9097                 $time .= $seconds;
9098
9099                 return $time;
9100         }
9101
9102         function absolutize_url($relative, $base)
9103         {
9104                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9105                 return $iri->get_iri();
9106         }
9107
9108         function remove_dot_segments($input)
9109         {
9110                 $output = '';
9111                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9112                 {
9113                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9114                         if (strpos($input, '../') === 0)
9115                         {
9116                                 $input = substr($input, 3);
9117                         }
9118                         elseif (strpos($input, './') === 0)
9119                         {
9120                                 $input = substr($input, 2);
9121                         }
9122                         // 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,
9123                         elseif (strpos($input, '/./') === 0)
9124                         {
9125                                 $input = substr_replace($input, '/', 0, 3);
9126                         }
9127                         elseif ($input === '/.')
9128                         {
9129                                 $input = '/';
9130                         }
9131                         // 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,
9132                         elseif (strpos($input, '/../') === 0)
9133                         {
9134                                 $input = substr_replace($input, '/', 0, 4);
9135                                 $output = substr_replace($output, '', strrpos($output, '/'));
9136                         }
9137                         elseif ($input === '/..')
9138                         {
9139                                 $input = '/';
9140                                 $output = substr_replace($output, '', strrpos($output, '/'));
9141                         }
9142                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9143                         elseif ($input === '.' || $input === '..')
9144                         {
9145                                 $input = '';
9146                         }
9147                         // 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
9148                         elseif (($pos = strpos($input, '/', 1)) !== false)
9149                         {
9150                                 $output .= substr($input, 0, $pos);
9151                                 $input = substr_replace($input, '', 0, $pos);
9152                         }
9153                         else
9154                         {
9155                                 $output .= $input;
9156                                 $input = '';
9157                         }
9158                 }
9159                 return $output . $input;
9160         }
9161
9162         function get_element($realname, $string)
9163         {
9164                 $return = array();
9165                 $name = preg_quote($realname, '/');
9166                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9167                 {
9168                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9169                         {
9170                                 $return[$i]['tag'] = $realname;
9171                                 $return[$i]['full'] = $matches[$i][0][0];
9172                                 $return[$i]['offset'] = $matches[$i][0][1];
9173                                 if (strlen($matches[$i][3][0]) <= 2)
9174                                 {
9175                                         $return[$i]['self_closing'] = true;
9176                                 }
9177                                 else
9178                                 {
9179                                         $return[$i]['self_closing'] = false;
9180                                         $return[$i]['content'] = $matches[$i][4][0];
9181                                 }
9182                                 $return[$i]['attribs'] = array();
9183                                 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))
9184                                 {
9185                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9186                                         {
9187                                                 if (count($attribs[$j]) === 2)
9188                                                 {
9189                                                         $attribs[$j][2] = $attribs[$j][1];
9190                                                 }
9191                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9192                                         }
9193                                 }
9194                         }
9195                 }
9196                 return $return;
9197         }
9198
9199         function element_implode($element)
9200         {
9201                 $full = "<$element[tag]";
9202                 foreach ($element['attribs'] as $key => $value)
9203                 {
9204                         $key = strtolower($key);
9205                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9206                 }
9207                 if ($element['self_closing'])
9208                 {
9209                         $full .= ' />';
9210                 }
9211                 else
9212                 {
9213                         $full .= ">$element[content]</$element[tag]>";
9214                 }
9215                 return $full;
9216         }
9217
9218         function error($message, $level, $file, $line)
9219         {
9220                 if ((ini_get('error_reporting') & $level) > 0)
9221                 {
9222                         switch ($level)
9223                         {
9224                                 case E_USER_ERROR:
9225                                         $note = 'PHP Error';
9226                                         break;
9227                                 case E_USER_WARNING:
9228                                         $note = 'PHP Warning';
9229                                         break;
9230                                 case E_USER_NOTICE:
9231                                         $note = 'PHP Notice';
9232                                         break;
9233                                 default:
9234                                         $note = 'Unknown Error';
9235                                         break;
9236                         }
9237                         error_log("$note: $message in $file on line $line", 0);
9238                 }
9239                 return $message;
9240         }
9241
9242         /**
9243          * If a file has been cached, retrieve and display it.
9244          *
9245          * This is most useful for caching images (get_favicon(), etc.),
9246          * however it works for all cached files.  This WILL NOT display ANY
9247          * file/image/page/whatever, but rather only display what has already
9248          * been cached by SimplePie.
9249          *
9250          * @access public
9251          * @see SimplePie::get_favicon()
9252          * @param str $identifier_url URL that is used to identify the content.
9253          * This may or may not be the actual URL of the live content.
9254          * @param str $cache_location Location of SimplePie's cache.  Defaults
9255          * to './cache'.
9256          * @param str $cache_extension The file extension that the file was
9257          * cached with.  Defaults to 'spc'.
9258          * @param str $cache_class Name of the cache-handling class being used
9259          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9260          * as-is unless you've overloaded the class.
9261          * @param str $cache_name_function Obsolete. Exists for backwards
9262          * compatibility reasons only.
9263          */
9264         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9265         {
9266                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9267
9268                 if ($file = $cache->load())
9269                 {
9270                         if (isset($file['headers']['content-type']))
9271                         {
9272                                 header('Content-type:' . $file['headers']['content-type']);
9273                         }
9274                         else
9275                         {
9276                                 header('Content-type: application/octet-stream');
9277                         }
9278                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9279                         echo $file['body'];
9280                         exit;
9281                 }
9282
9283                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9284         }
9285
9286         function fix_protocol($url, $http = 1)
9287         {
9288                 $url = SimplePie_Misc::normalize_url($url);
9289                 $parsed = SimplePie_Misc::parse_url($url);
9290                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9291                 {
9292                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9293                 }
9294
9295                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9296                 {
9297                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9298                 }
9299
9300                 if ($http === 2 && $parsed['scheme'] !== '')
9301                 {
9302                         return "feed:$url";
9303                 }
9304                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9305                 {
9306                         return substr_replace($url, 'podcast', 0, 4);
9307                 }
9308                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9309                 {
9310                         return substr_replace($url, 'itpc', 0, 4);
9311                 }
9312                 else
9313                 {
9314                         return $url;
9315                 }
9316         }
9317
9318         function parse_url($url)
9319         {
9320                 $iri =& new SimplePie_IRI($url);
9321                 return array(
9322                         'scheme' => (string) $iri->get_scheme(),
9323                         'authority' => (string) $iri->get_authority(),
9324                         'path' => (string) $iri->get_path(),
9325                         'query' => (string) $iri->get_query(),
9326                         'fragment' => (string) $iri->get_fragment()
9327                 );
9328         }
9329
9330         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9331         {
9332                 $iri =& new SimplePie_IRI('');
9333                 $iri->set_scheme($scheme);
9334                 $iri->set_authority($authority);
9335                 $iri->set_path($path);
9336                 $iri->set_query($query);
9337                 $iri->set_fragment($fragment);
9338                 return $iri->get_iri();
9339         }
9340
9341         function normalize_url($url)
9342         {
9343                 $iri =& new SimplePie_IRI($url);
9344                 return $iri->get_iri();
9345         }
9346
9347         function percent_encoding_normalization($match)
9348         {
9349                 $integer = hexdec($match[1]);
9350                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9351                 {
9352                         return chr($integer);
9353                 }
9354                 else
9355                 {
9356                         return strtoupper($match[0]);
9357                 }
9358         }
9359
9360         /**
9361          * Remove bad UTF-8 bytes
9362          *
9363          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9364          * FAQ: Multilingual Forms (modified to include full ASCII range)
9365          *
9366          * @author Geoffrey Sneddon
9367          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9368          * @param string $str String to remove bad UTF-8 bytes from
9369          * @return string UTF-8 string
9370          */
9371         function utf8_bad_replace($str)
9372         {
9373                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9374                 {
9375                         return $return;
9376                 }
9377                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9378                 {
9379                         return $return;
9380                 }
9381                 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))
9382                 {
9383                         return implode("\xEF\xBF\xBD", $matches[0]);
9384                 }
9385                 elseif ($str !== '')
9386                 {
9387                         return "\xEF\xBF\xBD";
9388                 }
9389                 else
9390                 {
9391                         return '';
9392                 }
9393         }
9394
9395         /**
9396          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9397          *
9398          * @static
9399          * @access public
9400          * @param string $string Windows-1252 encoded string
9401          * @return string UTF-8 encoded string
9402          */
9403         function windows_1252_to_utf8($string)
9404         {
9405                 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");
9406
9407                 return strtr($string, $convert_table);
9408         }
9409
9410         function change_encoding($data, $input, $output)
9411         {
9412                 $input = SimplePie_Misc::encoding($input);
9413                 $output = SimplePie_Misc::encoding($output);
9414
9415                 // We fail to fail on non US-ASCII bytes
9416                 if ($input === 'US-ASCII')
9417                 {
9418                         static $non_ascii_octects = '';
9419                         if (!$non_ascii_octects)
9420                         {
9421                                 for ($i = 0x80; $i <= 0xFF; $i++)
9422                                 {
9423                                         $non_ascii_octects .= chr($i);
9424                                 }
9425                         }
9426                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9427                 }
9428
9429                 // This is first, as behaviour of this is completely predictable
9430                 if ($input === 'windows-1252' && $output === 'UTF-8')
9431                 {
9432                         return SimplePie_Misc::windows_1252_to_utf8($data);
9433                 }
9434                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9435                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9436                 {
9437                         return $return;
9438                 }
9439                 // This is last, as behaviour of this varies with OS userland and PHP version
9440                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9441                 {
9442                         return $return;
9443                 }
9444                 // If we can't do anything, just fail
9445                 else
9446                 {
9447                         return false;
9448                 }
9449         }
9450
9451         function encoding($charset)
9452         {
9453                 // Normalization from UTS #22
9454                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9455                 {
9456                         case 'adobestandardencoding':
9457                         case 'csadobestandardencoding':
9458                                 return 'Adobe-Standard-Encoding';
9459
9460                         case 'adobesymbolencoding':
9461                         case 'cshppsmath':
9462                                 return 'Adobe-Symbol-Encoding';
9463
9464                         case 'ami1251':
9465                         case 'amiga1251':
9466                                 return 'Amiga-1251';
9467
9468                         case 'ansix31101983':
9469                         case 'csat5001983':
9470                         case 'csiso99naplps':
9471                         case 'isoir99':
9472                         case 'naplps':
9473                                 return 'ANSI_X3.110-1983';
9474
9475                         case 'arabic7':
9476                         case 'asmo449':
9477                         case 'csiso89asmo449':
9478                         case 'iso9036':
9479                         case 'isoir89':
9480                                 return 'ASMO_449';
9481
9482                         case 'big5':
9483                         case 'csbig5':
9484                         case 'xxbig5':
9485                                 return 'Big5';
9486
9487                         case 'big5hkscs':
9488                                 return 'Big5-HKSCS';
9489
9490                         case 'bocu1':
9491                         case 'csbocu1':
9492                                 return 'BOCU-1';
9493
9494                         case 'brf':
9495                         case 'csbrf':
9496                                 return 'BRF';
9497
9498                         case 'bs4730':
9499                         case 'csiso4unitedkingdom':
9500                         case 'gb':
9501                         case 'iso646gb':
9502                         case 'isoir4':
9503                         case 'uk':
9504                                 return 'BS_4730';
9505
9506                         case 'bsviewdata':
9507                         case 'csiso47bsviewdata':
9508                         case 'isoir47':
9509                                 return 'BS_viewdata';
9510
9511                         case 'cesu8':
9512                         case 'cscesu8':
9513                                 return 'CESU-8';
9514
9515                         case 'ca':
9516                         case 'csa71':
9517                         case 'csaz243419851':
9518                         case 'csiso121canadian1':
9519                         case 'iso646ca':
9520                         case 'isoir121':
9521                                 return 'CSA_Z243.4-1985-1';
9522
9523                         case 'csa72':
9524                         case 'csaz243419852':
9525                         case 'csiso122canadian2':
9526                         case 'iso646ca2':
9527                         case 'isoir122':
9528                                 return 'CSA_Z243.4-1985-2';
9529
9530                         case 'csaz24341985gr':
9531                         case 'csiso123csaz24341985gr':
9532                         case 'isoir123':
9533                                 return 'CSA_Z243.4-1985-gr';
9534
9535                         case 'csiso139csn369103':
9536                         case 'csn369103':
9537                         case 'isoir139':
9538                                 return 'CSN_369103';
9539
9540                         case 'csdecmcs':
9541                         case 'dec':
9542                         case 'decmcs':
9543                                 return 'DEC-MCS';
9544
9545                         case 'csiso21german':
9546                         case 'de':
9547                         case 'din66003':
9548                         case 'iso646de':
9549                         case 'isoir21':
9550                                 return 'DIN_66003';
9551
9552                         case 'csdkus':
9553                         case 'dkus':
9554                                 return 'dk-us';
9555
9556                         case 'csiso646danish':
9557                         case 'dk':
9558                         case 'ds2089':
9559                         case 'iso646dk':
9560                                 return 'DS_2089';
9561
9562                         case 'csibmebcdicatde':
9563                         case 'ebcdicatde':
9564                                 return 'EBCDIC-AT-DE';
9565
9566                         case 'csebcdicatdea':
9567                         case 'ebcdicatdea':
9568                                 return 'EBCDIC-AT-DE-A';
9569
9570                         case 'csebcdiccafr':
9571                         case 'ebcdiccafr':
9572                                 return 'EBCDIC-CA-FR';
9573
9574                         case 'csebcdicdkno':
9575                         case 'ebcdicdkno':
9576                                 return 'EBCDIC-DK-NO';
9577
9578                         case 'csebcdicdknoa':
9579                         case 'ebcdicdknoa':
9580                                 return 'EBCDIC-DK-NO-A';
9581
9582                         case 'csebcdices':
9583                         case 'ebcdices':
9584                                 return 'EBCDIC-ES';
9585
9586                         case 'csebcdicesa':
9587                         case 'ebcdicesa':
9588                                 return 'EBCDIC-ES-A';
9589
9590                         case 'csebcdicess':
9591                         case 'ebcdicess':
9592                                 return 'EBCDIC-ES-S';
9593
9594                         case 'csebcdicfise':
9595                         case 'ebcdicfise':
9596                                 return 'EBCDIC-FI-SE';
9597
9598                         case 'csebcdicfisea':
9599                         case 'ebcdicfisea':
9600                                 return 'EBCDIC-FI-SE-A';
9601
9602                         case 'csebcdicfr':
9603                         case 'ebcdicfr':
9604                                 return 'EBCDIC-FR';
9605
9606                         case 'csebcdicit':
9607                         case 'ebcdicit':
9608                                 return 'EBCDIC-IT';
9609
9610                         case 'csebcdicpt':
9611                         case 'ebcdicpt':
9612                                 return 'EBCDIC-PT';
9613
9614                         case 'csebcdicuk':
9615                         case 'ebcdicuk':
9616                                 return 'EBCDIC-UK';
9617
9618                         case 'csebcdicus':
9619                         case 'ebcdicus':
9620                                 return 'EBCDIC-US';
9621
9622                         case 'csiso111ecmacyrillic':
9623                         case 'ecmacyrillic':
9624                         case 'isoir111':
9625                         case 'koi8e':
9626                                 return 'ECMA-cyrillic';
9627
9628                         case 'csiso17spanish':
9629                         case 'es':
9630                         case 'iso646es':
9631                         case 'isoir17':
9632                                 return 'ES';
9633
9634                         case 'csiso85spanish2':
9635                         case 'es2':
9636                         case 'iso646es2':
9637                         case 'isoir85':
9638                                 return 'ES2';
9639
9640                         case 'cseucfixwidjapanese':
9641                         case 'extendedunixcodefixedwidthforjapanese':
9642                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9643
9644                         case 'cseucpkdfmtjapanese':
9645                         case 'eucjp':
9646                         case 'extendedunixcodepackedformatforjapanese':
9647                                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9648
9649                         case 'gb18030':
9650                                 return 'GB18030';
9651
9652                         case 'chinese':
9653                         case 'cp936':
9654                         case 'csgb2312':
9655                         case 'csiso58gb231280':
9656                         case 'gb2312':
9657                         case 'gb231280':
9658                         case 'gbk':
9659                         case 'isoir58':
9660                         case 'ms936':
9661                         case 'windows936':
9662                                 return 'GBK';
9663
9664                         case 'cn':
9665                         case 'csiso57gb1988':
9666                         case 'gb198880':
9667                         case 'iso646cn':
9668                         case 'isoir57':
9669                                 return 'GB_1988-80';
9670
9671                         case 'csiso153gost1976874':
9672                         case 'gost1976874':
9673                         case 'isoir153':
9674                         case 'stsev35888':
9675                                 return 'GOST_19768-74';
9676
9677                         case 'csiso150':
9678                         case 'csiso150greekccitt':
9679                         case 'greekccitt':
9680                         case 'isoir150':
9681                                 return 'greek-ccitt';
9682
9683                         case 'csiso88greek7':
9684                         case 'greek7':
9685                         case 'isoir88':
9686                                 return 'greek7';
9687
9688                         case 'csiso18greek7old':
9689                         case 'greek7old':
9690                         case 'isoir18':
9691                                 return 'greek7-old';
9692
9693                         case 'cshpdesktop':
9694                         case 'hpdesktop':
9695                                 return 'HP-DeskTop';
9696
9697                         case 'cshplegal':
9698                         case 'hplegal':
9699                                 return 'HP-Legal';
9700
9701                         case 'cshpmath8':
9702                         case 'hpmath8':
9703                                 return 'HP-Math8';
9704
9705                         case 'cshppifont':
9706                         case 'hppifont':
9707                                 return 'HP-Pi-font';
9708
9709                         case 'cshproman8':
9710                         case 'hproman8':
9711                         case 'r8':
9712                         case 'roman8':
9713                                 return 'hp-roman8';
9714
9715                         case 'hzgb2312':
9716                                 return 'HZ-GB-2312';
9717
9718                         case 'csibmsymbols':
9719                         case 'ibmsymbols':
9720                                 return 'IBM-Symbols';
9721
9722                         case 'csibmthai':
9723                         case 'ibmthai':
9724                                 return 'IBM-Thai';
9725
9726                         case 'ccsid858':
9727                         case 'cp858':
9728                         case 'ibm858':
9729                         case 'pcmultilingual850euro':
9730                                 return 'IBM00858';
9731
9732                         case 'ccsid924':
9733                         case 'cp924':
9734                         case 'ebcdiclatin9euro':
9735                         case 'ibm924':
9736                                 return 'IBM00924';
9737
9738                         case 'ccsid1140':
9739                         case 'cp1140':
9740                         case 'ebcdicus37euro':
9741                         case 'ibm1140':
9742                                 return 'IBM01140';
9743
9744                         case 'ccsid1141':
9745                         case 'cp1141':
9746                         case 'ebcdicde273euro':
9747                         case 'ibm1141':
9748                                 return 'IBM01141';
9749
9750                         case 'ccsid1142':
9751                         case 'cp1142':
9752                         case 'ebcdicdk277euro':
9753                         case 'ebcdicno277euro':
9754                         case 'ibm1142':
9755                                 return 'IBM01142';
9756
9757                         case 'ccsid1143':
9758                         case 'cp1143':
9759                         case 'ebcdicfi278euro':
9760                         case 'ebcdicse278euro':
9761                         case 'ibm1143':
9762                                 return 'IBM01143';
9763
9764                         case 'ccsid1144':
9765                         case 'cp1144':
9766                         case 'ebcdicit280euro':
9767                         case 'ibm1144':
9768                                 return 'IBM01144';
9769
9770                         case 'ccsid1145':
9771                         case 'cp1145':
9772                         case 'ebcdices284euro':
9773                         case 'ibm1145':
9774                                 return 'IBM01145';
9775
9776                         case 'ccsid1146':
9777                         case 'cp1146':
9778                         case 'ebcdicgb285euro':
9779                         case 'ibm1146':
9780                                 return 'IBM01146';
9781
9782                         case 'ccsid1147':
9783                         case 'cp1147':
9784                         case 'ebcdicfr297euro':
9785                         case 'ibm1147':
9786                                 return 'IBM01147';
9787
9788                         case 'ccsid1148':
9789                         case 'cp1148':
9790                         case 'ebcdicinternational500euro':
9791                         case 'ibm1148':
9792                                 return 'IBM01148';
9793
9794                         case 'ccsid1149':
9795                         case 'cp1149':
9796                         case 'ebcdicis871euro':
9797                         case 'ibm1149':
9798                                 return 'IBM01149';
9799
9800                         case 'cp37':
9801                         case 'csibm37':
9802                         case 'ebcdiccpca':
9803                         case 'ebcdiccpnl':
9804                         case 'ebcdiccpus':
9805                         case 'ebcdiccpwt':
9806                         case 'ibm37':
9807                                 return 'IBM037';
9808
9809                         case 'cp38':
9810                         case 'csibm38':
9811                         case 'ebcdicint':
9812                         case 'ibm38':
9813                                 return 'IBM038';
9814
9815                         case 'cp273':
9816                         case 'csibm273':
9817                         case 'ibm273':
9818                                 return 'IBM273';
9819
9820                         case 'cp274':
9821                         case 'csibm274':
9822                         case 'ebcdicbe':
9823                         case 'ibm274':
9824                                 return 'IBM274';
9825
9826                         case 'cp275':
9827                         case 'csibm275':
9828                         case 'ebcdicbr':
9829                         case 'ibm275':
9830                                 return 'IBM275';
9831
9832                         case 'csibm277':
9833                         case 'ebcdiccpdk':
9834                         case 'ebcdiccpno':
9835                         case 'ibm277':
9836                                 return 'IBM277';
9837
9838                         case 'cp278':
9839                         case 'csibm278':
9840                         case 'ebcdiccpfi':
9841                         case 'ebcdiccpse':
9842                         case 'ibm278':
9843                                 return 'IBM278';
9844
9845                         case 'cp280':
9846                         case 'csibm280':
9847                         case 'ebcdiccpit':
9848                         case 'ibm280':
9849                                 return 'IBM280';
9850
9851                         case 'cp281':
9852                         case 'csibm281':
9853                         case 'ebcdicjpe':
9854                         case 'ibm281':
9855                                 return 'IBM281';
9856
9857                         case 'cp284':
9858                         case 'csibm284':
9859                         case 'ebcdiccpes':
9860                         case 'ibm284':
9861                                 return 'IBM284';
9862
9863                         case 'cp285':
9864                         case 'csibm285':
9865                         case 'ebcdiccpgb':
9866                         case 'ibm285':
9867                                 return 'IBM285';
9868
9869                         case 'cp290':
9870                         case 'csibm290':
9871                         case 'ebcdicjpkana':
9872                         case 'ibm290':
9873                                 return 'IBM290';
9874
9875                         case 'cp297':
9876                         case 'csibm297':
9877                         case 'ebcdiccpfr':
9878                         case 'ibm297':
9879                                 return 'IBM297';
9880
9881                         case 'cp420':
9882                         case 'csibm420':
9883                         case 'ebcdiccpar1':
9884                         case 'ibm420':
9885                                 return 'IBM420';
9886
9887                         case 'cp423':
9888                         case 'csibm423':
9889                         case 'ebcdiccpgr':
9890                         case 'ibm423':
9891                                 return 'IBM423';
9892
9893                         case 'cp424':
9894                         case 'csibm424':
9895                         case 'ebcdiccphe':
9896                         case 'ibm424':
9897                                 return 'IBM424';
9898
9899                         case '437':
9900                         case 'cp437':
9901                         case 'cspc8codepage437':
9902                         case 'ibm437':
9903                                 return 'IBM437';
9904
9905                         case 'cp500':
9906                         case 'csibm500':
9907                         case 'ebcdiccpbe':
9908                         case 'ebcdiccpch':
9909                         case 'ibm500':
9910                                 return 'IBM500';
9911
9912                         case 'cp775':
9913                         case 'cspc775baltic':
9914                         case 'ibm775':
9915                                 return 'IBM775';
9916
9917                         case '850':
9918                         case 'cp850':
9919                         case 'cspc850multilingual':
9920                         case 'ibm850':
9921                                 return 'IBM850';
9922
9923                         case '851':
9924                         case 'cp851':
9925                         case 'csibm851':
9926                         case 'ibm851':
9927                                 return 'IBM851';
9928
9929                         case '852':
9930                         case 'cp852':
9931                         case 'cspcp852':
9932                         case 'ibm852':
9933                                 return 'IBM852';
9934
9935                         case '855':
9936                         case 'cp855':
9937                         case 'csibm855':
9938                         case 'ibm855':
9939                                 return 'IBM855';
9940
9941                         case '857':
9942                         case 'cp857':
9943                         case 'csibm857':
9944                         case 'ibm857':
9945                                 return 'IBM857';
9946
9947                         case '860':
9948                         case 'cp860':
9949                         case 'csibm860':
9950                         case 'ibm860':
9951                                 return 'IBM860';
9952
9953                         case '861':
9954                         case 'cp861':
9955                         case 'cpis':
9956                         case 'csibm861':
9957                         case 'ibm861':
9958                                 return 'IBM861';
9959
9960                         case '862':
9961                         case 'cp862':
9962                         case 'cspc862latinhebrew':
9963                         case 'ibm862':
9964                                 return 'IBM862';
9965
9966                         case '863':
9967                         case 'cp863':
9968                         case 'csibm863':
9969                         case 'ibm863':
9970                                 return 'IBM863';
9971
9972                         case 'cp864':
9973                         case 'csibm864':
9974                         case 'ibm864':
9975                                 return 'IBM864';
9976
9977                         case '865':
9978                         case 'cp865':
9979                         case 'csibm865':
9980                         case 'ibm865':
9981                                 return 'IBM865';
9982
9983                         case '866':
9984                         case 'cp866':
9985                         case 'csibm866':
9986                         case 'ibm866':
9987                                 return 'IBM866';
9988
9989                         case 'cp868':
9990                         case 'cpar':
9991                         case 'csibm868':
9992                         case 'ibm868':
9993                                 return 'IBM868';
9994
9995                         case '869':
9996                         case 'cp869':
9997                         case 'cpgr':
9998                         case 'csibm869':
9999                         case 'ibm869':
10000                                 return 'IBM869';
10001
10002                         case 'cp870':
10003                         case 'csibm870':
10004                         case 'ebcdiccproece':
10005                         case 'ebcdiccpyu':
10006                         case 'ibm870':
10007                                 return 'IBM870';
10008
10009                         case 'cp871':
10010                         case 'csibm871':
10011                         case 'ebcdiccpis':
10012                         case 'ibm871':
10013                                 return 'IBM871';
10014
10015                         case 'cp880':
10016                         case 'csibm880':
10017                         case 'ebcdiccyrillic':
10018                         case 'ibm880':
10019                                 return 'IBM880';
10020
10021                         case 'cp891':
10022                         case 'csibm891':
10023                         case 'ibm891':
10024                                 return 'IBM891';
10025
10026                         case 'cp903':
10027                         case 'csibm903':
10028                         case 'ibm903':
10029                                 return 'IBM903';
10030
10031                         case '904':
10032                         case 'cp904':
10033                         case 'csibbm904':
10034                         case 'ibm904':
10035                                 return 'IBM904';
10036
10037                         case 'cp905':
10038                         case 'csibm905':
10039                         case 'ebcdiccptr':
10040                         case 'ibm905':
10041                                 return 'IBM905';
10042
10043                         case 'cp918':
10044                         case 'csibm918':
10045                         case 'ebcdiccpar2':
10046                         case 'ibm918':
10047                                 return 'IBM918';
10048
10049                         case 'cp1026':
10050                         case 'csibm1026':
10051                         case 'ibm1026':
10052                                 return 'IBM1026';
10053
10054                         case 'ibm1047':
10055                                 return 'IBM1047';
10056
10057                         case 'csiso143iecp271':
10058                         case 'iecp271':
10059                         case 'isoir143':
10060                                 return 'IEC_P27-1';
10061
10062                         case 'csiso49inis':
10063                         case 'inis':
10064                         case 'isoir49':
10065                                 return 'INIS';
10066
10067                         case 'csiso50inis8':
10068                         case 'inis8':
10069                         case 'isoir50':
10070                                 return 'INIS-8';
10071
10072                         case 'csiso51iniscyrillic':
10073                         case 'iniscyrillic':
10074                         case 'isoir51':
10075                                 return 'INIS-cyrillic';
10076
10077                         case 'csinvariant':
10078                         case 'invariant':
10079                                 return 'INVARIANT';
10080
10081                         case 'iso2022cn':
10082                                 return 'ISO-2022-CN';
10083
10084                         case 'iso2022cnext':
10085                                 return 'ISO-2022-CN-EXT';
10086
10087                         case 'csiso2022jp':
10088                         case 'iso2022jp':
10089                                 return 'ISO-2022-JP';
10090
10091                         case 'csiso2022jp2':
10092                         case 'iso2022jp2':
10093                                 return 'ISO-2022-JP-2';
10094
10095                         case 'csiso2022kr':
10096                         case 'iso2022kr':
10097                                 return 'ISO-2022-KR';
10098
10099                         case 'cswindows30latin1':
10100                         case 'iso88591windows30latin1':
10101                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10102
10103                         case 'cswindows31latin1':
10104                         case 'iso88591windows31latin1':
10105                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10106
10107                         case 'csisolatin2':
10108                         case 'iso88592':
10109                         case 'iso885921987':
10110                         case 'isoir101':
10111                         case 'l2':
10112                         case 'latin2':
10113                                 return 'ISO-8859-2';
10114
10115                         case 'cswindows31latin2':
10116                         case 'iso88592windowslatin2':
10117                                 return 'ISO-8859-2-Windows-Latin-2';
10118
10119                         case 'csisolatin3':
10120                         case 'iso88593':
10121                         case 'iso885931988':
10122                         case 'isoir109':
10123                         case 'l3':
10124                         case 'latin3':
10125                                 return 'ISO-8859-3';
10126
10127                         case 'csisolatin4':
10128                         case 'iso88594':
10129                         case 'iso885941988':
10130                         case 'isoir110':
10131                         case 'l4':
10132                         case 'latin4':
10133                                 return 'ISO-8859-4';
10134
10135                         case 'csisolatincyrillic':
10136                         case 'cyrillic':
10137                         case 'iso88595':
10138                         case 'iso885951988':
10139                         case 'isoir144':
10140                                 return 'ISO-8859-5';
10141
10142                         case 'arabic':
10143                         case 'asmo708':
10144                         case 'csisolatinarabic':
10145                         case 'ecma114':
10146                         case 'iso88596':
10147                         case 'iso885961987':
10148                         case 'isoir127':
10149                                 return 'ISO-8859-6';
10150
10151                         case 'csiso88596e':
10152                         case 'iso88596e':
10153                                 return 'ISO-8859-6-E';
10154
10155                         case 'csiso88596i':
10156                         case 'iso88596i':
10157                                 return 'ISO-8859-6-I';
10158
10159                         case 'csisolatingreek':
10160                         case 'ecma118':
10161                         case 'elot928':
10162                         case 'greek':
10163                         case 'greek8':
10164                         case 'iso88597':
10165                         case 'iso885971987':
10166                         case 'isoir126':
10167                                 return 'ISO-8859-7';
10168
10169                         case 'csisolatinhebrew':
10170                         case 'hebrew':
10171                         case 'iso88598':
10172                         case 'iso885981988':
10173                         case 'isoir138':
10174                                 return 'ISO-8859-8';
10175
10176                         case 'csiso88598e':
10177                         case 'iso88598e':
10178                                 return 'ISO-8859-8-E';
10179
10180                         case 'csiso88598i':
10181                         case 'iso88598i':
10182                                 return 'ISO-8859-8-I';
10183
10184                         case 'cswindows31latin5':
10185                         case 'iso88599windowslatin5':
10186                                 return 'ISO-8859-9-Windows-Latin-5';
10187
10188                         case 'csisolatin6':
10189                         case 'iso885910':
10190                         case 'iso8859101992':
10191                         case 'isoir157':
10192                         case 'l6':
10193                         case 'latin6':
10194                                 return 'ISO-8859-10';
10195
10196                         case 'iso885913':
10197                                 return 'ISO-8859-13';
10198
10199                         case 'iso885914':
10200                         case 'iso8859141998':
10201                         case 'isoceltic':
10202                         case 'isoir199':
10203                         case 'l8':
10204                         case 'latin8':
10205                                 return 'ISO-8859-14';
10206
10207                         case 'iso885915':
10208                         case 'latin9':
10209                                 return 'ISO-8859-15';
10210
10211                         case 'iso885916':
10212                         case 'iso8859162001':
10213                         case 'isoir226':
10214                         case 'l10':
10215                         case 'latin10':
10216                                 return 'ISO-8859-16';
10217
10218                         case 'iso10646j1':
10219                                 return 'ISO-10646-J-1';
10220
10221                         case 'csunicode':
10222                         case 'iso10646ucs2':
10223                                 return 'ISO-10646-UCS-2';
10224
10225                         case 'csucs4':
10226                         case 'iso10646ucs4':
10227                                 return 'ISO-10646-UCS-4';
10228
10229                         case 'csunicodeascii':
10230                         case 'iso10646ucsbasic':
10231                                 return 'ISO-10646-UCS-Basic';
10232
10233                         case 'csunicodelatin1':
10234                         case 'iso10646':
10235                         case 'iso10646unicodelatin1':
10236                                 return 'ISO-10646-Unicode-Latin1';
10237
10238                         case 'csiso10646utf1':
10239                         case 'iso10646utf1':
10240                                 return 'ISO-10646-UTF-1';
10241
10242                         case 'csiso115481':
10243                         case 'iso115481':
10244                         case 'isotr115481':
10245                                 return 'ISO-11548-1';
10246
10247                         case 'csiso90':
10248                         case 'isoir90':
10249                                 return 'iso-ir-90';
10250
10251                         case 'csunicodeibm1261':
10252                         case 'isounicodeibm1261':
10253                                 return 'ISO-Unicode-IBM-1261';
10254
10255                         case 'csunicodeibm1264':
10256                         case 'isounicodeibm1264':
10257                                 return 'ISO-Unicode-IBM-1264';
10258
10259                         case 'csunicodeibm1265':
10260                         case 'isounicodeibm1265':
10261                                 return 'ISO-Unicode-IBM-1265';
10262
10263                         case 'csunicodeibm1268':
10264                         case 'isounicodeibm1268':
10265                                 return 'ISO-Unicode-IBM-1268';
10266
10267                         case 'csunicodeibm1276':
10268                         case 'isounicodeibm1276':
10269                                 return 'ISO-Unicode-IBM-1276';
10270
10271                         case 'csiso646basic1983':
10272                         case 'iso646basic1983':
10273                         case 'ref':
10274                                 return 'ISO_646.basic:1983';
10275
10276                         case 'csiso2intlrefversion':
10277                         case 'irv':
10278                         case 'iso646irv1983':
10279                         case 'isoir2':
10280                                 return 'ISO_646.irv:1983';
10281
10282                         case 'csiso2033':
10283                         case 'e13b':
10284                         case 'iso20331983':
10285                         case 'isoir98':
10286                                 return 'ISO_2033-1983';
10287
10288                         case 'csiso5427cyrillic':
10289                         case 'iso5427':
10290                         case 'isoir37':
10291                                 return 'ISO_5427';
10292
10293                         case 'iso5427cyrillic1981':
10294                         case 'iso54271981':
10295                         case 'isoir54':
10296                                 return 'ISO_5427:1981';
10297
10298                         case 'csiso5428greek':
10299                         case 'iso54281980':
10300                         case 'isoir55':
10301                                 return 'ISO_5428:1980';
10302
10303                         case 'csiso6937add':
10304                         case 'iso6937225':
10305                         case 'isoir152':
10306                                 return 'ISO_6937-2-25';
10307
10308                         case 'csisotextcomm':
10309                         case 'iso69372add':
10310                         case 'isoir142':
10311                                 return 'ISO_6937-2-add';
10312
10313                         case 'csiso8859supp':
10314                         case 'iso8859supp':
10315                         case 'isoir154':
10316                         case 'latin125':
10317                                 return 'ISO_8859-supp';
10318
10319                         case 'csiso10367box':
10320                         case 'iso10367box':
10321                         case 'isoir155':
10322                                 return 'ISO_10367-box';
10323
10324                         case 'csiso15italian':
10325                         case 'iso646it':
10326                         case 'isoir15':
10327                         case 'it':
10328                                 return 'IT';
10329
10330                         case 'csiso13jisc6220jp':
10331                         case 'isoir13':
10332                         case 'jisc62201969':
10333                         case 'jisc62201969jp':
10334                         case 'katakana':
10335                         case 'x2017':
10336                                 return 'JIS_C6220-1969-jp';
10337
10338                         case 'csiso14jisc6220ro':
10339                         case 'iso646jp':
10340                         case 'isoir14':
10341                         case 'jisc62201969ro':
10342                         case 'jp':
10343                                 return 'JIS_C6220-1969-ro';
10344
10345                         case 'csiso42jisc62261978':
10346                         case 'isoir42':
10347                         case 'jisc62261978':
10348                                 return 'JIS_C6226-1978';
10349
10350                         case 'csiso87jisx208':
10351                         case 'isoir87':
10352                         case 'jisc62261983':
10353                         case 'jisx2081983':
10354                         case 'x208':
10355                                 return 'JIS_C6226-1983';
10356
10357                         case 'csiso91jisc62291984a':
10358                         case 'isoir91':
10359                         case 'jisc62291984a':
10360                         case 'jpocra':
10361                                 return 'JIS_C6229-1984-a';
10362
10363                         case 'csiso92jisc62991984b':
10364                         case 'iso646jpocrb':
10365                         case 'isoir92':
10366                         case 'jisc62291984b':
10367                         case 'jpocrb':
10368                                 return 'JIS_C6229-1984-b';
10369
10370                         case 'csiso93jis62291984badd':
10371                         case 'isoir93':
10372                         case 'jisc62291984badd':
10373                         case 'jpocrbadd':
10374                                 return 'JIS_C6229-1984-b-add';
10375
10376                         case 'csiso94jis62291984hand':
10377                         case 'isoir94':
10378                         case 'jisc62291984hand':
10379                         case 'jpocrhand':
10380                                 return 'JIS_C6229-1984-hand';
10381
10382                         case 'csiso95jis62291984handadd':
10383                         case 'isoir95':
10384                         case 'jisc62291984handadd':
10385                         case 'jpocrhandadd':
10386                                 return 'JIS_C6229-1984-hand-add';
10387
10388                         case 'csiso96jisc62291984kana':
10389                         case 'isoir96':
10390                         case 'jisc62291984kana':
10391                                 return 'JIS_C6229-1984-kana';
10392
10393                         case 'csjisencoding':
10394                         case 'jisencoding':
10395                                 return 'JIS_Encoding';
10396
10397                         case 'cshalfwidthkatakana':
10398                         case 'jisx201':
10399                         case 'x201':
10400                                 return 'JIS_X0201';
10401
10402                         case 'csiso159jisx2121990':
10403                         case 'isoir159':
10404                         case 'jisx2121990':
10405                         case 'x212':
10406                                 return 'JIS_X0212-1990';
10407
10408                         case 'csiso141jusib1002':
10409                         case 'iso646yu':
10410                         case 'isoir141':
10411                         case 'js':
10412                         case 'jusib1002':
10413                         case 'yu':
10414                                 return 'JUS_I.B1.002';
10415
10416                         case 'csiso147macedonian':
10417                         case 'isoir147':
10418                         case 'jusib1003mac':
10419                         case 'macedonian':
10420                                 return 'JUS_I.B1.003-mac';
10421
10422                         case 'csiso146serbian':
10423                         case 'isoir146':
10424                         case 'jusib1003serb':
10425                         case 'serbian':
10426                                 return 'JUS_I.B1.003-serb';
10427
10428                         case 'koi7switched':
10429                                 return 'KOI7-switched';
10430
10431                         case 'cskoi8r':
10432                         case 'koi8r':
10433                                 return 'KOI8-R';
10434
10435                         case 'koi8u':
10436                                 return 'KOI8-U';
10437
10438                         case 'csksc5636':
10439                         case 'iso646kr':
10440                         case 'ksc5636':
10441                                 return 'KSC5636';
10442
10443                         case 'cskz1048':
10444                         case 'kz1048':
10445                         case 'rk1048':
10446                         case 'strk10482002':
10447                                 return 'KZ-1048';
10448
10449                         case 'csiso19latingreek':
10450                         case 'isoir19':
10451                         case 'latingreek':
10452                                 return 'latin-greek';
10453
10454                         case 'csiso27latingreek1':
10455                         case 'isoir27':
10456                         case 'latingreek1':
10457                                 return 'Latin-greek-1';
10458
10459                         case 'csiso158lap':
10460                         case 'isoir158':
10461                         case 'lap':
10462                         case 'latinlap':
10463                                 return 'latin-lap';
10464
10465                         case 'csmacintosh':
10466                         case 'mac':
10467                         case 'macintosh':
10468                                 return 'macintosh';
10469
10470                         case 'csmicrosoftpublishing':
10471                         case 'microsoftpublishing':
10472                                 return 'Microsoft-Publishing';
10473
10474                         case 'csmnem':
10475                         case 'mnem':
10476                                 return 'MNEM';
10477
10478                         case 'csmnemonic':
10479                         case 'mnemonic':
10480                                 return 'MNEMONIC';
10481
10482                         case 'csiso86hungarian':
10483                         case 'hu':
10484                         case 'iso646hu':
10485                         case 'isoir86':
10486                         case 'msz77953':
10487                                 return 'MSZ_7795.3';
10488
10489                         case 'csnatsdano':
10490                         case 'isoir91':
10491                         case 'natsdano':
10492                                 return 'NATS-DANO';
10493
10494                         case 'csnatsdanoadd':
10495                         case 'isoir92':
10496                         case 'natsdanoadd':
10497                                 return 'NATS-DANO-ADD';
10498
10499                         case 'csnatssefi':
10500                         case 'isoir81':
10501                         case 'natssefi':
10502                                 return 'NATS-SEFI';
10503
10504                         case 'csnatssefiadd':
10505                         case 'isoir82':
10506                         case 'natssefiadd':
10507                                 return 'NATS-SEFI-ADD';
10508
10509                         case 'csiso151cuba':
10510                         case 'cuba':
10511                         case 'iso646cu':
10512                         case 'isoir151':
10513                         case 'ncnc1081':
10514                                 return 'NC_NC00-10:81';
10515
10516                         case 'csiso69french':
10517                         case 'fr':
10518                         case 'iso646fr':
10519                         case 'isoir69':
10520                         case 'nfz62010':
10521                                 return 'NF_Z_62-010';
10522
10523                         case 'csiso25french':
10524                         case 'iso646fr1':
10525                         case 'isoir25':
10526                         case 'nfz620101973':
10527                                 return 'NF_Z_62-010_(1973)';
10528
10529                         case 'csiso60danishnorwegian':
10530                         case 'csiso60norwegian1':
10531                         case 'iso646no':
10532                         case 'isoir60':
10533                         case 'no':
10534                         case 'ns45511':
10535                                 return 'NS_4551-1';
10536
10537                         case 'csiso61norwegian2':
10538                         case 'iso646no2':
10539                         case 'isoir61':
10540                         case 'no2':
10541                         case 'ns45512':
10542                                 return 'NS_4551-2';
10543
10544                         case 'osdebcdicdf3irv':
10545                                 return 'OSD_EBCDIC_DF03_IRV';
10546
10547                         case 'osdebcdicdf41':
10548                                 return 'OSD_EBCDIC_DF04_1';
10549
10550                         case 'osdebcdicdf415':
10551                                 return 'OSD_EBCDIC_DF04_15';
10552
10553                         case 'cspc8danishnorwegian':
10554                         case 'pc8danishnorwegian':
10555                                 return 'PC8-Danish-Norwegian';
10556
10557                         case 'cspc8turkish':
10558                         case 'pc8turkish':
10559                                 return 'PC8-Turkish';
10560
10561                         case 'csiso16portuguese':
10562                         case 'iso646pt':
10563                         case 'isoir16':
10564                         case 'pt':
10565                                 return 'PT';
10566
10567                         case 'csiso84portuguese2':
10568                         case 'iso646pt2':
10569                         case 'isoir84':
10570                         case 'pt2':
10571                                 return 'PT2';
10572
10573                         case 'cp154':
10574                         case 'csptcp154':
10575                         case 'cyrillicasian':
10576                         case 'pt154':
10577                         case 'ptcp154':
10578                                 return 'PTCP154';
10579
10580                         case 'scsu':
10581                                 return 'SCSU';
10582
10583                         case 'csiso10swedish':
10584                         case 'fi':
10585                         case 'iso646fi':
10586                         case 'iso646se':
10587                         case 'isoir10':
10588                         case 'se':
10589                         case 'sen850200b':
10590                                 return 'SEN_850200_B';
10591
10592                         case 'csiso11swedishfornames':
10593                         case 'iso646se2':
10594                         case 'isoir11':
10595                         case 'se2':
10596                         case 'sen850200c':
10597                                 return 'SEN_850200_C';
10598
10599                         case 'csshiftjis':
10600                         case 'mskanji':
10601                         case 'shiftjis':
10602                                 return 'Shift_JIS';
10603
10604                         case 'csiso102t617bit':
10605                         case 'isoir102':
10606                         case 't617bit':
10607                                 return 'T.61-7bit';
10608
10609                         case 'csiso103t618bit':
10610                         case 'isoir103':
10611                         case 't61':
10612                         case 't618bit':
10613                                 return 'T.61-8bit';
10614
10615                         case 'csiso128t101g2':
10616                         case 'isoir128':
10617                         case 't101g2':
10618                                 return 'T.101-G2';
10619
10620                         case 'cstscii':
10621                         case 'tscii':
10622                                 return 'TSCII';
10623
10624                         case 'csunicode11':
10625                         case 'unicode11':
10626                                 return 'UNICODE-1-1';
10627
10628                         case 'csunicode11utf7':
10629                         case 'unicode11utf7':
10630                                 return 'UNICODE-1-1-UTF-7';
10631
10632                         case 'csunknown8bit':
10633                         case 'unknown8bit':
10634                                 return 'UNKNOWN-8BIT';
10635
10636                         case 'ansix341968':
10637                         case 'ansix341986':
10638                         case 'ascii':
10639                         case 'cp367':
10640                         case 'csascii':
10641                         case 'ibm367':
10642                         case 'iso646irv1991':
10643                         case 'iso646us':
10644                         case 'isoir6':
10645                         case 'us':
10646                         case 'usascii':
10647                                 return 'US-ASCII';
10648
10649                         case 'csusdk':
10650                         case 'usdk':
10651                                 return 'us-dk';
10652
10653                         case 'utf7':
10654                                 return 'UTF-7';
10655
10656                         case 'utf8':
10657                                 return 'UTF-8';
10658
10659                         case 'utf16':
10660                                 return 'UTF-16';
10661
10662                         case 'utf16be':
10663                                 return 'UTF-16BE';
10664
10665                         case 'utf16le':
10666                                 return 'UTF-16LE';
10667
10668                         case 'utf32':
10669                                 return 'UTF-32';
10670
10671                         case 'utf32be':
10672                                 return 'UTF-32BE';
10673
10674                         case 'utf32le':
10675                                 return 'UTF-32LE';
10676
10677                         case 'csventurainternational':
10678                         case 'venturainternational':
10679                                 return 'Ventura-International';
10680
10681                         case 'csventuramath':
10682                         case 'venturamath':
10683                                 return 'Ventura-Math';
10684
10685                         case 'csventuraus':
10686                         case 'venturaus':
10687                                 return 'Ventura-US';
10688
10689                         case 'csiso70videotexsupp1':
10690                         case 'isoir70':
10691                         case 'videotexsuppl':
10692                                 return 'videotex-suppl';
10693
10694                         case 'csviqr':
10695                         case 'viqr':
10696                                 return 'VIQR';
10697
10698                         case 'csviscii':
10699                         case 'viscii':
10700                                 return 'VISCII';
10701
10702                         case 'cswindows31j':
10703                         case 'windows31j':
10704                                 return 'Windows-31J';
10705
10706                         case 'iso885911':
10707                         case 'tis620':
10708                                 return 'windows-874';
10709
10710                         case 'cseuckr':
10711                         case 'csksc56011987':
10712                         case 'euckr':
10713                         case 'isoir149':
10714                         case 'korean':
10715                         case 'ksc5601':
10716                         case 'ksc56011987':
10717                         case 'ksc56011989':
10718                         case 'windows949':
10719                                 return 'windows-949';
10720
10721                         case 'windows1250':
10722                                 return 'windows-1250';
10723
10724                         case 'windows1251':
10725                                 return 'windows-1251';
10726
10727                         case 'cp819':
10728                         case 'csisolatin1':
10729                         case 'ibm819':
10730                         case 'iso88591':
10731                         case 'iso885911987':
10732                         case 'isoir100':
10733                         case 'l1':
10734                         case 'latin1':
10735                         case 'windows1252':
10736                                 return 'windows-1252';
10737
10738                         case 'windows1253':
10739                                 return 'windows-1253';
10740
10741                         case 'csisolatin5':
10742                         case 'iso88599':
10743                         case 'iso885991989':
10744                         case 'isoir148':
10745                         case 'l5':
10746                         case 'latin5':
10747                         case 'windows1254':
10748                                 return 'windows-1254';
10749
10750                         case 'windows1255':
10751                                 return 'windows-1255';
10752
10753                         case 'windows1256':
10754                                 return 'windows-1256';
10755
10756                         case 'windows1257':
10757                                 return 'windows-1257';
10758
10759                         case 'windows1258':
10760                                 return 'windows-1258';
10761
10762                         default:
10763                                 return $charset;
10764                 }
10765         }
10766
10767         function get_curl_version()
10768         {
10769                 if (is_array($curl = curl_version()))
10770                 {
10771                         $curl = $curl['version'];
10772                 }
10773                 elseif (substr($curl, 0, 5) === 'curl/')
10774                 {
10775                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10776                 }
10777                 elseif (substr($curl, 0, 8) === 'libcurl/')
10778                 {
10779                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10780                 }
10781                 else
10782                 {
10783                         $curl = 0;
10784                 }
10785                 return $curl;
10786         }
10787
10788         function is_subclass_of($class1, $class2)
10789         {
10790                 if (func_num_args() !== 2)
10791                 {
10792                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10793                 }
10794                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10795                 {
10796                         return is_subclass_of($class1, $class2);
10797                 }
10798                 elseif (is_string($class1) && is_string($class2))
10799                 {
10800                         if (class_exists($class1))
10801                         {
10802                                 if (class_exists($class2))
10803                                 {
10804                                         $class2 = strtolower($class2);
10805                                         while ($class1 = strtolower(get_parent_class($class1)))
10806                                         {
10807                                                 if ($class1 === $class2)
10808                                                 {
10809                                                         return true;
10810                                                 }
10811                                         }
10812                                 }
10813                         }
10814                         else
10815                         {
10816                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10817                         }
10818                 }
10819                 return false;
10820         }
10821
10822         /**
10823          * Strip HTML comments
10824          *
10825          * @access public
10826          * @param string $data Data to strip comments from
10827          * @return string Comment stripped string
10828          */
10829         function strip_comments($data)
10830         {
10831                 $output = '';
10832                 while (($start = strpos($data, '<!--')) !== false)
10833                 {
10834                         $output .= substr($data, 0, $start);
10835                         if (($end = strpos($data, '-->', $start)) !== false)
10836                         {
10837                                 $data = substr_replace($data, '', 0, $end + 3);
10838                         }
10839                         else
10840                         {
10841                                 $data = '';
10842                         }
10843                 }
10844                 return $output . $data;
10845         }
10846
10847         function parse_date($dt)
10848         {
10849                 $parser = SimplePie_Parse_Date::get();
10850                 return $parser->parse($dt);
10851         }
10852
10853         /**
10854          * Decode HTML entities
10855          *
10856          * @static
10857          * @access public
10858          * @param string $data Input data
10859          * @return string Output data
10860          */
10861         function entities_decode($data)
10862         {
10863                 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10864                 return $decoder->parse();
10865         }
10866
10867         /**
10868          * Remove RFC822 comments
10869          *
10870          * @access public
10871          * @param string $data Data to strip comments from
10872          * @return string Comment stripped string
10873          */
10874         function uncomment_rfc822($string)
10875         {
10876                 $string = (string) $string;
10877                 $position = 0;
10878                 $length = strlen($string);
10879                 $depth = 0;
10880
10881                 $output = '';
10882
10883                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10884                 {
10885                         $output .= substr($string, $position, $pos - $position);
10886                         $position = $pos + 1;
10887                         if ($string[$pos - 1] !== '\\')
10888                         {
10889                                 $depth++;
10890                                 while ($depth && $position < $length)
10891                                 {
10892                                         $position += strcspn($string, '()', $position);
10893                                         if ($string[$position - 1] === '\\')
10894                                         {
10895                                                 $position++;
10896                                                 continue;
10897                                         }
10898                                         elseif (isset($string[$position]))
10899                                         {
10900                                                 switch ($string[$position])
10901                                                 {
10902                                                         case '(':
10903                                                                 $depth++;
10904                                                                 break;
10905
10906                                                         case ')':
10907                                                                 $depth--;
10908                                                                 break;
10909                                                 }
10910                                                 $position++;
10911                                         }
10912                                         else
10913                                         {
10914                                                 break;
10915                                         }
10916                                 }
10917                         }
10918                         else
10919                         {
10920                                 $output .= '(';
10921                         }
10922                 }
10923                 $output .= substr($string, $position);
10924
10925                 return $output;
10926         }
10927
10928         function parse_mime($mime)
10929         {
10930                 if (($pos = strpos($mime, ';')) === false)
10931                 {
10932                         return trim($mime);
10933                 }
10934                 else
10935                 {
10936                         return trim(substr($mime, 0, $pos));
10937                 }
10938         }
10939
10940         function htmlspecialchars_decode($string, $quote_style)
10941         {
10942                 if (function_exists('htmlspecialchars_decode'))
10943                 {
10944                         return htmlspecialchars_decode($string, $quote_style);
10945                 }
10946                 else
10947                 {
10948                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10949                 }
10950         }
10951
10952         function atom_03_construct_type($attribs)
10953         {
10954                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10955                 {
10956                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10957                 }
10958                 else
10959                 {
10960                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
10961                 }
10962                 if (isset($attribs['']['type']))
10963                 {
10964                         switch (strtolower(trim($attribs['']['type'])))
10965                         {
10966                                 case 'text':
10967                                 case 'text/plain':
10968                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10969
10970                                 case 'html':
10971                                 case 'text/html':
10972                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10973
10974                                 case 'xhtml':
10975                                 case 'application/xhtml+xml':
10976                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10977
10978                                 default:
10979                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10980                         }
10981                 }
10982                 else
10983                 {
10984                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10985                 }
10986         }
10987
10988         function atom_10_construct_type($attribs)
10989         {
10990                 if (isset($attribs['']['type']))
10991                 {
10992                         switch (strtolower(trim($attribs['']['type'])))
10993                         {
10994                                 case 'text':
10995                                         return SIMPLEPIE_CONSTRUCT_TEXT;
10996
10997                                 case 'html':
10998                                         return SIMPLEPIE_CONSTRUCT_HTML;
10999
11000                                 case 'xhtml':
11001                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11002
11003                                 default:
11004                                         return SIMPLEPIE_CONSTRUCT_NONE;
11005                         }
11006                 }
11007                 return SIMPLEPIE_CONSTRUCT_TEXT;
11008         }
11009
11010         function atom_10_content_construct_type($attribs)
11011         {
11012                 if (isset($attribs['']['type']))
11013                 {
11014                         $type = strtolower(trim($attribs['']['type']));
11015                         switch ($type)
11016                         {
11017                                 case 'text':
11018                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11019
11020                                 case 'html':
11021                                         return SIMPLEPIE_CONSTRUCT_HTML;
11022
11023                                 case 'xhtml':
11024                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11025                         }
11026                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11027                         {
11028                                 return SIMPLEPIE_CONSTRUCT_NONE;
11029                         }
11030                         else
11031                         {
11032                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11033                         }
11034                 }
11035                 else
11036                 {
11037                         return SIMPLEPIE_CONSTRUCT_TEXT;
11038                 }
11039         }
11040
11041         function is_isegment_nz_nc($string)
11042         {
11043                 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);
11044         }
11045
11046         function space_seperated_tokens($string)
11047         {
11048                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11049                 $string_length = strlen($string);
11050
11051                 $position = strspn($string, $space_characters);
11052                 $tokens = array();
11053
11054                 while ($position < $string_length)
11055                 {
11056                         $len = strcspn($string, $space_characters, $position);
11057                         $tokens[] = substr($string, $position, $len);
11058                         $position += $len;
11059                         $position += strspn($string, $space_characters, $position);
11060                 }
11061
11062                 return $tokens;
11063         }
11064
11065         function array_unique($array)
11066         {
11067                 if (version_compare(PHP_VERSION, '5.2', '>='))
11068                 {
11069                         return array_unique($array);
11070                 }
11071                 else
11072                 {
11073                         $array = (array) $array;
11074                         $new_array = array();
11075                         $new_array_strings = array();
11076                         foreach ($array as $key => $value)
11077                         {
11078                                 if (is_object($value))
11079                                 {
11080                                         if (method_exists($value, '__toString'))
11081                                         {
11082                                                 $cmp = $value->__toString();
11083                                         }
11084                                         else
11085                                         {
11086                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11087                                         }
11088                                 }
11089                                 elseif (is_array($value))
11090                                 {
11091                                         $cmp = (string) reset($value);
11092                                 }
11093                                 else
11094                                 {
11095                                         $cmp = (string) $value;
11096                                 }
11097                                 if (!in_array($cmp, $new_array_strings))
11098                                 {
11099                                         $new_array[$key] = $value;
11100                                         $new_array_strings[] = $cmp;
11101                                 }
11102                         }
11103                         return $new_array;
11104                 }
11105         }
11106
11107         /**
11108          * Converts a unicode codepoint to a UTF-8 character
11109          *
11110          * @static
11111          * @access public
11112          * @param int $codepoint Unicode codepoint
11113          * @return string UTF-8 character
11114          */
11115         function codepoint_to_utf8($codepoint)
11116         {
11117                 $codepoint = (int) $codepoint;
11118                 if ($codepoint < 0)
11119                 {
11120                         return false;
11121                 }
11122                 else if ($codepoint <= 0x7f)
11123                 {
11124                         return chr($codepoint);
11125                 }
11126                 else if ($codepoint <= 0x7ff)
11127                 {
11128                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11129                 }
11130                 else if ($codepoint <= 0xffff)
11131                 {
11132                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11133                 }
11134                 else if ($codepoint <= 0x10ffff)
11135                 {
11136                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11137                 }
11138                 else
11139                 {
11140                         // U+FFFD REPLACEMENT CHARACTER
11141                         return "\xEF\xBF\xBD";
11142                 }
11143         }
11144
11145         /**
11146          * Re-implementation of PHP 5's stripos()
11147          *
11148          * Returns the numeric position of the first occurrence of needle in the
11149          * haystack string.
11150          *
11151          * @static
11152          * @access string
11153          * @param object $haystack
11154          * @param string $needle Note that the needle may be a string of one or more
11155          *     characters. If needle is not a string, it is converted to an integer
11156          *     and applied as the ordinal value of a character.
11157          * @param int $offset The optional offset parameter allows you to specify which
11158          *     character in haystack to start searching. The position returned is still
11159          *     relative to the beginning of haystack.
11160          * @return bool If needle is not found, stripos() will return boolean false.
11161          */
11162         function stripos($haystack, $needle, $offset = 0)
11163         {
11164                 if (function_exists('stripos'))
11165                 {
11166                         return stripos($haystack, $needle, $offset);
11167                 }
11168                 else
11169                 {
11170                         if (is_string($needle))
11171                         {
11172                                 $needle = strtolower($needle);
11173                         }
11174                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11175                         {
11176                                 $needle = strtolower(chr($needle));
11177                         }
11178                         else
11179                         {
11180                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11181                                 return false;
11182                         }
11183
11184                         return strpos(strtolower($haystack), $needle, $offset);
11185                 }
11186         }
11187
11188         /**
11189          * Similar to parse_str()
11190          *
11191          * Returns an associative array of name/value pairs, where the value is an
11192          * array of values that have used the same name
11193          *
11194          * @static
11195          * @access string
11196          * @param string $str The input string.
11197          * @return array
11198          */
11199         function parse_str($str)
11200         {
11201                 $return = array();
11202                 $str = explode('&', $str);
11203
11204                 foreach ($str as $section)
11205                 {
11206                         if (strpos($section, '=') !== false)
11207                         {
11208                                 list($name, $value) = explode('=', $section, 2);
11209                                 $return[urldecode($name)][] = urldecode($value);
11210                         }
11211                         else
11212                         {
11213                                 $return[urldecode($section)][] = null;
11214                         }
11215                 }
11216
11217                 return $return;
11218         }
11219
11220         /**
11221          * Detect XML encoding, as per XML 1.0 Appendix F.1
11222          *
11223          * @todo Add support for EBCDIC
11224          * @param string $data XML data
11225          * @return array Possible encodings
11226          */
11227         function xml_encoding($data)
11228         {
11229                 // UTF-32 Big Endian BOM
11230                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11231                 {
11232                         $encoding[] = 'UTF-32BE';
11233                 }
11234                 // UTF-32 Little Endian BOM
11235                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11236                 {
11237                         $encoding[] = 'UTF-32LE';
11238                 }
11239                 // UTF-16 Big Endian BOM
11240                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11241                 {
11242                         $encoding[] = 'UTF-16BE';
11243                 }
11244                 // UTF-16 Little Endian BOM
11245                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11246                 {
11247                         $encoding[] = 'UTF-16LE';
11248                 }
11249                 // UTF-8 BOM
11250                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11251                 {
11252                         $encoding[] = 'UTF-8';
11253                 }
11254                 // UTF-32 Big Endian Without BOM
11255                 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")
11256                 {
11257                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11258                         {
11259                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11260                                 if ($parser->parse())
11261                                 {
11262                                         $encoding[] = $parser->encoding;
11263                                 }
11264                         }
11265                         $encoding[] = 'UTF-32BE';
11266                 }
11267                 // UTF-32 Little Endian Without BOM
11268                 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")
11269                 {
11270                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11271                         {
11272                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11273                                 if ($parser->parse())
11274                                 {
11275                                         $encoding[] = $parser->encoding;
11276                                 }
11277                         }
11278                         $encoding[] = 'UTF-32LE';
11279                 }
11280                 // UTF-16 Big Endian Without BOM
11281                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11282                 {
11283                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11284                         {
11285                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11286                                 if ($parser->parse())
11287                                 {
11288                                         $encoding[] = $parser->encoding;
11289                                 }
11290                         }
11291                         $encoding[] = 'UTF-16BE';
11292                 }
11293                 // UTF-16 Little Endian Without BOM
11294                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11295                 {
11296                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11297                         {
11298                                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11299                                 if ($parser->parse())
11300                                 {
11301                                         $encoding[] = $parser->encoding;
11302                                 }
11303                         }
11304                         $encoding[] = 'UTF-16LE';
11305                 }
11306                 // US-ASCII (or superset)
11307                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11308                 {
11309                         if ($pos = strpos($data, "\x3F\x3E"))
11310                         {
11311                                 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11312                                 if ($parser->parse())
11313                                 {
11314                                         $encoding[] = $parser->encoding;
11315                                 }
11316                         }
11317                         $encoding[] = 'UTF-8';
11318                 }
11319                 // Fallback to UTF-8
11320                 else
11321                 {
11322                         $encoding[] = 'UTF-8';
11323                 }
11324                 return $encoding;
11325         }
11326
11327         function output_javascript()
11328         {
11329                 if (function_exists('ob_gzhandler'))
11330                 {
11331                         ob_start('ob_gzhandler');
11332                 }
11333                 header('Content-type: text/javascript; charset: UTF-8');
11334                 header('Cache-Control: must-revalidate');
11335                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11336                 ?>
11337 function embed_odeo(link) {
11338         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>');
11339 }
11340
11341 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11342         if (placeholder != '') {
11343                 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>');
11344         }
11345         else {
11346                 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>');
11347         }
11348 }
11349
11350 function embed_flash(bgcolor, width, height, link, loop, type) {
11351         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>');
11352 }
11353
11354 function embed_flv(width, height, link, placeholder, loop, player) {
11355         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>');
11356 }
11357
11358 function embed_wmedia(width, height, link) {
11359         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11360 }
11361                 <?php
11362         }
11363 }
11364
11365 /**
11366  * Decode HTML Entities
11367  *
11368  * This implements HTML5 as of revision 967 (2007-06-28)
11369  *
11370  * @package SimplePie
11371  */
11372 class SimplePie_Decode_HTML_Entities
11373 {
11374         /**
11375          * Data to be parsed
11376          *
11377          * @access private
11378          * @var string
11379          */
11380         var $data = '';
11381
11382         /**
11383          * Currently consumed bytes
11384          *
11385          * @access private
11386          * @var string
11387          */
11388         var $consumed = '';
11389
11390         /**
11391          * Position of the current byte being parsed
11392          *
11393          * @access private
11394          * @var int
11395          */
11396         var $position = 0;
11397
11398         /**
11399          * Create an instance of the class with the input data
11400          *
11401          * @access public
11402          * @param string $data Input data
11403          */
11404         function SimplePie_Decode_HTML_Entities($data)
11405         {
11406                 $this->data = $data;
11407         }
11408
11409         /**
11410          * Parse the input data
11411          *
11412          * @access public
11413          * @return string Output data
11414          */
11415         function parse()
11416         {
11417                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11418                 {
11419                         $this->consume();
11420                         $this->entity();
11421                         $this->consumed = '';
11422                 }
11423                 return $this->data;
11424         }
11425
11426         /**
11427          * Consume the next byte
11428          *
11429          * @access private
11430          * @return mixed The next byte, or false, if there is no more data
11431          */
11432         function consume()
11433         {
11434                 if (isset($this->data[$this->position]))
11435                 {
11436                         $this->consumed .= $this->data[$this->position];
11437                         return $this->data[$this->position++];
11438                 }
11439                 else
11440                 {
11441                         return false;
11442                 }
11443         }
11444
11445         /**
11446          * Consume a range of characters
11447          *
11448          * @access private
11449          * @param string $chars Characters to consume
11450          * @return mixed A series of characters that match the range, or false
11451          */
11452         function consume_range($chars)
11453         {
11454                 if ($len = strspn($this->data, $chars, $this->position))
11455                 {
11456                         $data = substr($this->data, $this->position, $len);
11457                         $this->consumed .= $data;
11458                         $this->position += $len;
11459                         return $data;
11460                 }
11461                 else
11462                 {
11463                         return false;
11464                 }
11465         }
11466
11467         /**
11468          * Unconsume one byte
11469          *
11470          * @access private
11471          */
11472         function unconsume()
11473         {
11474                 $this->consumed = substr($this->consumed, 0, -1);
11475                 $this->position--;
11476         }
11477
11478         /**
11479          * Decode an entity
11480          *
11481          * @access private
11482          */
11483         function entity()
11484         {
11485                 switch ($this->consume())
11486                 {
11487                         case "\x09":
11488                         case "\x0A":
11489                         case "\x0B":
11490                         case "\x0B":
11491                         case "\x0C":
11492                         case "\x20":
11493                         case "\x3C":
11494                         case "\x26":
11495                         case false:
11496                                 break;
11497
11498                         case "\x23":
11499                                 switch ($this->consume())
11500                                 {
11501                                         case "\x78":
11502                                         case "\x58":
11503                                                 $range = '0123456789ABCDEFabcdef';
11504                                                 $hex = true;
11505                                                 break;
11506
11507                                         default:
11508                                                 $range = '0123456789';
11509                                                 $hex = false;
11510                                                 $this->unconsume();
11511                                                 break;
11512                                 }
11513
11514                                 if ($codepoint = $this->consume_range($range))
11515                                 {
11516                                         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");
11517
11518                                         if ($hex)
11519                                         {
11520                                                 $codepoint = hexdec($codepoint);
11521                                         }
11522                                         else
11523                                         {
11524                                                 $codepoint = intval($codepoint);
11525                                         }
11526
11527                                         if (isset($windows_1252_specials[$codepoint]))
11528                                         {
11529                                                 $replacement = $windows_1252_specials[$codepoint];
11530                                         }
11531                                         else
11532                                         {
11533                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11534                                         }
11535
11536                                         if (!in_array($this->consume(), array(';', false), true))
11537                                         {
11538                                                 $this->unconsume();
11539                                         }
11540
11541                                         $consumed_length = strlen($this->consumed);
11542                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11543                                         $this->position += strlen($replacement) - $consumed_length;
11544                                 }
11545                                 break;
11546
11547                         default:
11548                                 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");
11549
11550                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11551                                 {
11552                                         $consumed = substr($this->consumed, 1);
11553                                         if (isset($entities[$consumed]))
11554                                         {
11555                                                 $match = $consumed;
11556                                         }
11557                                 }
11558
11559                                 if ($match !== null)
11560                                 {
11561                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11562                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11563                                 }
11564                                 break;
11565                 }
11566         }
11567 }
11568
11569 /**
11570  * IRI parser/serialiser
11571  *
11572  * @package SimplePie
11573  */
11574 class SimplePie_IRI
11575 {
11576         /**
11577          * Scheme
11578          *
11579          * @access private
11580          * @var string
11581          */
11582         var $scheme;
11583
11584         /**
11585          * User Information
11586          *
11587          * @access private
11588          * @var string
11589          */
11590         var $userinfo;
11591
11592         /**
11593          * Host
11594          *
11595          * @access private
11596          * @var string
11597          */
11598         var $host;
11599
11600         /**
11601          * Port
11602          *
11603          * @access private
11604          * @var string
11605          */
11606         var $port;
11607
11608         /**
11609          * Path
11610          *
11611          * @access private
11612          * @var string
11613          */
11614         var $path;
11615
11616         /**
11617          * Query
11618          *
11619          * @access private
11620          * @var string
11621          */
11622         var $query;
11623
11624         /**
11625          * Fragment
11626          *
11627          * @access private
11628          * @var string
11629          */
11630         var $fragment;
11631
11632         /**
11633          * Whether the object represents a valid IRI
11634          *
11635          * @access private
11636          * @var array
11637          */
11638         var $valid = array();
11639
11640         /**
11641          * Return the entire IRI when you try and read the object as a string
11642          *
11643          * @access public
11644          * @return string
11645          */
11646         function __toString()
11647         {
11648                 return $this->get_iri();
11649         }
11650
11651         /**
11652          * Create a new IRI object, from a specified string
11653          *
11654          * @access public
11655          * @param string $iri
11656          * @return SimplePie_IRI
11657          */
11658         function SimplePie_IRI($iri)
11659         {
11660                 $iri = (string) $iri;
11661                 if ($iri !== '')
11662                 {
11663                         $parsed = $this->parse_iri($iri);
11664                         $this->set_scheme($parsed['scheme']);
11665                         $this->set_authority($parsed['authority']);
11666                         $this->set_path($parsed['path']);
11667                         $this->set_query($parsed['query']);
11668                         $this->set_fragment($parsed['fragment']);
11669                 }
11670         }
11671
11672         /**
11673          * Create a new IRI object by resolving a relative IRI
11674          *
11675          * @static
11676          * @access public
11677          * @param SimplePie_IRI $base Base IRI
11678          * @param string $relative Relative IRI
11679          * @return SimplePie_IRI
11680          */
11681         function absolutize($base, $relative)
11682         {
11683                 $relative = (string) $relative;
11684                 if ($relative !== '')
11685                 {
11686                         $relative =& new SimplePie_IRI($relative);
11687                         if ($relative->get_scheme() !== null)
11688                         {
11689                                 $target = $relative;
11690                         }
11691                         elseif ($base->get_iri() !== null)
11692                         {
11693                                 if ($relative->get_authority() !== null)
11694                                 {
11695                                         $target = $relative;
11696                                         $target->set_scheme($base->get_scheme());
11697                                 }
11698                                 else
11699                                 {
11700                                         $target =& new SimplePie_IRI('');
11701                                         $target->set_scheme($base->get_scheme());
11702                                         $target->set_userinfo($base->get_userinfo());
11703                                         $target->set_host($base->get_host());
11704                                         $target->set_port($base->get_port());
11705                                         if ($relative->get_path() !== null)
11706                                         {
11707                                                 if (strpos($relative->get_path(), '/') === 0)
11708                                                 {
11709                                                         $target->set_path($relative->get_path());
11710                                                 }
11711                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11712                                                 {
11713                                                         $target->set_path('/' . $relative->get_path());
11714                                                 }
11715                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11716                                                 {
11717                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11718                                                 }
11719                                                 else
11720                                                 {
11721                                                         $target->set_path($relative->get_path());
11722                                                 }
11723                                                 $target->set_query($relative->get_query());
11724                                         }
11725                                         else
11726                                         {
11727                                                 $target->set_path($base->get_path());
11728                                                 if ($relative->get_query() !== null)
11729                                                 {
11730                                                         $target->set_query($relative->get_query());
11731                                                 }
11732                                                 elseif ($base->get_query() !== null)
11733                                                 {
11734                                                         $target->set_query($base->get_query());
11735                                                 }
11736                                         }
11737                                 }
11738                                 $target->set_fragment($relative->get_fragment());
11739                         }
11740                         else
11741                         {
11742                                 // No base URL, just return the relative URL
11743                                 $target = $relative;
11744                         }
11745                 }
11746                 else
11747                 {
11748                         $target = $base;
11749                 }
11750                 return $target;
11751         }
11752
11753         /**
11754          * Parse an IRI into scheme/authority/path/query/fragment segments
11755          *
11756          * @access private
11757          * @param string $iri
11758          * @return array
11759          */
11760         function parse_iri($iri)
11761         {
11762                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11763                 for ($i = count($match); $i <= 9; $i++)
11764                 {
11765                         $match[$i] = '';
11766                 }
11767                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11768         }
11769
11770         /**
11771          * Remove dot segments from a path
11772          *
11773          * @access private
11774          * @param string $input
11775          * @return string
11776          */
11777         function remove_dot_segments($input)
11778         {
11779                 $output = '';
11780                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11781                 {
11782                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11783                         if (strpos($input, '../') === 0)
11784                         {
11785                                 $input = substr($input, 3);
11786                         }
11787                         elseif (strpos($input, './') === 0)
11788                         {
11789                                 $input = substr($input, 2);
11790                         }
11791                         // 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,
11792                         elseif (strpos($input, '/./') === 0)
11793                         {
11794                                 $input = substr_replace($input, '/', 0, 3);
11795                         }
11796                         elseif ($input === '/.')
11797                         {
11798                                 $input = '/';
11799                         }
11800                         // 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,
11801                         elseif (strpos($input, '/../') === 0)
11802                         {
11803                                 $input = substr_replace($input, '/', 0, 4);
11804                                 $output = substr_replace($output, '', strrpos($output, '/'));
11805                         }
11806                         elseif ($input === '/..')
11807                         {
11808                                 $input = '/';
11809                                 $output = substr_replace($output, '', strrpos($output, '/'));
11810                         }
11811                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11812                         elseif ($input === '.' || $input === '..')
11813                         {
11814                                 $input = '';
11815                         }
11816                         // 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
11817                         elseif (($pos = strpos($input, '/', 1)) !== false)
11818                         {
11819                                 $output .= substr($input, 0, $pos);
11820                                 $input = substr_replace($input, '', 0, $pos);
11821                         }
11822                         else
11823                         {
11824                                 $output .= $input;
11825                                 $input = '';
11826                         }
11827                 }
11828                 return $output . $input;
11829         }
11830
11831         /**
11832          * Replace invalid character with percent encoding
11833          *
11834          * @access private
11835          * @param string $string Input string
11836          * @param string $valid_chars Valid characters
11837          * @param int $case Normalise case
11838          * @return string
11839          */
11840         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11841         {
11842                 // Normalise case
11843                 if ($case & SIMPLEPIE_LOWERCASE)
11844                 {
11845                         $string = strtolower($string);
11846                 }
11847                 elseif ($case & SIMPLEPIE_UPPERCASE)
11848                 {
11849                         $string = strtoupper($string);
11850                 }
11851
11852                 // Store position and string length (to avoid constantly recalculating this)
11853                 $position = 0;
11854                 $strlen = strlen($string);
11855
11856                 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11857                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11858                 {
11859                         // If we have a % character
11860                         if ($string[$position] === '%')
11861                         {
11862                                 // If we have a pct-encoded section
11863                                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11864                                 {
11865                                         // Get the the represented character
11866                                         $chr = chr(hexdec(substr($string, $position + 1, 2)));
11867
11868                                         // If the character is valid, replace the pct-encoded with the actual character while normalising case
11869                                         if (strpos($valid_chars, $chr) !== false)
11870                                         {
11871                                                 if ($case & SIMPLEPIE_LOWERCASE)
11872                                                 {
11873                                                         $chr = strtolower($chr);
11874                                                 }
11875                                                 elseif ($case & SIMPLEPIE_UPPERCASE)
11876                                                 {
11877                                                         $chr = strtoupper($chr);
11878                                                 }
11879                                                 $string = substr_replace($string, $chr, $position, 3);
11880                                                 $strlen -= 2;
11881                                                 $position++;
11882                                         }
11883
11884                                         // Otherwise just normalise the pct-encoded to uppercase
11885                                         else
11886                                         {
11887                                                 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11888                                                 $position += 3;
11889                                         }
11890                                 }
11891                                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11892                                 else
11893                                 {
11894                                         $string = substr_replace($string, '%25', $position, 1);
11895                                         $strlen += 2;
11896                                         $position += 3;
11897                                 }
11898                         }
11899                         // If we have an invalid character, change into its pct-encoded form
11900                         else
11901                         {
11902                                 $replacement = sprintf("%%%02X", ord($string[$position]));
11903                                 $string = str_replace($string[$position], $replacement, $string);
11904                                 $strlen = strlen($string);
11905                         }
11906                 }
11907                 return $string;
11908         }
11909
11910         /**
11911          * Check if the object represents a valid IRI
11912          *
11913          * @access public
11914          * @return bool
11915          */
11916         function is_valid()
11917         {
11918                 return array_sum($this->valid) === count($this->valid);
11919         }
11920
11921         /**
11922          * Set the scheme. Returns true on success, false on failure (if there are
11923          * any invalid characters).
11924          *
11925          * @access public
11926          * @param string $scheme
11927          * @return bool
11928          */
11929         function set_scheme($scheme)
11930         {
11931                 if ($scheme === null || $scheme === '')
11932                 {
11933                         $this->scheme = null;
11934                 }
11935                 else
11936                 {
11937                         $len = strlen($scheme);
11938                         switch (true)
11939                         {
11940                                 case $len > 1:
11941                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11942                                         {
11943                                                 $this->scheme = null;
11944                                                 $this->valid[__FUNCTION__] = false;
11945                                                 return false;
11946                                         }
11947
11948                                 case $len > 0:
11949                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11950                                         {
11951                                                 $this->scheme = null;
11952                                                 $this->valid[__FUNCTION__] = false;
11953                                                 return false;
11954                                         }
11955                         }
11956                         $this->scheme = strtolower($scheme);
11957                 }
11958                 $this->valid[__FUNCTION__] = true;
11959                 return true;
11960         }
11961
11962         /**
11963          * Set the authority. Returns true on success, false on failure (if there are
11964          * any invalid characters).
11965          *
11966          * @access public
11967          * @param string $authority
11968          * @return bool
11969          */
11970         function set_authority($authority)
11971         {
11972                 if (($userinfo_end = strrpos($authority, '@')) !== false)
11973                 {
11974                         $userinfo = substr($authority, 0, $userinfo_end);
11975                         $authority = substr($authority, $userinfo_end + 1);
11976                 }
11977                 else
11978                 {
11979                         $userinfo = null;
11980                 }
11981
11982                 if (($port_start = strpos($authority, ':')) !== false)
11983                 {
11984                         $port = substr($authority, $port_start + 1);
11985                         $authority = substr($authority, 0, $port_start);
11986                 }
11987                 else
11988                 {
11989                         $port = null;
11990                 }
11991
11992                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
11993         }
11994
11995         /**
11996          * Set the userinfo.
11997          *
11998          * @access public
11999          * @param string $userinfo
12000          * @return bool
12001          */
12002         function set_userinfo($userinfo)
12003         {
12004                 if ($userinfo === null || $userinfo === '')
12005                 {
12006                         $this->userinfo = null;
12007                 }
12008                 else
12009                 {
12010                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12011                 }
12012                 $this->valid[__FUNCTION__] = true;
12013                 return true;
12014         }
12015
12016         /**
12017          * Set the host. Returns true on success, false on failure (if there are
12018          * any invalid characters).
12019          *
12020          * @access public
12021          * @param string $host
12022          * @return bool
12023          */
12024         function set_host($host)
12025         {
12026                 if ($host === null || $host === '')
12027                 {
12028                         $this->host = null;
12029                         $this->valid[__FUNCTION__] = true;
12030                         return true;
12031                 }
12032                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12033                 {
12034                         if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12035                         {
12036                                 $this->host = $host;
12037                                 $this->valid[__FUNCTION__] = true;
12038                                 return true;
12039                         }
12040                         else
12041                         {
12042                                 $this->host = null;
12043                                 $this->valid[__FUNCTION__] = false;
12044                                 return false;
12045                         }
12046                 }
12047                 else
12048                 {
12049                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12050                         $this->valid[__FUNCTION__] = true;
12051                         return true;
12052                 }
12053         }
12054
12055         /**
12056          * Set the port. Returns true on success, false on failure (if there are
12057          * any invalid characters).
12058          *
12059          * @access public
12060          * @param string $port
12061          * @return bool
12062          */
12063         function set_port($port)
12064         {
12065                 if ($port === null || $port === '')
12066                 {
12067                         $this->port = null;
12068                         $this->valid[__FUNCTION__] = true;
12069                         return true;
12070                 }
12071                 elseif (strspn($port, '0123456789') === strlen($port))
12072                 {
12073                         $this->port = (int) $port;
12074                         $this->valid[__FUNCTION__] = true;
12075                         return true;
12076                 }
12077                 else
12078                 {
12079                         $this->port = null;
12080                         $this->valid[__FUNCTION__] = false;
12081                         return false;
12082                 }
12083         }
12084
12085         /**
12086          * Set the path.
12087          *
12088          * @access public
12089          * @param string $path
12090          * @return bool
12091          */
12092         function set_path($path)
12093         {
12094                 if ($path === null || $path === '')
12095                 {
12096                         $this->path = null;
12097                         $this->valid[__FUNCTION__] = true;
12098                         return true;
12099                 }
12100                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12101                 {
12102                         $this->path = null;
12103                         $this->valid[__FUNCTION__] = false;
12104                         return false;
12105                 }
12106                 else
12107                 {
12108                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12109                         if ($this->scheme !== null)
12110                         {
12111                                 $this->path = $this->remove_dot_segments($this->path);
12112                         }
12113                         $this->valid[__FUNCTION__] = true;
12114                         return true;
12115                 }
12116         }
12117
12118         /**
12119          * Set the query.
12120          *
12121          * @access public
12122          * @param string $query
12123          * @return bool
12124          */
12125         function set_query($query)
12126         {
12127                 if ($query === null || $query === '')
12128                 {
12129                         $this->query = null;
12130                 }
12131                 else
12132                 {
12133                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12134                 }
12135                 $this->valid[__FUNCTION__] = true;
12136                 return true;
12137         }
12138
12139         /**
12140          * Set the fragment.
12141          *
12142          * @access public
12143          * @param string $fragment
12144          * @return bool
12145          */
12146         function set_fragment($fragment)
12147         {
12148                 if ($fragment === null || $fragment === '')
12149                 {
12150                         $this->fragment = null;
12151                 }
12152                 else
12153                 {
12154                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12155                 }
12156                 $this->valid[__FUNCTION__] = true;
12157                 return true;
12158         }
12159
12160         /**
12161          * Get the complete IRI
12162          *
12163          * @access public
12164          * @return string
12165          */
12166         function get_iri()
12167         {
12168                 $iri = '';
12169                 if ($this->scheme !== null)
12170                 {
12171                         $iri .= $this->scheme . ':';
12172                 }
12173                 if (($authority = $this->get_authority()) !== null)
12174                 {
12175                         $iri .= '//' . $authority;
12176                 }
12177                 if ($this->path !== null)
12178                 {
12179                         $iri .= $this->path;
12180                 }
12181                 if ($this->query !== null)
12182                 {
12183                         $iri .= '?' . $this->query;
12184                 }
12185                 if ($this->fragment !== null)
12186                 {
12187                         $iri .= '#' . $this->fragment;
12188                 }
12189
12190                 if ($iri !== '')
12191                 {
12192                         return $iri;
12193                 }
12194                 else
12195                 {
12196                         return null;
12197                 }
12198         }
12199
12200         /**
12201          * Get the scheme
12202          *
12203          * @access public
12204          * @return string
12205          */
12206         function get_scheme()
12207         {
12208                 return $this->scheme;
12209         }
12210
12211         /**
12212          * Get the complete authority
12213          *
12214          * @access public
12215          * @return string
12216          */
12217         function get_authority()
12218         {
12219                 $authority = '';
12220                 if ($this->userinfo !== null)
12221                 {
12222                         $authority .= $this->userinfo . '@';
12223                 }
12224                 if ($this->host !== null)
12225                 {
12226                         $authority .= $this->host;
12227                 }
12228                 if ($this->port !== null)
12229                 {
12230                         $authority .= ':' . $this->port;
12231                 }
12232
12233                 if ($authority !== '')
12234                 {
12235                         return $authority;
12236                 }
12237                 else
12238                 {
12239                         return null;
12240                 }
12241         }
12242
12243         /**
12244          * Get the user information
12245          *
12246          * @access public
12247          * @return string
12248          */
12249         function get_userinfo()
12250         {
12251                 return $this->userinfo;
12252         }
12253
12254         /**
12255          * Get the host
12256          *
12257          * @access public
12258          * @return string
12259          */
12260         function get_host()
12261         {
12262                 return $this->host;
12263         }
12264
12265         /**
12266          * Get the port
12267          *
12268          * @access public
12269          * @return string
12270          */
12271         function get_port()
12272         {
12273                 return $this->port;
12274         }
12275
12276         /**
12277          * Get the path
12278          *
12279          * @access public
12280          * @return string
12281          */
12282         function get_path()
12283         {
12284                 return $this->path;
12285         }
12286
12287         /**
12288          * Get the query
12289          *
12290          * @access public
12291          * @return string
12292          */
12293         function get_query()
12294         {
12295                 return $this->query;
12296         }
12297
12298         /**
12299          * Get the fragment
12300          *
12301          * @access public
12302          * @return string
12303          */
12304         function get_fragment()
12305         {
12306                 return $this->fragment;
12307         }
12308 }
12309
12310 /**
12311  * Class to validate and to work with IPv6 addresses.
12312  *
12313  * @package SimplePie
12314  * @copyright 2003-2005 The PHP Group
12315  * @license http://www.opensource.org/licenses/bsd-license.php
12316  * @link http://pear.php.net/package/Net_IPv6
12317  * @author Alexander Merz <alexander.merz@web.de>
12318  * @author elfrink at introweb dot nl
12319  * @author Josh Peck <jmp at joshpeck dot org>
12320  * @author Geoffrey Sneddon <geoffers@gmail.com>
12321  */
12322 class SimplePie_Net_IPv6
12323 {
12324         /**
12325          * Removes a possible existing netmask specification of an IP address.
12326          *
12327          * @param string $ip the (compressed) IP as Hex representation
12328          * @return string the IP the without netmask
12329          * @since 1.1.0
12330          * @access public
12331          * @static
12332          */
12333         function removeNetmaskSpec($ip)
12334         {
12335                 if (strpos($ip, '/') !== false)
12336                 {
12337                         list($addr, $nm) = explode('/', $ip);
12338                 }
12339                 else
12340                 {
12341                         $addr = $ip;
12342                 }
12343                 return $addr;
12344         }
12345
12346         /**
12347          * Uncompresses an IPv6 address
12348          *
12349          * RFC 2373 allows you to compress zeros in an address to '::'. This
12350          * function expects an valid IPv6 address and expands the '::' to
12351          * the required zeros.
12352          *
12353          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12354          *                       ::1            ->      0:0:0:0:0:0:0:1
12355          *
12356          * @access public
12357          * @static
12358          * @param string $ip a valid IPv6-address (hex format)
12359          * @return string the uncompressed IPv6-address (hex format)
12360          */
12361         function Uncompress($ip)
12362         {
12363                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12364                 $c1 = -1;
12365                 $c2 = -1;
12366                 if (strpos($ip, '::') !== false)
12367                 {
12368                         list($ip1, $ip2) = explode('::', $ip);
12369                         if ($ip1 === '')
12370                         {
12371                                 $c1 = -1;
12372                         }
12373                         else
12374                         {
12375                                 $pos = 0;
12376                                 if (($pos = substr_count($ip1, ':')) > 0)
12377                                 {
12378                                         $c1 = $pos;
12379                                 }
12380                                 else
12381                                 {
12382                                         $c1 = 0;
12383                                 }
12384                         }
12385                         if ($ip2 === '')
12386                         {
12387                                 $c2 = -1;
12388                         }
12389                         else
12390                         {
12391                                 $pos = 0;
12392                                 if (($pos = substr_count($ip2, ':')) > 0)
12393                                 {
12394                                         $c2 = $pos;
12395                                 }
12396                                 else
12397                                 {
12398                                         $c2 = 0;
12399                                 }
12400                         }
12401                         if (strstr($ip2, '.'))
12402                         {
12403                                 $c2++;
12404                         }
12405                         // ::
12406                         if ($c1 === -1 && $c2 === -1)
12407                         {
12408                                 $uip = '0:0:0:0:0:0:0:0';
12409                         }
12410                         // ::xxx
12411                         else if ($c1 === -1)
12412                         {
12413                                 $fill = str_repeat('0:', 7 - $c2);
12414                                 $uip =  str_replace('::', $fill, $uip);
12415                         }
12416                         // xxx::
12417                         else if ($c2 === -1)
12418                         {
12419                                 $fill = str_repeat(':0', 7 - $c1);
12420                                 $uip =  str_replace('::', $fill, $uip);
12421                         }
12422                         // xxx::xxx
12423                         else
12424                         {
12425                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12426                                 $uip =  str_replace('::', $fill, $uip);
12427                                 $uip =  str_replace('::', ':', $uip);
12428                         }
12429                 }
12430                 return $uip;
12431         }
12432
12433         /**
12434          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12435          *
12436          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12437          * an IPv4 compatible address
12438          *
12439          * Example:      0:0:0:0:0:0:13.1.68.3
12440          *                       0:0:0:0:0:FFFF:129.144.52.38
12441          *
12442          * @access public
12443          * @static
12444          * @param string $ip a valid IPv6-address (hex format)
12445          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12446          */
12447         function SplitV64($ip)
12448         {
12449                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12450                 if (strstr($ip, '.'))
12451                 {
12452                         $pos = strrpos($ip, ':');
12453                         $ip[$pos] = '_';
12454                         $ipPart = explode('_', $ip);
12455                         return $ipPart;
12456                 }
12457                 else
12458                 {
12459                         return array($ip, '');
12460                 }
12461         }
12462
12463         /**
12464          * Checks an IPv6 address
12465          *
12466          * Checks if the given IP is IPv6-compatible
12467          *
12468          * @access public
12469          * @static
12470          * @param string $ip a valid IPv6-address
12471          * @return bool true if $ip is an IPv6 address
12472          */
12473         function checkIPv6($ip)
12474         {
12475                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12476                 $count = 0;
12477                 if (!empty($ipPart[0]))
12478                 {
12479                         $ipv6 = explode(':', $ipPart[0]);
12480                         for ($i = 0; $i < count($ipv6); $i++)
12481                         {
12482                                 $dec = hexdec($ipv6[$i]);
12483                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12484                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12485                                 {
12486                                         $count++;
12487                                 }
12488                         }
12489                         if ($count === 8)
12490                         {
12491                                 return true;
12492                         }
12493                         elseif ($count === 6 && !empty($ipPart[1]))
12494                         {
12495                                 $ipv4 = explode('.', $ipPart[1]);
12496                                 $count = 0;
12497                                 foreach ($ipv4 as $ipv4_part)
12498                                 {
12499                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12500                                         {
12501                                                 $count++;
12502                                         }
12503                                 }
12504                                 if ($count === 4)
12505                                 {
12506                                         return true;
12507                                 }
12508                         }
12509                         else
12510                         {
12511                                 return false;
12512                         }
12513
12514                 }
12515                 else
12516                 {
12517                         return false;
12518                 }
12519         }
12520 }
12521
12522 /**
12523  * Date Parser
12524  *
12525  * @package SimplePie
12526  */
12527 class SimplePie_Parse_Date
12528 {
12529         /**
12530          * Input data
12531          *
12532          * @access protected
12533          * @var string
12534          */
12535         var $date;
12536
12537         /**
12538          * List of days, calendar day name => ordinal day number in the week
12539          *
12540          * @access protected
12541          * @var array
12542          */
12543         var $day = array(
12544                 // English
12545                 'mon' => 1,
12546                 'monday' => 1,
12547                 'tue' => 2,
12548                 'tuesday' => 2,
12549                 'wed' => 3,
12550                 'wednesday' => 3,
12551                 'thu' => 4,
12552                 'thursday' => 4,
12553                 'fri' => 5,
12554                 'friday' => 5,
12555                 'sat' => 6,
12556                 'saturday' => 6,
12557                 'sun' => 7,
12558                 'sunday' => 7,
12559                 // Dutch
12560                 'maandag' => 1,
12561                 'dinsdag' => 2,
12562                 'woensdag' => 3,
12563                 'donderdag' => 4,
12564                 'vrijdag' => 5,
12565                 'zaterdag' => 6,
12566                 'zondag' => 7,
12567                 // French
12568                 'lundi' => 1,
12569                 'mardi' => 2,
12570                 'mercredi' => 3,
12571                 'jeudi' => 4,
12572                 'vendredi' => 5,
12573                 'samedi' => 6,
12574                 'dimanche' => 7,
12575                 // German
12576                 'montag' => 1,
12577                 'dienstag' => 2,
12578                 'mittwoch' => 3,
12579                 'donnerstag' => 4,
12580                 'freitag' => 5,
12581                 'samstag' => 6,
12582                 'sonnabend' => 6,
12583                 'sonntag' => 7,
12584                 // Italian
12585                 'lunedì' => 1,
12586                 'martedì' => 2,
12587                 'mercoledì' => 3,
12588                 'giovedì' => 4,
12589                 'venerdì' => 5,
12590                 'sabato' => 6,
12591                 'domenica' => 7,
12592                 // Spanish
12593                 'lunes' => 1,
12594                 'martes' => 2,
12595                 'miércoles' => 3,
12596                 'jueves' => 4,
12597                 'viernes' => 5,
12598                 'sábado' => 6,
12599                 'domingo' => 7,
12600                 // Finnish
12601                 'maanantai' => 1,
12602                 'tiistai' => 2,
12603                 'keskiviikko' => 3,
12604                 'torstai' => 4,
12605                 'perjantai' => 5,
12606                 'lauantai' => 6,
12607                 'sunnuntai' => 7,
12608                 // Hungarian
12609                 'hétfő' => 1,
12610                 'kedd' => 2,
12611                 'szerda' => 3,
12612                 'csütörtok' => 4,
12613                 'péntek' => 5,
12614                 'szombat' => 6,
12615                 'vasárnap' => 7,
12616                 // Greek
12617                 'Δευ' => 1,
12618                 'Τρι' => 2,
12619                 'Τετ' => 3,
12620                 'Πεμ' => 4,
12621                 'Παρ' => 5,
12622                 'Σαβ' => 6,
12623                 'Κυρ' => 7,
12624         );
12625
12626         /**
12627          * List of months, calendar month name => calendar month number
12628          *
12629          * @access protected
12630          * @var array
12631          */
12632         var $month = array(
12633                 // English
12634                 'jan' => 1,
12635                 'january' => 1,
12636                 'feb' => 2,
12637                 'february' => 2,
12638                 'mar' => 3,
12639                 'march' => 3,
12640                 'apr' => 4,
12641                 'april' => 4,
12642                 'may' => 5,
12643                 // No long form of May
12644                 'jun' => 6,
12645                 'june' => 6,
12646                 'jul' => 7,
12647                 'july' => 7,
12648                 'aug' => 8,
12649                 'august' => 8,
12650                 'sep' => 9,
12651                 'september' => 8,
12652                 'oct' => 10,
12653                 'october' => 10,
12654                 'nov' => 11,
12655                 'november' => 11,
12656                 'dec' => 12,
12657                 'december' => 12,
12658                 // Dutch
12659                 'januari' => 1,
12660                 'februari' => 2,
12661                 'maart' => 3,
12662                 'april' => 4,
12663                 'mei' => 5,
12664                 'juni' => 6,
12665                 'juli' => 7,
12666                 'augustus' => 8,
12667                 'september' => 9,
12668                 'oktober' => 10,
12669                 'november' => 11,
12670                 'december' => 12,
12671                 // French
12672                 'janvier' => 1,
12673                 'février' => 2,
12674                 'mars' => 3,
12675                 'avril' => 4,
12676                 'mai' => 5,
12677                 'juin' => 6,
12678                 'juillet' => 7,
12679                 'août' => 8,
12680                 'septembre' => 9,
12681                 'octobre' => 10,
12682                 'novembre' => 11,
12683                 'décembre' => 12,
12684                 // German
12685                 'januar' => 1,
12686                 'februar' => 2,
12687                 'märz' => 3,
12688                 'april' => 4,
12689                 'mai' => 5,
12690                 'juni' => 6,
12691                 'juli' => 7,
12692                 'august' => 8,
12693                 'september' => 9,
12694                 'oktober' => 10,
12695                 'november' => 11,
12696                 'dezember' => 12,
12697                 // Italian
12698                 'gennaio' => 1,
12699                 'febbraio' => 2,
12700                 'marzo' => 3,
12701                 'aprile' => 4,
12702                 'maggio' => 5,
12703                 'giugno' => 6,
12704                 'luglio' => 7,
12705                 'agosto' => 8,
12706                 'settembre' => 9,
12707                 'ottobre' => 10,
12708                 'novembre' => 11,
12709                 'dicembre' => 12,
12710                 // Spanish
12711                 'enero' => 1,
12712                 'febrero' => 2,
12713                 'marzo' => 3,
12714                 'abril' => 4,
12715                 'mayo' => 5,
12716                 'junio' => 6,
12717                 'julio' => 7,
12718                 'agosto' => 8,
12719                 'septiembre' => 9,
12720                 'setiembre' => 9,
12721                 'octubre' => 10,
12722                 'noviembre' => 11,
12723                 'diciembre' => 12,
12724                 // Finnish
12725                 'tammikuu' => 1,
12726                 'helmikuu' => 2,
12727                 'maaliskuu' => 3,
12728                 'huhtikuu' => 4,
12729                 'toukokuu' => 5,
12730                 'kesäkuu' => 6,
12731                 'heinäkuu' => 7,
12732                 'elokuu' => 8,
12733                 'suuskuu' => 9,
12734                 'lokakuu' => 10,
12735                 'marras' => 11,
12736                 'joulukuu' => 12,
12737                 // Hungarian
12738                 'január' => 1,
12739                 'február' => 2,
12740                 'március' => 3,
12741                 'április' => 4,
12742                 'május' => 5,
12743                 'június' => 6,
12744                 'július' => 7,
12745                 'augusztus' => 8,
12746                 'szeptember' => 9,
12747                 'október' => 10,
12748                 'november' => 11,
12749                 'december' => 12,
12750                 // Greek
12751                 'Ιαν' => 1,
12752                 'Φεβ' => 2,
12753                 'Μάώ' => 3,
12754                 'Μαώ' => 3,
12755                 'Απρ' => 4,
12756                 'Μάι' => 5,
12757                 'Μαϊ' => 5,
12758                 'Μαι' => 5,
12759                 'Ιούν' => 6,
12760                 'Ιον' => 6,
12761                 'Ιούλ' => 7,
12762                 'Ιολ' => 7,
12763                 'Αύγ' => 8,
12764                 'Αυγ' => 8,
12765                 'Σεπ' => 9,
12766                 'Οκτ' => 10,
12767                 'Νοέ' => 11,
12768                 'Δεκ' => 12,
12769         );
12770
12771         /**
12772          * List of timezones, abbreviation => offset from UTC
12773          *
12774          * @access protected
12775          * @var array
12776          */
12777         var $timezone = array(
12778                 'ACDT' => 37800,
12779                 'ACIT' => 28800,
12780                 'ACST' => 34200,
12781                 'ACT' => -18000,
12782                 'ACWDT' => 35100,
12783                 'ACWST' => 31500,
12784                 'AEDT' => 39600,
12785                 'AEST' => 36000,
12786                 'AFT' => 16200,
12787                 'AKDT' => -28800,
12788                 'AKST' => -32400,
12789                 'AMDT' => 18000,
12790                 'AMT' => -14400,
12791                 'ANAST' => 46800,
12792                 'ANAT' => 43200,
12793                 'ART' => -10800,
12794                 'AZOST' => -3600,
12795                 'AZST' => 18000,
12796                 'AZT' => 14400,
12797                 'BIOT' => 21600,
12798                 'BIT' => -43200,
12799                 'BOT' => -14400,
12800                 'BRST' => -7200,
12801                 'BRT' => -10800,
12802                 'BST' => 3600,
12803                 'BTT' => 21600,
12804                 'CAST' => 18000,
12805                 'CAT' => 7200,
12806                 'CCT' => 23400,
12807                 'CDT' => -18000,
12808                 'CEDT' => 7200,
12809                 'CET' => 3600,
12810                 'CGST' => -7200,
12811                 'CGT' => -10800,
12812                 'CHADT' => 49500,
12813                 'CHAST' => 45900,
12814                 'CIST' => -28800,
12815                 'CKT' => -36000,
12816                 'CLDT' => -10800,
12817                 'CLST' => -14400,
12818                 'COT' => -18000,
12819                 'CST' => -21600,
12820                 'CVT' => -3600,
12821                 'CXT' => 25200,
12822                 'DAVT' => 25200,
12823                 'DTAT' => 36000,
12824                 'EADT' => -18000,
12825                 'EAST' => -21600,
12826                 'EAT' => 10800,
12827                 'ECT' => -18000,
12828                 'EDT' => -14400,
12829                 'EEST' => 10800,
12830                 'EET' => 7200,
12831                 'EGT' => -3600,
12832                 'EKST' => 21600,
12833                 'EST' => -18000,
12834                 'FJT' => 43200,
12835                 'FKDT' => -10800,
12836                 'FKST' => -14400,
12837                 'FNT' => -7200,
12838                 'GALT' => -21600,
12839                 'GEDT' => 14400,
12840                 'GEST' => 10800,
12841                 'GFT' => -10800,
12842                 'GILT' => 43200,
12843                 'GIT' => -32400,
12844                 'GST' => 14400,
12845                 'GST' => -7200,
12846                 'GYT' => -14400,
12847                 'HAA' => -10800,
12848                 'HAC' => -18000,
12849                 'HADT' => -32400,
12850                 'HAE' => -14400,
12851                 'HAP' => -25200,
12852                 'HAR' => -21600,
12853                 'HAST' => -36000,
12854                 'HAT' => -9000,
12855                 'HAY' => -28800,
12856                 'HKST' => 28800,
12857                 'HMT' => 18000,
12858                 'HNA' => -14400,
12859                 'HNC' => -21600,
12860                 'HNE' => -18000,
12861                 'HNP' => -28800,
12862                 'HNR' => -25200,
12863                 'HNT' => -12600,
12864                 'HNY' => -32400,
12865                 'IRDT' => 16200,
12866                 'IRKST' => 32400,
12867                 'IRKT' => 28800,
12868                 'IRST' => 12600,
12869                 'JFDT' => -10800,
12870                 'JFST' => -14400,
12871                 'JST' => 32400,
12872                 'KGST' => 21600,
12873                 'KGT' => 18000,
12874                 'KOST' => 39600,
12875                 'KOVST' => 28800,
12876                 'KOVT' => 25200,
12877                 'KRAST' => 28800,
12878                 'KRAT' => 25200,
12879                 'KST' => 32400,
12880                 'LHDT' => 39600,
12881                 'LHST' => 37800,
12882                 'LINT' => 50400,
12883                 'LKT' => 21600,
12884                 'MAGST' => 43200,
12885                 'MAGT' => 39600,
12886                 'MAWT' => 21600,
12887                 'MDT' => -21600,
12888                 'MESZ' => 7200,
12889                 'MEZ' => 3600,
12890                 'MHT' => 43200,
12891                 'MIT' => -34200,
12892                 'MNST' => 32400,
12893                 'MSDT' => 14400,
12894                 'MSST' => 10800,
12895                 'MST' => -25200,
12896                 'MUT' => 14400,
12897                 'MVT' => 18000,
12898                 'MYT' => 28800,
12899                 'NCT' => 39600,
12900                 'NDT' => -9000,
12901                 'NFT' => 41400,
12902                 'NMIT' => 36000,
12903                 'NOVST' => 25200,
12904                 'NOVT' => 21600,
12905                 'NPT' => 20700,
12906                 'NRT' => 43200,
12907                 'NST' => -12600,
12908                 'NUT' => -39600,
12909                 'NZDT' => 46800,
12910                 'NZST' => 43200,
12911                 'OMSST' => 25200,
12912                 'OMST' => 21600,
12913                 'PDT' => -25200,
12914                 'PET' => -18000,
12915                 'PETST' => 46800,
12916                 'PETT' => 43200,
12917                 'PGT' => 36000,
12918                 'PHOT' => 46800,
12919                 'PHT' => 28800,
12920                 'PKT' => 18000,
12921                 'PMDT' => -7200,
12922                 'PMST' => -10800,
12923                 'PONT' => 39600,
12924                 'PST' => -28800,
12925                 'PWT' => 32400,
12926                 'PYST' => -10800,
12927                 'PYT' => -14400,
12928                 'RET' => 14400,
12929                 'ROTT' => -10800,
12930                 'SAMST' => 18000,
12931                 'SAMT' => 14400,
12932                 'SAST' => 7200,
12933                 'SBT' => 39600,
12934                 'SCDT' => 46800,
12935                 'SCST' => 43200,
12936                 'SCT' => 14400,
12937                 'SEST' => 3600,
12938                 'SGT' => 28800,
12939                 'SIT' => 28800,
12940                 'SRT' => -10800,
12941                 'SST' => -39600,
12942                 'SYST' => 10800,
12943                 'SYT' => 7200,
12944                 'TFT' => 18000,
12945                 'THAT' => -36000,
12946                 'TJT' => 18000,
12947                 'TKT' => -36000,
12948                 'TMT' => 18000,
12949                 'TOT' => 46800,
12950                 'TPT' => 32400,
12951                 'TRUT' => 36000,
12952                 'TVT' => 43200,
12953                 'TWT' => 28800,
12954                 'UYST' => -7200,
12955                 'UYT' => -10800,
12956                 'UZT' => 18000,
12957                 'VET' => -14400,
12958                 'VLAST' => 39600,
12959                 'VLAT' => 36000,
12960                 'VOST' => 21600,
12961                 'VUT' => 39600,
12962                 'WAST' => 7200,
12963                 'WAT' => 3600,
12964                 'WDT' => 32400,
12965                 'WEST' => 3600,
12966                 'WFT' => 43200,
12967                 'WIB' => 25200,
12968                 'WIT' => 32400,
12969                 'WITA' => 28800,
12970                 'WKST' => 18000,
12971                 'WST' => 28800,
12972                 'YAKST' => 36000,
12973                 'YAKT' => 32400,
12974                 'YAPT' => 36000,
12975                 'YEKST' => 21600,
12976                 'YEKT' => 18000,
12977         );
12978
12979         /**
12980          * Cached PCRE for SimplePie_Parse_Date::$day
12981          *
12982          * @access protected
12983          * @var string
12984          */
12985         var $day_pcre;
12986
12987         /**
12988          * Cached PCRE for SimplePie_Parse_Date::$month
12989          *
12990          * @access protected
12991          * @var string
12992          */
12993         var $month_pcre;
12994
12995         /**
12996          * Array of user-added callback methods
12997          *
12998          * @access private
12999          * @var array
13000          */
13001         var $built_in = array();
13002
13003         /**
13004          * Array of user-added callback methods
13005          *
13006          * @access private
13007          * @var array
13008          */
13009         var $user = array();
13010
13011         /**
13012          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13013          * self::month_pcre, and self::built_in
13014          *
13015          * @access private
13016          */
13017         function SimplePie_Parse_Date()
13018         {
13019                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13020                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13021
13022                 static $cache;
13023                 if (!isset($cache[get_class($this)]))
13024                 {
13025                         $all_methods = get_class_methods($this);
13026
13027                         foreach ($all_methods as $method)
13028                         {
13029                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13030                                 {
13031                                         $cache[get_class($this)][] = $method;
13032                                 }
13033                         }
13034                 }
13035
13036                 foreach ($cache[get_class($this)] as $method)
13037                 {
13038                         $this->built_in[] = $method;
13039                 }
13040         }
13041
13042         /**
13043          * Get the object
13044          *
13045          * @access public
13046          */
13047         function get()
13048         {
13049                 static $object;
13050                 if (!$object)
13051                 {
13052                         $object =& new SimplePie_Parse_Date;
13053                 }
13054                 return $object;
13055         }
13056
13057         /**
13058          * Parse a date
13059          *
13060          * @final
13061          * @access public
13062          * @param string $date Date to parse
13063          * @return int Timestamp corresponding to date string, or false on failure
13064          */
13065         function parse($date)
13066         {
13067                 foreach ($this->user as $method)
13068                 {
13069                         if (($returned = call_user_func($method, $date)) !== false)
13070                         {
13071                                 return $returned;
13072                         }
13073                 }
13074
13075                 foreach ($this->built_in as $method)
13076                 {
13077                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13078                         {
13079                                 return $returned;
13080                         }
13081                 }
13082
13083                 return false;
13084         }
13085
13086         /**
13087          * Add a callback method to parse a date
13088          *
13089          * @final
13090          * @access public
13091          * @param callback $callback
13092          */
13093         function add_callback($callback)
13094         {
13095                 if (is_callable($callback))
13096                 {
13097                         $this->user[] = $callback;
13098                 }
13099                 else
13100                 {
13101                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13102                 }
13103         }
13104
13105         /**
13106          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13107          * well as allowing any of upper or lower case "T", horizontal tabs, or
13108          * spaces to be used as the time seperator (including more than one))
13109          *
13110          * @access protected
13111          * @return int Timestamp
13112          */
13113         function date_w3cdtf($date)
13114         {
13115                 static $pcre;
13116                 if (!$pcre)
13117                 {
13118                         $year = '([0-9]{4})';
13119                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13120                         $decimal = '([0-9]*)';
13121                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13122                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13123                 }
13124                 if (preg_match($pcre, $date, $match))
13125                 {
13126                         /*
13127                         Capturing subpatterns:
13128                         1: Year
13129                         2: Month
13130                         3: Day
13131                         4: Hour
13132                         5: Minute
13133                         6: Second
13134                         7: Decimal fraction of a second
13135                         8: Zulu
13136                         9: Timezone ±
13137                         10: Timezone hours
13138                         11: Timezone minutes
13139                         */
13140
13141                         // Fill in empty matches
13142                         for ($i = count($match); $i <= 3; $i++)
13143                         {
13144                                 $match[$i] = '1';
13145                         }
13146
13147                         for ($i = count($match); $i <= 7; $i++)
13148                         {
13149                                 $match[$i] = '0';
13150                         }
13151
13152                         // Numeric timezone
13153                         if (isset($match[9]) && $match[9] !== '')
13154                         {
13155                                 $timezone = $match[10] * 3600;
13156                                 $timezone += $match[11] * 60;
13157                                 if ($match[9] === '-')
13158                                 {
13159                                         $timezone = 0 - $timezone;
13160                                 }
13161                         }
13162                         else
13163                         {
13164                                 $timezone = 0;
13165                         }
13166
13167                         // Convert the number of seconds to an integer, taking decimals into account
13168                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13169
13170                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13171                 }
13172                 else
13173                 {
13174                         return false;
13175                 }
13176         }
13177
13178         /**
13179          * Remove RFC822 comments
13180          *
13181          * @access protected
13182          * @param string $data Data to strip comments from
13183          * @return string Comment stripped string
13184          */
13185         function remove_rfc2822_comments($string)
13186         {
13187                 $string = (string) $string;
13188                 $position = 0;
13189                 $length = strlen($string);
13190                 $depth = 0;
13191
13192                 $output = '';
13193
13194                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13195                 {
13196                         $output .= substr($string, $position, $pos - $position);
13197                         $position = $pos + 1;
13198                         if ($string[$pos - 1] !== '\\')
13199                         {
13200                                 $depth++;
13201                                 while ($depth && $position < $length)
13202                                 {
13203                                         $position += strcspn($string, '()', $position);
13204                                         if ($string[$position - 1] === '\\')
13205                                         {
13206                                                 $position++;
13207                                                 continue;
13208                                         }
13209                                         elseif (isset($string[$position]))
13210                                         {
13211                                                 switch ($string[$position])
13212                                                 {
13213                                                         case '(':
13214                                                                 $depth++;
13215                                                                 break;
13216
13217                                                         case ')':
13218                                                                 $depth--;
13219                                                                 break;
13220                                                 }
13221                                                 $position++;
13222                                         }
13223                                         else
13224                                         {
13225                                                 break;
13226                                         }
13227                                 }
13228                         }
13229                         else
13230                         {
13231                                 $output .= '(';
13232                         }
13233                 }
13234                 $output .= substr($string, $position);
13235
13236                 return $output;
13237         }
13238
13239         /**
13240          * Parse RFC2822's date format
13241          *
13242          * @access protected
13243          * @return int Timestamp
13244          */
13245         function date_rfc2822($date)
13246         {
13247                 static $pcre;
13248                 if (!$pcre)
13249                 {
13250                         $wsp = '[\x09\x20]';
13251                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13252                         $optional_fws = $fws . '?';
13253                         $day_name = $this->day_pcre;
13254                         $month = $this->month_pcre;
13255                         $day = '([0-9]{1,2})';
13256                         $hour = $minute = $second = '([0-9]{2})';
13257                         $year = '([0-9]{2,4})';
13258                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13259                         $character_zone = '([A-Z]{1,5})';
13260                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13261                         $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';
13262                 }
13263                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13264                 {
13265                         /*
13266                         Capturing subpatterns:
13267                         1: Day name
13268                         2: Day
13269                         3: Month
13270                         4: Year
13271                         5: Hour
13272                         6: Minute
13273                         7: Second
13274                         8: Timezone ±
13275                         9: Timezone hours
13276                         10: Timezone minutes
13277                         11: Alphabetic timezone
13278                         */
13279
13280                         // Find the month number
13281                         $month = $this->month[strtolower($match[3])];
13282
13283                         // Numeric timezone
13284                         if ($match[8] !== '')
13285                         {
13286                                 $timezone = $match[9] * 3600;
13287                                 $timezone += $match[10] * 60;
13288                                 if ($match[8] === '-')
13289                                 {
13290                                         $timezone = 0 - $timezone;
13291                                 }
13292                         }
13293                         // Character timezone
13294                         elseif (isset($this->timezone[strtoupper($match[11])]))
13295                         {
13296                                 $timezone = $this->timezone[strtoupper($match[11])];
13297                         }
13298                         // Assume everything else to be -0000
13299                         else
13300                         {
13301                                 $timezone = 0;
13302                         }
13303
13304                         // Deal with 2/3 digit years
13305                         if ($match[4] < 50)
13306                         {
13307                                 $match[4] += 2000;
13308                         }
13309                         elseif ($match[4] < 1000)
13310                         {
13311                                 $match[4] += 1900;
13312                         }
13313
13314                         // Second is optional, if it is empty set it to zero
13315                         if ($match[7] !== '')
13316                         {
13317                                 $second = $match[7];
13318                         }
13319                         else
13320                         {
13321                                 $second = 0;
13322                         }
13323
13324                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13325                 }
13326                 else
13327                 {
13328                         return false;
13329                 }
13330         }
13331
13332         /**
13333          * Parse RFC850's date format
13334          *
13335          * @access protected
13336          * @return int Timestamp
13337          */
13338         function date_rfc850($date)
13339         {
13340                 static $pcre;
13341                 if (!$pcre)
13342                 {
13343                         $space = '[\x09\x20]+';
13344                         $day_name = $this->day_pcre;
13345                         $month = $this->month_pcre;
13346                         $day = '([0-9]{1,2})';
13347                         $year = $hour = $minute = $second = '([0-9]{2})';
13348                         $zone = '([A-Z]{1,5})';
13349                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13350                 }
13351                 if (preg_match($pcre, $date, $match))
13352                 {
13353                         /*
13354                         Capturing subpatterns:
13355                         1: Day name
13356                         2: Day
13357                         3: Month
13358                         4: Year
13359                         5: Hour
13360                         6: Minute
13361                         7: Second
13362                         8: Timezone
13363                         */
13364
13365                         // Month
13366                         $month = $this->month[strtolower($match[3])];
13367
13368                         // Character timezone
13369                         if (isset($this->timezone[strtoupper($match[8])]))
13370                         {
13371                                 $timezone = $this->timezone[strtoupper($match[8])];
13372                         }
13373                         // Assume everything else to be -0000
13374                         else
13375                         {
13376                                 $timezone = 0;
13377                         }
13378
13379                         // Deal with 2 digit year
13380                         if ($match[4] < 50)
13381                         {
13382                                 $match[4] += 2000;
13383                         }
13384                         else
13385                         {
13386                                 $match[4] += 1900;
13387                         }
13388
13389                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13390                 }
13391                 else
13392                 {
13393                         return false;
13394                 }
13395         }
13396
13397         /**
13398          * Parse C99's asctime()'s date format
13399          *
13400          * @access protected
13401          * @return int Timestamp
13402          */
13403         function date_asctime($date)
13404         {
13405                 static $pcre;
13406                 if (!$pcre)
13407                 {
13408                         $space = '[\x09\x20]+';
13409                         $wday_name = $this->day_pcre;
13410                         $mon_name = $this->month_pcre;
13411                         $day = '([0-9]{1,2})';
13412                         $hour = $sec = $min = '([0-9]{2})';
13413                         $year = '([0-9]{4})';
13414                         $terminator = '\x0A?\x00?';
13415                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13416                 }
13417                 if (preg_match($pcre, $date, $match))
13418                 {
13419                         /*
13420                         Capturing subpatterns:
13421                         1: Day name
13422                         2: Month
13423                         3: Day
13424                         4: Hour
13425                         5: Minute
13426                         6: Second
13427                         7: Year
13428                         */
13429
13430                         $month = $this->month[strtolower($match[2])];
13431                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13432                 }
13433                 else
13434                 {
13435                         return false;
13436                 }
13437         }
13438
13439         /**
13440          * Parse dates using strtotime()
13441          *
13442          * @access protected
13443          * @return int Timestamp
13444          */
13445         function date_strtotime($date)
13446         {
13447                 $strtotime = strtotime($date);
13448                 if ($strtotime === -1 || $strtotime === false)
13449                 {
13450                         return false;
13451                 }
13452                 else
13453                 {
13454                         return $strtotime;
13455                 }
13456         }
13457 }
13458
13459 /**
13460  * Content-type sniffing
13461  *
13462  * @package SimplePie
13463  */
13464 class SimplePie_Content_Type_Sniffer
13465 {
13466         /**
13467          * File object
13468          *
13469          * @var SimplePie_File
13470          * @access private
13471          */
13472         var $file;
13473
13474         /**
13475          * Create an instance of the class with the input file
13476          *
13477          * @access public
13478          * @param SimplePie_Content_Type_Sniffer $file Input file
13479          */
13480         function SimplePie_Content_Type_Sniffer($file)
13481         {
13482                 $this->file = $file;
13483         }
13484
13485         /**
13486          * Get the Content-Type of the specified file
13487          *
13488          * @access public
13489          * @return string Actual Content-Type
13490          */
13491         function get_type()
13492         {
13493                 if (isset($this->file->headers['content-type']))
13494                 {
13495                         if (!isset($this->file->headers['content-encoding'])
13496                                 && ($this->file->headers['content-type'] === 'text/plain'
13497                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13498                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13499                         {
13500                                 return $this->text_or_binary();
13501                         }
13502
13503                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13504                         {
13505                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13506                         }
13507                         else
13508                         {
13509                                 $official = $this->file->headers['content-type'];
13510                         }
13511                         $official = strtolower($official);
13512
13513                         if ($official === 'unknown/unknown'
13514                                 || $official === 'application/unknown')
13515                         {
13516                                 return $this->unknown();
13517                         }
13518                         elseif (substr($official, -4) === '+xml'
13519                                 || $official === 'text/xml'
13520                                 || $official === 'application/xml')
13521                         {
13522                                 return $official;
13523                         }
13524                         elseif (substr($official, 0, 6) === 'image/')
13525                         {
13526                                 if ($return = $this->image())
13527                                 {
13528                                         return $return;
13529                                 }
13530                                 else
13531                                 {
13532                                         return $official;
13533                                 }
13534                         }
13535                         elseif ($official === 'text/html')
13536                         {
13537                                 return $this->feed_or_html();
13538                         }
13539                         else
13540                         {
13541                                 return $official;
13542                         }
13543                 }
13544                 else
13545                 {
13546                         return $this->unknown();
13547                 }
13548         }
13549
13550         /**
13551          * Sniff text or binary
13552          *
13553          * @access private
13554          * @return string Actual Content-Type
13555          */
13556         function text_or_binary()
13557         {
13558                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13559                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13560                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13561                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13562                 {
13563                         return 'text/plain';
13564                 }
13565                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13566                 {
13567                         return 'application/octect-stream';
13568                 }
13569                 else
13570                 {
13571                         return 'text/plain';
13572                 }
13573         }
13574
13575         /**
13576          * Sniff unknown
13577          *
13578          * @access private
13579          * @return string Actual Content-Type
13580          */
13581         function unknown()
13582         {
13583                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13584                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13585                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13586                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13587                 {
13588                         return 'text/html';
13589                 }
13590                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13591                 {
13592                         return 'application/pdf';
13593                 }
13594                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13595                 {
13596                         return 'application/postscript';
13597                 }
13598                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13599                         || substr($this->file->body, 0, 6) === 'GIF89a')
13600                 {
13601                         return 'image/gif';
13602                 }
13603                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13604                 {
13605                         return 'image/png';
13606                 }
13607                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13608                 {
13609                         return 'image/jpeg';
13610                 }
13611                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13612                 {
13613                         return 'image/bmp';
13614                 }
13615                 else
13616                 {
13617                         return $this->text_or_binary();
13618                 }
13619         }
13620
13621         /**
13622          * Sniff images
13623          *
13624          * @access private
13625          * @return string Actual Content-Type
13626          */
13627         function image()
13628         {
13629                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13630                         || substr($this->file->body, 0, 6) === 'GIF89a')
13631                 {
13632                         return 'image/gif';
13633                 }
13634                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13635                 {
13636                         return 'image/png';
13637                 }
13638                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13639                 {
13640                         return 'image/jpeg';
13641                 }
13642                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13643                 {
13644                         return 'image/bmp';
13645                 }
13646                 else
13647                 {
13648                         return false;
13649                 }
13650         }
13651
13652         /**
13653          * Sniff HTML
13654          *
13655          * @access private
13656          * @return string Actual Content-Type
13657          */
13658         function feed_or_html()
13659         {
13660                 $len = strlen($this->file->body);
13661                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13662
13663                 while ($pos < $len)
13664                 {
13665                         switch ($this->file->body[$pos])
13666                         {
13667                                 case "\x09":
13668                                 case "\x0A":
13669                                 case "\x0D":
13670                                 case "\x20":
13671                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13672                                         continue 2;
13673
13674                                 case '<':
13675                                         $pos++;
13676                                         break;
13677
13678                                 default:
13679                                         return 'text/html';
13680                         }
13681
13682                         if (substr($this->file->body, $pos, 3) === '!--')
13683                         {
13684                                 $pos += 3;
13685                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13686                                 {
13687                                         $pos += 3;
13688                                 }
13689                                 else
13690                                 {
13691                                         return 'text/html';
13692                                 }
13693                         }
13694                         elseif (substr($this->file->body, $pos, 1) === '!')
13695                         {
13696                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13697                                 {
13698                                         $pos++;
13699                                 }
13700                                 else
13701                                 {
13702                                         return 'text/html';
13703                                 }
13704                         }
13705                         elseif (substr($this->file->body, $pos, 1) === '?')
13706                         {
13707                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13708                                 {
13709                                         $pos += 2;
13710                                 }
13711                                 else
13712                                 {
13713                                         return 'text/html';
13714                                 }
13715                         }
13716                         elseif (substr($this->file->body, $pos, 3) === 'rss'
13717                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13718                         {
13719                                 return 'application/rss+xml';
13720                         }
13721                         elseif (substr($this->file->body, $pos, 4) === 'feed')
13722                         {
13723                                 return 'application/atom+xml';
13724                         }
13725                         else
13726                         {
13727                                 return 'text/html';
13728                         }
13729                 }
13730
13731                 return 'text/html';
13732         }
13733 }
13734
13735 /**
13736  * Parses the XML Declaration
13737  *
13738  * @package SimplePie
13739  */
13740 class SimplePie_XML_Declaration_Parser
13741 {
13742         /**
13743          * XML Version
13744          *
13745          * @access public
13746          * @var string
13747          */
13748         var $version = '1.0';
13749
13750         /**
13751          * Encoding
13752          *
13753          * @access public
13754          * @var string
13755          */
13756         var $encoding = 'UTF-8';
13757
13758         /**
13759          * Standalone
13760          *
13761          * @access public
13762          * @var bool
13763          */
13764         var $standalone = false;
13765
13766         /**
13767          * Current state of the state machine
13768          *
13769          * @access private
13770          * @var string
13771          */
13772         var $state = 'before_version_name';
13773
13774         /**
13775          * Input data
13776          *
13777          * @access private
13778          * @var string
13779          */
13780         var $data = '';
13781
13782         /**
13783          * Input data length (to avoid calling strlen() everytime this is needed)
13784          *
13785          * @access private
13786          * @var int
13787          */
13788         var $data_length = 0;
13789
13790         /**
13791          * Current position of the pointer
13792          *
13793          * @var int
13794          * @access private
13795          */
13796         var $position = 0;
13797
13798         /**
13799          * Create an instance of the class with the input data
13800          *
13801          * @access public
13802          * @param string $data Input data
13803          */
13804         function SimplePie_XML_Declaration_Parser($data)
13805         {
13806                 $this->data = $data;
13807                 $this->data_length = strlen($this->data);
13808         }
13809
13810         /**
13811          * Parse the input data
13812          *
13813          * @access public
13814          * @return bool true on success, false on failure
13815          */
13816         function parse()
13817         {
13818                 while ($this->state && $this->state !== 'emit' && $this->has_data())
13819                 {
13820                         $state = $this->state;
13821                         $this->$state();
13822                 }
13823                 $this->data = '';
13824                 if ($this->state === 'emit')
13825                 {
13826                         return true;
13827                 }
13828                 else
13829                 {
13830                         $this->version = '';
13831                         $this->encoding = '';
13832                         $this->standalone = '';
13833                         return false;
13834                 }
13835         }
13836
13837         /**
13838          * Check whether there is data beyond the pointer
13839          *
13840          * @access private
13841          * @return bool true if there is further data, false if not
13842          */
13843         function has_data()
13844         {
13845                 return (bool) ($this->position < $this->data_length);
13846         }
13847
13848         /**
13849          * Advance past any whitespace
13850          *
13851          * @return int Number of whitespace characters passed
13852          */
13853         function skip_whitespace()
13854         {
13855                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13856                 $this->position += $whitespace;
13857                 return $whitespace;
13858         }
13859
13860         /**
13861          * Read value
13862          */
13863         function get_value()
13864         {
13865                 $quote = substr($this->data, $this->position, 1);
13866                 if ($quote === '"' || $quote === "'")
13867                 {
13868                         $this->position++;
13869                         $len = strcspn($this->data, $quote, $this->position);
13870                         if ($this->has_data())
13871                         {
13872                                 $value = substr($this->data, $this->position, $len);
13873                                 $this->position += $len + 1;
13874                                 return $value;
13875                         }
13876                 }
13877                 return false;
13878         }
13879
13880         function before_version_name()
13881         {
13882                 if ($this->skip_whitespace())
13883                 {
13884                         $this->state = 'version_name';
13885                 }
13886                 else
13887                 {
13888                         $this->state = false;
13889                 }
13890         }
13891
13892         function version_name()
13893         {
13894                 if (substr($this->data, $this->position, 7) === 'version')
13895                 {
13896                         $this->position += 7;
13897                         $this->skip_whitespace();
13898                         $this->state = 'version_equals';
13899                 }
13900                 else
13901                 {
13902                         $this->state = false;
13903                 }
13904         }
13905
13906         function version_equals()
13907         {
13908                 if (substr($this->data, $this->position, 1) === '=')
13909                 {
13910                         $this->position++;
13911                         $this->skip_whitespace();
13912                         $this->state = 'version_value';
13913                 }
13914                 else
13915                 {
13916                         $this->state = false;
13917                 }
13918         }
13919
13920         function version_value()
13921         {
13922                 if ($this->version = $this->get_value())
13923                 {
13924                         $this->skip_whitespace();
13925                         if ($this->has_data())
13926                         {
13927                                 $this->state = 'encoding_name';
13928                         }
13929                         else
13930                         {
13931                                 $this->state = 'emit';
13932                         }
13933                 }
13934                 else
13935                 {
13936                         $this->state = 'standalone_name';
13937                 }
13938         }
13939
13940         function encoding_name()
13941         {
13942                 if (substr($this->data, $this->position, 8) === 'encoding')
13943                 {
13944                         $this->position += 8;
13945                         $this->skip_whitespace();
13946                         $this->state = 'encoding_equals';
13947                 }
13948                 else
13949                 {
13950                         $this->state = false;
13951                 }
13952         }
13953
13954         function encoding_equals()
13955         {
13956                 if (substr($this->data, $this->position, 1) === '=')
13957                 {
13958                         $this->position++;
13959                         $this->skip_whitespace();
13960                         $this->state = 'encoding_value';
13961                 }
13962                 else
13963                 {
13964                         $this->state = false;
13965                 }
13966         }
13967
13968         function encoding_value()
13969         {
13970                 if ($this->encoding = $this->get_value())
13971                 {
13972                         $this->skip_whitespace();
13973                         if ($this->has_data())
13974                         {
13975                                 $this->state = 'standalone_name';
13976                         }
13977                         else
13978                         {
13979                                 $this->state = 'emit';
13980                         }
13981                 }
13982                 else
13983                 {
13984                         $this->state = false;
13985                 }
13986         }
13987
13988         function standalone_name()
13989         {
13990                 if (substr($this->data, $this->position, 10) === 'standalone')
13991                 {
13992                         $this->position += 10;
13993                         $this->skip_whitespace();
13994                         $this->state = 'standalone_equals';
13995                 }
13996                 else
13997                 {
13998                         $this->state = false;
13999                 }
14000         }
14001
14002         function standalone_equals()
14003         {
14004                 if (substr($this->data, $this->position, 1) === '=')
14005                 {
14006                         $this->position++;
14007                         $this->skip_whitespace();
14008                         $this->state = 'standalone_value';
14009                 }
14010                 else
14011                 {
14012                         $this->state = false;
14013                 }
14014         }
14015
14016         function standalone_value()
14017         {
14018                 if ($standalone = $this->get_value())
14019                 {
14020                         switch ($standalone)
14021                         {
14022                                 case 'yes':
14023                                         $this->standalone = true;
14024                                         break;
14025
14026                                 case 'no':
14027                                         $this->standalone = false;
14028                                         break;
14029
14030                                 default:
14031                                         $this->state = false;
14032                                         return;
14033                         }
14034
14035                         $this->skip_whitespace();
14036                         if ($this->has_data())
14037                         {
14038                                 $this->state = false;
14039                         }
14040                         else
14041                         {
14042                                 $this->state = 'emit';
14043                         }
14044                 }
14045                 else
14046                 {
14047                         $this->state = false;
14048                 }
14049         }
14050 }
14051
14052 class SimplePie_Locator
14053 {
14054         var $useragent;
14055         var $timeout;
14056         var $file;
14057         var $local = array();
14058         var $elsewhere = array();
14059         var $file_class = 'SimplePie_File';
14060         var $cached_entities = array();
14061         var $http_base;
14062         var $base;
14063         var $base_location = 0;
14064         var $checked_feeds = 0;
14065         var $max_checked_feeds = 10;
14066         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14067
14068         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14069         {
14070                 $this->file =& $file;
14071                 $this->file_class = $file_class;
14072                 $this->useragent = $useragent;
14073                 $this->timeout = $timeout;
14074                 $this->max_checked_feeds = $max_checked_feeds;
14075                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14076         }
14077
14078         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14079         {
14080                 if ($this->is_feed($this->file))
14081                 {
14082                         return $this->file;
14083                 }
14084
14085                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14086                 {
14087                         $sniffer =& new $this->content_type_sniffer_class($this->file);
14088                         if ($sniffer->get_type() !== 'text/html')
14089                         {
14090                                 return null;
14091                         }
14092                 }
14093
14094                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14095                 {
14096                         $this->get_base();
14097                 }
14098
14099                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14100                 {
14101                         return $working[0];
14102                 }
14103
14104                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14105                 {
14106                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14107                         {
14108                                 return $working;
14109                         }
14110
14111                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14112                         {
14113                                 return $working;
14114                         }
14115
14116                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14117                         {
14118                                 return $working;
14119                         }
14120
14121                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14122                         {
14123                                 return $working;
14124                         }
14125                 }
14126                 return null;
14127         }
14128
14129         function is_feed(&$file)
14130         {
14131                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14132                 {
14133                         $sniffer =& new $this->content_type_sniffer_class($file);
14134                         $sniffed = $sniffer->get_type();
14135                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14136                         {
14137                                 return true;
14138                         }
14139                         else
14140                         {
14141                                 return false;
14142                         }
14143                 }
14144                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14145                 {
14146                         return true;
14147                 }
14148                 else
14149                 {
14150                         return false;
14151                 }
14152         }
14153
14154         function get_base()
14155         {
14156                 $this->http_base = $this->file->url;
14157                 $this->base = $this->http_base;
14158                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14159                 foreach ($elements as $element)
14160                 {
14161                         if ($element['attribs']['href']['data'] !== '')
14162                         {
14163                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14164                                 $this->base_location = $element['offset'];
14165                                 break;
14166                         }
14167                 }
14168         }
14169
14170         function autodiscovery()
14171         {
14172                 $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));
14173                 $done = array();
14174                 $feeds = array();
14175                 foreach ($links as $link)
14176                 {
14177                         if ($this->checked_feeds === $this->max_checked_feeds)
14178                         {
14179                                 break;
14180                         }
14181                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14182                         {
14183                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14184
14185                                 if ($this->base_location < $link['offset'])
14186                                 {
14187                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14188                                 }
14189                                 else
14190                                 {
14191                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14192                                 }
14193
14194                                 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]))
14195                                 {
14196                                         $this->checked_feeds++;
14197                                         $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14198                                         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))
14199                                         {
14200                                                 $feeds[$href] = $feed;
14201                                         }
14202                                 }
14203                                 $done[] = $href;
14204                         }
14205                 }
14206
14207                 if (!empty($feeds))
14208                 {
14209                         return array_values($feeds);
14210                 }
14211                 else {
14212                         return null;
14213                 }
14214         }
14215
14216         function get_links()
14217         {
14218                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14219                 foreach ($links as $link)
14220                 {
14221                         if (isset($link['attribs']['href']['data']))
14222                         {
14223                                 $href = trim($link['attribs']['href']['data']);
14224                                 $parsed = SimplePie_Misc::parse_url($href);
14225                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14226                                 {
14227                                         if ($this->base_location < $link['offset'])
14228                                         {
14229                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14230                                         }
14231                                         else
14232                                         {
14233                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14234                                         }
14235
14236                                         $current = SimplePie_Misc::parse_url($this->file->url);
14237
14238                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14239                                         {
14240                                                 $this->local[] = $href;
14241                                         }
14242                                         else
14243                                         {
14244                                                 $this->elsewhere[] = $href;
14245                                         }
14246                                 }
14247                         }
14248                 }
14249                 $this->local = array_unique($this->local);
14250                 $this->elsewhere = array_unique($this->elsewhere);
14251                 if (!empty($this->local) || !empty($this->elsewhere))
14252                 {
14253                         return true;
14254                 }
14255                 return null;
14256         }
14257
14258         function extension(&$array)
14259         {
14260                 foreach ($array as $key => $value)
14261                 {
14262                         if ($this->checked_feeds === $this->max_checked_feeds)
14263                         {
14264                                 break;
14265                         }
14266                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14267                         {
14268                                 $this->checked_feeds++;
14269                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14270                                 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))
14271                                 {
14272                                         return $feed;
14273                                 }
14274                                 else
14275                                 {
14276                                         unset($array[$key]);
14277                                 }
14278                         }
14279                 }
14280                 return null;
14281         }
14282
14283         function body(&$array)
14284         {
14285                 foreach ($array as $key => $value)
14286                 {
14287                         if ($this->checked_feeds === $this->max_checked_feeds)
14288                         {
14289                                 break;
14290                         }
14291                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14292                         {
14293                                 $this->checked_feeds++;
14294                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14295                                 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))
14296                                 {
14297                                         return $feed;
14298                                 }
14299                                 else
14300                                 {
14301                                         unset($array[$key]);
14302                                 }
14303                         }
14304                 }
14305                 return null;
14306         }
14307 }
14308
14309 class SimplePie_Parser
14310 {
14311         var $error_code;
14312         var $error_string;
14313         var $current_line;
14314         var $current_column;
14315         var $current_byte;
14316         var $separator = ' ';
14317         var $namespace = array('');
14318         var $element = array('');
14319         var $xml_base = array('');
14320         var $xml_base_explicit = array(false);
14321         var $xml_lang = array('');
14322         var $data = array();
14323         var $datas = array(array());
14324         var $current_xhtml_construct = -1;
14325         var $encoding;
14326
14327         function parse(&$data, $encoding)
14328         {
14329                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14330                 if (strtoupper($encoding) === 'US-ASCII')
14331                 {
14332                         $this->encoding = 'UTF-8';
14333                 }
14334                 else
14335                 {
14336                         $this->encoding = $encoding;
14337                 }
14338
14339                 // Strip BOM:
14340                 // UTF-32 Big Endian BOM
14341                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14342                 {
14343                         $data = substr($data, 4);
14344                 }
14345                 // UTF-32 Little Endian BOM
14346                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14347                 {
14348                         $data = substr($data, 4);
14349                 }
14350                 // UTF-16 Big Endian BOM
14351                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14352                 {
14353                         $data = substr($data, 2);
14354                 }
14355                 // UTF-16 Little Endian BOM
14356                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14357                 {
14358                         $data = substr($data, 2);
14359                 }
14360                 // UTF-8 BOM
14361                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14362                 {
14363                         $data = substr($data, 3);
14364                 }
14365
14366                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14367                 {
14368                         $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14369                         if ($declaration->parse())
14370                         {
14371                                 $data = substr($data, $pos + 2);
14372                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14373                         }
14374                         else
14375                         {
14376                                 $this->error_string = 'SimplePie bug! Please report this!';
14377                                 return false;
14378                         }
14379                 }
14380
14381                 $return = true;
14382
14383                 static $xml_is_sane = null;
14384                 if ($xml_is_sane === null)
14385                 {
14386                         $parser_check = xml_parser_create();
14387                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14388                         xml_parser_free($parser_check);
14389                         $xml_is_sane = isset($values[0]['value']);
14390                 }
14391
14392                 // Create the parser
14393                 if ($xml_is_sane)
14394                 {
14395                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14396                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14397                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14398                         xml_set_object($xml, $this);
14399                         xml_set_character_data_handler($xml, 'cdata');
14400                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14401
14402                         // Parse!
14403                         if (!xml_parse($xml, $data, true))
14404                         {
14405                                 $this->error_code = xml_get_error_code($xml);
14406                                 $this->error_string = xml_error_string($this->error_code);
14407                                 $return = false;
14408                         }
14409                         $this->current_line = xml_get_current_line_number($xml);
14410                         $this->current_column = xml_get_current_column_number($xml);
14411                         $this->current_byte = xml_get_current_byte_index($xml);
14412                         xml_parser_free($xml);
14413                         return $return;
14414                 }
14415                 else
14416                 {
14417                         libxml_clear_errors();
14418                         $xml =& new XMLReader();
14419                         $xml->xml($data);
14420                         while (@$xml->read())
14421                         {
14422                                 switch ($xml->nodeType)
14423                                 {
14424
14425                                         case constant('XMLReader::END_ELEMENT'):
14426                                                 if ($xml->namespaceURI !== '')
14427                                                 {
14428                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14429                                                 }
14430                                                 else
14431                                                 {
14432                                                         $tagName = $xml->localName;
14433                                                 }
14434                                                 $this->tag_close(null, $tagName);
14435                                                 break;
14436                                         case constant('XMLReader::ELEMENT'):
14437                                                 $empty = $xml->isEmptyElement;
14438                                                 if ($xml->namespaceURI !== '')
14439                                                 {
14440                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14441                                                 }
14442                                                 else
14443                                                 {
14444                                                         $tagName = $xml->localName;
14445                                                 }
14446                                                 $attributes = array();
14447                                                 while ($xml->moveToNextAttribute())
14448                                                 {
14449                                                         if ($xml->namespaceURI !== '')
14450                                                         {
14451                                                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14452                                                         }
14453                                                         else
14454                                                         {
14455                                                                 $attrName = $xml->localName;
14456                                                         }
14457                                                         $attributes[$attrName] = $xml->value;
14458                                                 }
14459                                                 $this->tag_open(null, $tagName, $attributes);
14460                                                 if ($empty)
14461                                                 {
14462                                                         $this->tag_close(null, $tagName);
14463                                                 }
14464                                                 break;
14465                                         case constant('XMLReader::TEXT'):
14466
14467                                         case constant('XMLReader::CDATA'):
14468                                                 $this->cdata(null, $xml->value);
14469                                                 break;
14470                                 }
14471                         }
14472                         if ($error = libxml_get_last_error())
14473                         {
14474                                 $this->error_code = $error->code;
14475                                 $this->error_string = $error->message;
14476                                 $this->current_line = $error->line;
14477                                 $this->current_column = $error->column;
14478                                 return false;
14479                         }
14480                         else
14481                         {
14482                                 return true;
14483                         }
14484                 }
14485         }
14486
14487         function get_error_code()
14488         {
14489                 return $this->error_code;
14490         }
14491
14492         function get_error_string()
14493         {
14494                 return $this->error_string;
14495         }
14496
14497         function get_current_line()
14498         {
14499                 return $this->current_line;
14500         }
14501
14502         function get_current_column()
14503         {
14504                 return $this->current_column;
14505         }
14506
14507         function get_current_byte()
14508         {
14509                 return $this->current_byte;
14510         }
14511
14512         function get_data()
14513         {
14514                 return $this->data;
14515         }
14516
14517         function tag_open($parser, $tag, $attributes)
14518         {
14519                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14520
14521                 $attribs = array();
14522                 foreach ($attributes as $name => $value)
14523                 {
14524                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14525                         $attribs[$attrib_namespace][$attribute] = $value;
14526                 }
14527
14528                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14529                 {
14530                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14531                         $this->xml_base_explicit[] = true;
14532                 }
14533                 else
14534                 {
14535                         $this->xml_base[] = end($this->xml_base);
14536                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14537                 }
14538
14539                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14540                 {
14541                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14542                 }
14543                 else
14544                 {
14545                         $this->xml_lang[] = end($this->xml_lang);
14546                 }
14547
14548                 if ($this->current_xhtml_construct >= 0)
14549                 {
14550                         $this->current_xhtml_construct++;
14551                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14552                         {
14553                                 $this->data['data'] .= '<' . end($this->element);
14554                                 if (isset($attribs['']))
14555                                 {
14556                                         foreach ($attribs[''] as $name => $value)
14557                                         {
14558                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14559                                         }
14560                                 }
14561                                 $this->data['data'] .= '>';
14562                         }
14563                 }
14564                 else
14565                 {
14566                         $this->datas[] =& $this->data;
14567                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14568                         $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));
14569                         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')
14570                         || (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'))
14571                         {
14572                                 $this->current_xhtml_construct = 0;
14573                         }
14574                 }
14575         }
14576
14577         function cdata($parser, $cdata)
14578         {
14579                 if ($this->current_xhtml_construct >= 0)
14580                 {
14581                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14582                 }
14583                 else
14584                 {
14585                         $this->data['data'] .= $cdata;
14586                 }
14587         }
14588
14589         function tag_close($parser, $tag)
14590         {
14591                 if ($this->current_xhtml_construct >= 0)
14592                 {
14593                         $this->current_xhtml_construct--;
14594                         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')))
14595                         {
14596                                 $this->data['data'] .= '</' . end($this->element) . '>';
14597                         }
14598                 }
14599                 if ($this->current_xhtml_construct === -1)
14600                 {
14601                         $this->data =& $this->datas[count($this->datas) - 1];
14602                         array_pop($this->datas);
14603                 }
14604
14605                 array_pop($this->element);
14606                 array_pop($this->namespace);
14607                 array_pop($this->xml_base);
14608                 array_pop($this->xml_base_explicit);
14609                 array_pop($this->xml_lang);
14610         }
14611
14612         function split_ns($string)
14613         {
14614                 static $cache = array();
14615                 if (!isset($cache[$string]))
14616                 {
14617                         if ($pos = strpos($string, $this->separator))
14618                         {
14619                                 static $separator_length;
14620                                 if (!$separator_length)
14621                                 {
14622                                         $separator_length = strlen($this->separator);
14623                                 }
14624                                 $namespace = substr($string, 0, $pos);
14625                                 $local_name = substr($string, $pos + $separator_length);
14626                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14627                                 {
14628                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14629                                 }
14630
14631                                 // Normalize the Media RSS namespaces
14632                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14633                                 {
14634                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14635                                 }
14636                                 $cache[$string] = array($namespace, $local_name);
14637                         }
14638                         else
14639                         {
14640                                 $cache[$string] = array('', $string);
14641                         }
14642                 }
14643                 return $cache[$string];
14644         }
14645 }
14646
14647 /**
14648  * @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
14649  */
14650 class SimplePie_Sanitize
14651 {
14652         // Private vars
14653         var $base;
14654
14655         // Options
14656         var $remove_div = true;
14657         var $image_handler = '';
14658         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14659         var $encode_instead_of_strip = false;
14660         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14661         var $strip_comments = false;
14662         var $output_encoding = 'UTF-8';
14663         var $enable_cache = true;
14664         var $cache_location = './cache';
14665         var $cache_name_function = 'md5';
14666         var $cache_class = 'SimplePie_Cache';
14667         var $file_class = 'SimplePie_File';
14668         var $timeout = 10;
14669         var $useragent = '';
14670         var $force_fsockopen = false;
14671
14672         var $replace_url_attributes = array(
14673                 'a' => 'href',
14674                 'area' => 'href',
14675                 'blockquote' => 'cite',
14676                 'del' => 'cite',
14677                 'form' => 'action',
14678                 'img' => array('longdesc', 'src'),
14679                 'input' => 'src',
14680                 'ins' => 'cite',
14681                 'q' => 'cite'
14682         );
14683
14684         function remove_div($enable = true)
14685         {
14686                 $this->remove_div = (bool) $enable;
14687         }
14688
14689         function set_image_handler($page = false)
14690         {
14691                 if ($page)
14692                 {
14693                         $this->image_handler = (string) $page;
14694                 }
14695                 else
14696                 {
14697                         $this->image_handler = false;
14698                 }
14699         }
14700
14701         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14702         {
14703                 if (isset($enable_cache))
14704                 {
14705                         $this->enable_cache = (bool) $enable_cache;
14706                 }
14707
14708                 if ($cache_location)
14709                 {
14710                         $this->cache_location = (string) $cache_location;
14711                 }
14712
14713                 if ($cache_name_function)
14714                 {
14715                         $this->cache_name_function = (string) $cache_name_function;
14716                 }
14717
14718                 if ($cache_class)
14719                 {
14720                         $this->cache_class = (string) $cache_class;
14721                 }
14722         }
14723
14724         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14725         {
14726                 if ($file_class)
14727                 {
14728                         $this->file_class = (string) $file_class;
14729                 }
14730
14731                 if ($timeout)
14732                 {
14733                         $this->timeout = (string) $timeout;
14734                 }
14735
14736                 if ($useragent)
14737                 {
14738                         $this->useragent = (string) $useragent;
14739                 }
14740
14741                 if ($force_fsockopen)
14742                 {
14743                         $this->force_fsockopen = (string) $force_fsockopen;
14744                 }
14745         }
14746
14747         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14748         {
14749                 if ($tags)
14750                 {
14751                         if (is_array($tags))
14752                         {
14753                                 $this->strip_htmltags = $tags;
14754                         }
14755                         else
14756                         {
14757                                 $this->strip_htmltags = explode(',', $tags);
14758                         }
14759                 }
14760                 else
14761                 {
14762                         $this->strip_htmltags = false;
14763                 }
14764         }
14765
14766         function encode_instead_of_strip($encode = false)
14767         {
14768                 $this->encode_instead_of_strip = (bool) $encode;
14769         }
14770
14771         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14772         {
14773                 if ($attribs)
14774                 {
14775                         if (is_array($attribs))
14776                         {
14777                                 $this->strip_attributes = $attribs;
14778                         }
14779                         else
14780                         {
14781                                 $this->strip_attributes = explode(',', $attribs);
14782                         }
14783                 }
14784                 else
14785                 {
14786                         $this->strip_attributes = false;
14787                 }
14788         }
14789
14790         function strip_comments($strip = false)
14791         {
14792                 $this->strip_comments = (bool) $strip;
14793         }
14794
14795         function set_output_encoding($encoding = 'UTF-8')
14796         {
14797                 $this->output_encoding = (string) $encoding;
14798         }
14799
14800         /**
14801          * Set element/attribute key/value pairs of HTML attributes
14802          * containing URLs that need to be resolved relative to the feed
14803          *
14804          * @access public
14805          * @since 1.0
14806          * @param array $element_attribute Element/attribute key/value pairs
14807          */
14808         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'))
14809         {
14810                 $this->replace_url_attributes = (array) $element_attribute;
14811         }
14812
14813         function sanitize($data, $type, $base = '')
14814         {
14815                 $data = trim($data);
14816                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14817                 {
14818                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14819                         {
14820                                 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))
14821                                 {
14822                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
14823                                 }
14824                                 else
14825                                 {
14826                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14827                                 }
14828                         }
14829
14830                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14831                         {
14832                                 $data = base64_decode($data);
14833                         }
14834
14835                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14836                         {
14837                                 if ($this->remove_div)
14838                                 {
14839                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14840                                         $data = preg_replace('/<\/div>$/', '', $data);
14841                                 }
14842                                 else
14843                                 {
14844                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14845                                 }
14846                         }
14847
14848                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14849                         {
14850                                 // Strip comments
14851                                 if ($this->strip_comments)
14852                                 {
14853                                         $data = SimplePie_Misc::strip_comments($data);
14854                                 }
14855
14856                                 // Strip out HTML tags and attributes that might cause various security problems.
14857                                 // Based on recommendations by Mark Pilgrim at:
14858                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14859                                 if ($this->strip_htmltags)
14860                                 {
14861                                         foreach ($this->strip_htmltags as $tag)
14862                                         {
14863                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14864                                                 while (preg_match($pcre, $data))
14865                                                 {
14866                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14867                                                 }
14868                                         }
14869                                 }
14870
14871                                 if ($this->strip_attributes)
14872                                 {
14873                                         foreach ($this->strip_attributes as $attrib)
14874                                         {
14875                                                 $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);
14876                                         }
14877                                 }
14878
14879                                 // Replace relative URLs
14880                                 $this->base = $base;
14881                                 foreach ($this->replace_url_attributes as $element => $attributes)
14882                                 {
14883                                         $data = $this->replace_urls($data, $element, $attributes);
14884                                 }
14885
14886                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14887                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14888                                 {
14889                                         $images = SimplePie_Misc::get_element('img', $data);
14890                                         foreach ($images as $img)
14891                                         {
14892                                                 if (isset($img['attribs']['src']['data']))
14893                                                 {
14894                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14895                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14896
14897                                                         if ($cache->load())
14898                                                         {
14899                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14900                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14901                                                         }
14902                                                         else
14903                                                         {
14904                                                                 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14905                                                                 $headers = $file->headers;
14906
14907                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14908                                                                 {
14909                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14910                                                                         {
14911                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14912                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14913                                                                         }
14914                                                                         else
14915                                                                         {
14916                                                                                 trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
14917                                                                         }
14918                                                                 }
14919                                                         }
14920                                                 }
14921                                         }
14922                                 }
14923
14924                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14925                                 $data = trim($data);
14926                         }
14927
14928                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14929                         {
14930                                 $data = SimplePie_Misc::absolutize_url($data, $base);
14931                         }
14932
14933                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14934                         {
14935                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14936                         }
14937
14938                         if ($this->output_encoding !== 'UTF-8')
14939                         {
14940                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14941                         }
14942                 }
14943                 return $data;
14944         }
14945
14946         function replace_urls($data, $tag, $attributes)
14947         {
14948                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14949                 {
14950                         $elements = SimplePie_Misc::get_element($tag, $data);
14951                         foreach ($elements as $element)
14952                         {
14953                                 if (is_array($attributes))
14954                                 {
14955                                         foreach ($attributes as $attribute)
14956                                         {
14957                                                 if (isset($element['attribs'][$attribute]['data']))
14958                                                 {
14959                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14960                                                         $new_element = SimplePie_Misc::element_implode($element);
14961                                                         $data = str_replace($element['full'], $new_element, $data);
14962                                                         $element['full'] = $new_element;
14963                                                 }
14964                                         }
14965                                 }
14966                                 elseif (isset($element['attribs'][$attributes]['data']))
14967                                 {
14968                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14969                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14970                                 }
14971                         }
14972                 }
14973                 return $data;
14974         }
14975
14976         function do_strip_htmltags($match)
14977         {
14978                 if ($this->encode_instead_of_strip)
14979                 {
14980                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14981                         {
14982                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
14983                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
14984                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
14985                         }
14986                         else
14987                         {
14988                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
14989                         }
14990                 }
14991                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14992                 {
14993                         return $match[4];
14994                 }
14995                 else
14996                 {
14997                         return '';
14998                 }
14999         }
15000 }
15001 endif;
15002 ?>