]> git.mxchange.org Git - friendica.git/blob - simplepie/simplepie.inc
sanitise all incoming url's - also stop them from getting mangled by simplepie
[friendica.git] / simplepie / simplepie.inc
1 <?php
2 /**
3  * SimplePie
4  *
5  * A PHP-Based RSS and Atom Feed Framework.
6  * Takes the hard work out of managing a complete RSS/Atom solution.
7  *
8  * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification, are
12  * permitted provided that the following conditions are met:
13  *
14  *      * Redistributions of source code must retain the above copyright notice, this list of
15  *        conditions and the following disclaimer.
16  *
17  *      * Redistributions in binary form must reproduce the above copyright notice, this list
18  *        of conditions and the following disclaimer in the documentation and/or other materials
19  *        provided with the distribution.
20  *
21  *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
22  *        to endorse or promote products derived from this software without specific prior
23  *        written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * @package SimplePie
36  * @version 1.2.1-dev
37  * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
38  * @author Ryan Parman
39  * @author Geoffrey Sneddon
40  * @link http://simplepie.org/ SimplePie
41  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43  * @todo phpDoc comments
44  */
45
46 /**
47  * SimplePie Name
48  */
49 define('SIMPLEPIE_NAME', 'SimplePie');
50
51 /**
52  * SimplePie Version
53  */
54 define('SIMPLEPIE_VERSION', '1.2.1-dev');
55
56 /**
57  * SimplePie Build
58  * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
59  */
60 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
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. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", 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. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
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("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1781                                                         }
1782                                                         return true;
1783                                                 }
1784                                                 else
1785                                                 {
1786                                                         $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
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('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1797                         }
1798                         else
1799                         {
1800                                 $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
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 occured 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. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", 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                         $avatar = null;
2435                         $name_date = null;
2436                         $uri_date = null;
2437                         $avatar_date = null;
2438
2439                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2440                         {
2441                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2442                         }
2443                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2444                         {
2445                                 $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]));
2446                         }
2447                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2448                         {
2449                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2450                         }
2451                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
2452                         {
2453                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
2454                         }
2455                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
2456                         {
2457                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
2458                         }
2459                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
2460                         {
2461                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
2462                         }
2463                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
2464                         {
2465                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
2466                         }
2467
2468                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
2469                         {
2470                                 $authors[] = new $this->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
2471                         }
2472                 }
2473                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2474                 {
2475                         $name = null;
2476                         $url = null;
2477                         $email = null;
2478                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2479                         {
2480                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2481                         }
2482                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2483                         {
2484                                 $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]));
2485                         }
2486                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2487                         {
2488                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2489                         }
2490                         if ($name !== null || $email !== null || $url !== null)
2491                         {
2492                                 $authors[] = new $this->author_class($name, $url, $email);
2493                         }
2494                 }
2495                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2496                 {
2497                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2498                 }
2499                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2500                 {
2501                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2502                 }
2503                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2504                 {
2505                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2506                 }
2507
2508                 if (!empty($authors))
2509                 {
2510                         return SimplePie_Misc::array_unique($authors);
2511                 }
2512                 else
2513                 {
2514                         return null;
2515                 }
2516         }
2517
2518         function get_contributor($key = 0)
2519         {
2520                 $contributors = $this->get_contributors();
2521                 if (isset($contributors[$key]))
2522                 {
2523                         return $contributors[$key];
2524                 }
2525                 else
2526                 {
2527                         return null;
2528                 }
2529         }
2530
2531         function get_contributors()
2532         {
2533                 $contributors = array();
2534                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2535                 {
2536                         $name = null;
2537                         $uri = null;
2538                         $email = null;
2539                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2540                         {
2541                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2542                         }
2543                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2544                         {
2545                                 $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]));
2546                         }
2547                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2548                         {
2549                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2550                         }
2551                         if ($name !== null || $email !== null || $uri !== null)
2552                         {
2553                                 $contributors[] = new $this->author_class($name, $uri, $email);
2554                         }
2555                 }
2556                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2557                 {
2558                         $name = null;
2559                         $url = null;
2560                         $email = null;
2561                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2562                         {
2563                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2564                         }
2565                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2566                         {
2567                                 $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]));
2568                         }
2569                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2570                         {
2571                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2572                         }
2573                         if ($name !== null || $email !== null || $url !== null)
2574                         {
2575                                 $contributors[] = new $this->author_class($name, $url, $email);
2576                         }
2577                 }
2578
2579                 if (!empty($contributors))
2580                 {
2581                         return SimplePie_Misc::array_unique($contributors);
2582                 }
2583                 else
2584                 {
2585                         return null;
2586                 }
2587         }
2588
2589         function get_link($key = 0, $rel = 'alternate')
2590         {
2591                 $links = $this->get_links($rel);
2592                 if (isset($links[$key]))
2593                 {
2594                         return $links[$key];
2595                 }
2596                 else
2597                 {
2598                         return null;
2599                 }
2600         }
2601
2602         /**
2603          * Added for parity between the parent-level and the item/entry-level.
2604          */
2605         function get_permalink()
2606         {
2607                 return $this->get_link(0);
2608         }
2609
2610         function get_links($rel = 'alternate')
2611         {
2612                 if (!isset($this->data['links']))
2613                 {
2614                         $this->data['links'] = array();
2615                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2616                         {
2617                                 foreach ($links as $link)
2618                                 {
2619                                         if (isset($link['attribs']['']['href']))
2620                                         {
2621                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2622                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2623                                         }
2624                                 }
2625                         }
2626                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2627                         {
2628                                 foreach ($links as $link)
2629                                 {
2630                                         if (isset($link['attribs']['']['href']))
2631                                         {
2632                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2633                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2634
2635                                         }
2636                                 }
2637                         }
2638                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2639                         {
2640                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2641                         }
2642                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2643                         {
2644                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2645                         }
2646                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2647                         {
2648                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2649                         }
2650
2651                         $keys = array_keys($this->data['links']);
2652                         foreach ($keys as $key)
2653                         {
2654                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2655                                 {
2656                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2657                                         {
2658                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2659                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2660                                         }
2661                                         else
2662                                         {
2663                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2664                                         }
2665                                 }
2666                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2667                                 {
2668                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2669                                 }
2670                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2671                         }
2672                 }
2673
2674                 if (isset($this->data['links'][$rel]))
2675                 {
2676                         return $this->data['links'][$rel];
2677                 }
2678                 else
2679                 {
2680                         return null;
2681                 }
2682         }
2683
2684         function get_all_discovered_feeds()
2685         {
2686                 return $this->all_discovered_feeds;
2687         }
2688
2689         function get_description()
2690         {
2691                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2692                 {
2693                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2694                 }
2695                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2696                 {
2697                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2698                 }
2699                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2700                 {
2701                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2702                 }
2703                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2704                 {
2705                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2706                 }
2707                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2708                 {
2709                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2710                 }
2711                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2712                 {
2713                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2714                 }
2715                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2716                 {
2717                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2718                 }
2719                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2720                 {
2721                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2722                 }
2723                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2724                 {
2725                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2726                 }
2727                 else
2728                 {
2729                         return null;
2730                 }
2731         }
2732
2733         function get_copyright()
2734         {
2735                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2736                 {
2737                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2738                 }
2739                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2740                 {
2741                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2742                 }
2743                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2744                 {
2745                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2746                 }
2747                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2748                 {
2749                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2750                 }
2751                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2752                 {
2753                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2754                 }
2755                 else
2756                 {
2757                         return null;
2758                 }
2759         }
2760
2761         function get_language()
2762         {
2763                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2764                 {
2765                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2766                 }
2767                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2768                 {
2769                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2770                 }
2771                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2772                 {
2773                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2774                 }
2775                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2776                 {
2777                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2778                 }
2779                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2780                 {
2781                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2782                 }
2783                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2784                 {
2785                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2786                 }
2787                 elseif (isset($this->data['headers']['content-language']))
2788                 {
2789                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2790                 }
2791                 else
2792                 {
2793                         return null;
2794                 }
2795         }
2796
2797         function get_latitude()
2798         {
2799                 
2800                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2801                 {
2802                         return (float) $return[0]['data'];
2803                 }
2804                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2805                 {
2806                         return (float) $match[1];
2807                 }
2808                 else
2809                 {
2810                         return null;
2811                 }
2812         }
2813
2814         function get_longitude()
2815         {
2816                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2817                 {
2818                         return (float) $return[0]['data'];
2819                 }
2820                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2821                 {
2822                         return (float) $return[0]['data'];
2823                 }
2824                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2825                 {
2826                         return (float) $match[2];
2827                 }
2828                 else
2829                 {
2830                         return null;
2831                 }
2832         }
2833
2834         function get_image_title()
2835         {
2836                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2837                 {
2838                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2839                 }
2840                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2841                 {
2842                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2843                 }
2844                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2845                 {
2846                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2847                 }
2848                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2849                 {
2850                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2851                 }
2852                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2853                 {
2854                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2855                 }
2856                 else
2857                 {
2858                         return null;
2859                 }
2860         }
2861
2862         function get_image_url()
2863         {
2864                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2865                 {
2866                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2867                 }
2868                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2869                 {
2870                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2871                 }
2872                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2873                 {
2874                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2875                 }
2876                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2877                 {
2878                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879                 }
2880                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2881                 {
2882                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883                 }
2884                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2885                 {
2886                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2887                 }
2888                 else
2889                 {
2890                         return null;
2891                 }
2892         }
2893
2894         function get_image_link()
2895         {
2896                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2897                 {
2898                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2899                 }
2900                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2901                 {
2902                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2903                 }
2904                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2905                 {
2906                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2907                 }
2908                 else
2909                 {
2910                         return null;
2911                 }
2912         }
2913
2914         function get_image_width()
2915         {
2916                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2917                 {
2918                         return round($return[0]['data']);
2919                 }
2920                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2921                 {
2922                         return 88.0;
2923                 }
2924                 else
2925                 {
2926                         return null;
2927                 }
2928         }
2929
2930         function get_image_height()
2931         {
2932                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2933                 {
2934                         return round($return[0]['data']);
2935                 }
2936                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2937                 {
2938                         return 31.0;
2939                 }
2940                 else
2941                 {
2942                         return null;
2943                 }
2944         }
2945
2946         function get_item_quantity($max = 0)
2947         {
2948                 $max = (int) $max;
2949                 $qty = count($this->get_items());
2950                 if ($max === 0)
2951                 {
2952                         return $qty;
2953                 }
2954                 else
2955                 {
2956                         return ($qty > $max) ? $max : $qty;
2957                 }
2958         }
2959
2960         function get_item($key = 0)
2961         {
2962                 $items = $this->get_items();
2963                 if (isset($items[$key]))
2964                 {
2965                         return $items[$key];
2966                 }
2967                 else
2968                 {
2969                         return null;
2970                 }
2971         }
2972
2973         function get_items($start = 0, $end = 0)
2974         {
2975                 if (!isset($this->data['items']))
2976                 {
2977                         if (!empty($this->multifeed_objects))
2978                         {
2979                                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2980                         }
2981                         else
2982                         {
2983                                 $this->data['items'] = array();
2984                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2985                                 {
2986                                         $keys = array_keys($items);
2987                                         foreach ($keys as $key)
2988                                         {
2989                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2990                                         }
2991                                 }
2992                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2993                                 {
2994                                         $keys = array_keys($items);
2995                                         foreach ($keys as $key)
2996                                         {
2997                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2998                                         }
2999                                 }
3000                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
3001                                 {
3002                                         $keys = array_keys($items);
3003                                         foreach ($keys as $key)
3004                                         {
3005                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3006                                         }
3007                                 }
3008                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
3009                                 {
3010                                         $keys = array_keys($items);
3011                                         foreach ($keys as $key)
3012                                         {
3013                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3014                                         }
3015                                 }
3016                                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
3017                                 {
3018                                         $keys = array_keys($items);
3019                                         foreach ($keys as $key)
3020                                         {
3021                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3022                                         }
3023                                 }
3024                         }
3025                 }
3026
3027                 if (!empty($this->data['items']))
3028                 {
3029                         // If we want to order it by date, check if all items have a date, and then sort it
3030                         if ($this->order_by_date && empty($this->multifeed_objects))
3031                         {
3032                                 if (!isset($this->data['ordered_items']))
3033                                 {
3034                                         $do_sort = true;
3035                                         foreach ($this->data['items'] as $item)
3036                                         {
3037                                                 if (!$item->get_date('U'))
3038                                                 {
3039                                                         $do_sort = false;
3040                                                         break;
3041                                                 }
3042                                         }
3043                                         $item = null;
3044                                         $this->data['ordered_items'] = $this->data['items'];
3045                                         if ($do_sort)
3046                                         {
3047                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3048                                         }
3049                                 }
3050                                 $items = $this->data['ordered_items'];
3051                         }
3052                         else
3053                         {
3054                                 $items = $this->data['items'];
3055                         }
3056
3057                         // Slice the data as desired
3058                         if ($end === 0)
3059                         {
3060                                 return array_slice($items, $start);
3061                         }
3062                         else
3063                         {
3064                                 return array_slice($items, $start, $end);
3065                         }
3066                 }
3067                 else
3068                 {
3069                         return array();
3070                 }
3071         }
3072
3073         /**
3074          * @static
3075          */
3076         function sort_items($a, $b)
3077         {
3078                 return $a->get_date('U') <= $b->get_date('U');
3079         }
3080
3081         /**
3082          * @static
3083          */
3084         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3085         {
3086                 if (is_array($urls) && sizeof($urls) > 0)
3087                 {
3088                         $items = array();
3089                         foreach ($urls as $arg)
3090                         {
3091                                 if (is_a($arg, 'SimplePie'))
3092                                 {
3093                                         $items = array_merge($items, $arg->get_items(0, $limit));
3094                                 }
3095                                 else
3096                                 {
3097                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3098                                 }
3099                         }
3100
3101                         $do_sort = true;
3102                         foreach ($items as $item)
3103                         {
3104                                 if (!$item->get_date('U'))
3105                                 {
3106                                         $do_sort = false;
3107                                         break;
3108                                 }
3109                         }
3110                         $item = null;
3111                         if ($do_sort)
3112                         {
3113                                 usort($items, array('SimplePie', 'sort_items'));
3114                         }
3115
3116                         if ($end === 0)
3117                         {
3118                                 return array_slice($items, $start);
3119                         }
3120                         else
3121                         {
3122                                 return array_slice($items, $start, $end);
3123                         }
3124                 }
3125                 else
3126                 {
3127                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3128                         return array();
3129                 }
3130         }
3131 }
3132
3133 class SimplePie_Item
3134 {
3135         var $feed;
3136         var $data = array();
3137
3138         function SimplePie_Item($feed, $data)
3139         {
3140                 $this->feed = $feed;
3141                 $this->data = $data;
3142         }
3143
3144         function __toString()
3145         {
3146                 return md5(serialize($this->data));
3147         }
3148
3149         /**
3150          * Remove items that link back to this before destroying this object
3151          */
3152         function __destruct()
3153         {
3154                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3155                 {
3156                         unset($this->feed);
3157                 }
3158         }
3159
3160         function get_item_tags($namespace, $tag)
3161         {
3162                 if (isset($this->data['child'][$namespace][$tag]))
3163                 {
3164                         return $this->data['child'][$namespace][$tag];
3165                 }
3166                 else
3167                 {
3168                         return null;
3169                 }
3170         }
3171
3172         function get_base($element = array())
3173         {
3174                 return $this->feed->get_base($element);
3175         }
3176
3177         function sanitize($data, $type, $base = '')
3178         {
3179                 return $this->feed->sanitize($data, $type, $base);
3180         }
3181
3182         function get_feed()
3183         {
3184                 return $this->feed;
3185         }
3186
3187         function get_id($hash = false)
3188         {
3189                 if (!$hash)
3190                 {
3191                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3192                         {
3193                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3194                         }
3195                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3196                         {
3197                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3198                         }
3199                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3200                         {
3201                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3202                         }
3203                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3204                         {
3205                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3206                         }
3207                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3208                         {
3209                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3210                         }
3211                         elseif (($return = $this->get_permalink()) !== null)
3212                         {
3213                                 return $return;
3214                         }
3215                         elseif (($return = $this->get_title()) !== null)
3216                         {
3217                                 return $return;
3218                         }
3219                 }
3220                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3221                 {
3222                         return md5($this->get_permalink() . $this->get_title());
3223                 }
3224                 else
3225                 {
3226                         return md5(serialize($this->data));
3227                 }
3228         }
3229
3230         function get_title()
3231         {
3232                 if (!isset($this->data['title']))
3233                 {
3234                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3235                         {
3236                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3237                         }
3238                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3239                         {
3240                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3241                         }
3242                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3243                         {
3244                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3245                         }
3246                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3247                         {
3248                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3249                         }
3250                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3251                         {
3252                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3253                         }
3254                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3255                         {
3256                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3257                         }
3258                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3259                         {
3260                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3261                         }
3262                         else
3263                         {
3264                                 $this->data['title'] = null;
3265                         }
3266                 }
3267                 return $this->data['title'];
3268         }
3269
3270         function get_description($description_only = false)
3271         {
3272                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3273                 {
3274                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3275                 }
3276                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3277                 {
3278                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3279                 }
3280                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3281                 {
3282                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3283                 }
3284                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3285                 {
3286                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3287                 }
3288                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3289                 {
3290                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3291                 }
3292                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3293                 {
3294                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3295                 }
3296                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3297                 {
3298                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3299                 }
3300                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3301                 {
3302                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3303                 }
3304                 elseif (!$description_only)
3305                 {
3306                         return $this->get_content(true);
3307                 }
3308                 else
3309                 {
3310                         return null;
3311                 }
3312         }
3313
3314         function get_content($content_only = false)
3315         {
3316                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3317                 {
3318                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3319                 }
3320                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3321                 {
3322                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3323                 }
3324                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3325                 {
3326                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3327                 }
3328                 elseif (!$content_only)
3329                 {
3330                         return $this->get_description(true);
3331                 }
3332                 else
3333                 {
3334                         return null;
3335                 }
3336         }
3337
3338         function get_category($key = 0)
3339         {
3340                 $categories = $this->get_categories();
3341                 if (isset($categories[$key]))
3342                 {
3343                         return $categories[$key];
3344                 }
3345                 else
3346                 {
3347                         return null;
3348                 }
3349         }
3350
3351         function get_categories()
3352         {
3353                 $categories = array();
3354
3355                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3356                 {
3357                         $term = null;
3358                         $scheme = null;
3359                         $label = null;
3360                         if (isset($category['attribs']['']['term']))
3361                         {
3362                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3363                         }
3364                         if (isset($category['attribs']['']['scheme']))
3365                         {
3366                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3367                         }
3368                         if (isset($category['attribs']['']['label']))
3369                         {
3370                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3371                         }
3372                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
3373                 }
3374                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3375                 {
3376                         // This is really the label, but keep this as the term also for BC.
3377                         // Label will also work on retrieving because that falls back to term.
3378                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3379                         if (isset($category['attribs']['']['domain']))
3380                         {
3381                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3382                         }
3383                         else
3384                         {
3385                                 $scheme = null;
3386                         }
3387                         $categories[] = new $this->feed->category_class($term, $scheme, null);
3388                 }
3389                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3390                 {
3391                         $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3392                 }
3393                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3394                 {
3395                         $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3396                 }
3397
3398                 if (!empty($categories))
3399                 {
3400                         return SimplePie_Misc::array_unique($categories);
3401                 }
3402                 else
3403                 {
3404                         return null;
3405                 }
3406         }
3407
3408         function get_author($key = 0)
3409         {
3410                 $authors = $this->get_authors();
3411                 if (isset($authors[$key]))
3412                 {
3413                         return $authors[$key];
3414                 }
3415                 else
3416                 {
3417                         return null;
3418                 }
3419         }
3420
3421         function get_contributor($key = 0)
3422         {
3423                 $contributors = $this->get_contributors();
3424                 if (isset($contributors[$key]))
3425                 {
3426                         return $contributors[$key];
3427                 }
3428                 else
3429                 {
3430                         return null;
3431                 }
3432         }
3433
3434         function get_contributors()
3435         {
3436                 $contributors = array();
3437                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3438                 {
3439                         $name = null;
3440                         $uri = null;
3441                         $email = null;
3442                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3443                         {
3444                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3445                         }
3446                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3447                         {
3448                                 $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]));
3449                         }
3450                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3451                         {
3452                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3453                         }
3454                         if ($name !== null || $email !== null || $uri !== null)
3455                         {
3456                                 $contributors[] = new $this->feed->author_class($name, $uri, $email);
3457                         }
3458                 }
3459                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3460                 {
3461                         $name = null;
3462                         $url = null;
3463                         $email = null;
3464                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3465                         {
3466                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3467                         }
3468                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3469                         {
3470                                 $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]));
3471                         }
3472                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3473                         {
3474                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3475                         }
3476                         if ($name !== null || $email !== null || $url !== null)
3477                         {
3478                                 $contributors[] = new $this->feed->author_class($name, $url, $email);
3479                         }
3480                 }
3481
3482                 if (!empty($contributors))
3483                 {
3484                         return SimplePie_Misc::array_unique($contributors);
3485                 }
3486                 else
3487                 {
3488                         return null;
3489                 }
3490         }
3491
3492         function get_authors()
3493         {
3494                 $authors = array();
3495                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3496                 {
3497                         $name = null;
3498                         $uri = null;
3499                         $email = null;
3500                         $avatar = null;
3501                         $name_date = null;
3502                         $uri_date = null;
3503                         $avatar_date = null;
3504                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3505                         {
3506                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3507                         }
3508                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3509                         {
3510                                 $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]));
3511                         }
3512                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3513                         {
3514                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3515                         }
3516                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
3517                         {
3518                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
3519                         }
3520                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
3521                         {
3522                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
3523                         }
3524                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
3525                         {
3526                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
3527                         }
3528                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
3529                         {
3530                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
3531                         }
3532
3533                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
3534                         {
3535                                 $authors[] = new $this->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
3536                         }
3537                 }
3538                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3539                 {
3540                         $name = null;
3541                         $url = null;
3542                         $email = null;
3543                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3544                         {
3545                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3546                         }
3547                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3548                         {
3549                                 $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]));
3550                         }
3551                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3552                         {
3553                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3554                         }
3555                         if ($name !== null || $email !== null || $url !== null)
3556                         {
3557                                 $authors[] = new $this->feed->author_class($name, $url, $email);
3558                         }
3559                 }
3560                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3561                 {
3562                         $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3563                 }
3564                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3565                 {
3566                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3567                 }
3568                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3569                 {
3570                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3571                 }
3572                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3573                 {
3574                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3575                 }
3576
3577                 if (!empty($authors))
3578                 {
3579                         return SimplePie_Misc::array_unique($authors);
3580                 }
3581                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3582                 {
3583                         return $authors;
3584                 }
3585                 elseif ($authors = $this->feed->get_authors())
3586                 {
3587                         return $authors;
3588                 }
3589                 else
3590                 {
3591                         return null;
3592                 }
3593         }
3594
3595         function get_copyright()
3596         {
3597                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3598                 {
3599                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3600                 }
3601                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3602                 {
3603                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3604                 }
3605                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3606                 {
3607                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3608                 }
3609                 else
3610                 {
3611                         return null;
3612                 }
3613         }
3614
3615         function get_date($date_format = 'j F Y, g:i a')
3616         {
3617                 if (!isset($this->data['date']))
3618                 {
3619                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3620                         {
3621                                 $this->data['date']['raw'] = $return[0]['data'];
3622                         }
3623                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3624                         {
3625                                 $this->data['date']['raw'] = $return[0]['data'];
3626                         }
3627                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3628                         {
3629                                 $this->data['date']['raw'] = $return[0]['data'];
3630                         }
3631                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3632                         {
3633                                 $this->data['date']['raw'] = $return[0]['data'];
3634                         }
3635                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3636                         {
3637                                 $this->data['date']['raw'] = $return[0]['data'];
3638                         }
3639                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3640                         {
3641                                 $this->data['date']['raw'] = $return[0]['data'];
3642                         }
3643                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3644                         {
3645                                 $this->data['date']['raw'] = $return[0]['data'];
3646                         }
3647                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3648                         {
3649                                 $this->data['date']['raw'] = $return[0]['data'];
3650                         }
3651
3652                         if (!empty($this->data['date']['raw']))
3653                         {
3654                                 $parser = SimplePie_Parse_Date::get();
3655                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3656                         }
3657                         else
3658                         {
3659                                 $this->data['date'] = null;
3660                         }
3661                 }
3662                 if ($this->data['date'])
3663                 {
3664                         $date_format = (string) $date_format;
3665                         switch ($date_format)
3666                         {
3667                                 case '':
3668                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3669
3670                                 case 'U':
3671                                         return $this->data['date']['parsed'];
3672
3673                                 default:
3674                                         return date($date_format, $this->data['date']['parsed']);
3675                         }
3676                 }
3677                 else
3678                 {
3679                         return null;
3680                 }
3681         }
3682
3683         function get_local_date($date_format = '%c')
3684         {
3685                 if (!$date_format)
3686                 {
3687                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3688                 }
3689                 elseif (($date = $this->get_date('U')) !== null)
3690                 {
3691                         return strftime($date_format, $date);
3692                 }
3693                 else
3694                 {
3695                         return null;
3696                 }
3697         }
3698
3699         function get_permalink()
3700         {
3701                 $link = $this->get_link();
3702                 $enclosure = $this->get_enclosure(0);
3703                 if ($link !== null)
3704                 {
3705                         return $link;
3706                 }
3707                 elseif ($enclosure !== null)
3708                 {
3709                         return $enclosure->get_link();
3710                 }
3711                 else
3712                 {
3713                         return null;
3714                 }
3715         }
3716
3717         function get_link($key = 0, $rel = 'alternate')
3718         {
3719                 $links = $this->get_links($rel);
3720                 if ($links[$key] !== null)
3721                 {
3722                         return $links[$key];
3723                 }
3724                 else
3725                 {
3726                         return null;
3727                 }
3728         }
3729
3730         function get_links($rel = 'alternate')
3731         {
3732                 if (!isset($this->data['links']))
3733                 {
3734                         $this->data['links'] = array();
3735                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3736                         {
3737                                 if (isset($link['attribs']['']['href']))
3738                                 {
3739                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3740                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3741
3742                                 }
3743                         }
3744                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3745                         {
3746                                 if (isset($link['attribs']['']['href']))
3747                                 {
3748                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3749                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3750                                 }
3751                         }
3752                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3753                         {
3754                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3755                         }
3756                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3757                         {
3758                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3759                         }
3760                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3761                         {
3762                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3763                         }
3764                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3765                         {
3766                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3767                                 {
3768                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3769                                 }
3770                         }
3771
3772                         $keys = array_keys($this->data['links']);
3773                         foreach ($keys as $key)
3774                         {
3775                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3776                                 {
3777                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3778                                         {
3779                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3780                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3781                                         }
3782                                         else
3783                                         {
3784                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3785                                         }
3786                                 }
3787                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3788                                 {
3789                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3790                                 }
3791                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3792                         }
3793                 }
3794                 if (isset($this->data['links'][$rel]))
3795                 {
3796                         return $this->data['links'][$rel];
3797                 }
3798                 else
3799                 {
3800                         return null;
3801                 }
3802         }
3803
3804         /**
3805          * @todo Add ability to prefer one type of content over another (in a media group).
3806          */
3807         function get_enclosure($key = 0, $prefer = null)
3808         {
3809                 $enclosures = $this->get_enclosures();
3810                 if (isset($enclosures[$key]))
3811                 {
3812                         return $enclosures[$key];
3813                 }
3814                 else
3815                 {
3816                         return null;
3817                 }
3818         }
3819
3820         /**
3821          * Grabs all available enclosures (podcasts, etc.)
3822          *
3823          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3824          *
3825          * 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.
3826          *
3827          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3828          * @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).
3829          */
3830         function get_enclosures()
3831         {
3832                 if (!isset($this->data['enclosures']))
3833                 {
3834                         $this->data['enclosures'] = array();
3835
3836                         // Elements
3837                         $captions_parent = null;
3838                         $categories_parent = null;
3839                         $copyrights_parent = null;
3840                         $credits_parent = null;
3841                         $description_parent = null;
3842                         $duration_parent = null;
3843                         $hashes_parent = null;
3844                         $keywords_parent = null;
3845                         $player_parent = null;
3846                         $ratings_parent = null;
3847                         $restrictions_parent = null;
3848                         $thumbnails_parent = null;
3849                         $title_parent = null;
3850
3851                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3852                         $parent = $this->get_feed();
3853
3854                         // CAPTIONS
3855                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3856                         {
3857                                 foreach ($captions as $caption)
3858                                 {
3859                                         $caption_type = null;
3860                                         $caption_lang = null;
3861                                         $caption_startTime = null;
3862                                         $caption_endTime = null;
3863                                         $caption_text = null;
3864                                         if (isset($caption['attribs']['']['type']))
3865                                         {
3866                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3867                                         }
3868                                         if (isset($caption['attribs']['']['lang']))
3869                                         {
3870                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3871                                         }
3872                                         if (isset($caption['attribs']['']['start']))
3873                                         {
3874                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3875                                         }
3876                                         if (isset($caption['attribs']['']['end']))
3877                                         {
3878                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3879                                         }
3880                                         if (isset($caption['data']))
3881                                         {
3882                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3883                                         }
3884                                         $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3885                                 }
3886                         }
3887                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3888                         {
3889                                 foreach ($captions as $caption)
3890                                 {
3891                                         $caption_type = null;
3892                                         $caption_lang = null;
3893                                         $caption_startTime = null;
3894                                         $caption_endTime = null;
3895                                         $caption_text = null;
3896                                         if (isset($caption['attribs']['']['type']))
3897                                         {
3898                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3899                                         }
3900                                         if (isset($caption['attribs']['']['lang']))
3901                                         {
3902                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3903                                         }
3904                                         if (isset($caption['attribs']['']['start']))
3905                                         {
3906                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3907                                         }
3908                                         if (isset($caption['attribs']['']['end']))
3909                                         {
3910                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3911                                         }
3912                                         if (isset($caption['data']))
3913                                         {
3914                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3915                                         }
3916                                         $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3917                                 }
3918                         }
3919                         if (is_array($captions_parent))
3920                         {
3921                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3922                         }
3923
3924                         // CATEGORIES
3925                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3926                         {
3927                                 $term = null;
3928                                 $scheme = null;
3929                                 $label = null;
3930                                 if (isset($category['data']))
3931                                 {
3932                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3933                                 }
3934                                 if (isset($category['attribs']['']['scheme']))
3935                                 {
3936                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3937                                 }
3938                                 else
3939                                 {
3940                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3941                                 }
3942                                 if (isset($category['attribs']['']['label']))
3943                                 {
3944                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3945                                 }
3946                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3947                         }
3948                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3949                         {
3950                                 $term = null;
3951                                 $scheme = null;
3952                                 $label = null;
3953                                 if (isset($category['data']))
3954                                 {
3955                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3956                                 }
3957                                 if (isset($category['attribs']['']['scheme']))
3958                                 {
3959                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3960                                 }
3961                                 else
3962                                 {
3963                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3964                                 }
3965                                 if (isset($category['attribs']['']['label']))
3966                                 {
3967                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3968                                 }
3969                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3970                         }
3971                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3972                         {
3973                                 $term = null;
3974                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3975                                 $label = null;
3976                                 if (isset($category['attribs']['']['text']))
3977                                 {
3978                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3979                                 }
3980                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3981
3982                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3983                                 {
3984                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3985                                         {
3986                                                 if (isset($subcategory['attribs']['']['text']))
3987                                                 {
3988                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3989                                                 }
3990                                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3991                                         }
3992                                 }
3993                         }
3994                         if (is_array($categories_parent))
3995                         {
3996                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3997                         }
3998
3999                         // COPYRIGHT
4000                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4001                         {
4002                                 $copyright_url = null;
4003                                 $copyright_label = null;
4004                                 if (isset($copyright[0]['attribs']['']['url']))
4005                                 {
4006                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4007                                 }
4008                                 if (isset($copyright[0]['data']))
4009                                 {
4010                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4011                                 }
4012                                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
4013                         }
4014                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4015                         {
4016                                 $copyright_url = null;
4017                                 $copyright_label = null;
4018                                 if (isset($copyright[0]['attribs']['']['url']))
4019                                 {
4020                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4021                                 }
4022                                 if (isset($copyright[0]['data']))
4023                                 {
4024                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4025                                 }
4026                                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
4027                         }
4028
4029                         // CREDITS
4030                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4031                         {
4032                                 foreach ($credits as $credit)
4033                                 {
4034                                         $credit_role = null;
4035                                         $credit_scheme = null;
4036                                         $credit_name = null;
4037                                         if (isset($credit['attribs']['']['role']))
4038                                         {
4039                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4040                                         }
4041                                         if (isset($credit['attribs']['']['scheme']))
4042                                         {
4043                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4044                                         }
4045                                         else
4046                                         {
4047                                                 $credit_scheme = 'urn:ebu';
4048                                         }
4049                                         if (isset($credit['data']))
4050                                         {
4051                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4052                                         }
4053                                         $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4054                                 }
4055                         }
4056                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4057                         {
4058                                 foreach ($credits as $credit)
4059                                 {
4060                                         $credit_role = null;
4061                                         $credit_scheme = null;
4062                                         $credit_name = null;
4063                                         if (isset($credit['attribs']['']['role']))
4064                                         {
4065                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4066                                         }
4067                                         if (isset($credit['attribs']['']['scheme']))
4068                                         {
4069                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4070                                         }
4071                                         else
4072                                         {
4073                                                 $credit_scheme = 'urn:ebu';
4074                                         }
4075                                         if (isset($credit['data']))
4076                                         {
4077                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4078                                         }
4079                                         $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4080                                 }
4081                         }
4082                         if (is_array($credits_parent))
4083                         {
4084                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4085                         }
4086
4087                         // DESCRIPTION
4088                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4089                         {
4090                                 if (isset($description_parent[0]['data']))
4091                                 {
4092                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4093                                 }
4094                         }
4095                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4096                         {
4097                                 if (isset($description_parent[0]['data']))
4098                                 {
4099                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4100                                 }
4101                         }
4102
4103                         // DURATION
4104                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4105                         {
4106                                 $seconds = null;
4107                                 $minutes = null;
4108                                 $hours = null;
4109                                 if (isset($duration_parent[0]['data']))
4110                                 {
4111                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4112                                         if (sizeof($temp) > 0)
4113                                         {
4114                                                 (int) $seconds = array_pop($temp);
4115                                         }
4116                                         if (sizeof($temp) > 0)
4117                                         {
4118                                                 (int) $minutes = array_pop($temp);
4119                                                 $seconds += $minutes * 60;
4120                                         }
4121                                         if (sizeof($temp) > 0)
4122                                         {
4123                                                 (int) $hours = array_pop($temp);
4124                                                 $seconds += $hours * 3600;
4125                                         }
4126                                         unset($temp);
4127                                         $duration_parent = $seconds;
4128                                 }
4129                         }
4130
4131                         // HASHES
4132                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4133                         {
4134                                 foreach ($hashes_iterator as $hash)
4135                                 {
4136                                         $value = null;
4137                                         $algo = null;
4138                                         if (isset($hash['data']))
4139                                         {
4140                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4141                                         }
4142                                         if (isset($hash['attribs']['']['algo']))
4143                                         {
4144                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4145                                         }
4146                                         else
4147                                         {
4148                                                 $algo = 'md5';
4149                                         }
4150                                         $hashes_parent[] = $algo.':'.$value;
4151                                 }
4152                         }
4153                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4154                         {
4155                                 foreach ($hashes_iterator as $hash)
4156                                 {
4157                                         $value = null;
4158                                         $algo = null;
4159                                         if (isset($hash['data']))
4160                                         {
4161                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4162                                         }
4163                                         if (isset($hash['attribs']['']['algo']))
4164                                         {
4165                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4166                                         }
4167                                         else
4168                                         {
4169                                                 $algo = 'md5';
4170                                         }
4171                                         $hashes_parent[] = $algo.':'.$value;
4172                                 }
4173                         }
4174                         if (is_array($hashes_parent))
4175                         {
4176                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4177                         }
4178
4179                         // KEYWORDS
4180                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4181                         {
4182                                 if (isset($keywords[0]['data']))
4183                                 {
4184                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4185                                         foreach ($temp as $word)
4186                                         {
4187                                                 $keywords_parent[] = trim($word);
4188                                         }
4189                                 }
4190                                 unset($temp);
4191                         }
4192                         elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4193                         {
4194                                 if (isset($keywords[0]['data']))
4195                                 {
4196                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4197                                         foreach ($temp as $word)
4198                                         {
4199                                                 $keywords_parent[] = trim($word);
4200                                         }
4201                                 }
4202                                 unset($temp);
4203                         }
4204                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4205                         {
4206                                 if (isset($keywords[0]['data']))
4207                                 {
4208                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4209                                         foreach ($temp as $word)
4210                                         {
4211                                                 $keywords_parent[] = trim($word);
4212                                         }
4213                                 }
4214                                 unset($temp);
4215                         }
4216                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4217                         {
4218                                 if (isset($keywords[0]['data']))
4219                                 {
4220                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4221                                         foreach ($temp as $word)
4222                                         {
4223                                                 $keywords_parent[] = trim($word);
4224                                         }
4225                                 }
4226                                 unset($temp);
4227                         }
4228                         if (is_array($keywords_parent))
4229                         {
4230                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4231                         }
4232
4233                         // PLAYER
4234                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4235                         {
4236                                 if (isset($player_parent[0]['attribs']['']['url']))
4237                                 {
4238                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4239                                 }
4240                         }
4241                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4242                         {
4243                                 if (isset($player_parent[0]['attribs']['']['url']))
4244                                 {
4245                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4246                                 }
4247                         }
4248
4249                         // RATINGS
4250                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4251                         {
4252                                 foreach ($ratings as $rating)
4253                                 {
4254                                         $rating_scheme = null;
4255                                         $rating_value = null;
4256                                         if (isset($rating['attribs']['']['scheme']))
4257                                         {
4258                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4259                                         }
4260                                         else
4261                                         {
4262                                                 $rating_scheme = 'urn:simple';
4263                                         }
4264                                         if (isset($rating['data']))
4265                                         {
4266                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4267                                         }
4268                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4269                                 }
4270                         }
4271                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4272                         {
4273                                 foreach ($ratings as $rating)
4274                                 {
4275                                         $rating_scheme = 'urn:itunes';
4276                                         $rating_value = null;
4277                                         if (isset($rating['data']))
4278                                         {
4279                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4280                                         }
4281                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4282                                 }
4283                         }
4284                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4285                         {
4286                                 foreach ($ratings as $rating)
4287                                 {
4288                                         $rating_scheme = null;
4289                                         $rating_value = null;
4290                                         if (isset($rating['attribs']['']['scheme']))
4291                                         {
4292                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4293                                         }
4294                                         else
4295                                         {
4296                                                 $rating_scheme = 'urn:simple';
4297                                         }
4298                                         if (isset($rating['data']))
4299                                         {
4300                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4301                                         }
4302                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4303                                 }
4304                         }
4305                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4306                         {
4307                                 foreach ($ratings as $rating)
4308                                 {
4309                                         $rating_scheme = 'urn:itunes';
4310                                         $rating_value = null;
4311                                         if (isset($rating['data']))
4312                                         {
4313                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4314                                         }
4315                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4316                                 }
4317                         }
4318                         if (is_array($ratings_parent))
4319                         {
4320                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4321                         }
4322
4323                         // RESTRICTIONS
4324                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4325                         {
4326                                 foreach ($restrictions as $restriction)
4327                                 {
4328                                         $restriction_relationship = null;
4329                                         $restriction_type = null;
4330                                         $restriction_value = null;
4331                                         if (isset($restriction['attribs']['']['relationship']))
4332                                         {
4333                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4334                                         }
4335                                         if (isset($restriction['attribs']['']['type']))
4336                                         {
4337                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4338                                         }
4339                                         if (isset($restriction['data']))
4340                                         {
4341                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4342                                         }
4343                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4344                                 }
4345                         }
4346                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4347                         {
4348                                 foreach ($restrictions as $restriction)
4349                                 {
4350                                         $restriction_relationship = 'allow';
4351                                         $restriction_type = null;
4352                                         $restriction_value = 'itunes';
4353                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4354                                         {
4355                                                 $restriction_relationship = 'deny';
4356                                         }
4357                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4358                                 }
4359                         }
4360                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4361                         {
4362                                 foreach ($restrictions as $restriction)
4363                                 {
4364                                         $restriction_relationship = null;
4365                                         $restriction_type = null;
4366                                         $restriction_value = null;
4367                                         if (isset($restriction['attribs']['']['relationship']))
4368                                         {
4369                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4370                                         }
4371                                         if (isset($restriction['attribs']['']['type']))
4372                                         {
4373                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4374                                         }
4375                                         if (isset($restriction['data']))
4376                                         {
4377                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4378                                         }
4379                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4380                                 }
4381                         }
4382                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4383                         {
4384                                 foreach ($restrictions as $restriction)
4385                                 {
4386                                         $restriction_relationship = 'allow';
4387                                         $restriction_type = null;
4388                                         $restriction_value = 'itunes';
4389                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4390                                         {
4391                                                 $restriction_relationship = 'deny';
4392                                         }
4393                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4394                                 }
4395                         }
4396                         if (is_array($restrictions_parent))
4397                         {
4398                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4399                         }
4400
4401                         // THUMBNAILS
4402                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4403                         {
4404                                 foreach ($thumbnails as $thumbnail)
4405                                 {
4406                                         if (isset($thumbnail['attribs']['']['url']))
4407                                         {
4408                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4409                                         }
4410                                 }
4411                         }
4412                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4413                         {
4414                                 foreach ($thumbnails as $thumbnail)
4415                                 {
4416                                         if (isset($thumbnail['attribs']['']['url']))
4417                                         {
4418                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4419                                         }
4420                                 }
4421                         }
4422
4423                         // TITLES
4424                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4425                         {
4426                                 if (isset($title_parent[0]['data']))
4427                                 {
4428                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4429                                 }
4430                         }
4431                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4432                         {
4433                                 if (isset($title_parent[0]['data']))
4434                                 {
4435                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4436                                 }
4437                         }
4438
4439                         // Clear the memory
4440                         unset($parent);
4441
4442                         // Attributes
4443                         $bitrate = null;
4444                         $channels = null;
4445                         $duration = null;
4446                         $expression = null;
4447                         $framerate = null;
4448                         $height = null;
4449                         $javascript = null;
4450                         $lang = null;
4451                         $length = null;
4452                         $medium = null;
4453                         $samplingrate = null;
4454                         $type = null;
4455                         $url = null;
4456                         $width = null;
4457
4458                         // Elements
4459                         $captions = null;
4460                         $categories = null;
4461                         $copyrights = null;
4462                         $credits = null;
4463                         $description = null;
4464                         $hashes = null;
4465                         $keywords = null;
4466                         $player = null;
4467                         $ratings = null;
4468                         $restrictions = null;
4469                         $thumbnails = null;
4470                         $title = null;
4471
4472                         // If we have media:group tags, loop through them.
4473                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4474                         {
4475                                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4476                                 {
4477                                         // If we have media:content tags, loop through them.
4478                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4479                                         {
4480                                                 if (isset($content['attribs']['']['url']))
4481                                                 {
4482                                                         // Attributes
4483                                                         $bitrate = null;
4484                                                         $channels = null;
4485                                                         $duration = null;
4486                                                         $expression = null;
4487                                                         $framerate = null;
4488                                                         $height = null;
4489                                                         $javascript = null;
4490                                                         $lang = null;
4491                                                         $length = null;
4492                                                         $medium = null;
4493                                                         $samplingrate = null;
4494                                                         $type = null;
4495                                                         $url = null;
4496                                                         $width = null;
4497
4498                                                         // Elements
4499                                                         $captions = null;
4500                                                         $categories = null;
4501                                                         $copyrights = null;
4502                                                         $credits = null;
4503                                                         $description = null;
4504                                                         $hashes = null;
4505                                                         $keywords = null;
4506                                                         $player = null;
4507                                                         $ratings = null;
4508                                                         $restrictions = null;
4509                                                         $thumbnails = null;
4510                                                         $title = null;
4511
4512                                                         // Start checking the attributes of media:content
4513                                                         if (isset($content['attribs']['']['bitrate']))
4514                                                         {
4515                                                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4516                                                         }
4517                                                         if (isset($content['attribs']['']['channels']))
4518                                                         {
4519                                                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4520                                                         }
4521                                                         if (isset($content['attribs']['']['duration']))
4522                                                         {
4523                                                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4524                                                         }
4525                                                         else
4526                                                         {
4527                                                                 $duration = $duration_parent;
4528                                                         }
4529                                                         if (isset($content['attribs']['']['expression']))
4530                                                         {
4531                                                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4532                                                         }
4533                                                         if (isset($content['attribs']['']['framerate']))
4534                                                         {
4535                                                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4536                                                         }
4537                                                         if (isset($content['attribs']['']['height']))
4538                                                         {
4539                                                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4540                                                         }
4541                                                         if (isset($content['attribs']['']['lang']))
4542                                                         {
4543                                                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4544                                                         }
4545                                                         if (isset($content['attribs']['']['fileSize']))
4546                                                         {
4547                                                                 $length = ceil($content['attribs']['']['fileSize']);
4548                                                         }
4549                                                         if (isset($content['attribs']['']['medium']))
4550                                                         {
4551                                                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4552                                                         }
4553                                                         if (isset($content['attribs']['']['samplingrate']))
4554                                                         {
4555                                                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4556                                                         }
4557                                                         if (isset($content['attribs']['']['type']))
4558                                                         {
4559                                                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4560                                                         }
4561                                                         if (isset($content['attribs']['']['width']))
4562                                                         {
4563                                                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4564                                                         }
4565                                                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4566
4567                                                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4568
4569                                                         // CAPTIONS
4570                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4571                                                         {
4572                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4573                                                                 {
4574                                                                         $caption_type = null;
4575                                                                         $caption_lang = null;
4576                                                                         $caption_startTime = null;
4577                                                                         $caption_endTime = null;
4578                                                                         $caption_text = null;
4579                                                                         if (isset($caption['attribs']['']['type']))
4580                                                                         {
4581                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4582                                                                         }
4583                                                                         if (isset($caption['attribs']['']['lang']))
4584                                                                         {
4585                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4586                                                                         }
4587                                                                         if (isset($caption['attribs']['']['start']))
4588                                                                         {
4589                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4590                                                                         }
4591                                                                         if (isset($caption['attribs']['']['end']))
4592                                                                         {
4593                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4594                                                                         }
4595                                                                         if (isset($caption['data']))
4596                                                                         {
4597                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4598                                                                         }
4599                                                                         $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4600                                                                 }
4601                                                                 if (is_array($captions))
4602                                                                 {
4603                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4604                                                                 }
4605                                                         }
4606                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4607                                                         {
4608                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4609                                                                 {
4610                                                                         $caption_type = null;
4611                                                                         $caption_lang = null;
4612                                                                         $caption_startTime = null;
4613                                                                         $caption_endTime = null;
4614                                                                         $caption_text = null;
4615                                                                         if (isset($caption['attribs']['']['type']))
4616                                                                         {
4617                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4618                                                                         }
4619                                                                         if (isset($caption['attribs']['']['lang']))
4620                                                                         {
4621                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4622                                                                         }
4623                                                                         if (isset($caption['attribs']['']['start']))
4624                                                                         {
4625                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4626                                                                         }
4627                                                                         if (isset($caption['attribs']['']['end']))
4628                                                                         {
4629                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4630                                                                         }
4631                                                                         if (isset($caption['data']))
4632                                                                         {
4633                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4634                                                                         }
4635                                                                         $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4636                                                                 }
4637                                                                 if (is_array($captions))
4638                                                                 {
4639                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4640                                                                 }
4641                                                         }
4642                                                         else
4643                                                         {
4644                                                                 $captions = $captions_parent;
4645                                                         }
4646
4647                                                         // CATEGORIES
4648                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4649                                                         {
4650                                                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4651                                                                 {
4652                                                                         $term = null;
4653                                                                         $scheme = null;
4654                                                                         $label = null;
4655                                                                         if (isset($category['data']))
4656                                                                         {
4657                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4658                                                                         }
4659                                                                         if (isset($category['attribs']['']['scheme']))
4660                                                                         {
4661                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4662                                                                         }
4663                                                                         else
4664                                                                         {
4665                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4666                                                                         }
4667                                                                         if (isset($category['attribs']['']['label']))
4668                                                                         {
4669                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4670                                                                         }
4671                                                                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
4672                                                                 }
4673                                                         }
4674                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4675                                                         {
4676                                                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4677                                                                 {
4678                                                                         $term = null;
4679                                                                         $scheme = null;
4680                                                                         $label = null;
4681                                                                         if (isset($category['data']))
4682                                                                         {
4683                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4684                                                                         }
4685                                                                         if (isset($category['attribs']['']['scheme']))
4686                                                                         {
4687                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4688                                                                         }
4689                                                                         else
4690                                                                         {
4691                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4692                                                                         }
4693                                                                         if (isset($category['attribs']['']['label']))
4694                                                                         {
4695                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4696                                                                         }
4697                                                                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
4698                                                                 }
4699                                                         }
4700                                                         if (is_array($categories) && is_array($categories_parent))
4701                                                         {
4702                                                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4703                                                         }
4704                                                         elseif (is_array($categories))
4705                                                         {
4706                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
4707                                                         }
4708                                                         elseif (is_array($categories_parent))
4709                                                         {
4710                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4711                                                         }
4712
4713                                                         // COPYRIGHTS
4714                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4715                                                         {
4716                                                                 $copyright_url = null;
4717                                                                 $copyright_label = null;
4718                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4719                                                                 {
4720                                                                         $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4721                                                                 }
4722                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4723                                                                 {
4724                                                                         $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4725                                                                 }
4726                                                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4727                                                         }
4728                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4729                                                         {
4730                                                                 $copyright_url = null;
4731                                                                 $copyright_label = null;
4732                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4733                                                                 {
4734                                                                         $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4735                                                                 }
4736                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4737                                                                 {
4738                                                                         $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4739                                                                 }
4740                                                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4741                                                         }
4742                                                         else
4743                                                         {
4744                                                                 $copyrights = $copyrights_parent;
4745                                                         }
4746
4747                                                         // CREDITS
4748                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4749                                                         {
4750                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4751                                                                 {
4752                                                                         $credit_role = null;
4753                                                                         $credit_scheme = null;
4754                                                                         $credit_name = null;
4755                                                                         if (isset($credit['attribs']['']['role']))
4756                                                                         {
4757                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4758                                                                         }
4759                                                                         if (isset($credit['attribs']['']['scheme']))
4760                                                                         {
4761                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4762                                                                         }
4763                                                                         else
4764                                                                         {
4765                                                                                 $credit_scheme = 'urn:ebu';
4766                                                                         }
4767                                                                         if (isset($credit['data']))
4768                                                                         {
4769                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4770                                                                         }
4771                                                                         $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4772                                                                 }
4773                                                                 if (is_array($credits))
4774                                                                 {
4775                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4776                                                                 }
4777                                                         }
4778                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4779                                                         {
4780                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4781                                                                 {
4782                                                                         $credit_role = null;
4783                                                                         $credit_scheme = null;
4784                                                                         $credit_name = null;
4785                                                                         if (isset($credit['attribs']['']['role']))
4786                                                                         {
4787                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4788                                                                         }
4789                                                                         if (isset($credit['attribs']['']['scheme']))
4790                                                                         {
4791                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4792                                                                         }
4793                                                                         else
4794                                                                         {
4795                                                                                 $credit_scheme = 'urn:ebu';
4796                                                                         }
4797                                                                         if (isset($credit['data']))
4798                                                                         {
4799                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4800                                                                         }
4801                                                                         $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4802                                                                 }
4803                                                                 if (is_array($credits))
4804                                                                 {
4805                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4806                                                                 }
4807                                                         }
4808                                                         else
4809                                                         {
4810                                                                 $credits = $credits_parent;
4811                                                         }
4812
4813                                                         // DESCRIPTION
4814                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4815                                                         {
4816                                                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4817                                                         }
4818                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4819                                                         {
4820                                                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4821                                                         }
4822                                                         else
4823                                                         {
4824                                                                 $description = $description_parent;
4825                                                         }
4826
4827                                                         // HASHES
4828                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4829                                                         {
4830                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4831                                                                 {
4832                                                                         $value = null;
4833                                                                         $algo = null;
4834                                                                         if (isset($hash['data']))
4835                                                                         {
4836                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4837                                                                         }
4838                                                                         if (isset($hash['attribs']['']['algo']))
4839                                                                         {
4840                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4841                                                                         }
4842                                                                         else
4843                                                                         {
4844                                                                                 $algo = 'md5';
4845                                                                         }
4846                                                                         $hashes[] = $algo.':'.$value;
4847                                                                 }
4848                                                                 if (is_array($hashes))
4849                                                                 {
4850                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4851                                                                 }
4852                                                         }
4853                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4854                                                         {
4855                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4856                                                                 {
4857                                                                         $value = null;
4858                                                                         $algo = null;
4859                                                                         if (isset($hash['data']))
4860                                                                         {
4861                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4862                                                                         }
4863                                                                         if (isset($hash['attribs']['']['algo']))
4864                                                                         {
4865                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4866                                                                         }
4867                                                                         else
4868                                                                         {
4869                                                                                 $algo = 'md5';
4870                                                                         }
4871                                                                         $hashes[] = $algo.':'.$value;
4872                                                                 }
4873                                                                 if (is_array($hashes))
4874                                                                 {
4875                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4876                                                                 }
4877                                                         }
4878                                                         else
4879                                                         {
4880                                                                 $hashes = $hashes_parent;
4881                                                         }
4882
4883                                                         // KEYWORDS
4884                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4885                                                         {
4886                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4887                                                                 {
4888                                                                         $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4889                                                                         foreach ($temp as $word)
4890                                                                         {
4891                                                                                 $keywords[] = trim($word);
4892                                                                         }
4893                                                                         unset($temp);
4894                                                                 }
4895                                                                 if (is_array($keywords))
4896                                                                 {
4897                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4898                                                                 }
4899                                                         }
4900                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4901                                                         {
4902                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4903                                                                 {
4904                                                                         $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4905                                                                         foreach ($temp as $word)
4906                                                                         {
4907                                                                                 $keywords[] = trim($word);
4908                                                                         }
4909                                                                         unset($temp);
4910                                                                 }
4911                                                                 if (is_array($keywords))
4912                                                                 {
4913                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4914                                                                 }
4915                                                         }
4916                                                         else
4917                                                         {
4918                                                                 $keywords = $keywords_parent;
4919                                                         }
4920
4921                                                         // PLAYER
4922                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4923                                                         {
4924                                                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4925                                                         }
4926                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4927                                                         {
4928                                                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4929                                                         }
4930                                                         else
4931                                                         {
4932                                                                 $player = $player_parent;
4933                                                         }
4934
4935                                                         // RATINGS
4936                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4937                                                         {
4938                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4939                                                                 {
4940                                                                         $rating_scheme = null;
4941                                                                         $rating_value = null;
4942                                                                         if (isset($rating['attribs']['']['scheme']))
4943                                                                         {
4944                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4945                                                                         }
4946                                                                         else
4947                                                                         {
4948                                                                                 $rating_scheme = 'urn:simple';
4949                                                                         }
4950                                                                         if (isset($rating['data']))
4951                                                                         {
4952                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4953                                                                         }
4954                                                                         $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4955                                                                 }
4956                                                                 if (is_array($ratings))
4957                                                                 {
4958                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4959                                                                 }
4960                                                         }
4961                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4962                                                         {
4963                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4964                                                                 {
4965                                                                         $rating_scheme = null;
4966                                                                         $rating_value = null;
4967                                                                         if (isset($rating['attribs']['']['scheme']))
4968                                                                         {
4969                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4970                                                                         }
4971                                                                         else
4972                                                                         {
4973                                                                                 $rating_scheme = 'urn:simple';
4974                                                                         }
4975                                                                         if (isset($rating['data']))
4976                                                                         {
4977                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4978                                                                         }
4979                                                                         $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4980                                                                 }
4981                                                                 if (is_array($ratings))
4982                                                                 {
4983                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4984                                                                 }
4985                                                         }
4986                                                         else
4987                                                         {
4988                                                                 $ratings = $ratings_parent;
4989                                                         }
4990
4991                                                         // RESTRICTIONS
4992                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4993                                                         {
4994                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4995                                                                 {
4996                                                                         $restriction_relationship = null;
4997                                                                         $restriction_type = null;
4998                                                                         $restriction_value = null;
4999                                                                         if (isset($restriction['attribs']['']['relationship']))
5000                                                                         {
5001                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5002                                                                         }
5003                                                                         if (isset($restriction['attribs']['']['type']))
5004                                                                         {
5005                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5006                                                                         }
5007                                                                         if (isset($restriction['data']))
5008                                                                         {
5009                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5010                                                                         }
5011                                                                         $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5012                                                                 }
5013                                                                 if (is_array($restrictions))
5014                                                                 {
5015                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5016                                                                 }
5017                                                         }
5018                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5019                                                         {
5020                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5021                                                                 {
5022                                                                         $restriction_relationship = null;
5023                                                                         $restriction_type = null;
5024                                                                         $restriction_value = null;
5025                                                                         if (isset($restriction['attribs']['']['relationship']))
5026                                                                         {
5027                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5028                                                                         }
5029                                                                         if (isset($restriction['attribs']['']['type']))
5030                                                                         {
5031                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5032                                                                         }
5033                                                                         if (isset($restriction['data']))
5034                                                                         {
5035                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5036                                                                         }
5037                                                                         $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5038                                                                 }
5039                                                                 if (is_array($restrictions))
5040                                                                 {
5041                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5042                                                                 }
5043                                                         }
5044                                                         else
5045                                                         {
5046                                                                 $restrictions = $restrictions_parent;
5047                                                         }
5048
5049                                                         // THUMBNAILS
5050                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5051                                                         {
5052                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5053                                                                 {
5054                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5055                                                                 }
5056                                                                 if (is_array($thumbnails))
5057                                                                 {
5058                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5059                                                                 }
5060                                                         }
5061                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5062                                                         {
5063                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5064                                                                 {
5065                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5066                                                                 }
5067                                                                 if (is_array($thumbnails))
5068                                                                 {
5069                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5070                                                                 }
5071                                                         }
5072                                                         else
5073                                                         {
5074                                                                 $thumbnails = $thumbnails_parent;
5075                                                         }
5076
5077                                                         // TITLES
5078                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5079                                                         {
5080                                                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5081                                                         }
5082                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5083                                                         {
5084                                                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5085                                                         }
5086                                                         else
5087                                                         {
5088                                                                 $title = $title_parent;
5089                                                         }
5090
5091                                                         $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);
5092                                                 }
5093                                         }
5094                                 }
5095                         }
5096
5097                         // If we have standalone media:content tags, loop through them.
5098                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5099                         {
5100                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5101                                 {
5102                                         if (isset($content['attribs']['']['url']))
5103                                         {
5104                                                 // Attributes
5105                                                 $bitrate = null;
5106                                                 $channels = null;
5107                                                 $duration = null;
5108                                                 $expression = null;
5109                                                 $framerate = null;
5110                                                 $height = null;
5111                                                 $javascript = null;
5112                                                 $lang = null;
5113                                                 $length = null;
5114                                                 $medium = null;
5115                                                 $samplingrate = null;
5116                                                 $type = null;
5117                                                 $url = null;
5118                                                 $width = null;
5119
5120                                                 // Elements
5121                                                 $captions = null;
5122                                                 $categories = null;
5123                                                 $copyrights = null;
5124                                                 $credits = null;
5125                                                 $description = null;
5126                                                 $hashes = null;
5127                                                 $keywords = null;
5128                                                 $player = null;
5129                                                 $ratings = null;
5130                                                 $restrictions = null;
5131                                                 $thumbnails = null;
5132                                                 $title = null;
5133
5134                                                 // Start checking the attributes of media:content
5135                                                 if (isset($content['attribs']['']['bitrate']))
5136                                                 {
5137                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5138                                                 }
5139                                                 if (isset($content['attribs']['']['channels']))
5140                                                 {
5141                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5142                                                 }
5143                                                 if (isset($content['attribs']['']['duration']))
5144                                                 {
5145                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5146                                                 }
5147                                                 else
5148                                                 {
5149                                                         $duration = $duration_parent;
5150                                                 }
5151                                                 if (isset($content['attribs']['']['expression']))
5152                                                 {
5153                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5154                                                 }
5155                                                 if (isset($content['attribs']['']['framerate']))
5156                                                 {
5157                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5158                                                 }
5159                                                 if (isset($content['attribs']['']['height']))
5160                                                 {
5161                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5162                                                 }
5163                                                 if (isset($content['attribs']['']['lang']))
5164                                                 {
5165                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5166                                                 }
5167                                                 if (isset($content['attribs']['']['fileSize']))
5168                                                 {
5169                                                         $length = ceil($content['attribs']['']['fileSize']);
5170                                                 }
5171                                                 if (isset($content['attribs']['']['medium']))
5172                                                 {
5173                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5174                                                 }
5175                                                 if (isset($content['attribs']['']['samplingrate']))
5176                                                 {
5177                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5178                                                 }
5179                                                 if (isset($content['attribs']['']['type']))
5180                                                 {
5181                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5182                                                 }
5183                                                 if (isset($content['attribs']['']['width']))
5184                                                 {
5185                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5186                                                 }
5187                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5188
5189                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5190
5191                                                 // CAPTIONS
5192                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5193                                                 {
5194                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5195                                                         {
5196                                                                 $caption_type = null;
5197                                                                 $caption_lang = null;
5198                                                                 $caption_startTime = null;
5199                                                                 $caption_endTime = null;
5200                                                                 $caption_text = null;
5201                                                                 if (isset($caption['attribs']['']['type']))
5202                                                                 {
5203                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5204                                                                 }
5205                                                                 if (isset($caption['attribs']['']['lang']))
5206                                                                 {
5207                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5208                                                                 }
5209                                                                 if (isset($caption['attribs']['']['start']))
5210                                                                 {
5211                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5212                                                                 }
5213                                                                 if (isset($caption['attribs']['']['end']))
5214                                                                 {
5215                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5216                                                                 }
5217                                                                 if (isset($caption['data']))
5218                                                                 {
5219                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5220                                                                 }
5221                                                                 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5222                                                         }
5223                                                         if (is_array($captions))
5224                                                         {
5225                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5226                                                         }
5227                                                 }
5228                                                 else
5229                                                 {
5230                                                         $captions = $captions_parent;
5231                                                 }
5232
5233                                                 // CATEGORIES
5234                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5235                                                 {
5236                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5237                                                         {
5238                                                                 $term = null;
5239                                                                 $scheme = null;
5240                                                                 $label = null;
5241                                                                 if (isset($category['data']))
5242                                                                 {
5243                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5244                                                                 }
5245                                                                 if (isset($category['attribs']['']['scheme']))
5246                                                                 {
5247                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5248                                                                 }
5249                                                                 else
5250                                                                 {
5251                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5252                                                                 }
5253                                                                 if (isset($category['attribs']['']['label']))
5254                                                                 {
5255                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5256                                                                 }
5257                                                                 $categories[] = new $this->feed->category_class($term, $scheme, $label);
5258                                                         }
5259                                                 }
5260                                                 if (is_array($categories) && is_array($categories_parent))
5261                                                 {
5262                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5263                                                 }
5264                                                 elseif (is_array($categories))
5265                                                 {
5266                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5267                                                 }
5268                                                 elseif (is_array($categories_parent))
5269                                                 {
5270                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5271                                                 }
5272                                                 else
5273                                                 {
5274                                                         $categories = null;
5275                                                 }
5276
5277                                                 // COPYRIGHTS
5278                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5279                                                 {
5280                                                         $copyright_url = null;
5281                                                         $copyright_label = null;
5282                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5283                                                         {
5284                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5285                                                         }
5286                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5287                                                         {
5288                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5289                                                         }
5290                                                         $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
5291                                                 }
5292                                                 else
5293                                                 {
5294                                                         $copyrights = $copyrights_parent;
5295                                                 }
5296
5297                                                 // CREDITS
5298                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5299                                                 {
5300                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5301                                                         {
5302                                                                 $credit_role = null;
5303                                                                 $credit_scheme = null;
5304                                                                 $credit_name = null;
5305                                                                 if (isset($credit['attribs']['']['role']))
5306                                                                 {
5307                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5308                                                                 }
5309                                                                 if (isset($credit['attribs']['']['scheme']))
5310                                                                 {
5311                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5312                                                                 }
5313                                                                 else
5314                                                                 {
5315                                                                         $credit_scheme = 'urn:ebu';
5316                                                                 }
5317                                                                 if (isset($credit['data']))
5318                                                                 {
5319                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5320                                                                 }
5321                                                                 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5322                                                         }
5323                                                         if (is_array($credits))
5324                                                         {
5325                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5326                                                         }
5327                                                 }
5328                                                 else
5329                                                 {
5330                                                         $credits = $credits_parent;
5331                                                 }
5332
5333                                                 // DESCRIPTION
5334                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5335                                                 {
5336                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5337                                                 }
5338                                                 else
5339                                                 {
5340                                                         $description = $description_parent;
5341                                                 }
5342
5343                                                 // HASHES
5344                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5345                                                 {
5346                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5347                                                         {
5348                                                                 $value = null;
5349                                                                 $algo = null;
5350                                                                 if (isset($hash['data']))
5351                                                                 {
5352                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5353                                                                 }
5354                                                                 if (isset($hash['attribs']['']['algo']))
5355                                                                 {
5356                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5357                                                                 }
5358                                                                 else
5359                                                                 {
5360                                                                         $algo = 'md5';
5361                                                                 }
5362                                                                 $hashes[] = $algo.':'.$value;
5363                                                         }
5364                                                         if (is_array($hashes))
5365                                                         {
5366                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5367                                                         }
5368                                                 }
5369                                                 else
5370                                                 {
5371                                                         $hashes = $hashes_parent;
5372                                                 }
5373
5374                                                 // KEYWORDS
5375                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5376                                                 {
5377                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5378                                                         {
5379                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5380                                                                 foreach ($temp as $word)
5381                                                                 {
5382                                                                         $keywords[] = trim($word);
5383                                                                 }
5384                                                                 unset($temp);
5385                                                         }
5386                                                         if (is_array($keywords))
5387                                                         {
5388                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5389                                                         }
5390                                                 }
5391                                                 else
5392                                                 {
5393                                                         $keywords = $keywords_parent;
5394                                                 }
5395
5396                                                 // PLAYER
5397                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5398                                                 {
5399                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5400                                                 }
5401                                                 else
5402                                                 {
5403                                                         $player = $player_parent;
5404                                                 }
5405
5406                                                 // RATINGS
5407                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5408                                                 {
5409                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5410                                                         {
5411                                                                 $rating_scheme = null;
5412                                                                 $rating_value = null;
5413                                                                 if (isset($rating['attribs']['']['scheme']))
5414                                                                 {
5415                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5416                                                                 }
5417                                                                 else
5418                                                                 {
5419                                                                         $rating_scheme = 'urn:simple';
5420                                                                 }
5421                                                                 if (isset($rating['data']))
5422                                                                 {
5423                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5424                                                                 }
5425                                                                 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
5426                                                         }
5427                                                         if (is_array($ratings))
5428                                                         {
5429                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5430                                                         }
5431                                                 }
5432                                                 else
5433                                                 {
5434                                                         $ratings = $ratings_parent;
5435                                                 }
5436
5437                                                 // RESTRICTIONS
5438                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5439                                                 {
5440                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5441                                                         {
5442                                                                 $restriction_relationship = null;
5443                                                                 $restriction_type = null;
5444                                                                 $restriction_value = null;
5445                                                                 if (isset($restriction['attribs']['']['relationship']))
5446                                                                 {
5447                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5448                                                                 }
5449                                                                 if (isset($restriction['attribs']['']['type']))
5450                                                                 {
5451                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5452                                                                 }
5453                                                                 if (isset($restriction['data']))
5454                                                                 {
5455                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5456                                                                 }
5457                                                                 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5458                                                         }
5459                                                         if (is_array($restrictions))
5460                                                         {
5461                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5462                                                         }
5463                                                 }
5464                                                 else
5465                                                 {
5466                                                         $restrictions = $restrictions_parent;
5467                                                 }
5468
5469                                                 // THUMBNAILS
5470                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5471                                                 {
5472                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5473                                                         {
5474                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5475                                                         }
5476                                                         if (is_array($thumbnails))
5477                                                         {
5478                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5479                                                         }
5480                                                 }
5481                                                 else
5482                                                 {
5483                                                         $thumbnails = $thumbnails_parent;
5484                                                 }
5485
5486                                                 // TITLES
5487                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5488                                                 {
5489                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5490                                                 }
5491                                                 else
5492                                                 {
5493                                                         $title = $title_parent;
5494                                                 }
5495
5496                                                 $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);
5497                                         }
5498                                 }
5499                         }
5500
5501                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5502                         {
5503                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5504                                 {
5505                                         // Attributes
5506                                         $bitrate = null;
5507                                         $channels = null;
5508                                         $duration = null;
5509                                         $expression = null;
5510                                         $framerate = null;
5511                                         $height = null;
5512                                         $javascript = null;
5513                                         $lang = null;
5514                                         $length = null;
5515                                         $medium = null;
5516                                         $samplingrate = null;
5517                                         $type = null;
5518                                         $url = null;
5519                                         $width = null;
5520
5521                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5522                                         if (isset($link['attribs']['']['type']))
5523                                         {
5524                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5525                                         }
5526                                         if (isset($link['attribs']['']['length']))
5527                                         {
5528                                                 $length = ceil($link['attribs']['']['length']);
5529                                         }
5530
5531                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5532                                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5533                                 }
5534                         }
5535
5536                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5537                         {
5538                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5539                                 {
5540                                         // Attributes
5541                                         $bitrate = null;
5542                                         $channels = null;
5543                                         $duration = null;
5544                                         $expression = null;
5545                                         $framerate = null;
5546                                         $height = null;
5547                                         $javascript = null;
5548                                         $lang = null;
5549                                         $length = null;
5550                                         $medium = null;
5551                                         $samplingrate = null;
5552                                         $type = null;
5553                                         $url = null;
5554                                         $width = null;
5555
5556                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5557                                         if (isset($link['attribs']['']['type']))
5558                                         {
5559                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5560                                         }
5561                                         if (isset($link['attribs']['']['length']))
5562                                         {
5563                                                 $length = ceil($link['attribs']['']['length']);
5564                                         }
5565
5566                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5567                                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5568                                 }
5569                         }
5570
5571                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5572                         {
5573                                 if (isset($enclosure[0]['attribs']['']['url']))
5574                                 {
5575                                         // Attributes
5576                                         $bitrate = null;
5577                                         $channels = null;
5578                                         $duration = null;
5579                                         $expression = null;
5580                                         $framerate = null;
5581                                         $height = null;
5582                                         $javascript = null;
5583                                         $lang = null;
5584                                         $length = null;
5585                                         $medium = null;
5586                                         $samplingrate = null;
5587                                         $type = null;
5588                                         $url = null;
5589                                         $width = null;
5590
5591                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5592                                         if (isset($enclosure[0]['attribs']['']['type']))
5593                                         {
5594                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5595                                         }
5596                                         if (isset($enclosure[0]['attribs']['']['length']))
5597                                         {
5598                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5599                                         }
5600
5601                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5602                                         $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);
5603                                 }
5604                         }
5605
5606                         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))
5607                         {
5608                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5609                                 $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);
5610                         }
5611
5612                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5613                 }
5614                 if (!empty($this->data['enclosures']))
5615                 {
5616                         return $this->data['enclosures'];
5617                 }
5618                 else
5619                 {
5620                         return null;
5621                 }
5622         }
5623
5624         function get_latitude()
5625         {
5626                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5627                 {
5628                         return (float) $return[0]['data'];
5629                 }
5630                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5631                 {
5632                         return (float) $match[1];
5633                 }
5634                 else
5635                 {
5636                         return null;
5637                 }
5638         }
5639
5640         function get_longitude()
5641         {
5642                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5643                 {
5644                         return (float) $return[0]['data'];
5645                 }
5646                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5647                 {
5648                         return (float) $return[0]['data'];
5649                 }
5650                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5651                 {
5652                         return (float) $match[2];
5653                 }
5654                 else
5655                 {
5656                         return null;
5657                 }
5658         }
5659
5660         function get_source()
5661         {
5662                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5663                 {
5664                         return new $this->feed->source_class($this, $return[0]);
5665                 }
5666                 else
5667                 {
5668                         return null;
5669                 }
5670         }
5671
5672         /**
5673          * Creates the add_to_* methods' return data
5674          *
5675          * @access private
5676          * @param string $item_url String to prefix to the item permalink
5677          * @param string $title_url String to prefix to the item title
5678          * (and suffix to the item permalink)
5679          * @return mixed URL if feed exists, false otherwise
5680          */
5681         function add_to_service($item_url, $title_url = null, $summary_url = null)
5682         {
5683                 if ($this->get_permalink() !== null)
5684                 {
5685                         $return = $item_url . rawurlencode($this->get_permalink());
5686                         if ($title_url !== null && $this->get_title() !== null)
5687                         {
5688                                 $return .= $title_url . rawurlencode($this->get_title());
5689                         }
5690                         if ($summary_url !== null && $this->get_description() !== null)
5691                         {
5692                                 $return .= $summary_url . rawurlencode($this->get_description());
5693                         }
5694                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5695                 }
5696                 else
5697                 {
5698                         return null;
5699                 }
5700         }
5701
5702         function add_to_blinklist()
5703         {
5704                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5705         }
5706
5707         function add_to_blogmarks()
5708         {
5709                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5710         }
5711
5712         function add_to_delicious()
5713         {
5714                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5715         }
5716
5717         function add_to_digg()
5718         {
5719                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5720         }
5721
5722         function add_to_furl()
5723         {
5724                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5725         }
5726
5727         function add_to_magnolia()
5728         {
5729                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5730         }
5731
5732         function add_to_myweb20()
5733         {
5734                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5735         }
5736
5737         function add_to_newsvine()
5738         {
5739                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5740         }
5741
5742         function add_to_reddit()
5743         {
5744                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5745         }
5746
5747         function add_to_segnalo()
5748         {
5749                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5750         }
5751
5752         function add_to_simpy()
5753         {
5754                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5755         }
5756
5757         function add_to_spurl()
5758         {
5759                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5760         }
5761
5762         function add_to_wists()
5763         {
5764                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5765         }
5766
5767         function search_technorati()
5768         {
5769                 return $this->add_to_service('http://www.technorati.com/search/');
5770         }
5771 }
5772
5773 class SimplePie_Source
5774 {
5775         var $item;
5776         var $data = array();
5777
5778         function SimplePie_Source($item, $data)
5779         {
5780                 $this->item = $item;
5781                 $this->data = $data;
5782         }
5783
5784         function __toString()
5785         {
5786                 return md5(serialize($this->data));
5787         }
5788
5789         function get_source_tags($namespace, $tag)
5790         {
5791                 if (isset($this->data['child'][$namespace][$tag]))
5792                 {
5793                         return $this->data['child'][$namespace][$tag];
5794                 }
5795                 else
5796                 {
5797                         return null;
5798                 }
5799         }
5800
5801         function get_base($element = array())
5802         {
5803                 return $this->item->get_base($element);
5804         }
5805
5806         function sanitize($data, $type, $base = '')
5807         {
5808                 return $this->item->sanitize($data, $type, $base);
5809         }
5810
5811         function get_item()
5812         {
5813                 return $this->item;
5814         }
5815
5816         function get_title()
5817         {
5818                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5819                 {
5820                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5821                 }
5822                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5823                 {
5824                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5825                 }
5826                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5827                 {
5828                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5829                 }
5830                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5831                 {
5832                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5833                 }
5834                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5835                 {
5836                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5837                 }
5838                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5839                 {
5840                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5841                 }
5842                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5843                 {
5844                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5845                 }
5846                 else
5847                 {
5848                         return null;
5849                 }
5850         }
5851
5852         function get_category($key = 0)
5853         {
5854                 $categories = $this->get_categories();
5855                 if (isset($categories[$key]))
5856                 {
5857                         return $categories[$key];
5858                 }
5859                 else
5860                 {
5861                         return null;
5862                 }
5863         }
5864
5865         function get_categories()
5866         {
5867                 $categories = array();
5868
5869                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5870                 {
5871                         $term = null;
5872                         $scheme = null;
5873                         $label = null;
5874                         if (isset($category['attribs']['']['term']))
5875                         {
5876                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5877                         }
5878                         if (isset($category['attribs']['']['scheme']))
5879                         {
5880                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5881                         }
5882                         if (isset($category['attribs']['']['label']))
5883                         {
5884                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5885                         }
5886                         $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5887                 }
5888                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5889                 {
5890                         // This is really the label, but keep this as the term also for BC.
5891                         // Label will also work on retrieving because that falls back to term.
5892                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5893                         if (isset($category['attribs']['']['domain']))
5894                         {
5895                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5896                         }
5897                         else
5898                         {
5899                                 $scheme = null;
5900                         }
5901                         $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5902                 }
5903                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5904                 {
5905                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5906                 }
5907                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5908                 {
5909                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5910                 }
5911
5912                 if (!empty($categories))
5913                 {
5914                         return SimplePie_Misc::array_unique($categories);
5915                 }
5916                 else
5917                 {
5918                         return null;
5919                 }
5920         }
5921
5922         function get_author($key = 0)
5923         {
5924                 $authors = $this->get_authors();
5925                 if (isset($authors[$key]))
5926                 {
5927                         return $authors[$key];
5928                 }
5929                 else
5930                 {
5931                         return null;
5932                 }
5933         }
5934
5935         function get_authors()
5936         {
5937                 $authors = array();
5938                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5939                 {
5940                         $name = null;
5941                         $uri = null;
5942                         $email = null;
5943                         $avatar = null;
5944                         $name_date = null;
5945                         $uri_date = null;
5946                         $avatar_date = null;
5947
5948                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5949                         {
5950                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5951                         }
5952                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5953                         {
5954                                 $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]));
5955                         }
5956                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5957                         {
5958                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5959                         }
5960                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
5961                         {
5962                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
5963                         }
5964                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
5965                         {
5966                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
5967                         }
5968                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
5969                         {
5970                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
5971                         }
5972                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
5973                         {
5974                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
5975                         }
5976
5977                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
5978                         {
5979                                 $authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
5980                         }
5981                 }
5982                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5983                 {
5984                         $name = null;
5985                         $url = null;
5986                         $email = null;
5987                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5988                         {
5989                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5990                         }
5991                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5992                         {
5993                                 $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]));
5994                         }
5995                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5996                         {
5997                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5998                         }
5999                         if ($name !== null || $email !== null || $url !== null)
6000                         {
6001                                 $authors[] = new $this->item->feed->author_class($name, $url, $email);
6002                         }
6003                 }
6004                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
6005                 {
6006                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6007                 }
6008                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
6009                 {
6010                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6011                 }
6012                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
6013                 {
6014                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6015                 }
6016
6017                 if (!empty($authors))
6018                 {
6019                         return SimplePie_Misc::array_unique($authors);
6020                 }
6021                 else
6022                 {
6023                         return null;
6024                 }
6025         }
6026
6027         function get_contributor($key = 0)
6028         {
6029                 $contributors = $this->get_contributors();
6030                 if (isset($contributors[$key]))
6031                 {
6032                         return $contributors[$key];
6033                 }
6034                 else
6035                 {
6036                         return null;
6037                 }
6038         }
6039
6040         function get_contributors()
6041         {
6042                 $contributors = array();
6043                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
6044                 {
6045                         $name = null;
6046                         $uri = null;
6047                         $email = null;
6048                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6049                         {
6050                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6051                         }
6052                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6053                         {
6054                                 $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]));
6055                         }
6056                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6057                         {
6058                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6059                         }
6060                         if ($name !== null || $email !== null || $uri !== null)
6061                         {
6062                                 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
6063                         }
6064                 }
6065                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6066                 {
6067                         $name = null;
6068                         $url = null;
6069                         $email = null;
6070                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6071                         {
6072                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6073                         }
6074                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6075                         {
6076                                 $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]));
6077                         }
6078                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6079                         {
6080                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6081                         }
6082                         if ($name !== null || $email !== null || $url !== null)
6083                         {
6084                                 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
6085                         }
6086                 }
6087
6088                 if (!empty($contributors))
6089                 {
6090                         return SimplePie_Misc::array_unique($contributors);
6091                 }
6092                 else
6093                 {
6094                         return null;
6095                 }
6096         }
6097
6098         function get_link($key = 0, $rel = 'alternate')
6099         {
6100                 $links = $this->get_links($rel);
6101                 if (isset($links[$key]))
6102                 {
6103                         return $links[$key];
6104                 }
6105                 else
6106                 {
6107                         return null;
6108                 }
6109         }
6110
6111         /**
6112          * Added for parity between the parent-level and the item/entry-level.
6113          */
6114         function get_permalink()
6115         {
6116                 return $this->get_link(0);
6117         }
6118
6119         function get_links($rel = 'alternate')
6120         {
6121                 if (!isset($this->data['links']))
6122                 {
6123                         $this->data['links'] = array();
6124                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6125                         {
6126                                 foreach ($links as $link)
6127                                 {
6128                                         if (isset($link['attribs']['']['href']))
6129                                         {
6130                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6131                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6132                                         }
6133                                 }
6134                         }
6135                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6136                         {
6137                                 foreach ($links as $link)
6138                                 {
6139                                         if (isset($link['attribs']['']['href']))
6140                                         {
6141                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6142                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6143
6144                                         }
6145                                 }
6146                         }
6147                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6148                         {
6149                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6150                         }
6151                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6152                         {
6153                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6154                         }
6155                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6156                         {
6157                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6158                         }
6159
6160                         $keys = array_keys($this->data['links']);
6161                         foreach ($keys as $key)
6162                         {
6163                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6164                                 {
6165                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6166                                         {
6167                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6168                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6169                                         }
6170                                         else
6171                                         {
6172                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6173                                         }
6174                                 }
6175                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6176                                 {
6177                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6178                                 }
6179                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6180                         }
6181                 }
6182
6183                 if (isset($this->data['links'][$rel]))
6184                 {
6185                         return $this->data['links'][$rel];
6186                 }
6187                 else
6188                 {
6189                         return null;
6190                 }
6191         }
6192
6193         function get_description()
6194         {
6195                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6196                 {
6197                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6198                 }
6199                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6200                 {
6201                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6202                 }
6203                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6204                 {
6205                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6206                 }
6207                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6208                 {
6209                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6210                 }
6211                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6212                 {
6213                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6214                 }
6215                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6216                 {
6217                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6218                 }
6219                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6220                 {
6221                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6222                 }
6223                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6224                 {
6225                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6226                 }
6227                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6228                 {
6229                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6230                 }
6231                 else
6232                 {
6233                         return null;
6234                 }
6235         }
6236
6237         function get_copyright()
6238         {
6239                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6240                 {
6241                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6242                 }
6243                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6244                 {
6245                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6246                 }
6247                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6248                 {
6249                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6250                 }
6251                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6252                 {
6253                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6254                 }
6255                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6256                 {
6257                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6258                 }
6259                 else
6260                 {
6261                         return null;
6262                 }
6263         }
6264
6265         function get_language()
6266         {
6267                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6268                 {
6269                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6270                 }
6271                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6272                 {
6273                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6274                 }
6275                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6276                 {
6277                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6278                 }
6279                 elseif (isset($this->data['xml_lang']))
6280                 {
6281                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6282                 }
6283                 else
6284                 {
6285                         return null;
6286                 }
6287         }
6288
6289         function get_latitude()
6290         {
6291                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6292                 {
6293                         return (float) $return[0]['data'];
6294                 }
6295                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6296                 {
6297                         return (float) $match[1];
6298                 }
6299                 else
6300                 {
6301                         return null;
6302                 }
6303         }
6304
6305         function get_longitude()
6306         {
6307                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6308                 {
6309                         return (float) $return[0]['data'];
6310                 }
6311                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6312                 {
6313                         return (float) $return[0]['data'];
6314                 }
6315                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6316                 {
6317                         return (float) $match[2];
6318                 }
6319                 else
6320                 {
6321                         return null;
6322                 }
6323         }
6324
6325         function get_image_url()
6326         {
6327                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6328                 {
6329                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6330                 }
6331                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6332                 {
6333                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6334                 }
6335                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6336                 {
6337                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6338                 }
6339                 else
6340                 {
6341                         return null;
6342                 }
6343         }
6344 }
6345
6346 class SimplePie_Author
6347 {
6348         var $name;
6349         var $link;
6350         var $email;
6351         var $avatar;
6352         var $name_date;
6353         var $uri_date;
6354         var $avatar_date;
6355
6356         // Constructor, used to input the data
6357         function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null, $name_date = null, $uri_date = null, $avatar_date = null)
6358         {
6359                 $this->name = $name;
6360                 $this->link = $link;
6361                 $this->email = $email;
6362                 $this->avatar = $avatar;
6363                 $this->name_date = $name_date;
6364                 $this->uri_date = $uri_date;
6365                 $this->avatar_date = $avatar_date;
6366         }
6367
6368         function __toString()
6369         {
6370                 // There is no $this->data here
6371                 return md5(serialize($this));
6372         }
6373
6374         function get_name()
6375         {
6376                 if ($this->name !== null)
6377                 {
6378                         return $this->name;
6379                 }
6380                 else
6381                 {
6382                         return null;
6383                 }
6384         }
6385
6386         function get_link()
6387         {
6388                 if ($this->link !== null)
6389                 {
6390                         return $this->link;
6391                 }
6392                 else
6393                 {
6394                         return null;
6395                 }
6396         }
6397
6398         function get_email()
6399         {
6400                 if ($this->email !== null)
6401                 {
6402                         return $this->email;
6403                 }
6404                 else
6405                 {
6406                         return null;
6407                 }
6408         }
6409
6410         function get_avatar()
6411         {
6412                 if ($this->avatar !== null)
6413                 {
6414                         return $this->avatar;
6415                 }
6416                 else
6417                 {
6418                         return null;
6419                 }
6420         }
6421
6422         function get_name_date()
6423         {
6424                 if ($this->name_date !== null)
6425                 {
6426                         return $this->name_date;
6427                 }
6428                 else
6429                 {
6430                         return null;
6431                 }
6432         }
6433         function get_uri_date()
6434         {
6435                 if ($this->uri_date !== null)
6436                 {
6437                         return $this->uri_date;
6438                 }
6439                 else
6440                 {
6441                         return null;
6442                 }
6443         }
6444         function get_avatar_date()
6445         {
6446                 if ($this->avatar_date !== null)
6447                 {
6448                         return $this->avatar_date;
6449                 }
6450                 else
6451                 {
6452                         return null;
6453                 }
6454         }
6455
6456
6457 }
6458
6459 class SimplePie_Category
6460 {
6461         var $term;
6462         var $scheme;
6463         var $label;
6464
6465         // Constructor, used to input the data
6466         function SimplePie_Category($term = null, $scheme = null, $label = null)
6467         {
6468                 $this->term = $term;
6469                 $this->scheme = $scheme;
6470                 $this->label = $label;
6471         }
6472
6473         function __toString()
6474         {
6475                 // There is no $this->data here
6476                 return md5(serialize($this));
6477         }
6478
6479         function get_term()
6480         {
6481                 if ($this->term !== null)
6482                 {
6483                         return $this->term;
6484                 }
6485                 else
6486                 {
6487                         return null;
6488                 }
6489         }
6490
6491         function get_scheme()
6492         {
6493                 if ($this->scheme !== null)
6494                 {
6495                         return $this->scheme;
6496                 }
6497                 else
6498                 {
6499                         return null;
6500                 }
6501         }
6502
6503         function get_label()
6504         {
6505                 if ($this->label !== null)
6506                 {
6507                         return $this->label;
6508                 }
6509                 else
6510                 {
6511                         return $this->get_term();
6512                 }
6513         }
6514 }
6515
6516 class SimplePie_Enclosure
6517 {
6518         var $bitrate;
6519         var $captions;
6520         var $categories;
6521         var $channels;
6522         var $copyright;
6523         var $credits;
6524         var $description;
6525         var $duration;
6526         var $expression;
6527         var $framerate;
6528         var $handler;
6529         var $hashes;
6530         var $height;
6531         var $javascript;
6532         var $keywords;
6533         var $lang;
6534         var $length;
6535         var $link;
6536         var $medium;
6537         var $player;
6538         var $ratings;
6539         var $restrictions;
6540         var $samplingrate;
6541         var $thumbnails;
6542         var $title;
6543         var $type;
6544         var $width;
6545
6546         // Constructor, used to input the data
6547         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)
6548         {
6549                 $this->bitrate = $bitrate;
6550                 $this->captions = $captions;
6551                 $this->categories = $categories;
6552                 $this->channels = $channels;
6553                 $this->copyright = $copyright;
6554                 $this->credits = $credits;
6555                 $this->description = $description;
6556                 $this->duration = $duration;
6557                 $this->expression = $expression;
6558                 $this->framerate = $framerate;
6559                 $this->hashes = $hashes;
6560                 $this->height = $height;
6561                 $this->javascript = $javascript;
6562                 $this->keywords = $keywords;
6563                 $this->lang = $lang;
6564                 $this->length = $length;
6565                 $this->link = $link;
6566                 $this->medium = $medium;
6567                 $this->player = $player;
6568                 $this->ratings = $ratings;
6569                 $this->restrictions = $restrictions;
6570                 $this->samplingrate = $samplingrate;
6571                 $this->thumbnails = $thumbnails;
6572                 $this->title = $title;
6573                 $this->type = $type;
6574                 $this->width = $width;
6575                 if (class_exists('idna_convert'))
6576                 {
6577                         $idn = new idna_convert;
6578                         $parsed = SimplePie_Misc::parse_url($link);
6579                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6580                 }
6581                 $this->handler = $this->get_handler(); // Needs to load last
6582         }
6583
6584         function __toString()
6585         {
6586                 // There is no $this->data here
6587                 return md5(serialize($this));
6588         }
6589
6590         function get_bitrate()
6591         {
6592                 if ($this->bitrate !== null)
6593                 {
6594                         return $this->bitrate;
6595                 }
6596                 else
6597                 {
6598                         return null;
6599                 }
6600         }
6601
6602         function get_caption($key = 0)
6603         {
6604                 $captions = $this->get_captions();
6605                 if (isset($captions[$key]))
6606                 {
6607                         return $captions[$key];
6608                 }
6609                 else
6610                 {
6611                         return null;
6612                 }
6613         }
6614
6615         function get_captions()
6616         {
6617                 if ($this->captions !== null)
6618                 {
6619                         return $this->captions;
6620                 }
6621                 else
6622                 {
6623                         return null;
6624                 }
6625         }
6626
6627         function get_category($key = 0)
6628         {
6629                 $categories = $this->get_categories();
6630                 if (isset($categories[$key]))
6631                 {
6632                         return $categories[$key];
6633                 }
6634                 else
6635                 {
6636                         return null;
6637                 }
6638         }
6639
6640         function get_categories()
6641         {
6642                 if ($this->categories !== null)
6643                 {
6644                         return $this->categories;
6645                 }
6646                 else
6647                 {
6648                         return null;
6649                 }
6650         }
6651
6652         function get_channels()
6653         {
6654                 if ($this->channels !== null)
6655                 {
6656                         return $this->channels;
6657                 }
6658                 else
6659                 {
6660                         return null;
6661                 }
6662         }
6663
6664         function get_copyright()
6665         {
6666                 if ($this->copyright !== null)
6667                 {
6668                         return $this->copyright;
6669                 }
6670                 else
6671                 {
6672                         return null;
6673                 }
6674         }
6675
6676         function get_credit($key = 0)
6677         {
6678                 $credits = $this->get_credits();
6679                 if (isset($credits[$key]))
6680                 {
6681                         return $credits[$key];
6682                 }
6683                 else
6684                 {
6685                         return null;
6686                 }
6687         }
6688
6689         function get_credits()
6690         {
6691                 if ($this->credits !== null)
6692                 {
6693                         return $this->credits;
6694                 }
6695                 else
6696                 {
6697                         return null;
6698                 }
6699         }
6700
6701         function get_description()
6702         {
6703                 if ($this->description !== null)
6704                 {
6705                         return $this->description;
6706                 }
6707                 else
6708                 {
6709                         return null;
6710                 }
6711         }
6712
6713         function get_duration($convert = false)
6714         {
6715                 if ($this->duration !== null)
6716                 {
6717                         if ($convert)
6718                         {
6719                                 $time = SimplePie_Misc::time_hms($this->duration);
6720                                 return $time;
6721                         }
6722                         else
6723                         {
6724                                 return $this->duration;
6725                         }
6726                 }
6727                 else
6728                 {
6729                         return null;
6730                 }
6731         }
6732
6733         function get_expression()
6734         {
6735                 if ($this->expression !== null)
6736                 {
6737                         return $this->expression;
6738                 }
6739                 else
6740                 {
6741                         return 'full';
6742                 }
6743         }
6744
6745         function get_extension()
6746         {
6747                 if ($this->link !== null)
6748                 {
6749                         $url = SimplePie_Misc::parse_url($this->link);
6750                         if ($url['path'] !== '')
6751                         {
6752                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6753                         }
6754                 }
6755                 return null;
6756         }
6757
6758         function get_framerate()
6759         {
6760                 if ($this->framerate !== null)
6761                 {
6762                         return $this->framerate;
6763                 }
6764                 else
6765                 {
6766                         return null;
6767                 }
6768         }
6769
6770         function get_handler()
6771         {
6772                 return $this->get_real_type(true);
6773         }
6774
6775         function get_hash($key = 0)
6776         {
6777                 $hashes = $this->get_hashes();
6778                 if (isset($hashes[$key]))
6779                 {
6780                         return $hashes[$key];
6781                 }
6782                 else
6783                 {
6784                         return null;
6785                 }
6786         }
6787
6788         function get_hashes()
6789         {
6790                 if ($this->hashes !== null)
6791                 {
6792                         return $this->hashes;
6793                 }
6794                 else
6795                 {
6796                         return null;
6797                 }
6798         }
6799
6800         function get_height()
6801         {
6802                 if ($this->height !== null)
6803                 {
6804                         return $this->height;
6805                 }
6806                 else
6807                 {
6808                         return null;
6809                 }
6810         }
6811
6812         function get_language()
6813         {
6814                 if ($this->lang !== null)
6815                 {
6816                         return $this->lang;
6817                 }
6818                 else
6819                 {
6820                         return null;
6821                 }
6822         }
6823
6824         function get_keyword($key = 0)
6825         {
6826                 $keywords = $this->get_keywords();
6827                 if (isset($keywords[$key]))
6828                 {
6829                         return $keywords[$key];
6830                 }
6831                 else
6832                 {
6833                         return null;
6834                 }
6835         }
6836
6837         function get_keywords()
6838         {
6839                 if ($this->keywords !== null)
6840                 {
6841                         return $this->keywords;
6842                 }
6843                 else
6844                 {
6845                         return null;
6846                 }
6847         }
6848
6849         function get_length()
6850         {
6851                 if ($this->length !== null)
6852                 {
6853                         return $this->length;
6854                 }
6855                 else
6856                 {
6857                         return null;
6858                 }
6859         }
6860
6861         function get_link()
6862         {
6863                 if ($this->link !== null)
6864                 {
6865                         return urldecode($this->link);
6866                 }
6867                 else
6868                 {
6869                         return null;
6870                 }
6871         }
6872
6873         function get_medium()
6874         {
6875                 if ($this->medium !== null)
6876                 {
6877                         return $this->medium;
6878                 }
6879                 else
6880                 {
6881                         return null;
6882                 }
6883         }
6884
6885         function get_player()
6886         {
6887                 if ($this->player !== null)
6888                 {
6889                         return $this->player;
6890                 }
6891                 else
6892                 {
6893                         return null;
6894                 }
6895         }
6896
6897         function get_rating($key = 0)
6898         {
6899                 $ratings = $this->get_ratings();
6900                 if (isset($ratings[$key]))
6901                 {
6902                         return $ratings[$key];
6903                 }
6904                 else
6905                 {
6906                         return null;
6907                 }
6908         }
6909
6910         function get_ratings()
6911         {
6912                 if ($this->ratings !== null)
6913                 {
6914                         return $this->ratings;
6915                 }
6916                 else
6917                 {
6918                         return null;
6919                 }
6920         }
6921
6922         function get_restriction($key = 0)
6923         {
6924                 $restrictions = $this->get_restrictions();
6925                 if (isset($restrictions[$key]))
6926                 {
6927                         return $restrictions[$key];
6928                 }
6929                 else
6930                 {
6931                         return null;
6932                 }
6933         }
6934
6935         function get_restrictions()
6936         {
6937                 if ($this->restrictions !== null)
6938                 {
6939                         return $this->restrictions;
6940                 }
6941                 else
6942                 {
6943                         return null;
6944                 }
6945         }
6946
6947         function get_sampling_rate()
6948         {
6949                 if ($this->samplingrate !== null)
6950                 {
6951                         return $this->samplingrate;
6952                 }
6953                 else
6954                 {
6955                         return null;
6956                 }
6957         }
6958
6959         function get_size()
6960         {
6961                 $length = $this->get_length();
6962                 if ($length !== null)
6963                 {
6964                         return round($length/1048576, 2);
6965                 }
6966                 else
6967                 {
6968                         return null;
6969                 }
6970         }
6971
6972         function get_thumbnail($key = 0)
6973         {
6974                 $thumbnails = $this->get_thumbnails();
6975                 if (isset($thumbnails[$key]))
6976                 {
6977                         return $thumbnails[$key];
6978                 }
6979                 else
6980                 {
6981                         return null;
6982                 }
6983         }
6984
6985         function get_thumbnails()
6986         {
6987                 if ($this->thumbnails !== null)
6988                 {
6989                         return $this->thumbnails;
6990                 }
6991                 else
6992                 {
6993                         return null;
6994                 }
6995         }
6996
6997         function get_title()
6998         {
6999                 if ($this->title !== null)
7000                 {
7001                         return $this->title;
7002                 }
7003                 else
7004                 {
7005                         return null;
7006                 }
7007         }
7008
7009         function get_type()
7010         {
7011                 if ($this->type !== null)
7012                 {
7013                         return $this->type;
7014                 }
7015                 else
7016                 {
7017                         return null;
7018                 }
7019         }
7020
7021         function get_width()
7022         {
7023                 if ($this->width !== null)
7024                 {
7025                         return $this->width;
7026                 }
7027                 else
7028                 {
7029                         return null;
7030                 }
7031         }
7032
7033         function native_embed($options='')
7034         {
7035                 return $this->embed($options, true);
7036         }
7037
7038         /**
7039          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
7040          */
7041         function embed($options = '', $native = false)
7042         {
7043                 // Set up defaults
7044                 $audio = '';
7045                 $video = '';
7046                 $alt = '';
7047                 $altclass = '';
7048                 $loop = 'false';
7049                 $width = 'auto';
7050                 $height = 'auto';
7051                 $bgcolor = '#ffffff';
7052                 $mediaplayer = '';
7053                 $widescreen = false;
7054                 $handler = $this->get_handler();
7055                 $type = $this->get_real_type();
7056
7057                 // Process options and reassign values as necessary
7058                 if (is_array($options))
7059                 {
7060                         extract($options);
7061                 }
7062                 else
7063                 {
7064                         $options = explode(',', $options);
7065                         foreach($options as $option)
7066                         {
7067                                 $opt = explode(':', $option, 2);
7068                                 if (isset($opt[0], $opt[1]))
7069                                 {
7070                                         $opt[0] = trim($opt[0]);
7071                                         $opt[1] = trim($opt[1]);
7072                                         switch ($opt[0])
7073                                         {
7074                                                 case 'audio':
7075                                                         $audio = $opt[1];
7076                                                         break;
7077
7078                                                 case 'video':
7079                                                         $video = $opt[1];
7080                                                         break;
7081
7082                                                 case 'alt':
7083                                                         $alt = $opt[1];
7084                                                         break;
7085
7086                                                 case 'altclass':
7087                                                         $altclass = $opt[1];
7088                                                         break;
7089
7090                                                 case 'loop':
7091                                                         $loop = $opt[1];
7092                                                         break;
7093
7094                                                 case 'width':
7095                                                         $width = $opt[1];
7096                                                         break;
7097
7098                                                 case 'height':
7099                                                         $height = $opt[1];
7100                                                         break;
7101
7102                                                 case 'bgcolor':
7103                                                         $bgcolor = $opt[1];
7104                                                         break;
7105
7106                                                 case 'mediaplayer':
7107                                                         $mediaplayer = $opt[1];
7108                                                         break;
7109
7110                                                 case 'widescreen':
7111                                                         $widescreen = $opt[1];
7112                                                         break;
7113                                         }
7114                                 }
7115                         }
7116                 }
7117
7118                 $mime = explode('/', $type, 2);
7119                 $mime = $mime[0];
7120
7121                 // Process values for 'auto'
7122                 if ($width === 'auto')
7123                 {
7124                         if ($mime === 'video')
7125                         {
7126                                 if ($height === 'auto')
7127                                 {
7128                                         $width = 480;
7129                                 }
7130                                 elseif ($widescreen)
7131                                 {
7132                                         $width = round((intval($height)/9)*16);
7133                                 }
7134                                 else
7135                                 {
7136                                         $width = round((intval($height)/3)*4);
7137                                 }
7138                         }
7139                         else
7140                         {
7141                                 $width = '100%';
7142                         }
7143                 }
7144
7145                 if ($height === 'auto')
7146                 {
7147                         if ($mime === 'audio')
7148                         {
7149                                 $height = 0;
7150                         }
7151                         elseif ($mime === 'video')
7152                         {
7153                                 if ($width === 'auto')
7154                                 {
7155                                         if ($widescreen)
7156                                         {
7157                                                 $height = 270;
7158                                         }
7159                                         else
7160                                         {
7161                                                 $height = 360;
7162                                         }
7163                                 }
7164                                 elseif ($widescreen)
7165                                 {
7166                                         $height = round((intval($width)/16)*9);
7167                                 }
7168                                 else
7169                                 {
7170                                         $height = round((intval($width)/4)*3);
7171                                 }
7172                         }
7173                         else
7174                         {
7175                                 $height = 376;
7176                         }
7177                 }
7178                 elseif ($mime === 'audio')
7179                 {
7180                         $height = 0;
7181                 }
7182
7183                 // Set proper placeholder value
7184                 if ($mime === 'audio')
7185                 {
7186                         $placeholder = $audio;
7187                 }
7188                 elseif ($mime === 'video')
7189                 {
7190                         $placeholder = $video;
7191                 }
7192
7193                 $embed = '';
7194
7195                 // Make sure the JS library is included
7196                 if (!$native)
7197                 {
7198                         static $javascript_outputted = null;
7199                         if (!$javascript_outputted && $this->javascript)
7200                         {
7201                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7202                                 $javascript_outputted = true;
7203                         }
7204                 }
7205
7206                 // Odeo Feed MP3's
7207                 if ($handler === 'odeo')
7208                 {
7209                         if ($native)
7210                         {
7211                                 $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>';
7212                         }
7213                         else
7214                         {
7215                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7216                         }
7217                 }
7218
7219                 // Flash
7220                 elseif ($handler === 'flash')
7221                 {
7222                         if ($native)
7223                         {
7224                                 $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>";
7225                         }
7226                         else
7227                         {
7228                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7229                         }
7230                 }
7231
7232                 // Flash Media Player file types.
7233                 // Preferred handler for MP3 file types.
7234                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7235                 {
7236                         $height += 20;
7237                         if ($native)
7238                         {
7239                                 $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>";
7240                         }
7241                         else
7242                         {
7243                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7244                         }
7245                 }
7246
7247                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7248                 // Only handle MP3's if the Flash Media Player is not present.
7249                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7250                 {
7251                         $height += 16;
7252                         if ($native)
7253                         {
7254                                 if ($placeholder !== '')
7255                                 {
7256                                         $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>";
7257                                 }
7258                                 else
7259                                 {
7260                                         $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>";
7261                                 }
7262                         }
7263                         else
7264                         {
7265                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7266                         }
7267                 }
7268
7269                 // Windows Media
7270                 elseif ($handler === 'wmedia')
7271                 {
7272                         $height += 45;
7273                         if ($native)
7274                         {
7275                                 $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>";
7276                         }
7277                         else
7278                         {
7279                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7280                         }
7281                 }
7282
7283                 // Everything else
7284                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7285
7286                 return $embed;
7287         }
7288
7289         function get_real_type($find_handler = false)
7290         {
7291                 // If it's Odeo, let's get it out of the way.
7292                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7293                 {
7294                         return 'odeo';
7295                 }
7296
7297                 // Mime-types by handler.
7298                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7299                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7300                 $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
7301                 $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
7302                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7303
7304                 if ($this->get_type() !== null)
7305                 {
7306                         $type = strtolower($this->type);
7307                 }
7308                 else
7309                 {
7310                         $type = null;
7311                 }
7312
7313                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7314                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7315                 {
7316                         switch (strtolower($this->get_extension()))
7317                         {
7318                                 // Audio mime-types
7319                                 case 'aac':
7320                                 case 'adts':
7321                                         $type = 'audio/acc';
7322                                         break;
7323
7324                                 case 'aif':
7325                                 case 'aifc':
7326                                 case 'aiff':
7327                                 case 'cdda':
7328                                         $type = 'audio/aiff';
7329                                         break;
7330
7331                                 case 'bwf':
7332                                         $type = 'audio/wav';
7333                                         break;
7334
7335                                 case 'kar':
7336                                 case 'mid':
7337                                 case 'midi':
7338                                 case 'smf':
7339                                         $type = 'audio/midi';
7340                                         break;
7341
7342                                 case 'm4a':
7343                                         $type = 'audio/x-m4a';
7344                                         break;
7345
7346                                 case 'mp3':
7347                                 case 'swa':
7348                                         $type = 'audio/mp3';
7349                                         break;
7350
7351                                 case 'wav':
7352                                         $type = 'audio/wav';
7353                                         break;
7354
7355                                 case 'wax':
7356                                         $type = 'audio/x-ms-wax';
7357                                         break;
7358
7359                                 case 'wma':
7360                                         $type = 'audio/x-ms-wma';
7361                                         break;
7362
7363                                 // Video mime-types
7364                                 case '3gp':
7365                                 case '3gpp':
7366                                         $type = 'video/3gpp';
7367                                         break;
7368
7369                                 case '3g2':
7370                                 case '3gp2':
7371                                         $type = 'video/3gpp2';
7372                                         break;
7373
7374                                 case 'asf':
7375                                         $type = 'video/x-ms-asf';
7376                                         break;
7377
7378                                 case 'flv':
7379                                         $type = 'video/x-flv';
7380                                         break;
7381
7382                                 case 'm1a':
7383                                 case 'm1s':
7384                                 case 'm1v':
7385                                 case 'm15':
7386                                 case 'm75':
7387                                 case 'mp2':
7388                                 case 'mpa':
7389                                 case 'mpeg':
7390                                 case 'mpg':
7391                                 case 'mpm':
7392                                 case 'mpv':
7393                                         $type = 'video/mpeg';
7394                                         break;
7395
7396                                 case 'm4v':
7397                                         $type = 'video/x-m4v';
7398                                         break;
7399
7400                                 case 'mov':
7401                                 case 'qt':
7402                                         $type = 'video/quicktime';
7403                                         break;
7404
7405                                 case 'mp4':
7406                                 case 'mpg4':
7407                                         $type = 'video/mp4';
7408                                         break;
7409
7410                                 case 'sdv':
7411                                         $type = 'video/sd-video';
7412                                         break;
7413
7414                                 case 'wm':
7415                                         $type = 'video/x-ms-wm';
7416                                         break;
7417
7418                                 case 'wmv':
7419                                         $type = 'video/x-ms-wmv';
7420                                         break;
7421
7422                                 case 'wvx':
7423                                         $type = 'video/x-ms-wvx';
7424                                         break;
7425
7426                                 // Flash mime-types
7427                                 case 'spl':
7428                                         $type = 'application/futuresplash';
7429                                         break;
7430
7431                                 case 'swf':
7432                                         $type = 'application/x-shockwave-flash';
7433                                         break;
7434                         }
7435                 }
7436
7437                 if ($find_handler)
7438                 {
7439                         if (in_array($type, $types_flash))
7440                         {
7441                                 return 'flash';
7442                         }
7443                         elseif (in_array($type, $types_fmedia))
7444                         {
7445                                 return 'fmedia';
7446                         }
7447                         elseif (in_array($type, $types_quicktime))
7448                         {
7449                                 return 'quicktime';
7450                         }
7451                         elseif (in_array($type, $types_wmedia))
7452                         {
7453                                 return 'wmedia';
7454                         }
7455                         elseif (in_array($type, $types_mp3))
7456                         {
7457                                 return 'mp3';
7458                         }
7459                         else
7460                         {
7461                                 return null;
7462                         }
7463                 }
7464                 else
7465                 {
7466                         return $type;
7467                 }
7468         }
7469 }
7470
7471 class SimplePie_Caption
7472 {
7473         var $type;
7474         var $lang;
7475         var $startTime;
7476         var $endTime;
7477         var $text;
7478
7479         // Constructor, used to input the data
7480         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7481         {
7482                 $this->type = $type;
7483                 $this->lang = $lang;
7484                 $this->startTime = $startTime;
7485                 $this->endTime = $endTime;
7486                 $this->text = $text;
7487         }
7488
7489         function __toString()
7490         {
7491                 // There is no $this->data here
7492                 return md5(serialize($this));
7493         }
7494
7495         function get_endtime()
7496         {
7497                 if ($this->endTime !== null)
7498                 {
7499                         return $this->endTime;
7500                 }
7501                 else
7502                 {
7503                         return null;
7504                 }
7505         }
7506
7507         function get_language()
7508         {
7509                 if ($this->lang !== null)
7510                 {
7511                         return $this->lang;
7512                 }
7513                 else
7514                 {
7515                         return null;
7516                 }
7517         }
7518
7519         function get_starttime()
7520         {
7521                 if ($this->startTime !== null)
7522                 {
7523                         return $this->startTime;
7524                 }
7525                 else
7526                 {
7527                         return null;
7528                 }
7529         }
7530
7531         function get_text()
7532         {
7533                 if ($this->text !== null)
7534                 {
7535                         return $this->text;
7536                 }
7537                 else
7538                 {
7539                         return null;
7540                 }
7541         }
7542
7543         function get_type()
7544         {
7545                 if ($this->type !== null)
7546                 {
7547                         return $this->type;
7548                 }
7549                 else
7550                 {
7551                         return null;
7552                 }
7553         }
7554 }
7555
7556 class SimplePie_Credit
7557 {
7558         var $role;
7559         var $scheme;
7560         var $name;
7561
7562         // Constructor, used to input the data
7563         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7564         {
7565                 $this->role = $role;
7566                 $this->scheme = $scheme;
7567                 $this->name = $name;
7568         }
7569
7570         function __toString()
7571         {
7572                 // There is no $this->data here
7573                 return md5(serialize($this));
7574         }
7575
7576         function get_role()
7577         {
7578                 if ($this->role !== null)
7579                 {
7580                         return $this->role;
7581                 }
7582                 else
7583                 {
7584                         return null;
7585                 }
7586         }
7587
7588         function get_scheme()
7589         {
7590                 if ($this->scheme !== null)
7591                 {
7592                         return $this->scheme;
7593                 }
7594                 else
7595                 {
7596                         return null;
7597                 }
7598         }
7599
7600         function get_name()
7601         {
7602                 if ($this->name !== null)
7603                 {
7604                         return $this->name;
7605                 }
7606                 else
7607                 {
7608                         return null;
7609                 }
7610         }
7611 }
7612
7613 class SimplePie_Copyright
7614 {
7615         var $url;
7616         var $label;
7617
7618         // Constructor, used to input the data
7619         function SimplePie_Copyright($url = null, $label = null)
7620         {
7621                 $this->url = $url;
7622                 $this->label = $label;
7623         }
7624
7625         function __toString()
7626         {
7627                 // There is no $this->data here
7628                 return md5(serialize($this));
7629         }
7630
7631         function get_url()
7632         {
7633                 if ($this->url !== null)
7634                 {
7635                         return $this->url;
7636                 }
7637                 else
7638                 {
7639                         return null;
7640                 }
7641         }
7642
7643         function get_attribution()
7644         {
7645                 if ($this->label !== null)
7646                 {
7647                         return $this->label;
7648                 }
7649                 else
7650                 {
7651                         return null;
7652                 }
7653         }
7654 }
7655
7656 class SimplePie_Rating
7657 {
7658         var $scheme;
7659         var $value;
7660
7661         // Constructor, used to input the data
7662         function SimplePie_Rating($scheme = null, $value = null)
7663         {
7664                 $this->scheme = $scheme;
7665                 $this->value = $value;
7666         }
7667
7668         function __toString()
7669         {
7670                 // There is no $this->data here
7671                 return md5(serialize($this));
7672         }
7673
7674         function get_scheme()
7675         {
7676                 if ($this->scheme !== null)
7677                 {
7678                         return $this->scheme;
7679                 }
7680                 else
7681                 {
7682                         return null;
7683                 }
7684         }
7685
7686         function get_value()
7687         {
7688                 if ($this->value !== null)
7689                 {
7690                         return $this->value;
7691                 }
7692                 else
7693                 {
7694                         return null;
7695                 }
7696         }
7697 }
7698
7699 class SimplePie_Restriction
7700 {
7701         var $relationship;
7702         var $type;
7703         var $value;
7704
7705         // Constructor, used to input the data
7706         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7707         {
7708                 $this->relationship = $relationship;
7709                 $this->type = $type;
7710                 $this->value = $value;
7711         }
7712
7713         function __toString()
7714         {
7715                 // There is no $this->data here
7716                 return md5(serialize($this));
7717         }
7718
7719         function get_relationship()
7720         {
7721                 if ($this->relationship !== null)
7722                 {
7723                         return $this->relationship;
7724                 }
7725                 else
7726                 {
7727                         return null;
7728                 }
7729         }
7730
7731         function get_type()
7732         {
7733                 if ($this->type !== null)
7734                 {
7735                         return $this->type;
7736                 }
7737                 else
7738                 {
7739                         return null;
7740                 }
7741         }
7742
7743         function get_value()
7744         {
7745                 if ($this->value !== null)
7746                 {
7747                         return $this->value;
7748                 }
7749                 else
7750                 {
7751                         return null;
7752                 }
7753         }
7754 }
7755
7756 /**
7757  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7758  */
7759 class SimplePie_File
7760 {
7761         var $url;
7762         var $useragent;
7763         var $success = true;
7764         var $headers = array();
7765         var $body;
7766         var $status_code;
7767         var $redirects = 0;
7768         var $error;
7769         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7770
7771         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7772         {
7773                 if (class_exists('idna_convert'))
7774                 {
7775                         $idn = new idna_convert;
7776                         $parsed = SimplePie_Misc::parse_url($url);
7777                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7778                 }
7779                 $this->url = $url;
7780                 $this->useragent = $useragent;
7781                 if (preg_match('/^http(s)?:\/\//i', $url))
7782                 {
7783                         if ($useragent === null)
7784                         {
7785                                 $useragent = ini_get('user_agent');
7786                                 $this->useragent = $useragent;
7787                         }
7788                         if (!is_array($headers))
7789                         {
7790                                 $headers = array();
7791                         }
7792                         if (!$force_fsockopen && function_exists('curl_exec'))
7793                         {
7794                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7795                                 $fp = curl_init();
7796                                 $headers2 = array();
7797                                 foreach ($headers as $key => $value)
7798                                 {
7799                                         $headers2[] = "$key: $value";
7800                                 }
7801                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7802                                 {
7803                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7804                                 }
7805                                 curl_setopt($fp, CURLOPT_URL, $url);
7806                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7807                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7808                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7809                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7810                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7811                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7812                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7813                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7814                                 {
7815                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7816                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7817                                 }
7818
7819                                 $this->headers = curl_exec($fp);
7820                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7821                                 {
7822                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7823                                         $this->headers = curl_exec($fp);
7824                                 }
7825                                 if (curl_errno($fp))
7826                                 {
7827                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7828                                         $this->success = false;
7829                                 }
7830                                 else
7831                                 {
7832                                         $info = curl_getinfo($fp);
7833                                         curl_close($fp);
7834                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7835                                         $this->headers = array_pop($this->headers);
7836                                         $parser = new SimplePie_HTTP_Parser($this->headers);
7837                                         if ($parser->parse())
7838                                         {
7839                                                 $this->headers = $parser->headers;
7840                                                 $this->body = $parser->body;
7841                                                 $this->status_code = $parser->status_code;
7842                                                 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)
7843                                                 {
7844                                                         $this->redirects++;
7845                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7846                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7847                                                 }
7848                                         }
7849                                 }
7850                         }
7851                         else
7852                         {
7853                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7854                                 $url_parts = parse_url($url);
7855                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7856                                 {
7857                                         $url_parts['host'] = "ssl://$url_parts[host]";
7858                                         $url_parts['port'] = 443;
7859                                 }
7860                                 if (!isset($url_parts['port']))
7861                                 {
7862                                         $url_parts['port'] = 80;
7863                                 }
7864                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7865                                 if (!$fp)
7866                                 {
7867                                         $this->error = 'fsockopen error: ' . $errstr;
7868                                         $this->success = false;
7869                                 }
7870                                 else
7871                                 {
7872                                         stream_set_timeout($fp, $timeout);
7873                                         if (isset($url_parts['path']))
7874                                         {
7875                                                 if (isset($url_parts['query']))
7876                                                 {
7877                                                         $get = "$url_parts[path]?$url_parts[query]";
7878                                                 }
7879                                                 else
7880                                                 {
7881                                                         $get = $url_parts['path'];
7882                                                 }
7883                                         }
7884                                         else
7885                                         {
7886                                                 $get = '/';
7887                                         }
7888                                         $out = "GET $get HTTP/1.0\r\n";
7889                                         $out .= "Host: $url_parts[host]\r\n";
7890                                         $out .= "User-Agent: $useragent\r\n";
7891                                         if (extension_loaded('zlib'))
7892                                         {
7893                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7894                                         }
7895
7896                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7897                                         {
7898                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7899                                         }
7900                                         foreach ($headers as $key => $value)
7901                                         {
7902                                                 $out .= "$key: $value\r\n";
7903                                         }
7904                                         $out .= "Connection: Close\r\n\r\n";
7905                                         fwrite($fp, $out);
7906
7907                                         $info = stream_get_meta_data($fp);
7908
7909                                         $this->headers = '';
7910                                         while (!$info['eof'] && !$info['timed_out'])
7911                                         {
7912                                                 $this->headers .= fread($fp, 1160);
7913                                                 $info = stream_get_meta_data($fp);
7914                                         }
7915                                         if (!$info['timed_out'])
7916                                         {
7917                                                 $parser = new SimplePie_HTTP_Parser($this->headers);
7918                                                 if ($parser->parse())
7919                                                 {
7920                                                         $this->headers = $parser->headers;
7921                                                         $this->body = $parser->body;
7922                                                         $this->status_code = $parser->status_code;
7923                                                         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)
7924                                                         {
7925                                                                 $this->redirects++;
7926                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7927                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7928                                                         }
7929                                                         if (isset($this->headers['content-encoding']))
7930                                                         {
7931                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7932                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7933                                                                 {
7934                                                                         case 'gzip':
7935                                                                         case 'x-gzip':
7936                                                                                 $decoder = new SimplePie_gzdecode($this->body);
7937                                                                                 if (!$decoder->parse())
7938                                                                                 {
7939                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7940                                                                                         $this->success = false;
7941                                                                                 }
7942                                                                                 else
7943                                                                                 {
7944                                                                                         $this->body = $decoder->data;
7945                                                                                 }
7946                                                                                 break;
7947
7948                                                                         case 'deflate':
7949                                                                                 if (($body = gzuncompress($this->body)) === false)
7950                                                                                 {
7951                                                                                         if (($body = gzinflate($this->body)) === false)
7952                                                                                         {
7953                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7954                                                                                                 $this->success = false;
7955                                                                                         }
7956                                                                                 }
7957                                                                                 $this->body = $body;
7958                                                                                 break;
7959
7960                                                                         default:
7961                                                                                 $this->error = 'Unknown content coding';
7962                                                                                 $this->success = false;
7963                                                                 }
7964                                                         }
7965                                                 }
7966                                         }
7967                                         else
7968                                         {
7969                                                 $this->error = 'fsocket timed out';
7970                                                 $this->success = false;
7971                                         }
7972                                         fclose($fp);
7973                                 }
7974                         }
7975                 }
7976                 else
7977                 {
7978                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7979                         if (!$this->body = file_get_contents($url))
7980                         {
7981                                 $this->error = 'file_get_contents could not read the file';
7982                                 $this->success = false;
7983                         }
7984                 }
7985         }
7986 }
7987
7988 /**
7989  * HTTP Response Parser
7990  *
7991  * @package SimplePie
7992  */
7993 class SimplePie_HTTP_Parser
7994 {
7995         /**
7996          * HTTP Version
7997          *
7998          * @access public
7999          * @var float
8000          */
8001         var $http_version = 0.0;
8002
8003         /**
8004          * Status code
8005          *
8006          * @access public
8007          * @var int
8008          */
8009         var $status_code = 0;
8010
8011         /**
8012          * Reason phrase
8013          *
8014          * @access public
8015          * @var string
8016          */
8017         var $reason = '';
8018
8019         /**
8020          * Key/value pairs of the headers
8021          *
8022          * @access public
8023          * @var array
8024          */
8025         var $headers = array();
8026
8027         /**
8028          * Body of the response
8029          *
8030          * @access public
8031          * @var string
8032          */
8033         var $body = '';
8034
8035         /**
8036          * Current state of the state machine
8037          *
8038          * @access private
8039          * @var string
8040          */
8041         var $state = 'http_version';
8042
8043         /**
8044          * Input data
8045          *
8046          * @access private
8047          * @var string
8048          */
8049         var $data = '';
8050
8051         /**
8052          * Input data length (to avoid calling strlen() everytime this is needed)
8053          *
8054          * @access private
8055          * @var int
8056          */
8057         var $data_length = 0;
8058
8059         /**
8060          * Current position of the pointer
8061          *
8062          * @var int
8063          * @access private
8064          */
8065         var $position = 0;
8066
8067         /**
8068          * Name of the hedaer currently being parsed
8069          *
8070          * @access private
8071          * @var string
8072          */
8073         var $name = '';
8074
8075         /**
8076          * Value of the hedaer currently being parsed
8077          *
8078          * @access private
8079          * @var string
8080          */
8081         var $value = '';
8082
8083         /**
8084          * Create an instance of the class with the input data
8085          *
8086          * @access public
8087          * @param string $data Input data
8088          */
8089         function SimplePie_HTTP_Parser($data)
8090         {
8091                 $this->data = $data;
8092                 $this->data_length = strlen($this->data);
8093         }
8094
8095         /**
8096          * Parse the input data
8097          *
8098          * @access public
8099          * @return bool true on success, false on failure
8100          */
8101         function parse()
8102         {
8103                 while ($this->state && $this->state !== 'emit' && $this->has_data())
8104                 {
8105                         $state = $this->state;
8106                         $this->$state();
8107                 }
8108                 $this->data = '';
8109                 if ($this->state === 'emit' || $this->state === 'body')
8110                 {
8111                         return true;
8112                 }
8113                 else
8114                 {
8115                         $this->http_version = '';
8116                         $this->status_code = '';
8117                         $this->reason = '';
8118                         $this->headers = array();
8119                         $this->body = '';
8120                         return false;
8121                 }
8122         }
8123
8124         /**
8125          * Check whether there is data beyond the pointer
8126          *
8127          * @access private
8128          * @return bool true if there is further data, false if not
8129          */
8130         function has_data()
8131         {
8132                 return (bool) ($this->position < $this->data_length);
8133         }
8134
8135         /**
8136          * See if the next character is LWS
8137          *
8138          * @access private
8139          * @return bool true if the next character is LWS, false if not
8140          */
8141         function is_linear_whitespace()
8142         {
8143                 return (bool) ($this->data[$this->position] === "\x09"
8144                         || $this->data[$this->position] === "\x20"
8145                         || ($this->data[$this->position] === "\x0A"
8146                                 && isset($this->data[$this->position + 1])
8147                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8148         }
8149
8150         /**
8151          * Parse the HTTP version
8152          *
8153          * @access private
8154          */
8155         function http_version()
8156         {
8157                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8158                 {
8159                         $len = strspn($this->data, '0123456789.', 5);
8160                         $this->http_version = substr($this->data, 5, $len);
8161                         $this->position += 5 + $len;
8162                         if (substr_count($this->http_version, '.') <= 1)
8163                         {
8164                                 $this->http_version = (float) $this->http_version;
8165                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8166                                 $this->state = 'status';
8167                         }
8168                         else
8169                         {
8170                                 $this->state = false;
8171                         }
8172                 }
8173                 else
8174                 {
8175                         $this->state = false;
8176                 }
8177         }
8178
8179         /**
8180          * Parse the status code
8181          *
8182          * @access private
8183          */
8184         function status()
8185         {
8186                 if ($len = strspn($this->data, '0123456789', $this->position))
8187                 {
8188                         $this->status_code = (int) substr($this->data, $this->position, $len);
8189                         $this->position += $len;
8190                         $this->state = 'reason';
8191                 }
8192                 else
8193                 {
8194                         $this->state = false;
8195                 }
8196         }
8197
8198         /**
8199          * Parse the reason phrase
8200          *
8201          * @access private
8202          */
8203         function reason()
8204         {
8205                 $len = strcspn($this->data, "\x0A", $this->position);
8206                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8207                 $this->position += $len + 1;
8208                 $this->state = 'new_line';
8209         }
8210
8211         /**
8212          * Deal with a new line, shifting data around as needed
8213          *
8214          * @access private
8215          */
8216         function new_line()
8217         {
8218                 $this->value = trim($this->value, "\x0D\x20");
8219                 if ($this->name !== '' && $this->value !== '')
8220                 {
8221                         $this->name = strtolower($this->name);
8222                         if (isset($this->headers[$this->name]))
8223                         {
8224                                 $this->headers[$this->name] .= ', ' . $this->value;
8225                         }
8226                         else
8227                         {
8228                                 $this->headers[$this->name] = $this->value;
8229                         }
8230                 }
8231                 $this->name = '';
8232                 $this->value = '';
8233                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8234                 {
8235                         $this->position += 2;
8236                         $this->state = 'body';
8237                 }
8238                 elseif ($this->data[$this->position] === "\x0A")
8239                 {
8240                         $this->position++;
8241                         $this->state = 'body';
8242                 }
8243                 else
8244                 {
8245                         $this->state = 'name';
8246                 }
8247         }
8248
8249         /**
8250          * Parse a header name
8251          *
8252          * @access private
8253          */
8254         function name()
8255         {
8256                 $len = strcspn($this->data, "\x0A:", $this->position);
8257                 if (isset($this->data[$this->position + $len]))
8258                 {
8259                         if ($this->data[$this->position + $len] === "\x0A")
8260                         {
8261                                 $this->position += $len;
8262                                 $this->state = 'new_line';
8263                         }
8264                         else
8265                         {
8266                                 $this->name = substr($this->data, $this->position, $len);
8267                                 $this->position += $len + 1;
8268                                 $this->state = 'value';
8269                         }
8270                 }
8271                 else
8272                 {
8273                         $this->state = false;
8274                 }
8275         }
8276
8277         /**
8278          * Parse LWS, replacing consecutive LWS characters with a single space
8279          *
8280          * @access private
8281          */
8282         function linear_whitespace()
8283         {
8284                 do
8285                 {
8286                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8287                         {
8288                                 $this->position += 2;
8289                         }
8290                         elseif ($this->data[$this->position] === "\x0A")
8291                         {
8292                                 $this->position++;
8293                         }
8294                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8295                 } while ($this->has_data() && $this->is_linear_whitespace());
8296                 $this->value .= "\x20";
8297         }
8298
8299         /**
8300          * See what state to move to while within non-quoted header values
8301          *
8302          * @access private
8303          */
8304         function value()
8305         {
8306                 if ($this->is_linear_whitespace())
8307                 {
8308                         $this->linear_whitespace();
8309                 }
8310                 else
8311                 {
8312                         switch ($this->data[$this->position])
8313                         {
8314                                 case '"':
8315                                         $this->position++;
8316                                         $this->state = 'quote';
8317                                         break;
8318
8319                                 case "\x0A":
8320                                         $this->position++;
8321                                         $this->state = 'new_line';
8322                                         break;
8323
8324                                 default:
8325                                         $this->state = 'value_char';
8326                                         break;
8327                         }
8328                 }
8329         }
8330
8331         /**
8332          * Parse a header value while outside quotes
8333          *
8334          * @access private
8335          */
8336         function value_char()
8337         {
8338                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8339                 $this->value .= substr($this->data, $this->position, $len);
8340                 $this->position += $len;
8341                 $this->state = 'value';
8342         }
8343
8344         /**
8345          * See what state to move to while within quoted header values
8346          *
8347          * @access private
8348          */
8349         function quote()
8350         {
8351                 if ($this->is_linear_whitespace())
8352                 {
8353                         $this->linear_whitespace();
8354                 }
8355                 else
8356                 {
8357                         switch ($this->data[$this->position])
8358                         {
8359                                 case '"':
8360                                         $this->position++;
8361                                         $this->state = 'value';
8362                                         break;
8363
8364                                 case "\x0A":
8365                                         $this->position++;
8366                                         $this->state = 'new_line';
8367                                         break;
8368
8369                                 case '\\':
8370                                         $this->position++;
8371                                         $this->state = 'quote_escaped';
8372                                         break;
8373
8374                                 default:
8375                                         $this->state = 'quote_char';
8376                                         break;
8377                         }
8378                 }
8379         }
8380
8381         /**
8382          * Parse a header value while within quotes
8383          *
8384          * @access private
8385          */
8386         function quote_char()
8387         {
8388                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8389                 $this->value .= substr($this->data, $this->position, $len);
8390                 $this->position += $len;
8391                 $this->state = 'value';
8392         }
8393
8394         /**
8395          * Parse an escaped character within quotes
8396          *
8397          * @access private
8398          */
8399         function quote_escaped()
8400         {
8401                 $this->value .= $this->data[$this->position];
8402                 $this->position++;
8403                 $this->state = 'quote';
8404         }
8405
8406         /**
8407          * Parse the body
8408          *
8409          * @access private
8410          */
8411         function body()
8412         {
8413                 $this->body = substr($this->data, $this->position);
8414                 $this->state = 'emit';
8415         }
8416 }
8417
8418 /**
8419  * gzdecode
8420  *
8421  * @package SimplePie
8422  */
8423 class SimplePie_gzdecode
8424 {
8425         /**
8426          * Compressed data
8427          *
8428          * @access private
8429          * @see gzdecode::$data
8430          */
8431         var $compressed_data;
8432
8433         /**
8434          * Size of compressed data
8435          *
8436          * @access private
8437          */
8438         var $compressed_size;
8439
8440         /**
8441          * Minimum size of a valid gzip string
8442          *
8443          * @access private
8444          */
8445         var $min_compressed_size = 18;
8446
8447         /**
8448          * Current position of pointer
8449          *
8450          * @access private
8451          */
8452         var $position = 0;
8453
8454         /**
8455          * Flags (FLG)
8456          *
8457          * @access private
8458          */
8459         var $flags;
8460
8461         /**
8462          * Uncompressed data
8463          *
8464          * @access public
8465          * @see gzdecode::$compressed_data
8466          */
8467         var $data;
8468
8469         /**
8470          * Modified time
8471          *
8472          * @access public
8473          */
8474         var $MTIME;
8475
8476         /**
8477          * Extra Flags
8478          *
8479          * @access public
8480          */
8481         var $XFL;
8482
8483         /**
8484          * Operating System
8485          *
8486          * @access public
8487          */
8488         var $OS;
8489
8490         /**
8491          * Subfield ID 1
8492          *
8493          * @access public
8494          * @see gzdecode::$extra_field
8495          * @see gzdecode::$SI2
8496          */
8497         var $SI1;
8498
8499         /**
8500          * Subfield ID 2
8501          *
8502          * @access public
8503          * @see gzdecode::$extra_field
8504          * @see gzdecode::$SI1
8505          */
8506         var $SI2;
8507
8508         /**
8509          * Extra field content
8510          *
8511          * @access public
8512          * @see gzdecode::$SI1
8513          * @see gzdecode::$SI2
8514          */
8515         var $extra_field;
8516
8517         /**
8518          * Original filename
8519          *
8520          * @access public
8521          */
8522         var $filename;
8523
8524         /**
8525          * Human readable comment
8526          *
8527          * @access public
8528          */
8529         var $comment;
8530
8531         /**
8532          * Don't allow anything to be set
8533          *
8534          * @access public
8535          */
8536         function __set($name, $value)
8537         {
8538                 trigger_error("Cannot write property $name", E_USER_ERROR);
8539         }
8540
8541         /**
8542          * Set the compressed string and related properties
8543          *
8544          * @access public
8545          */
8546         function SimplePie_gzdecode($data)
8547         {
8548                 $this->compressed_data = $data;
8549                 $this->compressed_size = strlen($data);
8550         }
8551
8552         /**
8553          * Decode the GZIP stream
8554          *
8555          * @access public
8556          */
8557         function parse()
8558         {
8559                 if ($this->compressed_size >= $this->min_compressed_size)
8560                 {
8561                         // Check ID1, ID2, and CM
8562                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8563                         {
8564                                 return false;
8565                         }
8566
8567                         // Get the FLG (FLaGs)
8568                         $this->flags = ord($this->compressed_data[3]);
8569
8570                         // FLG bits above (1 << 4) are reserved
8571                         if ($this->flags > 0x1F)
8572                         {
8573                                 return false;
8574                         }
8575
8576                         // Advance the pointer after the above
8577                         $this->position += 4;
8578
8579                         // MTIME
8580                         $mtime = substr($this->compressed_data, $this->position, 4);
8581                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8582                         if (current(unpack('S', "\x00\x01")) === 1)
8583                         {
8584                                 $mtime = strrev($mtime);
8585                         }
8586                         $this->MTIME = current(unpack('l', $mtime));
8587                         $this->position += 4;
8588
8589                         // Get the XFL (eXtra FLags)
8590                         $this->XFL = ord($this->compressed_data[$this->position++]);
8591
8592                         // Get the OS (Operating System)
8593                         $this->OS = ord($this->compressed_data[$this->position++]);
8594
8595                         // Parse the FEXTRA
8596                         if ($this->flags & 4)
8597                         {
8598                                 // Read subfield IDs
8599                                 $this->SI1 = $this->compressed_data[$this->position++];
8600                                 $this->SI2 = $this->compressed_data[$this->position++];
8601
8602                                 // SI2 set to zero is reserved for future use
8603                                 if ($this->SI2 === "\x00")
8604                                 {
8605                                         return false;
8606                                 }
8607
8608                                 // Get the length of the extra field
8609                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8610                                 $position += 2;
8611
8612                                 // Check the length of the string is still valid
8613                                 $this->min_compressed_size += $len + 4;
8614                                 if ($this->compressed_size >= $this->min_compressed_size)
8615                                 {
8616                                         // Set the extra field to the given data
8617                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8618                                         $this->position += $len;
8619                                 }
8620                                 else
8621                                 {
8622                                         return false;
8623                                 }
8624                         }
8625
8626                         // Parse the FNAME
8627                         if ($this->flags & 8)
8628                         {
8629                                 // Get the length of the filename
8630                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8631
8632                                 // Check the length of the string is still valid
8633                                 $this->min_compressed_size += $len + 1;
8634                                 if ($this->compressed_size >= $this->min_compressed_size)
8635                                 {
8636                                         // Set the original filename to the given string
8637                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8638                                         $this->position += $len + 1;
8639                                 }
8640                                 else
8641                                 {
8642                                         return false;
8643                                 }
8644                         }
8645
8646                         // Parse the FCOMMENT
8647                         if ($this->flags & 16)
8648                         {
8649                                 // Get the length of the comment
8650                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8651
8652                                 // Check the length of the string is still valid
8653                                 $this->min_compressed_size += $len + 1;
8654                                 if ($this->compressed_size >= $this->min_compressed_size)
8655                                 {
8656                                         // Set the original comment to the given string
8657                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8658                                         $this->position += $len + 1;
8659                                 }
8660                                 else
8661                                 {
8662                                         return false;
8663                                 }
8664                         }
8665
8666                         // Parse the FHCRC
8667                         if ($this->flags & 2)
8668                         {
8669                                 // Check the length of the string is still valid
8670                                 $this->min_compressed_size += $len + 2;
8671                                 if ($this->compressed_size >= $this->min_compressed_size)
8672                                 {
8673                                         // Read the CRC
8674                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8675
8676                                         // Check the CRC matches
8677                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8678                                         {
8679                                                 $this->position += 2;
8680                                         }
8681                                         else
8682                                         {
8683                                                 return false;
8684                                         }
8685                                 }
8686                                 else
8687                                 {
8688                                         return false;
8689                                 }
8690                         }
8691
8692                         // Decompress the actual data
8693                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8694                         {
8695                                 return false;
8696                         }
8697                         else
8698                         {
8699                                 $this->position = $this->compressed_size - 8;
8700                         }
8701
8702                         // Check CRC of data
8703                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8704                         $this->position += 4;
8705                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8706                         {
8707                                 return false;
8708                         }*/
8709
8710                         // Check ISIZE of data
8711                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8712                         $this->position += 4;
8713                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8714                         {
8715                                 return false;
8716                         }
8717
8718                         // Wow, against all odds, we've actually got a valid gzip string
8719                         return true;
8720                 }
8721                 else
8722                 {
8723                         return false;
8724                 }
8725         }
8726 }
8727
8728 class SimplePie_Cache
8729 {
8730         /**
8731          * Don't call the constructor. Please.
8732          *
8733          * @access private
8734          */
8735         function SimplePie_Cache()
8736         {
8737                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8738         }
8739
8740         /**
8741          * Create a new SimplePie_Cache object
8742          *
8743          * @static
8744          * @access public
8745          */
8746         function create($location, $filename, $extension)
8747         {
8748                 $location_iri = new SimplePie_IRI($location);
8749                 switch ($location_iri->get_scheme())
8750                 {
8751                         case 'mysql':
8752                                 if (extension_loaded('mysql'))
8753                                 {
8754                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8755                                 }
8756                                 break;
8757
8758                         default:
8759                                 return new SimplePie_Cache_File($location, $filename, $extension);
8760                 }
8761         }
8762 }
8763
8764 class SimplePie_Cache_File
8765 {
8766         var $location;
8767         var $filename;
8768         var $extension;
8769         var $name;
8770
8771         function SimplePie_Cache_File($location, $filename, $extension)
8772         {
8773                 $this->location = $location;
8774                 $this->filename = $filename;
8775                 $this->extension = $extension;
8776                 $this->name = "$this->location/$this->filename.$this->extension";
8777         }
8778
8779         function save($data)
8780         {
8781                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8782                 {
8783                         if (is_a($data, 'SimplePie'))
8784                         {
8785                                 $data = $data->data;
8786                         }
8787
8788                         $data = serialize($data);
8789
8790                         if (function_exists('file_put_contents'))
8791                         {
8792                                 return (bool) file_put_contents($this->name, $data);
8793                         }
8794                         else
8795                         {
8796                                 $fp = fopen($this->name, 'wb');
8797                                 if ($fp)
8798                                 {
8799                                         fwrite($fp, $data);
8800                                         fclose($fp);
8801                                         return true;
8802                                 }
8803                         }
8804                 }
8805                 return false;
8806         }
8807
8808         function load()
8809         {
8810                 if (file_exists($this->name) && is_readable($this->name))
8811                 {
8812                         return unserialize(file_get_contents($this->name));
8813                 }
8814                 return false;
8815         }
8816
8817         function mtime()
8818         {
8819                 if (file_exists($this->name))
8820                 {
8821                         return filemtime($this->name);
8822                 }
8823                 return false;
8824         }
8825
8826         function touch()
8827         {
8828                 if (file_exists($this->name))
8829                 {
8830                         return touch($this->name);
8831                 }
8832                 return false;
8833         }
8834
8835         function unlink()
8836         {
8837                 if (file_exists($this->name))
8838                 {
8839                         return unlink($this->name);
8840                 }
8841                 return false;
8842         }
8843 }
8844
8845 class SimplePie_Cache_DB
8846 {
8847         function prepare_simplepie_object_for_cache($data)
8848         {
8849                 $items = $data->get_items();
8850                 $items_by_id = array();
8851
8852                 if (!empty($items))
8853                 {
8854                         foreach ($items as $item)
8855                         {
8856                                 $items_by_id[$item->get_id()] = $item;
8857                         }
8858
8859                         if (count($items_by_id) !== count($items))
8860                         {
8861                                 $items_by_id = array();
8862                                 foreach ($items as $item)
8863                                 {
8864                                         $items_by_id[$item->get_id(true)] = $item;
8865                                 }
8866                         }
8867
8868                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8869                         {
8870                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8871                         }
8872                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8873                         {
8874                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8875                         }
8876                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8877                         {
8878                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8879                         }
8880                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8881                         {
8882                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8883                         }
8884                         else
8885                         {
8886                                 $channel = null;
8887                         }
8888
8889                         if ($channel !== null)
8890                         {
8891                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8892                                 {
8893                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8894                                 }
8895                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8896                                 {
8897                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8898                                 }
8899                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8900                                 {
8901                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8902                                 }
8903                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8904                                 {
8905                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8906                                 }
8907                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8908                                 {
8909                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8910                                 }
8911                         }
8912                         if (isset($data->data['items']))
8913                         {
8914                                 unset($data->data['items']);
8915                         }
8916                         if (isset($data->data['ordered_items']))
8917                         {
8918                                 unset($data->data['ordered_items']);
8919                         }
8920                 }
8921                 return array(serialize($data->data), $items_by_id);
8922         }
8923 }
8924
8925 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8926 {
8927         var $mysql;
8928         var $options;
8929         var $id;
8930
8931         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8932         {
8933                 $host = $mysql_location->get_host();
8934                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8935                 {
8936                         $server = ':' . substr($host, 5, -1);
8937                 }
8938                 else
8939                 {
8940                         $server = $host;
8941                         if ($mysql_location->get_port() !== null)
8942                         {
8943                                 $server .= ':' . $mysql_location->get_port();
8944                         }
8945                 }
8946
8947                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8948                 {
8949                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8950                 }
8951                 else
8952                 {
8953                         $username = $mysql_location->get_userinfo();
8954                         $password = null;
8955                 }
8956
8957                 if ($this->mysql = mysql_connect($server, $username, $password))
8958                 {
8959                         $this->id = $name . $extension;
8960                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8961                         if (!isset($this->options['prefix'][0]))
8962                         {
8963                                 $this->options['prefix'][0] = '';
8964                         }
8965
8966                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8967                                 && mysql_query('SET NAMES utf8')
8968                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8969                         {
8970                                 $db = array();
8971                                 while ($row = mysql_fetch_row($query))
8972                                 {
8973                                         $db[] = $row[0];
8974                                 }
8975
8976                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8977                                 {
8978                                         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)))'))
8979                                         {
8980                                                 $this->mysql = null;
8981                                         }
8982                                 }
8983
8984                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8985                                 {
8986                                         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)))'))
8987                                         {
8988                                                 $this->mysql = null;
8989                                         }
8990                                 }
8991                         }
8992                         else
8993                         {
8994                                 $this->mysql = null;
8995                         }
8996                 }
8997         }
8998
8999         function save($data)
9000         {
9001                 if ($this->mysql)
9002                 {
9003                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
9004
9005                         if (is_a($data, 'SimplePie'))
9006                         {
9007                                 if (SIMPLEPIE_PHP5)
9008                                 {
9009                                         // This keyword needs to defy coding standards for PHP4 compatibility
9010                                         $data = clone($data);
9011                                 }
9012
9013                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
9014
9015                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9016                                 {
9017                                         if (mysql_num_rows($query))
9018                                         {
9019                                                 $items = count($prepared[1]);
9020                                                 if ($items)
9021                                                 {
9022                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9023                                                 }
9024                                                 else
9025                                                 {
9026                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9027                                                 }
9028
9029                                                 if (!mysql_query($sql, $this->mysql))
9030                                                 {
9031                                                         return false;
9032                                                 }
9033                                         }
9034                                         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))
9035                                         {
9036                                                 return false;
9037                                         }
9038
9039                                         $ids = array_keys($prepared[1]);
9040                                         if (!empty($ids))
9041                                         {
9042                                                 foreach ($ids as $id)
9043                                                 {
9044                                                         $database_ids[] = mysql_real_escape_string($id);
9045                                                 }
9046
9047                                                 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))
9048                                                 {
9049                                                         $existing_ids = array();
9050                                                         while ($row = mysql_fetch_row($query))
9051                                                         {
9052                                                                 $existing_ids[] = $row[0];
9053                                                         }
9054
9055                                                         $new_ids = array_diff($ids, $existing_ids);
9056
9057                                                         foreach ($new_ids as $new_id)
9058                                                         {
9059                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
9060                                                                 {
9061                                                                         $date = time();
9062                                                                 }
9063
9064                                                                 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))
9065                                                                 {
9066                                                                         return false;
9067                                                                 }
9068                                                         }
9069                                                         return true;
9070                                                 }
9071                                         }
9072                                         else
9073                                         {
9074                                                 return true;
9075                                         }
9076                                 }
9077                         }
9078                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9079                         {
9080                                 if (mysql_num_rows($query))
9081                                 {
9082                                         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))
9083                                         {
9084                                                 return true;
9085                                         }
9086                                 }
9087                                 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))
9088                                 {
9089                                         return true;
9090                                 }
9091                         }
9092                 }
9093                 return false;
9094         }
9095
9096         function load()
9097         {
9098                 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)))
9099                 {
9100                         $data = unserialize($row[1]);
9101
9102                         if (isset($this->options['items'][0]))
9103                         {
9104                                 $items = (int) $this->options['items'][0];
9105                         }
9106                         else
9107                         {
9108                                 $items = (int) $row[0];
9109                         }
9110
9111                         if ($items !== 0)
9112                         {
9113                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9114                                 {
9115                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9116                                 }
9117                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9118                                 {
9119                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9120                                 }
9121                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9122                                 {
9123                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9124                                 }
9125                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9126                                 {
9127                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9128                                 }
9129                                 else
9130                                 {
9131                                         $feed = null;
9132                                 }
9133
9134                                 if ($feed !== null)
9135                                 {
9136                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9137                                         if ($items > 0)
9138                                         {
9139                                                 $sql .= ' LIMIT ' . $items;
9140                                         }
9141
9142                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9143                                         {
9144                                                 while ($row = mysql_fetch_row($query))
9145                                                 {
9146                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9147                                                 }
9148                                         }
9149                                         else
9150                                         {
9151                                                 return false;
9152                                         }
9153                                 }
9154                         }
9155                         return $data;
9156                 }
9157                 return false;
9158         }
9159
9160         function mtime()
9161         {
9162                 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)))
9163                 {
9164                         return $row[0];
9165                 }
9166                 else
9167                 {
9168                         return false;
9169                 }
9170         }
9171
9172         function touch()
9173         {
9174                 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))
9175                 {
9176                         return true;
9177                 }
9178                 else
9179                 {
9180                         return false;
9181                 }
9182         }
9183
9184         function unlink()
9185         {
9186                 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)))
9187                 {
9188                         return true;
9189                 }
9190                 else
9191                 {
9192                         return false;
9193                 }
9194         }
9195 }
9196
9197 class SimplePie_Misc
9198 {
9199         function time_hms($seconds)
9200         {
9201                 $time = '';
9202
9203                 $hours = floor($seconds / 3600);
9204                 $remainder = $seconds % 3600;
9205                 if ($hours > 0)
9206                 {
9207                         $time .= $hours.':';
9208                 }
9209
9210                 $minutes = floor($remainder / 60);
9211                 $seconds = $remainder % 60;
9212                 if ($minutes < 10 && $hours > 0)
9213                 {
9214                         $minutes = '0' . $minutes;
9215                 }
9216                 if ($seconds < 10)
9217                 {
9218                         $seconds = '0' . $seconds;
9219                 }
9220
9221                 $time .= $minutes.':';
9222                 $time .= $seconds;
9223
9224                 return $time;
9225         }
9226
9227         function absolutize_url($relative, $base)
9228         {
9229 return $relative;
9230                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9231                 return $iri->get_iri();
9232         }
9233
9234         function remove_dot_segments($input)
9235         {
9236                 $output = '';
9237                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9238                 {
9239                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9240                         if (strpos($input, '../') === 0)
9241                         {
9242                                 $input = substr($input, 3);
9243                         }
9244                         elseif (strpos($input, './') === 0)
9245                         {
9246                                 $input = substr($input, 2);
9247                         }
9248                         // 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,
9249                         elseif (strpos($input, '/./') === 0)
9250                         {
9251                                 $input = substr_replace($input, '/', 0, 3);
9252                         }
9253                         elseif ($input === '/.')
9254                         {
9255                                 $input = '/';
9256                         }
9257                         // 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,
9258                         elseif (strpos($input, '/../') === 0)
9259                         {
9260                                 $input = substr_replace($input, '/', 0, 4);
9261                                 $output = substr_replace($output, '', strrpos($output, '/'));
9262                         }
9263                         elseif ($input === '/..')
9264                         {
9265                                 $input = '/';
9266                                 $output = substr_replace($output, '', strrpos($output, '/'));
9267                         }
9268                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9269                         elseif ($input === '.' || $input === '..')
9270                         {
9271                                 $input = '';
9272                         }
9273                         // 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
9274                         elseif (($pos = strpos($input, '/', 1)) !== false)
9275                         {
9276                                 $output .= substr($input, 0, $pos);
9277                                 $input = substr_replace($input, '', 0, $pos);
9278                         }
9279                         else
9280                         {
9281                                 $output .= $input;
9282                                 $input = '';
9283                         }
9284                 }
9285                 return $output . $input;
9286         }
9287
9288         function get_element($realname, $string)
9289         {
9290                 $return = array();
9291                 $name = preg_quote($realname, '/');
9292                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9293                 {
9294                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9295                         {
9296                                 $return[$i]['tag'] = $realname;
9297                                 $return[$i]['full'] = $matches[$i][0][0];
9298                                 $return[$i]['offset'] = $matches[$i][0][1];
9299                                 if (strlen($matches[$i][3][0]) <= 2)
9300                                 {
9301                                         $return[$i]['self_closing'] = true;
9302                                 }
9303                                 else
9304                                 {
9305                                         $return[$i]['self_closing'] = false;
9306                                         $return[$i]['content'] = $matches[$i][4][0];
9307                                 }
9308                                 $return[$i]['attribs'] = array();
9309                                 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))
9310                                 {
9311                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9312                                         {
9313                                                 if (count($attribs[$j]) === 2)
9314                                                 {
9315                                                         $attribs[$j][2] = $attribs[$j][1];
9316                                                 }
9317                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9318                                         }
9319                                 }
9320                         }
9321                 }
9322                 return $return;
9323         }
9324
9325         function element_implode($element)
9326         {
9327                 $full = "<$element[tag]";
9328                 foreach ($element['attribs'] as $key => $value)
9329                 {
9330                         $key = strtolower($key);
9331                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9332                 }
9333                 if ($element['self_closing'])
9334                 {
9335                         $full .= ' />';
9336                 }
9337                 else
9338                 {
9339                         $full .= ">$element[content]</$element[tag]>";
9340                 }
9341                 return $full;
9342         }
9343
9344         function error($message, $level, $file, $line)
9345         {
9346                 if ((ini_get('error_reporting') & $level) > 0)
9347                 {
9348                         switch ($level)
9349                         {
9350                                 case E_USER_ERROR:
9351                                         $note = 'PHP Error';
9352                                         break;
9353                                 case E_USER_WARNING:
9354                                         $note = 'PHP Warning';
9355                                         break;
9356                                 case E_USER_NOTICE:
9357                                         $note = 'PHP Notice';
9358                                         break;
9359                                 default:
9360                                         $note = 'Unknown Error';
9361                                         break;
9362                         }
9363
9364                         $log_error = true;
9365                         if (!function_exists('error_log'))
9366                         {
9367                                 $log_error = false;
9368                         }
9369
9370                         $log_file = @ini_get('error_log');
9371                         if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9372                         {
9373                                 $log_error = false;
9374                         }
9375
9376                         if ($log_error)
9377                         {
9378                                 @error_log("$note: $message in $file on line $line", 0);
9379                         }
9380                 }
9381
9382                 return $message;
9383         }
9384
9385         /**
9386          * If a file has been cached, retrieve and display it.
9387          *
9388          * This is most useful for caching images (get_favicon(), etc.),
9389          * however it works for all cached files.  This WILL NOT display ANY
9390          * file/image/page/whatever, but rather only display what has already
9391          * been cached by SimplePie.
9392          *
9393          * @access public
9394          * @see SimplePie::get_favicon()
9395          * @param str $identifier_url URL that is used to identify the content.
9396          * This may or may not be the actual URL of the live content.
9397          * @param str $cache_location Location of SimplePie's cache.  Defaults
9398          * to './cache'.
9399          * @param str $cache_extension The file extension that the file was
9400          * cached with.  Defaults to 'spc'.
9401          * @param str $cache_class Name of the cache-handling class being used
9402          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9403          * as-is unless you've overloaded the class.
9404          * @param str $cache_name_function Obsolete. Exists for backwards
9405          * compatibility reasons only.
9406          */
9407         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9408         {
9409                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9410
9411                 if ($file = $cache->load())
9412                 {
9413                         if (isset($file['headers']['content-type']))
9414                         {
9415                                 header('Content-type:' . $file['headers']['content-type']);
9416                         }
9417                         else
9418                         {
9419                                 header('Content-type: application/octet-stream');
9420                         }
9421                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9422                         echo $file['body'];
9423                         exit;
9424                 }
9425
9426                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9427         }
9428
9429         function fix_protocol($url, $http = 1)
9430         {
9431                 $url = SimplePie_Misc::normalize_url($url);
9432                 $parsed = SimplePie_Misc::parse_url($url);
9433                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9434                 {
9435                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9436                 }
9437
9438                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9439                 {
9440                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9441                 }
9442
9443                 if ($http === 2 && $parsed['scheme'] !== '')
9444                 {
9445                         return "feed:$url";
9446                 }
9447                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9448                 {
9449                         return substr_replace($url, 'podcast', 0, 4);
9450                 }
9451                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9452                 {
9453                         return substr_replace($url, 'itpc', 0, 4);
9454                 }
9455                 else
9456                 {
9457                         return $url;
9458                 }
9459         }
9460
9461         function parse_url($url)
9462         {
9463                 $iri = new SimplePie_IRI($url);
9464                 return array(
9465                         'scheme' => (string) $iri->get_scheme(),
9466                         'authority' => (string) $iri->get_authority(),
9467                         'path' => (string) $iri->get_path(),
9468                         'query' => (string) $iri->get_query(),
9469                         'fragment' => (string) $iri->get_fragment()
9470                 );
9471         }
9472
9473         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9474         {
9475                 $iri = new SimplePie_IRI('');
9476                 $iri->set_scheme($scheme);
9477                 $iri->set_authority($authority);
9478                 $iri->set_path($path);
9479                 $iri->set_query($query);
9480                 $iri->set_fragment($fragment);
9481                 return $iri->get_iri();
9482         }
9483
9484         function normalize_url($url)
9485         {
9486                 $iri = new SimplePie_IRI($url);
9487                 return $iri->get_iri();
9488         }
9489
9490         function percent_encoding_normalization($match)
9491         {
9492                 $integer = hexdec($match[1]);
9493                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9494                 {
9495                         return chr($integer);
9496                 }
9497                 else
9498                 {
9499                         return strtoupper($match[0]);
9500                 }
9501         }
9502
9503         /**
9504          * Remove bad UTF-8 bytes
9505          *
9506          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9507          * FAQ: Multilingual Forms (modified to include full ASCII range)
9508          *
9509          * @author Geoffrey Sneddon
9510          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9511          * @param string $str String to remove bad UTF-8 bytes from
9512          * @return string UTF-8 string
9513          */
9514         function utf8_bad_replace($str)
9515         {
9516                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9517                 {
9518                         return $return;
9519                 }
9520                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9521                 {
9522                         return $return;
9523                 }
9524                 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))
9525                 {
9526                         return implode("\xEF\xBF\xBD", $matches[0]);
9527                 }
9528                 elseif ($str !== '')
9529                 {
9530                         return "\xEF\xBF\xBD";
9531                 }
9532                 else
9533                 {
9534                         return '';
9535                 }
9536         }
9537
9538         /**
9539          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9540          *
9541          * @static
9542          * @access public
9543          * @param string $string Windows-1252 encoded string
9544          * @return string UTF-8 encoded string
9545          */
9546         function windows_1252_to_utf8($string)
9547         {
9548                 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");
9549
9550                 return strtr($string, $convert_table);
9551         }
9552
9553         function change_encoding($data, $input, $output)
9554         {
9555                 $input = SimplePie_Misc::encoding($input);
9556                 $output = SimplePie_Misc::encoding($output);
9557
9558                 // We fail to fail on non US-ASCII bytes
9559                 if ($input === 'US-ASCII')
9560                 {
9561                         static $non_ascii_octects = '';
9562                         if (!$non_ascii_octects)
9563                         {
9564                                 for ($i = 0x80; $i <= 0xFF; $i++)
9565                                 {
9566                                         $non_ascii_octects .= chr($i);
9567                                 }
9568                         }
9569                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9570                 }
9571
9572                 // This is first, as behaviour of this is completely predictable
9573                 if ($input === 'Windows-1252' && $output === 'UTF-8')
9574                 {
9575                         return SimplePie_Misc::windows_1252_to_utf8($data);
9576                 }
9577                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9578                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9579                 {
9580                         return $return;
9581                 }
9582                 // This is last, as behaviour of this varies with OS userland and PHP version
9583                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9584                 {
9585                         return $return;
9586                 }
9587                 // If we can't do anything, just fail
9588                 else
9589                 {
9590                         return false;
9591                 }
9592         }
9593
9594         function encoding($charset)
9595         {
9596                 // Normalization from UTS #22
9597                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9598                 {
9599                         case 'adobestandardencoding':
9600                         case 'csadobestandardencoding':
9601                                 return 'Adobe-Standard-Encoding';
9602
9603                         case 'adobesymbolencoding':
9604                         case 'cshppsmath':
9605                                 return 'Adobe-Symbol-Encoding';
9606
9607                         case 'ami1251':
9608                         case 'amiga1251':
9609                                 return 'Amiga-1251';
9610
9611                         case 'ansix31101983':
9612                         case 'csat5001983':
9613                         case 'csiso99naplps':
9614                         case 'isoir99':
9615                         case 'naplps':
9616                                 return 'ANSI_X3.110-1983';
9617
9618                         case 'arabic7':
9619                         case 'asmo449':
9620                         case 'csiso89asmo449':
9621                         case 'iso9036':
9622                         case 'isoir89':
9623                                 return 'ASMO_449';
9624
9625                         case 'big5':
9626                         case 'csbig5':
9627                         case 'xxbig5':
9628                                 return 'Big5';
9629
9630                         case 'big5hkscs':
9631                                 return 'Big5-HKSCS';
9632
9633                         case 'bocu1':
9634                         case 'csbocu1':
9635                                 return 'BOCU-1';
9636
9637                         case 'brf':
9638                         case 'csbrf':
9639                                 return 'BRF';
9640
9641                         case 'bs4730':
9642                         case 'csiso4unitedkingdom':
9643                         case 'gb':
9644                         case 'iso646gb':
9645                         case 'isoir4':
9646                         case 'uk':
9647                                 return 'BS_4730';
9648
9649                         case 'bsviewdata':
9650                         case 'csiso47bsviewdata':
9651                         case 'isoir47':
9652                                 return 'BS_viewdata';
9653
9654                         case 'cesu8':
9655                         case 'cscesu8':
9656                                 return 'CESU-8';
9657
9658                         case 'ca':
9659                         case 'csa71':
9660                         case 'csaz243419851':
9661                         case 'csiso121canadian1':
9662                         case 'iso646ca':
9663                         case 'isoir121':
9664                                 return 'CSA_Z243.4-1985-1';
9665
9666                         case 'csa72':
9667                         case 'csaz243419852':
9668                         case 'csiso122canadian2':
9669                         case 'iso646ca2':
9670                         case 'isoir122':
9671                                 return 'CSA_Z243.4-1985-2';
9672
9673                         case 'csaz24341985gr':
9674                         case 'csiso123csaz24341985gr':
9675                         case 'isoir123':
9676                                 return 'CSA_Z243.4-1985-gr';
9677
9678                         case 'csiso139csn369103':
9679                         case 'csn369103':
9680                         case 'isoir139':
9681                                 return 'CSN_369103';
9682
9683                         case 'csdecmcs':
9684                         case 'dec':
9685                         case 'decmcs':
9686                                 return 'DEC-MCS';
9687
9688                         case 'csiso21german':
9689                         case 'de':
9690                         case 'din66003':
9691                         case 'iso646de':
9692                         case 'isoir21':
9693                                 return 'DIN_66003';
9694
9695                         case 'csdkus':
9696                         case 'dkus':
9697                                 return 'dk-us';
9698
9699                         case 'csiso646danish':
9700                         case 'dk':
9701                         case 'ds2089':
9702                         case 'iso646dk':
9703                                 return 'DS_2089';
9704
9705                         case 'csibmebcdicatde':
9706                         case 'ebcdicatde':
9707                                 return 'EBCDIC-AT-DE';
9708
9709                         case 'csebcdicatdea':
9710                         case 'ebcdicatdea':
9711                                 return 'EBCDIC-AT-DE-A';
9712
9713                         case 'csebcdiccafr':
9714                         case 'ebcdiccafr':
9715                                 return 'EBCDIC-CA-FR';
9716
9717                         case 'csebcdicdkno':
9718                         case 'ebcdicdkno':
9719                                 return 'EBCDIC-DK-NO';
9720
9721                         case 'csebcdicdknoa':
9722                         case 'ebcdicdknoa':
9723                                 return 'EBCDIC-DK-NO-A';
9724
9725                         case 'csebcdices':
9726                         case 'ebcdices':
9727                                 return 'EBCDIC-ES';
9728
9729                         case 'csebcdicesa':
9730                         case 'ebcdicesa':
9731                                 return 'EBCDIC-ES-A';
9732
9733                         case 'csebcdicess':
9734                         case 'ebcdicess':
9735                                 return 'EBCDIC-ES-S';
9736
9737                         case 'csebcdicfise':
9738                         case 'ebcdicfise':
9739                                 return 'EBCDIC-FI-SE';
9740
9741                         case 'csebcdicfisea':
9742                         case 'ebcdicfisea':
9743                                 return 'EBCDIC-FI-SE-A';
9744
9745                         case 'csebcdicfr':
9746                         case 'ebcdicfr':
9747                                 return 'EBCDIC-FR';
9748
9749                         case 'csebcdicit':
9750                         case 'ebcdicit':
9751                                 return 'EBCDIC-IT';
9752
9753                         case 'csebcdicpt':
9754                         case 'ebcdicpt':
9755                                 return 'EBCDIC-PT';
9756
9757                         case 'csebcdicuk':
9758                         case 'ebcdicuk':
9759                                 return 'EBCDIC-UK';
9760
9761                         case 'csebcdicus':
9762                         case 'ebcdicus':
9763                                 return 'EBCDIC-US';
9764
9765                         case 'csiso111ecmacyrillic':
9766                         case 'ecmacyrillic':
9767                         case 'isoir111':
9768                         case 'koi8e':
9769                                 return 'ECMA-cyrillic';
9770
9771                         case 'csiso17spanish':
9772                         case 'es':
9773                         case 'iso646es':
9774                         case 'isoir17':
9775                                 return 'ES';
9776
9777                         case 'csiso85spanish2':
9778                         case 'es2':
9779                         case 'iso646es2':
9780                         case 'isoir85':
9781                                 return 'ES2';
9782
9783                         case 'cseucfixwidjapanese':
9784                         case 'extendedunixcodefixedwidthforjapanese':
9785                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9786
9787                         case 'cseucpkdfmtjapanese':
9788                         case 'eucjp':
9789                         case 'extendedunixcodepackedformatforjapanese':
9790                                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9791
9792                         case 'gb18030':
9793                                 return 'GB18030';
9794
9795                         case 'chinese':
9796                         case 'cp936':
9797                         case 'csgb2312':
9798                         case 'csiso58gb231280':
9799                         case 'gb2312':
9800                         case 'gb231280':
9801                         case 'gbk':
9802                         case 'isoir58':
9803                         case 'ms936':
9804                         case 'windows936':
9805                                 return 'GBK';
9806
9807                         case 'cn':
9808                         case 'csiso57gb1988':
9809                         case 'gb198880':
9810                         case 'iso646cn':
9811                         case 'isoir57':
9812                                 return 'GB_1988-80';
9813
9814                         case 'csiso153gost1976874':
9815                         case 'gost1976874':
9816                         case 'isoir153':
9817                         case 'stsev35888':
9818                                 return 'GOST_19768-74';
9819
9820                         case 'csiso150':
9821                         case 'csiso150greekccitt':
9822                         case 'greekccitt':
9823                         case 'isoir150':
9824                                 return 'greek-ccitt';
9825
9826                         case 'csiso88greek7':
9827                         case 'greek7':
9828                         case 'isoir88':
9829                                 return 'greek7';
9830
9831                         case 'csiso18greek7old':
9832                         case 'greek7old':
9833                         case 'isoir18':
9834                                 return 'greek7-old';
9835
9836                         case 'cshpdesktop':
9837                         case 'hpdesktop':
9838                                 return 'HP-DeskTop';
9839
9840                         case 'cshplegal':
9841                         case 'hplegal':
9842                                 return 'HP-Legal';
9843
9844                         case 'cshpmath8':
9845                         case 'hpmath8':
9846                                 return 'HP-Math8';
9847
9848                         case 'cshppifont':
9849                         case 'hppifont':
9850                                 return 'HP-Pi-font';
9851
9852                         case 'cshproman8':
9853                         case 'hproman8':
9854                         case 'r8':
9855                         case 'roman8':
9856                                 return 'hp-roman8';
9857
9858                         case 'hzgb2312':
9859                                 return 'HZ-GB-2312';
9860
9861                         case 'csibmsymbols':
9862                         case 'ibmsymbols':
9863                                 return 'IBM-Symbols';
9864
9865                         case 'csibmthai':
9866                         case 'ibmthai':
9867                                 return 'IBM-Thai';
9868
9869                         case 'ccsid858':
9870                         case 'cp858':
9871                         case 'ibm858':
9872                         case 'pcmultilingual850euro':
9873                                 return 'IBM00858';
9874
9875                         case 'ccsid924':
9876                         case 'cp924':
9877                         case 'ebcdiclatin9euro':
9878                         case 'ibm924':
9879                                 return 'IBM00924';
9880
9881                         case 'ccsid1140':
9882                         case 'cp1140':
9883                         case 'ebcdicus37euro':
9884                         case 'ibm1140':
9885                                 return 'IBM01140';
9886
9887                         case 'ccsid1141':
9888                         case 'cp1141':
9889                         case 'ebcdicde273euro':
9890                         case 'ibm1141':
9891                                 return 'IBM01141';
9892
9893                         case 'ccsid1142':
9894                         case 'cp1142':
9895                         case 'ebcdicdk277euro':
9896                         case 'ebcdicno277euro':
9897                         case 'ibm1142':
9898                                 return 'IBM01142';
9899
9900                         case 'ccsid1143':
9901                         case 'cp1143':
9902                         case 'ebcdicfi278euro':
9903                         case 'ebcdicse278euro':
9904                         case 'ibm1143':
9905                                 return 'IBM01143';
9906
9907                         case 'ccsid1144':
9908                         case 'cp1144':
9909                         case 'ebcdicit280euro':
9910                         case 'ibm1144':
9911                                 return 'IBM01144';
9912
9913                         case 'ccsid1145':
9914                         case 'cp1145':
9915                         case 'ebcdices284euro':
9916                         case 'ibm1145':
9917                                 return 'IBM01145';
9918
9919                         case 'ccsid1146':
9920                         case 'cp1146':
9921                         case 'ebcdicgb285euro':
9922                         case 'ibm1146':
9923                                 return 'IBM01146';
9924
9925                         case 'ccsid1147':
9926                         case 'cp1147':
9927                         case 'ebcdicfr297euro':
9928                         case 'ibm1147':
9929                                 return 'IBM01147';
9930
9931                         case 'ccsid1148':
9932                         case 'cp1148':
9933                         case 'ebcdicinternational500euro':
9934                         case 'ibm1148':
9935                                 return 'IBM01148';
9936
9937                         case 'ccsid1149':
9938                         case 'cp1149':
9939                         case 'ebcdicis871euro':
9940                         case 'ibm1149':
9941                                 return 'IBM01149';
9942
9943                         case 'cp37':
9944                         case 'csibm37':
9945                         case 'ebcdiccpca':
9946                         case 'ebcdiccpnl':
9947                         case 'ebcdiccpus':
9948                         case 'ebcdiccpwt':
9949                         case 'ibm37':
9950                                 return 'IBM037';
9951
9952                         case 'cp38':
9953                         case 'csibm38':
9954                         case 'ebcdicint':
9955                         case 'ibm38':
9956                                 return 'IBM038';
9957
9958                         case 'cp273':
9959                         case 'csibm273':
9960                         case 'ibm273':
9961                                 return 'IBM273';
9962
9963                         case 'cp274':
9964                         case 'csibm274':
9965                         case 'ebcdicbe':
9966                         case 'ibm274':
9967                                 return 'IBM274';
9968
9969                         case 'cp275':
9970                         case 'csibm275':
9971                         case 'ebcdicbr':
9972                         case 'ibm275':
9973                                 return 'IBM275';
9974
9975                         case 'csibm277':
9976                         case 'ebcdiccpdk':
9977                         case 'ebcdiccpno':
9978                         case 'ibm277':
9979                                 return 'IBM277';
9980
9981                         case 'cp278':
9982                         case 'csibm278':
9983                         case 'ebcdiccpfi':
9984                         case 'ebcdiccpse':
9985                         case 'ibm278':
9986                                 return 'IBM278';
9987
9988                         case 'cp280':
9989                         case 'csibm280':
9990                         case 'ebcdiccpit':
9991                         case 'ibm280':
9992                                 return 'IBM280';
9993
9994                         case 'cp281':
9995                         case 'csibm281':
9996                         case 'ebcdicjpe':
9997                         case 'ibm281':
9998                                 return 'IBM281';
9999
10000                         case 'cp284':
10001                         case 'csibm284':
10002                         case 'ebcdiccpes':
10003                         case 'ibm284':
10004                                 return 'IBM284';
10005
10006                         case 'cp285':
10007                         case 'csibm285':
10008                         case 'ebcdiccpgb':
10009                         case 'ibm285':
10010                                 return 'IBM285';
10011
10012                         case 'cp290':
10013                         case 'csibm290':
10014                         case 'ebcdicjpkana':
10015                         case 'ibm290':
10016                                 return 'IBM290';
10017
10018                         case 'cp297':
10019                         case 'csibm297':
10020                         case 'ebcdiccpfr':
10021                         case 'ibm297':
10022                                 return 'IBM297';
10023
10024                         case 'cp420':
10025                         case 'csibm420':
10026                         case 'ebcdiccpar1':
10027                         case 'ibm420':
10028                                 return 'IBM420';
10029
10030                         case 'cp423':
10031                         case 'csibm423':
10032                         case 'ebcdiccpgr':
10033                         case 'ibm423':
10034                                 return 'IBM423';
10035
10036                         case 'cp424':
10037                         case 'csibm424':
10038                         case 'ebcdiccphe':
10039                         case 'ibm424':
10040                                 return 'IBM424';
10041
10042                         case '437':
10043                         case 'cp437':
10044                         case 'cspc8codepage437':
10045                         case 'ibm437':
10046                                 return 'IBM437';
10047
10048                         case 'cp500':
10049                         case 'csibm500':
10050                         case 'ebcdiccpbe':
10051                         case 'ebcdiccpch':
10052                         case 'ibm500':
10053                                 return 'IBM500';
10054
10055                         case 'cp775':
10056                         case 'cspc775baltic':
10057                         case 'ibm775':
10058                                 return 'IBM775';
10059
10060                         case '850':
10061                         case 'cp850':
10062                         case 'cspc850multilingual':
10063                         case 'ibm850':
10064                                 return 'IBM850';
10065
10066                         case '851':
10067                         case 'cp851':
10068                         case 'csibm851':
10069                         case 'ibm851':
10070                                 return 'IBM851';
10071
10072                         case '852':
10073                         case 'cp852':
10074                         case 'cspcp852':
10075                         case 'ibm852':
10076                                 return 'IBM852';
10077
10078                         case '855':
10079                         case 'cp855':
10080                         case 'csibm855':
10081                         case 'ibm855':
10082                                 return 'IBM855';
10083
10084                         case '857':
10085                         case 'cp857':
10086                         case 'csibm857':
10087                         case 'ibm857':
10088                                 return 'IBM857';
10089
10090                         case '860':
10091                         case 'cp860':
10092                         case 'csibm860':
10093                         case 'ibm860':
10094                                 return 'IBM860';
10095
10096                         case '861':
10097                         case 'cp861':
10098                         case 'cpis':
10099                         case 'csibm861':
10100                         case 'ibm861':
10101                                 return 'IBM861';
10102
10103                         case '862':
10104                         case 'cp862':
10105                         case 'cspc862latinhebrew':
10106                         case 'ibm862':
10107                                 return 'IBM862';
10108
10109                         case '863':
10110                         case 'cp863':
10111                         case 'csibm863':
10112                         case 'ibm863':
10113                                 return 'IBM863';
10114
10115                         case 'cp864':
10116                         case 'csibm864':
10117                         case 'ibm864':
10118                                 return 'IBM864';
10119
10120                         case '865':
10121                         case 'cp865':
10122                         case 'csibm865':
10123                         case 'ibm865':
10124                                 return 'IBM865';
10125
10126                         case '866':
10127                         case 'cp866':
10128                         case 'csibm866':
10129                         case 'ibm866':
10130                                 return 'IBM866';
10131
10132                         case 'cp868':
10133                         case 'cpar':
10134                         case 'csibm868':
10135                         case 'ibm868':
10136                                 return 'IBM868';
10137
10138                         case '869':
10139                         case 'cp869':
10140                         case 'cpgr':
10141                         case 'csibm869':
10142                         case 'ibm869':
10143                                 return 'IBM869';
10144
10145                         case 'cp870':
10146                         case 'csibm870':
10147                         case 'ebcdiccproece':
10148                         case 'ebcdiccpyu':
10149                         case 'ibm870':
10150                                 return 'IBM870';
10151
10152                         case 'cp871':
10153                         case 'csibm871':
10154                         case 'ebcdiccpis':
10155                         case 'ibm871':
10156                                 return 'IBM871';
10157
10158                         case 'cp880':
10159                         case 'csibm880':
10160                         case 'ebcdiccyrillic':
10161                         case 'ibm880':
10162                                 return 'IBM880';
10163
10164                         case 'cp891':
10165                         case 'csibm891':
10166                         case 'ibm891':
10167                                 return 'IBM891';
10168
10169                         case 'cp903':
10170                         case 'csibm903':
10171                         case 'ibm903':
10172                                 return 'IBM903';
10173
10174                         case '904':
10175                         case 'cp904':
10176                         case 'csibbm904':
10177                         case 'ibm904':
10178                                 return 'IBM904';
10179
10180                         case 'cp905':
10181                         case 'csibm905':
10182                         case 'ebcdiccptr':
10183                         case 'ibm905':
10184                                 return 'IBM905';
10185
10186                         case 'cp918':
10187                         case 'csibm918':
10188                         case 'ebcdiccpar2':
10189                         case 'ibm918':
10190                                 return 'IBM918';
10191
10192                         case 'cp1026':
10193                         case 'csibm1026':
10194                         case 'ibm1026':
10195                                 return 'IBM1026';
10196
10197                         case 'ibm1047':
10198                                 return 'IBM1047';
10199
10200                         case 'csiso143iecp271':
10201                         case 'iecp271':
10202                         case 'isoir143':
10203                                 return 'IEC_P27-1';
10204
10205                         case 'csiso49inis':
10206                         case 'inis':
10207                         case 'isoir49':
10208                                 return 'INIS';
10209
10210                         case 'csiso50inis8':
10211                         case 'inis8':
10212                         case 'isoir50':
10213                                 return 'INIS-8';
10214
10215                         case 'csiso51iniscyrillic':
10216                         case 'iniscyrillic':
10217                         case 'isoir51':
10218                                 return 'INIS-cyrillic';
10219
10220                         case 'csinvariant':
10221                         case 'invariant':
10222                                 return 'INVARIANT';
10223
10224                         case 'iso2022cn':
10225                                 return 'ISO-2022-CN';
10226
10227                         case 'iso2022cnext':
10228                                 return 'ISO-2022-CN-EXT';
10229
10230                         case 'csiso2022jp':
10231                         case 'iso2022jp':
10232                                 return 'ISO-2022-JP';
10233
10234                         case 'csiso2022jp2':
10235                         case 'iso2022jp2':
10236                                 return 'ISO-2022-JP-2';
10237
10238                         case 'csiso2022kr':
10239                         case 'iso2022kr':
10240                                 return 'ISO-2022-KR';
10241
10242                         case 'cswindows30latin1':
10243                         case 'iso88591windows30latin1':
10244                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10245
10246                         case 'cswindows31latin1':
10247                         case 'iso88591windows31latin1':
10248                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10249
10250                         case 'csisolatin2':
10251                         case 'iso88592':
10252                         case 'iso885921987':
10253                         case 'isoir101':
10254                         case 'l2':
10255                         case 'latin2':
10256                                 return 'ISO-8859-2';
10257
10258                         case 'cswindows31latin2':
10259                         case 'iso88592windowslatin2':
10260                                 return 'ISO-8859-2-Windows-Latin-2';
10261
10262                         case 'csisolatin3':
10263                         case 'iso88593':
10264                         case 'iso885931988':
10265                         case 'isoir109':
10266                         case 'l3':
10267                         case 'latin3':
10268                                 return 'ISO-8859-3';
10269
10270                         case 'csisolatin4':
10271                         case 'iso88594':
10272                         case 'iso885941988':
10273                         case 'isoir110':
10274                         case 'l4':
10275                         case 'latin4':
10276                                 return 'ISO-8859-4';
10277
10278                         case 'csisolatincyrillic':
10279                         case 'cyrillic':
10280                         case 'iso88595':
10281                         case 'iso885951988':
10282                         case 'isoir144':
10283                                 return 'ISO-8859-5';
10284
10285                         case 'arabic':
10286                         case 'asmo708':
10287                         case 'csisolatinarabic':
10288                         case 'ecma114':
10289                         case 'iso88596':
10290                         case 'iso885961987':
10291                         case 'isoir127':
10292                                 return 'ISO-8859-6';
10293
10294                         case 'csiso88596e':
10295                         case 'iso88596e':
10296                                 return 'ISO-8859-6-E';
10297
10298                         case 'csiso88596i':
10299                         case 'iso88596i':
10300                                 return 'ISO-8859-6-I';
10301
10302                         case 'csisolatingreek':
10303                         case 'ecma118':
10304                         case 'elot928':
10305                         case 'greek':
10306                         case 'greek8':
10307                         case 'iso88597':
10308                         case 'iso885971987':
10309                         case 'isoir126':
10310                                 return 'ISO-8859-7';
10311
10312                         case 'csisolatinhebrew':
10313                         case 'hebrew':
10314                         case 'iso88598':
10315                         case 'iso885981988':
10316                         case 'isoir138':
10317                                 return 'ISO-8859-8';
10318
10319                         case 'csiso88598e':
10320                         case 'iso88598e':
10321                                 return 'ISO-8859-8-E';
10322
10323                         case 'csiso88598i':
10324                         case 'iso88598i':
10325                                 return 'ISO-8859-8-I';
10326
10327                         case 'cswindows31latin5':
10328                         case 'iso88599windowslatin5':
10329                                 return 'ISO-8859-9-Windows-Latin-5';
10330
10331                         case 'csisolatin6':
10332                         case 'iso885910':
10333                         case 'iso8859101992':
10334                         case 'isoir157':
10335                         case 'l6':
10336                         case 'latin6':
10337                                 return 'ISO-8859-10';
10338
10339                         case 'iso885913':
10340                                 return 'ISO-8859-13';
10341
10342                         case 'iso885914':
10343                         case 'iso8859141998':
10344                         case 'isoceltic':
10345                         case 'isoir199':
10346                         case 'l8':
10347                         case 'latin8':
10348                                 return 'ISO-8859-14';
10349
10350                         case 'iso885915':
10351                         case 'latin9':
10352                                 return 'ISO-8859-15';
10353
10354                         case 'iso885916':
10355                         case 'iso8859162001':
10356                         case 'isoir226':
10357                         case 'l10':
10358                         case 'latin10':
10359                                 return 'ISO-8859-16';
10360
10361                         case 'iso10646j1':
10362                                 return 'ISO-10646-J-1';
10363
10364                         case 'csunicode':
10365                         case 'iso10646ucs2':
10366                                 return 'ISO-10646-UCS-2';
10367
10368                         case 'csucs4':
10369                         case 'iso10646ucs4':
10370                                 return 'ISO-10646-UCS-4';
10371
10372                         case 'csunicodeascii':
10373                         case 'iso10646ucsbasic':
10374                                 return 'ISO-10646-UCS-Basic';
10375
10376                         case 'csunicodelatin1':
10377                         case 'iso10646':
10378                         case 'iso10646unicodelatin1':
10379                                 return 'ISO-10646-Unicode-Latin1';
10380
10381                         case 'csiso10646utf1':
10382                         case 'iso10646utf1':
10383                                 return 'ISO-10646-UTF-1';
10384
10385                         case 'csiso115481':
10386                         case 'iso115481':
10387                         case 'isotr115481':
10388                                 return 'ISO-11548-1';
10389
10390                         case 'csiso90':
10391                         case 'isoir90':
10392                                 return 'iso-ir-90';
10393
10394                         case 'csunicodeibm1261':
10395                         case 'isounicodeibm1261':
10396                                 return 'ISO-Unicode-IBM-1261';
10397
10398                         case 'csunicodeibm1264':
10399                         case 'isounicodeibm1264':
10400                                 return 'ISO-Unicode-IBM-1264';
10401
10402                         case 'csunicodeibm1265':
10403                         case 'isounicodeibm1265':
10404                                 return 'ISO-Unicode-IBM-1265';
10405
10406                         case 'csunicodeibm1268':
10407                         case 'isounicodeibm1268':
10408                                 return 'ISO-Unicode-IBM-1268';
10409
10410                         case 'csunicodeibm1276':
10411                         case 'isounicodeibm1276':
10412                                 return 'ISO-Unicode-IBM-1276';
10413
10414                         case 'csiso646basic1983':
10415                         case 'iso646basic1983':
10416                         case 'ref':
10417                                 return 'ISO_646.basic:1983';
10418
10419                         case 'csiso2intlrefversion':
10420                         case 'irv':
10421                         case 'iso646irv1983':
10422                         case 'isoir2':
10423                                 return 'ISO_646.irv:1983';
10424
10425                         case 'csiso2033':
10426                         case 'e13b':
10427                         case 'iso20331983':
10428                         case 'isoir98':
10429                                 return 'ISO_2033-1983';
10430
10431                         case 'csiso5427cyrillic':
10432                         case 'iso5427':
10433                         case 'isoir37':
10434                                 return 'ISO_5427';
10435
10436                         case 'iso5427cyrillic1981':
10437                         case 'iso54271981':
10438                         case 'isoir54':
10439                                 return 'ISO_5427:1981';
10440
10441                         case 'csiso5428greek':
10442                         case 'iso54281980':
10443                         case 'isoir55':
10444                                 return 'ISO_5428:1980';
10445
10446                         case 'csiso6937add':
10447                         case 'iso6937225':
10448                         case 'isoir152':
10449                                 return 'ISO_6937-2-25';
10450
10451                         case 'csisotextcomm':
10452                         case 'iso69372add':
10453                         case 'isoir142':
10454                                 return 'ISO_6937-2-add';
10455
10456                         case 'csiso8859supp':
10457                         case 'iso8859supp':
10458                         case 'isoir154':
10459                         case 'latin125':
10460                                 return 'ISO_8859-supp';
10461
10462                         case 'csiso10367box':
10463                         case 'iso10367box':
10464                         case 'isoir155':
10465                                 return 'ISO_10367-box';
10466
10467                         case 'csiso15italian':
10468                         case 'iso646it':
10469                         case 'isoir15':
10470                         case 'it':
10471                                 return 'IT';
10472
10473                         case 'csiso13jisc6220jp':
10474                         case 'isoir13':
10475                         case 'jisc62201969':
10476                         case 'jisc62201969jp':
10477                         case 'katakana':
10478                         case 'x2017':
10479                                 return 'JIS_C6220-1969-jp';
10480
10481                         case 'csiso14jisc6220ro':
10482                         case 'iso646jp':
10483                         case 'isoir14':
10484                         case 'jisc62201969ro':
10485                         case 'jp':
10486                                 return 'JIS_C6220-1969-ro';
10487
10488                         case 'csiso42jisc62261978':
10489                         case 'isoir42':
10490                         case 'jisc62261978':
10491                                 return 'JIS_C6226-1978';
10492
10493                         case 'csiso87jisx208':
10494                         case 'isoir87':
10495                         case 'jisc62261983':
10496                         case 'jisx2081983':
10497                         case 'x208':
10498                                 return 'JIS_C6226-1983';
10499
10500                         case 'csiso91jisc62291984a':
10501                         case 'isoir91':
10502                         case 'jisc62291984a':
10503                         case 'jpocra':
10504                                 return 'JIS_C6229-1984-a';
10505
10506                         case 'csiso92jisc62991984b':
10507                         case 'iso646jpocrb':
10508                         case 'isoir92':
10509                         case 'jisc62291984b':
10510                         case 'jpocrb':
10511                                 return 'JIS_C6229-1984-b';
10512
10513                         case 'csiso93jis62291984badd':
10514                         case 'isoir93':
10515                         case 'jisc62291984badd':
10516                         case 'jpocrbadd':
10517                                 return 'JIS_C6229-1984-b-add';
10518
10519                         case 'csiso94jis62291984hand':
10520                         case 'isoir94':
10521                         case 'jisc62291984hand':
10522                         case 'jpocrhand':
10523                                 return 'JIS_C6229-1984-hand';
10524
10525                         case 'csiso95jis62291984handadd':
10526                         case 'isoir95':
10527                         case 'jisc62291984handadd':
10528                         case 'jpocrhandadd':
10529                                 return 'JIS_C6229-1984-hand-add';
10530
10531                         case 'csiso96jisc62291984kana':
10532                         case 'isoir96':
10533                         case 'jisc62291984kana':
10534                                 return 'JIS_C6229-1984-kana';
10535
10536                         case 'csjisencoding':
10537                         case 'jisencoding':
10538                                 return 'JIS_Encoding';
10539
10540                         case 'cshalfwidthkatakana':
10541                         case 'jisx201':
10542                         case 'x201':
10543                                 return 'JIS_X0201';
10544
10545                         case 'csiso159jisx2121990':
10546                         case 'isoir159':
10547                         case 'jisx2121990':
10548                         case 'x212':
10549                                 return 'JIS_X0212-1990';
10550
10551                         case 'csiso141jusib1002':
10552                         case 'iso646yu':
10553                         case 'isoir141':
10554                         case 'js':
10555                         case 'jusib1002':
10556                         case 'yu':
10557                                 return 'JUS_I.B1.002';
10558
10559                         case 'csiso147macedonian':
10560                         case 'isoir147':
10561                         case 'jusib1003mac':
10562                         case 'macedonian':
10563                                 return 'JUS_I.B1.003-mac';
10564
10565                         case 'csiso146serbian':
10566                         case 'isoir146':
10567                         case 'jusib1003serb':
10568                         case 'serbian':
10569                                 return 'JUS_I.B1.003-serb';
10570
10571                         case 'koi7switched':
10572                                 return 'KOI7-switched';
10573
10574                         case 'cskoi8r':
10575                         case 'koi8r':
10576                                 return 'KOI8-R';
10577
10578                         case 'koi8u':
10579                                 return 'KOI8-U';
10580
10581                         case 'csksc5636':
10582                         case 'iso646kr':
10583                         case 'ksc5636':
10584                                 return 'KSC5636';
10585
10586                         case 'cskz1048':
10587                         case 'kz1048':
10588                         case 'rk1048':
10589                         case 'strk10482002':
10590                                 return 'KZ-1048';
10591
10592                         case 'csiso19latingreek':
10593                         case 'isoir19':
10594                         case 'latingreek':
10595                                 return 'latin-greek';
10596
10597                         case 'csiso27latingreek1':
10598                         case 'isoir27':
10599                         case 'latingreek1':
10600                                 return 'Latin-greek-1';
10601
10602                         case 'csiso158lap':
10603                         case 'isoir158':
10604                         case 'lap':
10605                         case 'latinlap':
10606                                 return 'latin-lap';
10607
10608                         case 'csmacintosh':
10609                         case 'mac':
10610                         case 'macintosh':
10611                                 return 'macintosh';
10612
10613                         case 'csmicrosoftpublishing':
10614                         case 'microsoftpublishing':
10615                                 return 'Microsoft-Publishing';
10616
10617                         case 'csmnem':
10618                         case 'mnem':
10619                                 return 'MNEM';
10620
10621                         case 'csmnemonic':
10622                         case 'mnemonic':
10623                                 return 'MNEMONIC';
10624
10625                         case 'csiso86hungarian':
10626                         case 'hu':
10627                         case 'iso646hu':
10628                         case 'isoir86':
10629                         case 'msz77953':
10630                                 return 'MSZ_7795.3';
10631
10632                         case 'csnatsdano':
10633                         case 'isoir91':
10634                         case 'natsdano':
10635                                 return 'NATS-DANO';
10636
10637                         case 'csnatsdanoadd':
10638                         case 'isoir92':
10639                         case 'natsdanoadd':
10640                                 return 'NATS-DANO-ADD';
10641
10642                         case 'csnatssefi':
10643                         case 'isoir81':
10644                         case 'natssefi':
10645                                 return 'NATS-SEFI';
10646
10647                         case 'csnatssefiadd':
10648                         case 'isoir82':
10649                         case 'natssefiadd':
10650                                 return 'NATS-SEFI-ADD';
10651
10652                         case 'csiso151cuba':
10653                         case 'cuba':
10654                         case 'iso646cu':
10655                         case 'isoir151':
10656                         case 'ncnc1081':
10657                                 return 'NC_NC00-10:81';
10658
10659                         case 'csiso69french':
10660                         case 'fr':
10661                         case 'iso646fr':
10662                         case 'isoir69':
10663                         case 'nfz62010':
10664                                 return 'NF_Z_62-010';
10665
10666                         case 'csiso25french':
10667                         case 'iso646fr1':
10668                         case 'isoir25':
10669                         case 'nfz620101973':
10670                                 return 'NF_Z_62-010_(1973)';
10671
10672                         case 'csiso60danishnorwegian':
10673                         case 'csiso60norwegian1':
10674                         case 'iso646no':
10675                         case 'isoir60':
10676                         case 'no':
10677                         case 'ns45511':
10678                                 return 'NS_4551-1';
10679
10680                         case 'csiso61norwegian2':
10681                         case 'iso646no2':
10682                         case 'isoir61':
10683                         case 'no2':
10684                         case 'ns45512':
10685                                 return 'NS_4551-2';
10686
10687                         case 'osdebcdicdf3irv':
10688                                 return 'OSD_EBCDIC_DF03_IRV';
10689
10690                         case 'osdebcdicdf41':
10691                                 return 'OSD_EBCDIC_DF04_1';
10692
10693                         case 'osdebcdicdf415':
10694                                 return 'OSD_EBCDIC_DF04_15';
10695
10696                         case 'cspc8danishnorwegian':
10697                         case 'pc8danishnorwegian':
10698                                 return 'PC8-Danish-Norwegian';
10699
10700                         case 'cspc8turkish':
10701                         case 'pc8turkish':
10702                                 return 'PC8-Turkish';
10703
10704                         case 'csiso16portuguese':
10705                         case 'iso646pt':
10706                         case 'isoir16':
10707                         case 'pt':
10708                                 return 'PT';
10709
10710                         case 'csiso84portuguese2':
10711                         case 'iso646pt2':
10712                         case 'isoir84':
10713                         case 'pt2':
10714                                 return 'PT2';
10715
10716                         case 'cp154':
10717                         case 'csptcp154':
10718                         case 'cyrillicasian':
10719                         case 'pt154':
10720                         case 'ptcp154':
10721                                 return 'PTCP154';
10722
10723                         case 'scsu':
10724                                 return 'SCSU';
10725
10726                         case 'csiso10swedish':
10727                         case 'fi':
10728                         case 'iso646fi':
10729                         case 'iso646se':
10730                         case 'isoir10':
10731                         case 'se':
10732                         case 'sen850200b':
10733                                 return 'SEN_850200_B';
10734
10735                         case 'csiso11swedishfornames':
10736                         case 'iso646se2':
10737                         case 'isoir11':
10738                         case 'se2':
10739                         case 'sen850200c':
10740                                 return 'SEN_850200_C';
10741
10742                         case 'csshiftjis':
10743                         case 'mskanji':
10744                         case 'shiftjis':
10745                                 return 'Shift_JIS';
10746
10747                         case 'csiso102t617bit':
10748                         case 'isoir102':
10749                         case 't617bit':
10750                                 return 'T.61-7bit';
10751
10752                         case 'csiso103t618bit':
10753                         case 'isoir103':
10754                         case 't61':
10755                         case 't618bit':
10756                                 return 'T.61-8bit';
10757
10758                         case 'csiso128t101g2':
10759                         case 'isoir128':
10760                         case 't101g2':
10761                                 return 'T.101-G2';
10762
10763                         case 'cstscii':
10764                         case 'tscii':
10765                                 return 'TSCII';
10766
10767                         case 'csunicode11':
10768                         case 'unicode11':
10769                                 return 'UNICODE-1-1';
10770
10771                         case 'csunicode11utf7':
10772                         case 'unicode11utf7':
10773                                 return 'UNICODE-1-1-UTF-7';
10774
10775                         case 'csunknown8bit':
10776                         case 'unknown8bit':
10777                                 return 'UNKNOWN-8BIT';
10778
10779                         case 'ansix341968':
10780                         case 'ansix341986':
10781                         case 'ascii':
10782                         case 'cp367':
10783                         case 'csascii':
10784                         case 'ibm367':
10785                         case 'iso646irv1991':
10786                         case 'iso646us':
10787                         case 'isoir6':
10788                         case 'us':
10789                         case 'usascii':
10790                                 return 'US-ASCII';
10791
10792                         case 'csusdk':
10793                         case 'usdk':
10794                                 return 'us-dk';
10795
10796                         case 'utf7':
10797                                 return 'UTF-7';
10798
10799                         case 'utf8':
10800                                 return 'UTF-8';
10801
10802                         case 'utf16':
10803                                 return 'UTF-16';
10804
10805                         case 'utf16be':
10806                                 return 'UTF-16BE';
10807
10808                         case 'utf16le':
10809                                 return 'UTF-16LE';
10810
10811                         case 'utf32':
10812                                 return 'UTF-32';
10813
10814                         case 'utf32be':
10815                                 return 'UTF-32BE';
10816
10817                         case 'utf32le':
10818                                 return 'UTF-32LE';
10819
10820                         case 'csventurainternational':
10821                         case 'venturainternational':
10822                                 return 'Ventura-International';
10823
10824                         case 'csventuramath':
10825                         case 'venturamath':
10826                                 return 'Ventura-Math';
10827
10828                         case 'csventuraus':
10829                         case 'venturaus':
10830                                 return 'Ventura-US';
10831
10832                         case 'csiso70videotexsupp1':
10833                         case 'isoir70':
10834                         case 'videotexsuppl':
10835                                 return 'videotex-suppl';
10836
10837                         case 'csviqr':
10838                         case 'viqr':
10839                                 return 'VIQR';
10840
10841                         case 'csviscii':
10842                         case 'viscii':
10843                                 return 'VISCII';
10844
10845                         case 'cswindows31j':
10846                         case 'windows31j':
10847                                 return 'Windows-31J';
10848
10849                         case 'iso885911':
10850                         case 'tis620':
10851                                 return 'windows-874';
10852
10853                         case 'cseuckr':
10854                         case 'csksc56011987':
10855                         case 'euckr':
10856                         case 'isoir149':
10857                         case 'korean':
10858                         case 'ksc5601':
10859                         case 'ksc56011987':
10860                         case 'ksc56011989':
10861                         case 'windows949':
10862                                 return 'windows-949';
10863
10864                         case 'windows1250':
10865                                 return 'windows-1250';
10866
10867                         case 'windows1251':
10868                                 return 'windows-1251';
10869
10870                         case 'cp819':
10871                         case 'csisolatin1':
10872                         case 'ibm819':
10873                         case 'iso88591':
10874                         case 'iso885911987':
10875                         case 'isoir100':
10876                         case 'l1':
10877                         case 'latin1':
10878                         case 'windows1252':
10879                                 return 'windows-1252';
10880
10881                         case 'windows1253':
10882                                 return 'windows-1253';
10883
10884                         case 'csisolatin5':
10885                         case 'iso88599':
10886                         case 'iso885991989':
10887                         case 'isoir148':
10888                         case 'l5':
10889                         case 'latin5':
10890                         case 'windows1254':
10891                                 return 'windows-1254';
10892
10893                         case 'windows1255':
10894                                 return 'windows-1255';
10895
10896                         case 'windows1256':
10897                                 return 'windows-1256';
10898
10899                         case 'windows1257':
10900                                 return 'windows-1257';
10901
10902                         case 'windows1258':
10903                                 return 'windows-1258';
10904
10905                         default:
10906                                 return $charset;
10907                 }
10908         }
10909
10910         function get_curl_version()
10911         {
10912                 if (is_array($curl = curl_version()))
10913                 {
10914                         $curl = $curl['version'];
10915                 }
10916                 elseif (substr($curl, 0, 5) === 'curl/')
10917                 {
10918                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10919                 }
10920                 elseif (substr($curl, 0, 8) === 'libcurl/')
10921                 {
10922                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10923                 }
10924                 else
10925                 {
10926                         $curl = 0;
10927                 }
10928                 return $curl;
10929         }
10930
10931         function is_subclass_of($class1, $class2)
10932         {
10933                 if (func_num_args() !== 2)
10934                 {
10935                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10936                 }
10937                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10938                 {
10939                         return is_subclass_of($class1, $class2);
10940                 }
10941                 elseif (is_string($class1) && is_string($class2))
10942                 {
10943                         if (class_exists($class1))
10944                         {
10945                                 if (class_exists($class2))
10946                                 {
10947                                         $class2 = strtolower($class2);
10948                                         while ($class1 = strtolower(get_parent_class($class1)))
10949                                         {
10950                                                 if ($class1 === $class2)
10951                                                 {
10952                                                         return true;
10953                                                 }
10954                                         }
10955                                 }
10956                         }
10957                         else
10958                         {
10959                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10960                         }
10961                 }
10962                 return false;
10963         }
10964
10965         /**
10966          * Strip HTML comments
10967          *
10968          * @access public
10969          * @param string $data Data to strip comments from
10970          * @return string Comment stripped string
10971          */
10972         function strip_comments($data)
10973         {
10974                 $output = '';
10975                 while (($start = strpos($data, '<!--')) !== false)
10976                 {
10977                         $output .= substr($data, 0, $start);
10978                         if (($end = strpos($data, '-->', $start)) !== false)
10979                         {
10980                                 $data = substr_replace($data, '', 0, $end + 3);
10981                         }
10982                         else
10983                         {
10984                                 $data = '';
10985                         }
10986                 }
10987                 return $output . $data;
10988         }
10989
10990         function parse_date($dt)
10991         {
10992                 $parser = SimplePie_Parse_Date::get();
10993                 return $parser->parse($dt);
10994         }
10995
10996         /**
10997          * Decode HTML entities
10998          *
10999          * @static
11000          * @access public
11001          * @param string $data Input data
11002          * @return string Output data
11003          */
11004         function entities_decode($data)
11005         {
11006                 $decoder = new SimplePie_Decode_HTML_Entities($data);
11007                 return $decoder->parse();
11008         }
11009
11010         /**
11011          * Remove RFC822 comments
11012          *
11013          * @access public
11014          * @param string $data Data to strip comments from
11015          * @return string Comment stripped string
11016          */
11017         function uncomment_rfc822($string)
11018         {
11019                 $string = (string) $string;
11020                 $position = 0;
11021                 $length = strlen($string);
11022                 $depth = 0;
11023
11024                 $output = '';
11025
11026                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11027                 {
11028                         $output .= substr($string, $position, $pos - $position);
11029                         $position = $pos + 1;
11030                         if ($string[$pos - 1] !== '\\')
11031                         {
11032                                 $depth++;
11033                                 while ($depth && $position < $length)
11034                                 {
11035                                         $position += strcspn($string, '()', $position);
11036                                         if ($string[$position - 1] === '\\')
11037                                         {
11038                                                 $position++;
11039                                                 continue;
11040                                         }
11041                                         elseif (isset($string[$position]))
11042                                         {
11043                                                 switch ($string[$position])
11044                                                 {
11045                                                         case '(':
11046                                                                 $depth++;
11047                                                                 break;
11048
11049                                                         case ')':
11050                                                                 $depth--;
11051                                                                 break;
11052                                                 }
11053                                                 $position++;
11054                                         }
11055                                         else
11056                                         {
11057                                                 break;
11058                                         }
11059                                 }
11060                         }
11061                         else
11062                         {
11063                                 $output .= '(';
11064                         }
11065                 }
11066                 $output .= substr($string, $position);
11067
11068                 return $output;
11069         }
11070
11071         function parse_mime($mime)
11072         {
11073                 if (($pos = strpos($mime, ';')) === false)
11074                 {
11075                         return trim($mime);
11076                 }
11077                 else
11078                 {
11079                         return trim(substr($mime, 0, $pos));
11080                 }
11081         }
11082
11083         function htmlspecialchars_decode($string, $quote_style)
11084         {
11085                 if (function_exists('htmlspecialchars_decode'))
11086                 {
11087                         return htmlspecialchars_decode($string, $quote_style);
11088                 }
11089                 else
11090                 {
11091                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11092                 }
11093         }
11094
11095         function atom_03_construct_type($attribs)
11096         {
11097                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11098                 {
11099                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11100                 }
11101                 else
11102                 {
11103                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
11104                 }
11105                 if (isset($attribs['']['type']))
11106                 {
11107                         switch (strtolower(trim($attribs['']['type'])))
11108                         {
11109                                 case 'text':
11110                                 case 'text/plain':
11111                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11112
11113                                 case 'html':
11114                                 case 'text/html':
11115                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11116
11117                                 case 'xhtml':
11118                                 case 'application/xhtml+xml':
11119                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11120
11121                                 default:
11122                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11123                         }
11124                 }
11125                 else
11126                 {
11127                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11128                 }
11129         }
11130
11131         function atom_10_construct_type($attribs)
11132         {
11133                 if (isset($attribs['']['type']))
11134                 {
11135                         switch (strtolower(trim($attribs['']['type'])))
11136                         {
11137                                 case 'text':
11138                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11139
11140                                 case 'html':
11141                                         return SIMPLEPIE_CONSTRUCT_HTML;
11142
11143                                 case 'xhtml':
11144                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11145
11146                                 default:
11147                                         return SIMPLEPIE_CONSTRUCT_NONE;
11148                         }
11149                 }
11150                 return SIMPLEPIE_CONSTRUCT_TEXT;
11151         }
11152
11153         function atom_10_content_construct_type($attribs)
11154         {
11155                 if (isset($attribs['']['type']))
11156                 {
11157                         $type = strtolower(trim($attribs['']['type']));
11158                         switch ($type)
11159                         {
11160                                 case 'text':
11161                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11162
11163                                 case 'html':
11164                                         return SIMPLEPIE_CONSTRUCT_HTML;
11165
11166                                 case 'xhtml':
11167                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11168                         }
11169                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11170                         {
11171                                 return SIMPLEPIE_CONSTRUCT_NONE;
11172                         }
11173                         else
11174                         {
11175                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11176                         }
11177                 }
11178                 else
11179                 {
11180                         return SIMPLEPIE_CONSTRUCT_TEXT;
11181                 }
11182         }
11183
11184         function is_isegment_nz_nc($string)
11185         {
11186                 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);
11187         }
11188
11189         function space_seperated_tokens($string)
11190         {
11191                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11192                 $string_length = strlen($string);
11193
11194                 $position = strspn($string, $space_characters);
11195                 $tokens = array();
11196
11197                 while ($position < $string_length)
11198                 {
11199                         $len = strcspn($string, $space_characters, $position);
11200                         $tokens[] = substr($string, $position, $len);
11201                         $position += $len;
11202                         $position += strspn($string, $space_characters, $position);
11203                 }
11204
11205                 return $tokens;
11206         }
11207
11208         function array_unique($array)
11209         {
11210                 if (version_compare(PHP_VERSION, '5.2', '>='))
11211                 {
11212                         return array_unique($array);
11213                 }
11214                 else
11215                 {
11216                         $array = (array) $array;
11217                         $new_array = array();
11218                         $new_array_strings = array();
11219                         foreach ($array as $key => $value)
11220                         {
11221                                 if (is_object($value))
11222                                 {
11223                                         if (method_exists($value, '__toString'))
11224                                         {
11225                                                 $cmp = $value->__toString();
11226                                         }
11227                                         else
11228                                         {
11229                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11230                                         }
11231                                 }
11232                                 elseif (is_array($value))
11233                                 {
11234                                         $cmp = (string) reset($value);
11235                                 }
11236                                 else
11237                                 {
11238                                         $cmp = (string) $value;
11239                                 }
11240                                 if (!in_array($cmp, $new_array_strings))
11241                                 {
11242                                         $new_array[$key] = $value;
11243                                         $new_array_strings[] = $cmp;
11244                                 }
11245                         }
11246                         return $new_array;
11247                 }
11248         }
11249
11250         /**
11251          * Converts a unicode codepoint to a UTF-8 character
11252          *
11253          * @static
11254          * @access public
11255          * @param int $codepoint Unicode codepoint
11256          * @return string UTF-8 character
11257          */
11258         function codepoint_to_utf8($codepoint)
11259         {
11260                 $codepoint = (int) $codepoint;
11261                 if ($codepoint < 0)
11262                 {
11263                         return false;
11264                 }
11265                 else if ($codepoint <= 0x7f)
11266                 {
11267                         return chr($codepoint);
11268                 }
11269                 else if ($codepoint <= 0x7ff)
11270                 {
11271                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11272                 }
11273                 else if ($codepoint <= 0xffff)
11274                 {
11275                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11276                 }
11277                 else if ($codepoint <= 0x10ffff)
11278                 {
11279                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11280                 }
11281                 else
11282                 {
11283                         // U+FFFD REPLACEMENT CHARACTER
11284                         return "\xEF\xBF\xBD";
11285                 }
11286         }
11287
11288         /**
11289          * Re-implementation of PHP 5's stripos()
11290          *
11291          * Returns the numeric position of the first occurrence of needle in the
11292          * haystack string.
11293          *
11294          * @static
11295          * @access string
11296          * @param object $haystack
11297          * @param string $needle Note that the needle may be a string of one or more
11298          *     characters. If needle is not a string, it is converted to an integer
11299          *     and applied as the ordinal value of a character.
11300          * @param int $offset The optional offset parameter allows you to specify which
11301          *     character in haystack to start searching. The position returned is still
11302          *     relative to the beginning of haystack.
11303          * @return bool If needle is not found, stripos() will return boolean false.
11304          */
11305         function stripos($haystack, $needle, $offset = 0)
11306         {
11307                 if (function_exists('stripos'))
11308                 {
11309                         return stripos($haystack, $needle, $offset);
11310                 }
11311                 else
11312                 {
11313                         if (is_string($needle))
11314                         {
11315                                 $needle = strtolower($needle);
11316                         }
11317                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11318                         {
11319                                 $needle = strtolower(chr($needle));
11320                         }
11321                         else
11322                         {
11323                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11324                                 return false;
11325                         }
11326
11327                         return strpos(strtolower($haystack), $needle, $offset);
11328                 }
11329         }
11330
11331         /**
11332          * Similar to parse_str()
11333          *
11334          * Returns an associative array of name/value pairs, where the value is an
11335          * array of values that have used the same name
11336          *
11337          * @static
11338          * @access string
11339          * @param string $str The input string.
11340          * @return array
11341          */
11342         function parse_str($str)
11343         {
11344                 $return = array();
11345                 $str = explode('&', $str);
11346
11347                 foreach ($str as $section)
11348                 {
11349                         if (strpos($section, '=') !== false)
11350                         {
11351                                 list($name, $value) = explode('=', $section, 2);
11352                                 $return[urldecode($name)][] = urldecode($value);
11353                         }
11354                         else
11355                         {
11356                                 $return[urldecode($section)][] = null;
11357                         }
11358                 }
11359
11360                 return $return;
11361         }
11362
11363         /**
11364          * Detect XML encoding, as per XML 1.0 Appendix F.1
11365          *
11366          * @todo Add support for EBCDIC
11367          * @param string $data XML data
11368          * @return array Possible encodings
11369          */
11370         function xml_encoding($data)
11371         {
11372                 // UTF-32 Big Endian BOM
11373                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11374                 {
11375                         $encoding[] = 'UTF-32BE';
11376                 }
11377                 // UTF-32 Little Endian BOM
11378                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11379                 {
11380                         $encoding[] = 'UTF-32LE';
11381                 }
11382                 // UTF-16 Big Endian BOM
11383                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11384                 {
11385                         $encoding[] = 'UTF-16BE';
11386                 }
11387                 // UTF-16 Little Endian BOM
11388                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11389                 {
11390                         $encoding[] = 'UTF-16LE';
11391                 }
11392                 // UTF-8 BOM
11393                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11394                 {
11395                         $encoding[] = 'UTF-8';
11396                 }
11397                 // UTF-32 Big Endian Without BOM
11398                 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")
11399                 {
11400                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11401                         {
11402                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11403                                 if ($parser->parse())
11404                                 {
11405                                         $encoding[] = $parser->encoding;
11406                                 }
11407                         }
11408                         $encoding[] = 'UTF-32BE';
11409                 }
11410                 // UTF-32 Little Endian Without BOM
11411                 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")
11412                 {
11413                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11414                         {
11415                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11416                                 if ($parser->parse())
11417                                 {
11418                                         $encoding[] = $parser->encoding;
11419                                 }
11420                         }
11421                         $encoding[] = 'UTF-32LE';
11422                 }
11423                 // UTF-16 Big Endian Without BOM
11424                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11425                 {
11426                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11427                         {
11428                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11429                                 if ($parser->parse())
11430                                 {
11431                                         $encoding[] = $parser->encoding;
11432                                 }
11433                         }
11434                         $encoding[] = 'UTF-16BE';
11435                 }
11436                 // UTF-16 Little Endian Without BOM
11437                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11438                 {
11439                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11440                         {
11441                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11442                                 if ($parser->parse())
11443                                 {
11444                                         $encoding[] = $parser->encoding;
11445                                 }
11446                         }
11447                         $encoding[] = 'UTF-16LE';
11448                 }
11449                 // US-ASCII (or superset)
11450                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11451                 {
11452                         if ($pos = strpos($data, "\x3F\x3E"))
11453                         {
11454                                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11455                                 if ($parser->parse())
11456                                 {
11457                                         $encoding[] = $parser->encoding;
11458                                 }
11459                         }
11460                         $encoding[] = 'UTF-8';
11461                 }
11462                 // Fallback to UTF-8
11463                 else
11464                 {
11465                         $encoding[] = 'UTF-8';
11466                 }
11467                 return $encoding;
11468         }
11469
11470         function output_javascript()
11471         {
11472                 if (function_exists('ob_gzhandler'))
11473                 {
11474                         ob_start('ob_gzhandler');
11475                 }
11476                 header('Content-type: text/javascript; charset: UTF-8');
11477                 header('Cache-Control: must-revalidate');
11478                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11479                 ?>
11480 function embed_odeo(link) {
11481         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>');
11482 }
11483
11484 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11485         if (placeholder != '') {
11486                 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>');
11487         }
11488         else {
11489                 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>');
11490         }
11491 }
11492
11493 function embed_flash(bgcolor, width, height, link, loop, type) {
11494         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>');
11495 }
11496
11497 function embed_flv(width, height, link, placeholder, loop, player) {
11498         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>');
11499 }
11500
11501 function embed_wmedia(width, height, link) {
11502         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11503 }
11504                 <?php
11505         }
11506 }
11507
11508 /**
11509  * Decode HTML Entities
11510  *
11511  * This implements HTML5 as of revision 967 (2007-06-28)
11512  *
11513  * @package SimplePie
11514  */
11515 class SimplePie_Decode_HTML_Entities
11516 {
11517         /**
11518          * Data to be parsed
11519          *
11520          * @access private
11521          * @var string
11522          */
11523         var $data = '';
11524
11525         /**
11526          * Currently consumed bytes
11527          *
11528          * @access private
11529          * @var string
11530          */
11531         var $consumed = '';
11532
11533         /**
11534          * Position of the current byte being parsed
11535          *
11536          * @access private
11537          * @var int
11538          */
11539         var $position = 0;
11540
11541         /**
11542          * Create an instance of the class with the input data
11543          *
11544          * @access public
11545          * @param string $data Input data
11546          */
11547         function SimplePie_Decode_HTML_Entities($data)
11548         {
11549                 $this->data = $data;
11550         }
11551
11552         /**
11553          * Parse the input data
11554          *
11555          * @access public
11556          * @return string Output data
11557          */
11558         function parse()
11559         {
11560                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11561                 {
11562                         $this->consume();
11563                         $this->entity();
11564                         $this->consumed = '';
11565                 }
11566                 return $this->data;
11567         }
11568
11569         /**
11570          * Consume the next byte
11571          *
11572          * @access private
11573          * @return mixed The next byte, or false, if there is no more data
11574          */
11575         function consume()
11576         {
11577                 if (isset($this->data[$this->position]))
11578                 {
11579                         $this->consumed .= $this->data[$this->position];
11580                         return $this->data[$this->position++];
11581                 }
11582                 else
11583                 {
11584                         return false;
11585                 }
11586         }
11587
11588         /**
11589          * Consume a range of characters
11590          *
11591          * @access private
11592          * @param string $chars Characters to consume
11593          * @return mixed A series of characters that match the range, or false
11594          */
11595         function consume_range($chars)
11596         {
11597                 if ($len = strspn($this->data, $chars, $this->position))
11598                 {
11599                         $data = substr($this->data, $this->position, $len);
11600                         $this->consumed .= $data;
11601                         $this->position += $len;
11602                         return $data;
11603                 }
11604                 else
11605                 {
11606                         return false;
11607                 }
11608         }
11609
11610         /**
11611          * Unconsume one byte
11612          *
11613          * @access private
11614          */
11615         function unconsume()
11616         {
11617                 $this->consumed = substr($this->consumed, 0, -1);
11618                 $this->position--;
11619         }
11620
11621         /**
11622          * Decode an entity
11623          *
11624          * @access private
11625          */
11626         function entity()
11627         {
11628                 switch ($this->consume())
11629                 {
11630                         case "\x09":
11631                         case "\x0A":
11632                         case "\x0B":
11633                         case "\x0B":
11634                         case "\x0C":
11635                         case "\x20":
11636                         case "\x3C":
11637                         case "\x26":
11638                         case false:
11639                                 break;
11640
11641                         case "\x23":
11642                                 switch ($this->consume())
11643                                 {
11644                                         case "\x78":
11645                                         case "\x58":
11646                                                 $range = '0123456789ABCDEFabcdef';
11647                                                 $hex = true;
11648                                                 break;
11649
11650                                         default:
11651                                                 $range = '0123456789';
11652                                                 $hex = false;
11653                                                 $this->unconsume();
11654                                                 break;
11655                                 }
11656
11657                                 if ($codepoint = $this->consume_range($range))
11658                                 {
11659                                         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");
11660
11661                                         if ($hex)
11662                                         {
11663                                                 $codepoint = hexdec($codepoint);
11664                                         }
11665                                         else
11666                                         {
11667                                                 $codepoint = intval($codepoint);
11668                                         }
11669
11670                                         if (isset($windows_1252_specials[$codepoint]))
11671                                         {
11672                                                 $replacement = $windows_1252_specials[$codepoint];
11673                                         }
11674                                         else
11675                                         {
11676                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11677                                         }
11678
11679                                         if (!in_array($this->consume(), array(';', false), true))
11680                                         {
11681                                                 $this->unconsume();
11682                                         }
11683
11684                                         $consumed_length = strlen($this->consumed);
11685                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11686                                         $this->position += strlen($replacement) - $consumed_length;
11687                                 }
11688                                 break;
11689
11690                         default:
11691                                 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");
11692
11693                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11694                                 {
11695                                         $consumed = substr($this->consumed, 1);
11696                                         if (isset($entities[$consumed]))
11697                                         {
11698                                                 $match = $consumed;
11699                                         }
11700                                 }
11701
11702                                 if ($match !== null)
11703                                 {
11704                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11705                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11706                                 }
11707                                 break;
11708                 }
11709         }
11710 }
11711
11712 /**
11713  * IRI parser/serialiser
11714  *
11715  * @package SimplePie
11716  */
11717 class SimplePie_IRI
11718 {
11719         /**
11720          * Scheme
11721          *
11722          * @access private
11723          * @var string
11724          */
11725         var $scheme;
11726
11727         /**
11728          * User Information
11729          *
11730          * @access private
11731          * @var string
11732          */
11733         var $userinfo;
11734
11735         /**
11736          * Host
11737          *
11738          * @access private
11739          * @var string
11740          */
11741         var $host;
11742
11743         /**
11744          * Port
11745          *
11746          * @access private
11747          * @var string
11748          */
11749         var $port;
11750
11751         /**
11752          * Path
11753          *
11754          * @access private
11755          * @var string
11756          */
11757         var $path;
11758
11759         /**
11760          * Query
11761          *
11762          * @access private
11763          * @var string
11764          */
11765         var $query;
11766
11767         /**
11768          * Fragment
11769          *
11770          * @access private
11771          * @var string
11772          */
11773         var $fragment;
11774
11775         /**
11776          * Whether the object represents a valid IRI
11777          *
11778          * @access private
11779          * @var array
11780          */
11781         var $valid = array();
11782
11783         /**
11784          * Return the entire IRI when you try and read the object as a string
11785          *
11786          * @access public
11787          * @return string
11788          */
11789         function __toString()
11790         {
11791                 return $this->get_iri();
11792         }
11793
11794         /**
11795          * Create a new IRI object, from a specified string
11796          *
11797          * @access public
11798          * @param string $iri
11799          * @return SimplePie_IRI
11800          */
11801         function SimplePie_IRI($iri)
11802         {
11803                 $iri = (string) $iri;
11804                 if ($iri !== '')
11805                 {
11806                         $parsed = $this->parse_iri($iri);
11807                         $this->set_scheme($parsed['scheme']);
11808                         $this->set_authority($parsed['authority']);
11809                         $this->set_path($parsed['path']);
11810                         $this->set_query($parsed['query']);
11811                         $this->set_fragment($parsed['fragment']);
11812                 }
11813         }
11814
11815         /**
11816          * Create a new IRI object by resolving a relative IRI
11817          *
11818          * @static
11819          * @access public
11820          * @param SimplePie_IRI $base Base IRI
11821          * @param string $relative Relative IRI
11822          * @return SimplePie_IRI
11823          */
11824         function absolutize($base, $relative)
11825         {
11826                 $relative = (string) $relative;
11827                 if ($relative !== '')
11828                 {
11829                         $relative = new SimplePie_IRI($relative);
11830                         if ($relative->get_scheme() !== null)
11831                         {
11832                                 $target = $relative;
11833                         }
11834                         elseif ($base->get_iri() !== null)
11835                         {
11836                                 if ($relative->get_authority() !== null)
11837                                 {
11838                                         $target = $relative;
11839                                         $target->set_scheme($base->get_scheme());
11840                                 }
11841                                 else
11842                                 {
11843                                         $target = new SimplePie_IRI('');
11844                                         $target->set_scheme($base->get_scheme());
11845                                         $target->set_userinfo($base->get_userinfo());
11846                                         $target->set_host($base->get_host());
11847                                         $target->set_port($base->get_port());
11848                                         if ($relative->get_path() !== null)
11849                                         {
11850                                                 if (strpos($relative->get_path(), '/') === 0)
11851                                                 {
11852                                                         $target->set_path($relative->get_path());
11853                                                 }
11854                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11855                                                 {
11856                                                         $target->set_path('/' . $relative->get_path());
11857                                                 }
11858                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11859                                                 {
11860                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11861                                                 }
11862                                                 else
11863                                                 {
11864                                                         $target->set_path($relative->get_path());
11865                                                 }
11866                                                 $target->set_query($relative->get_query());
11867                                         }
11868                                         else
11869                                         {
11870                                                 $target->set_path($base->get_path());
11871                                                 if ($relative->get_query() !== null)
11872                                                 {
11873                                                         $target->set_query($relative->get_query());
11874                                                 }
11875                                                 elseif ($base->get_query() !== null)
11876                                                 {
11877                                                         $target->set_query($base->get_query());
11878                                                 }
11879                                         }
11880                                 }
11881                                 $target->set_fragment($relative->get_fragment());
11882                         }
11883                         else
11884                         {
11885                                 // No base URL, just return the relative URL
11886                                 $target = $relative;
11887                         }
11888                 }
11889                 else
11890                 {
11891                         $target = $base;
11892                 }
11893                 return $target;
11894         }
11895
11896         /**
11897          * Parse an IRI into scheme/authority/path/query/fragment segments
11898          *
11899          * @access private
11900          * @param string $iri
11901          * @return array
11902          */
11903         function parse_iri($iri)
11904         {
11905                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11906                 for ($i = count($match); $i <= 9; $i++)
11907                 {
11908                         $match[$i] = '';
11909                 }
11910                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11911         }
11912
11913         /**
11914          * Remove dot segments from a path
11915          *
11916          * @access private
11917          * @param string $input
11918          * @return string
11919          */
11920         function remove_dot_segments($input)
11921         {
11922                 $output = '';
11923                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11924                 {
11925                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11926                         if (strpos($input, '../') === 0)
11927                         {
11928                                 $input = substr($input, 3);
11929                         }
11930                         elseif (strpos($input, './') === 0)
11931                         {
11932                                 $input = substr($input, 2);
11933                         }
11934                         // 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,
11935                         elseif (strpos($input, '/./') === 0)
11936                         {
11937                                 $input = substr_replace($input, '/', 0, 3);
11938                         }
11939                         elseif ($input === '/.')
11940                         {
11941                                 $input = '/';
11942                         }
11943                         // 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,
11944                         elseif (strpos($input, '/../') === 0)
11945                         {
11946                                 $input = substr_replace($input, '/', 0, 4);
11947                                 $output = substr_replace($output, '', strrpos($output, '/'));
11948                         }
11949                         elseif ($input === '/..')
11950                         {
11951                                 $input = '/';
11952                                 $output = substr_replace($output, '', strrpos($output, '/'));
11953                         }
11954                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11955                         elseif ($input === '.' || $input === '..')
11956                         {
11957                                 $input = '';
11958                         }
11959                         // 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
11960                         elseif (($pos = strpos($input, '/', 1)) !== false)
11961                         {
11962                                 $output .= substr($input, 0, $pos);
11963                                 $input = substr_replace($input, '', 0, $pos);
11964                         }
11965                         else
11966                         {
11967                                 $output .= $input;
11968                                 $input = '';
11969                         }
11970                 }
11971                 return $output . $input;
11972         }
11973
11974         /**
11975          * Replace invalid character with percent encoding
11976          *
11977          * @access private
11978          * @param string $string Input string
11979          * @param string $valid_chars Valid characters
11980          * @param int $case Normalise case
11981          * @return string
11982          */
11983         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11984         {
11985                 // Normalise case
11986                 if ($case & SIMPLEPIE_LOWERCASE)
11987                 {
11988                         $string = strtolower($string);
11989                 }
11990                 elseif ($case & SIMPLEPIE_UPPERCASE)
11991                 {
11992                         $string = strtoupper($string);
11993                 }
11994
11995                 // Store position and string length (to avoid constantly recalculating this)
11996                 $position = 0;
11997                 $strlen = strlen($string);
11998
11999                 // Loop as long as we have invalid characters, advancing the position to the next invalid character
12000                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
12001                 {
12002                         // If we have a % character
12003                         if ($string[$position] === '%')
12004                         {
12005                                 // If we have a pct-encoded section
12006                                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
12007                                 {
12008                                         // Get the the represented character
12009                                         $chr = chr(hexdec(substr($string, $position + 1, 2)));
12010
12011                                         // If the character is valid, replace the pct-encoded with the actual character while normalising case
12012                                         if (strpos($valid_chars, $chr) !== false)
12013                                         {
12014                                                 if ($case & SIMPLEPIE_LOWERCASE)
12015                                                 {
12016                                                         $chr = strtolower($chr);
12017                                                 }
12018                                                 elseif ($case & SIMPLEPIE_UPPERCASE)
12019                                                 {
12020                                                         $chr = strtoupper($chr);
12021                                                 }
12022                                                 $string = substr_replace($string, $chr, $position, 3);
12023                                                 $strlen -= 2;
12024                                                 $position++;
12025                                         }
12026
12027                                         // Otherwise just normalise the pct-encoded to uppercase
12028                                         else
12029                                         {
12030                                                 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
12031                                                 $position += 3;
12032                                         }
12033                                 }
12034                                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
12035                                 else
12036                                 {
12037                                         $string = substr_replace($string, '%25', $position, 1);
12038                                         $strlen += 2;
12039                                         $position += 3;
12040                                 }
12041                         }
12042                         // If we have an invalid character, change into its pct-encoded form
12043                         else
12044                         {
12045                                 $replacement = sprintf("%%%02X", ord($string[$position]));
12046                                 $string = str_replace($string[$position], $replacement, $string);
12047                                 $strlen = strlen($string);
12048                         }
12049                 }
12050                 return $string;
12051         }
12052
12053         /**
12054          * Check if the object represents a valid IRI
12055          *
12056          * @access public
12057          * @return bool
12058          */
12059         function is_valid()
12060         {
12061                 return array_sum($this->valid) === count($this->valid);
12062         }
12063
12064         /**
12065          * Set the scheme. Returns true on success, false on failure (if there are
12066          * any invalid characters).
12067          *
12068          * @access public
12069          * @param string $scheme
12070          * @return bool
12071          */
12072         function set_scheme($scheme)
12073         {
12074                 if ($scheme === null || $scheme === '')
12075                 {
12076                         $this->scheme = null;
12077                 }
12078                 else
12079                 {
12080                         $len = strlen($scheme);
12081                         switch (true)
12082                         {
12083                                 case $len > 1:
12084                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12085                                         {
12086                                                 $this->scheme = null;
12087                                                 $this->valid[__FUNCTION__] = false;
12088                                                 return false;
12089                                         }
12090
12091                                 case $len > 0:
12092                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12093                                         {
12094                                                 $this->scheme = null;
12095                                                 $this->valid[__FUNCTION__] = false;
12096                                                 return false;
12097                                         }
12098                         }
12099                         $this->scheme = strtolower($scheme);
12100                 }
12101                 $this->valid[__FUNCTION__] = true;
12102                 return true;
12103         }
12104
12105         /**
12106          * Set the authority. Returns true on success, false on failure (if there are
12107          * any invalid characters).
12108          *
12109          * @access public
12110          * @param string $authority
12111          * @return bool
12112          */
12113         function set_authority($authority)
12114         {
12115                 if (($userinfo_end = strrpos($authority, '@')) !== false)
12116                 {
12117                         $userinfo = substr($authority, 0, $userinfo_end);
12118                         $authority = substr($authority, $userinfo_end + 1);
12119                 }
12120                 else
12121                 {
12122                         $userinfo = null;
12123                 }
12124
12125                 if (($port_start = strpos($authority, ':')) !== false)
12126                 {
12127                         $port = substr($authority, $port_start + 1);
12128                         $authority = substr($authority, 0, $port_start);
12129                 }
12130                 else
12131                 {
12132                         $port = null;
12133                 }
12134
12135                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12136         }
12137
12138         /**
12139          * Set the userinfo.
12140          *
12141          * @access public
12142          * @param string $userinfo
12143          * @return bool
12144          */
12145         function set_userinfo($userinfo)
12146         {
12147                 if ($userinfo === null || $userinfo === '')
12148                 {
12149                         $this->userinfo = null;
12150                 }
12151                 else
12152                 {
12153                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12154                 }
12155                 $this->valid[__FUNCTION__] = true;
12156                 return true;
12157         }
12158
12159         /**
12160          * Set the host. Returns true on success, false on failure (if there are
12161          * any invalid characters).
12162          *
12163          * @access public
12164          * @param string $host
12165          * @return bool
12166          */
12167         function set_host($host)
12168         {
12169                 if ($host === null || $host === '')
12170                 {
12171                         $this->host = null;
12172                         $this->valid[__FUNCTION__] = true;
12173                         return true;
12174                 }
12175                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12176                 {
12177                         if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12178                         {
12179                                 $this->host = $host;
12180                                 $this->valid[__FUNCTION__] = true;
12181                                 return true;
12182                         }
12183                         else
12184                         {
12185                                 $this->host = null;
12186                                 $this->valid[__FUNCTION__] = false;
12187                                 return false;
12188                         }
12189                 }
12190                 else
12191                 {
12192                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12193                         $this->valid[__FUNCTION__] = true;
12194                         return true;
12195                 }
12196         }
12197
12198         /**
12199          * Set the port. Returns true on success, false on failure (if there are
12200          * any invalid characters).
12201          *
12202          * @access public
12203          * @param string $port
12204          * @return bool
12205          */
12206         function set_port($port)
12207         {
12208                 if ($port === null || $port === '')
12209                 {
12210                         $this->port = null;
12211                         $this->valid[__FUNCTION__] = true;
12212                         return true;
12213                 }
12214                 elseif (strspn($port, '0123456789') === strlen($port))
12215                 {
12216                         $this->port = (int) $port;
12217                         $this->valid[__FUNCTION__] = true;
12218                         return true;
12219                 }
12220                 else
12221                 {
12222                         $this->port = null;
12223                         $this->valid[__FUNCTION__] = false;
12224                         return false;
12225                 }
12226         }
12227
12228         /**
12229          * Set the path.
12230          *
12231          * @access public
12232          * @param string $path
12233          * @return bool
12234          */
12235         function set_path($path)
12236         {
12237                 if ($path === null || $path === '')
12238                 {
12239                         $this->path = null;
12240                         $this->valid[__FUNCTION__] = true;
12241                         return true;
12242                 }
12243                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12244                 {
12245                         $this->path = null;
12246                         $this->valid[__FUNCTION__] = false;
12247                         return false;
12248                 }
12249                 else
12250                 {
12251                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12252                         if ($this->scheme !== null)
12253                         {
12254                                 $this->path = $this->remove_dot_segments($this->path);
12255                         }
12256                         $this->valid[__FUNCTION__] = true;
12257                         return true;
12258                 }
12259         }
12260
12261         /**
12262          * Set the query.
12263          *
12264          * @access public
12265          * @param string $query
12266          * @return bool
12267          */
12268         function set_query($query)
12269         {
12270                 if ($query === null || $query === '')
12271                 {
12272                         $this->query = null;
12273                 }
12274                 else
12275                 {
12276                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
12277                 }
12278                 $this->valid[__FUNCTION__] = true;
12279                 return true;
12280         }
12281
12282         /**
12283          * Set the fragment.
12284          *
12285          * @access public
12286          * @param string $fragment
12287          * @return bool
12288          */
12289         function set_fragment($fragment)
12290         {
12291                 if ($fragment === null || $fragment === '')
12292                 {
12293                         $this->fragment = null;
12294                 }
12295                 else
12296                 {
12297                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12298                 }
12299                 $this->valid[__FUNCTION__] = true;
12300                 return true;
12301         }
12302
12303         /**
12304          * Get the complete IRI
12305          *
12306          * @access public
12307          * @return string
12308          */
12309         function get_iri()
12310         {
12311                 $iri = '';
12312                 if ($this->scheme !== null)
12313                 {
12314                         $iri .= $this->scheme . ':';
12315                 }
12316                 if (($authority = $this->get_authority()) !== null)
12317                 {
12318                         $iri .= '//' . $authority;
12319                 }
12320                 if ($this->path !== null)
12321                 {
12322                         $iri .= $this->path;
12323                 }
12324                 if ($this->query !== null)
12325                 {
12326                         $iri .= '?' . $this->query;
12327                 }
12328                 if ($this->fragment !== null)
12329                 {
12330                         $iri .= '#' . $this->fragment;
12331                 }
12332
12333                 if ($iri !== '')
12334                 {
12335                         return $iri;
12336                 }
12337                 else
12338                 {
12339                         return null;
12340                 }
12341         }
12342
12343         /**
12344          * Get the scheme
12345          *
12346          * @access public
12347          * @return string
12348          */
12349         function get_scheme()
12350         {
12351                 return $this->scheme;
12352         }
12353
12354         /**
12355          * Get the complete authority
12356          *
12357          * @access public
12358          * @return string
12359          */
12360         function get_authority()
12361         {
12362                 $authority = '';
12363                 if ($this->userinfo !== null)
12364                 {
12365                         $authority .= $this->userinfo . '@';
12366                 }
12367                 if ($this->host !== null)
12368                 {
12369                         $authority .= $this->host;
12370                 }
12371                 if ($this->port !== null)
12372                 {
12373                         $authority .= ':' . $this->port;
12374                 }
12375
12376                 if ($authority !== '')
12377                 {
12378                         return $authority;
12379                 }
12380                 else
12381                 {
12382                         return null;
12383                 }
12384         }
12385
12386         /**
12387          * Get the user information
12388          *
12389          * @access public
12390          * @return string
12391          */
12392         function get_userinfo()
12393         {
12394                 return $this->userinfo;
12395         }
12396
12397         /**
12398          * Get the host
12399          *
12400          * @access public
12401          * @return string
12402          */
12403         function get_host()
12404         {
12405                 return $this->host;
12406         }
12407
12408         /**
12409          * Get the port
12410          *
12411          * @access public
12412          * @return string
12413          */
12414         function get_port()
12415         {
12416                 return $this->port;
12417         }
12418
12419         /**
12420          * Get the path
12421          *
12422          * @access public
12423          * @return string
12424          */
12425         function get_path()
12426         {
12427                 return $this->path;
12428         }
12429
12430         /**
12431          * Get the query
12432          *
12433          * @access public
12434          * @return string
12435          */
12436         function get_query()
12437         {
12438                 return $this->query;
12439         }
12440
12441         /**
12442          * Get the fragment
12443          *
12444          * @access public
12445          * @return string
12446          */
12447         function get_fragment()
12448         {
12449                 return $this->fragment;
12450         }
12451 }
12452
12453 /**
12454  * Class to validate and to work with IPv6 addresses.
12455  *
12456  * @package SimplePie
12457  * @copyright 2003-2005 The PHP Group
12458  * @license http://www.opensource.org/licenses/bsd-license.php
12459  * @link http://pear.php.net/package/Net_IPv6
12460  * @author Alexander Merz <alexander.merz@web.de>
12461  * @author elfrink at introweb dot nl
12462  * @author Josh Peck <jmp at joshpeck dot org>
12463  * @author Geoffrey Sneddon <geoffers@gmail.com>
12464  */
12465 class SimplePie_Net_IPv6
12466 {
12467         /**
12468          * Removes a possible existing netmask specification of an IP address.
12469          *
12470          * @param string $ip the (compressed) IP as Hex representation
12471          * @return string the IP the without netmask
12472          * @since 1.1.0
12473          * @access public
12474          * @static
12475          */
12476         function removeNetmaskSpec($ip)
12477         {
12478                 if (strpos($ip, '/') !== false)
12479                 {
12480                         list($addr, $nm) = explode('/', $ip);
12481                 }
12482                 else
12483                 {
12484                         $addr = $ip;
12485                 }
12486                 return $addr;
12487         }
12488
12489         /**
12490          * Uncompresses an IPv6 address
12491          *
12492          * RFC 2373 allows you to compress zeros in an address to '::'. This
12493          * function expects an valid IPv6 address and expands the '::' to
12494          * the required zeros.
12495          *
12496          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12497          *                       ::1            ->      0:0:0:0:0:0:0:1
12498          *
12499          * @access public
12500          * @static
12501          * @param string $ip a valid IPv6-address (hex format)
12502          * @return string the uncompressed IPv6-address (hex format)
12503          */
12504         function Uncompress($ip)
12505         {
12506                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12507                 $c1 = -1;
12508                 $c2 = -1;
12509                 if (strpos($ip, '::') !== false)
12510                 {
12511                         list($ip1, $ip2) = explode('::', $ip);
12512                         if ($ip1 === '')
12513                         {
12514                                 $c1 = -1;
12515                         }
12516                         else
12517                         {
12518                                 $pos = 0;
12519                                 if (($pos = substr_count($ip1, ':')) > 0)
12520                                 {
12521                                         $c1 = $pos;
12522                                 }
12523                                 else
12524                                 {
12525                                         $c1 = 0;
12526                                 }
12527                         }
12528                         if ($ip2 === '')
12529                         {
12530                                 $c2 = -1;
12531                         }
12532                         else
12533                         {
12534                                 $pos = 0;
12535                                 if (($pos = substr_count($ip2, ':')) > 0)
12536                                 {
12537                                         $c2 = $pos;
12538                                 }
12539                                 else
12540                                 {
12541                                         $c2 = 0;
12542                                 }
12543                         }
12544                         if (strstr($ip2, '.'))
12545                         {
12546                                 $c2++;
12547                         }
12548                         // ::
12549                         if ($c1 === -1 && $c2 === -1)
12550                         {
12551                                 $uip = '0:0:0:0:0:0:0:0';
12552                         }
12553                         // ::xxx
12554                         else if ($c1 === -1)
12555                         {
12556                                 $fill = str_repeat('0:', 7 - $c2);
12557                                 $uip =  str_replace('::', $fill, $uip);
12558                         }
12559                         // xxx::
12560                         else if ($c2 === -1)
12561                         {
12562                                 $fill = str_repeat(':0', 7 - $c1);
12563                                 $uip =  str_replace('::', $fill, $uip);
12564                         }
12565                         // xxx::xxx
12566                         else
12567                         {
12568                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12569                                 $uip =  str_replace('::', $fill, $uip);
12570                                 $uip =  str_replace('::', ':', $uip);
12571                         }
12572                 }
12573                 return $uip;
12574         }
12575
12576         /**
12577          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12578          *
12579          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12580          * an IPv4 compatible address
12581          *
12582          * Example:      0:0:0:0:0:0:13.1.68.3
12583          *                       0:0:0:0:0:FFFF:129.144.52.38
12584          *
12585          * @access public
12586          * @static
12587          * @param string $ip a valid IPv6-address (hex format)
12588          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12589          */
12590         function SplitV64($ip)
12591         {
12592                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12593                 if (strstr($ip, '.'))
12594                 {
12595                         $pos = strrpos($ip, ':');
12596                         $ip[$pos] = '_';
12597                         $ipPart = explode('_', $ip);
12598                         return $ipPart;
12599                 }
12600                 else
12601                 {
12602                         return array($ip, '');
12603                 }
12604         }
12605
12606         /**
12607          * Checks an IPv6 address
12608          *
12609          * Checks if the given IP is IPv6-compatible
12610          *
12611          * @access public
12612          * @static
12613          * @param string $ip a valid IPv6-address
12614          * @return bool true if $ip is an IPv6 address
12615          */
12616         function checkIPv6($ip)
12617         {
12618                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12619                 $count = 0;
12620                 if (!empty($ipPart[0]))
12621                 {
12622                         $ipv6 = explode(':', $ipPart[0]);
12623                         for ($i = 0; $i < count($ipv6); $i++)
12624                         {
12625                                 $dec = hexdec($ipv6[$i]);
12626                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12627                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12628                                 {
12629                                         $count++;
12630                                 }
12631                         }
12632                         if ($count === 8)
12633                         {
12634                                 return true;
12635                         }
12636                         elseif ($count === 6 && !empty($ipPart[1]))
12637                         {
12638                                 $ipv4 = explode('.', $ipPart[1]);
12639                                 $count = 0;
12640                                 foreach ($ipv4 as $ipv4_part)
12641                                 {
12642                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12643                                         {
12644                                                 $count++;
12645                                         }
12646                                 }
12647                                 if ($count === 4)
12648                                 {
12649                                         return true;
12650                                 }
12651                         }
12652                         else
12653                         {
12654                                 return false;
12655                         }
12656
12657                 }
12658                 else
12659                 {
12660                         return false;
12661                 }
12662         }
12663 }
12664
12665 /**
12666  * Date Parser
12667  *
12668  * @package SimplePie
12669  */
12670 class SimplePie_Parse_Date
12671 {
12672         /**
12673          * Input data
12674          *
12675          * @access protected
12676          * @var string
12677          */
12678         var $date;
12679
12680         /**
12681          * List of days, calendar day name => ordinal day number in the week
12682          *
12683          * @access protected
12684          * @var array
12685          */
12686         var $day = array(
12687                 // English
12688                 'mon' => 1,
12689                 'monday' => 1,
12690                 'tue' => 2,
12691                 'tuesday' => 2,
12692                 'wed' => 3,
12693                 'wednesday' => 3,
12694                 'thu' => 4,
12695                 'thursday' => 4,
12696                 'fri' => 5,
12697                 'friday' => 5,
12698                 'sat' => 6,
12699                 'saturday' => 6,
12700                 'sun' => 7,
12701                 'sunday' => 7,
12702                 // Dutch
12703                 'maandag' => 1,
12704                 'dinsdag' => 2,
12705                 'woensdag' => 3,
12706                 'donderdag' => 4,
12707                 'vrijdag' => 5,
12708                 'zaterdag' => 6,
12709                 'zondag' => 7,
12710                 // French
12711                 'lundi' => 1,
12712                 'mardi' => 2,
12713                 'mercredi' => 3,
12714                 'jeudi' => 4,
12715                 'vendredi' => 5,
12716                 'samedi' => 6,
12717                 'dimanche' => 7,
12718                 // German
12719                 'montag' => 1,
12720                 'dienstag' => 2,
12721                 'mittwoch' => 3,
12722                 'donnerstag' => 4,
12723                 'freitag' => 5,
12724                 'samstag' => 6,
12725                 'sonnabend' => 6,
12726                 'sonntag' => 7,
12727                 // Italian
12728                 'lunedì' => 1,
12729                 'martedì' => 2,
12730                 'mercoledì' => 3,
12731                 'giovedì' => 4,
12732                 'venerdì' => 5,
12733                 'sabato' => 6,
12734                 'domenica' => 7,
12735                 // Spanish
12736                 'lunes' => 1,
12737                 'martes' => 2,
12738                 'miércoles' => 3,
12739                 'jueves' => 4,
12740                 'viernes' => 5,
12741                 'sábado' => 6,
12742                 'domingo' => 7,
12743                 // Finnish
12744                 'maanantai' => 1,
12745                 'tiistai' => 2,
12746                 'keskiviikko' => 3,
12747                 'torstai' => 4,
12748                 'perjantai' => 5,
12749                 'lauantai' => 6,
12750                 'sunnuntai' => 7,
12751                 // Hungarian
12752                 'hétfő' => 1,
12753                 'kedd' => 2,
12754                 'szerda' => 3,
12755                 'csütörtok' => 4,
12756                 'péntek' => 5,
12757                 'szombat' => 6,
12758                 'vasárnap' => 7,
12759                 // Greek
12760                 'Δευ' => 1,
12761                 'Τρι' => 2,
12762                 'Τετ' => 3,
12763                 'Πεμ' => 4,
12764                 'Παρ' => 5,
12765                 'Σαβ' => 6,
12766                 'Κυρ' => 7,
12767         );
12768
12769         /**
12770          * List of months, calendar month name => calendar month number
12771          *
12772          * @access protected
12773          * @var array
12774          */
12775         var $month = array(
12776                 // English
12777                 'jan' => 1,
12778                 'january' => 1,
12779                 'feb' => 2,
12780                 'february' => 2,
12781                 'mar' => 3,
12782                 'march' => 3,
12783                 'apr' => 4,
12784                 'april' => 4,
12785                 'may' => 5,
12786                 // No long form of May
12787                 'jun' => 6,
12788                 'june' => 6,
12789                 'jul' => 7,
12790                 'july' => 7,
12791                 'aug' => 8,
12792                 'august' => 8,
12793                 'sep' => 9,
12794                 'september' => 8,
12795                 'oct' => 10,
12796                 'october' => 10,
12797                 'nov' => 11,
12798                 'november' => 11,
12799                 'dec' => 12,
12800                 'december' => 12,
12801                 // Dutch
12802                 'januari' => 1,
12803                 'februari' => 2,
12804                 'maart' => 3,
12805                 'april' => 4,
12806                 'mei' => 5,
12807                 'juni' => 6,
12808                 'juli' => 7,
12809                 'augustus' => 8,
12810                 'september' => 9,
12811                 'oktober' => 10,
12812                 'november' => 11,
12813                 'december' => 12,
12814                 // French
12815                 'janvier' => 1,
12816                 'février' => 2,
12817                 'mars' => 3,
12818                 'avril' => 4,
12819                 'mai' => 5,
12820                 'juin' => 6,
12821                 'juillet' => 7,
12822                 'août' => 8,
12823                 'septembre' => 9,
12824                 'octobre' => 10,
12825                 'novembre' => 11,
12826                 'décembre' => 12,
12827                 // German
12828                 'januar' => 1,
12829                 'februar' => 2,
12830                 'märz' => 3,
12831                 'april' => 4,
12832                 'mai' => 5,
12833                 'juni' => 6,
12834                 'juli' => 7,
12835                 'august' => 8,
12836                 'september' => 9,
12837                 'oktober' => 10,
12838                 'november' => 11,
12839                 'dezember' => 12,
12840                 // Italian
12841                 'gennaio' => 1,
12842                 'febbraio' => 2,
12843                 'marzo' => 3,
12844                 'aprile' => 4,
12845                 'maggio' => 5,
12846                 'giugno' => 6,
12847                 'luglio' => 7,
12848                 'agosto' => 8,
12849                 'settembre' => 9,
12850                 'ottobre' => 10,
12851                 'novembre' => 11,
12852                 'dicembre' => 12,
12853                 // Spanish
12854                 'enero' => 1,
12855                 'febrero' => 2,
12856                 'marzo' => 3,
12857                 'abril' => 4,
12858                 'mayo' => 5,
12859                 'junio' => 6,
12860                 'julio' => 7,
12861                 'agosto' => 8,
12862                 'septiembre' => 9,
12863                 'setiembre' => 9,
12864                 'octubre' => 10,
12865                 'noviembre' => 11,
12866                 'diciembre' => 12,
12867                 // Finnish
12868                 'tammikuu' => 1,
12869                 'helmikuu' => 2,
12870                 'maaliskuu' => 3,
12871                 'huhtikuu' => 4,
12872                 'toukokuu' => 5,
12873                 'kesäkuu' => 6,
12874                 'heinäkuu' => 7,
12875                 'elokuu' => 8,
12876                 'suuskuu' => 9,
12877                 'lokakuu' => 10,
12878                 'marras' => 11,
12879                 'joulukuu' => 12,
12880                 // Hungarian
12881                 'január' => 1,
12882                 'február' => 2,
12883                 'március' => 3,
12884                 'április' => 4,
12885                 'május' => 5,
12886                 'június' => 6,
12887                 'július' => 7,
12888                 'augusztus' => 8,
12889                 'szeptember' => 9,
12890                 'október' => 10,
12891                 'november' => 11,
12892                 'december' => 12,
12893                 // Greek
12894                 'Ιαν' => 1,
12895                 'Φεβ' => 2,
12896                 'Μάώ' => 3,
12897                 'Μαώ' => 3,
12898                 'Απρ' => 4,
12899                 'Μάι' => 5,
12900                 'Μαϊ' => 5,
12901                 'Μαι' => 5,
12902                 'Ιούν' => 6,
12903                 'Ιον' => 6,
12904                 'Ιούλ' => 7,
12905                 'Ιολ' => 7,
12906                 'Αύγ' => 8,
12907                 'Αυγ' => 8,
12908                 'Σεπ' => 9,
12909                 'Οκτ' => 10,
12910                 'Νοέ' => 11,
12911                 'Δεκ' => 12,
12912         );
12913
12914         /**
12915          * List of timezones, abbreviation => offset from UTC
12916          *
12917          * @access protected
12918          * @var array
12919          */
12920         var $timezone = array(
12921                 'ACDT' => 37800,
12922                 'ACIT' => 28800,
12923                 'ACST' => 34200,
12924                 'ACT' => -18000,
12925                 'ACWDT' => 35100,
12926                 'ACWST' => 31500,
12927                 'AEDT' => 39600,
12928                 'AEST' => 36000,
12929                 'AFT' => 16200,
12930                 'AKDT' => -28800,
12931                 'AKST' => -32400,
12932                 'AMDT' => 18000,
12933                 'AMT' => -14400,
12934                 'ANAST' => 46800,
12935                 'ANAT' => 43200,
12936                 'ART' => -10800,
12937                 'AZOST' => -3600,
12938                 'AZST' => 18000,
12939                 'AZT' => 14400,
12940                 'BIOT' => 21600,
12941                 'BIT' => -43200,
12942                 'BOT' => -14400,
12943                 'BRST' => -7200,
12944                 'BRT' => -10800,
12945                 'BST' => 3600,
12946                 'BTT' => 21600,
12947                 'CAST' => 18000,
12948                 'CAT' => 7200,
12949                 'CCT' => 23400,
12950                 'CDT' => -18000,
12951                 'CEDT' => 7200,
12952                 'CET' => 3600,
12953                 'CGST' => -7200,
12954                 'CGT' => -10800,
12955                 'CHADT' => 49500,
12956                 'CHAST' => 45900,
12957                 'CIST' => -28800,
12958                 'CKT' => -36000,
12959                 'CLDT' => -10800,
12960                 'CLST' => -14400,
12961                 'COT' => -18000,
12962                 'CST' => -21600,
12963                 'CVT' => -3600,
12964                 'CXT' => 25200,
12965                 'DAVT' => 25200,
12966                 'DTAT' => 36000,
12967                 'EADT' => -18000,
12968                 'EAST' => -21600,
12969                 'EAT' => 10800,
12970                 'ECT' => -18000,
12971                 'EDT' => -14400,
12972                 'EEST' => 10800,
12973                 'EET' => 7200,
12974                 'EGT' => -3600,
12975                 'EKST' => 21600,
12976                 'EST' => -18000,
12977                 'FJT' => 43200,
12978                 'FKDT' => -10800,
12979                 'FKST' => -14400,
12980                 'FNT' => -7200,
12981                 'GALT' => -21600,
12982                 'GEDT' => 14400,
12983                 'GEST' => 10800,
12984                 'GFT' => -10800,
12985                 'GILT' => 43200,
12986                 'GIT' => -32400,
12987                 'GST' => 14400,
12988                 'GST' => -7200,
12989                 'GYT' => -14400,
12990                 'HAA' => -10800,
12991                 'HAC' => -18000,
12992                 'HADT' => -32400,
12993                 'HAE' => -14400,
12994                 'HAP' => -25200,
12995                 'HAR' => -21600,
12996                 'HAST' => -36000,
12997                 'HAT' => -9000,
12998                 'HAY' => -28800,
12999                 'HKST' => 28800,
13000                 'HMT' => 18000,
13001                 'HNA' => -14400,
13002                 'HNC' => -21600,
13003                 'HNE' => -18000,
13004                 'HNP' => -28800,
13005                 'HNR' => -25200,
13006                 'HNT' => -12600,
13007                 'HNY' => -32400,
13008                 'IRDT' => 16200,
13009                 'IRKST' => 32400,
13010                 'IRKT' => 28800,
13011                 'IRST' => 12600,
13012                 'JFDT' => -10800,
13013                 'JFST' => -14400,
13014                 'JST' => 32400,
13015                 'KGST' => 21600,
13016                 'KGT' => 18000,
13017                 'KOST' => 39600,
13018                 'KOVST' => 28800,
13019                 'KOVT' => 25200,
13020                 'KRAST' => 28800,
13021                 'KRAT' => 25200,
13022                 'KST' => 32400,
13023                 'LHDT' => 39600,
13024                 'LHST' => 37800,
13025                 'LINT' => 50400,
13026                 'LKT' => 21600,
13027                 'MAGST' => 43200,
13028                 'MAGT' => 39600,
13029                 'MAWT' => 21600,
13030                 'MDT' => -21600,
13031                 'MESZ' => 7200,
13032                 'MEZ' => 3600,
13033                 'MHT' => 43200,
13034                 'MIT' => -34200,
13035                 'MNST' => 32400,
13036                 'MSDT' => 14400,
13037                 'MSST' => 10800,
13038                 'MST' => -25200,
13039                 'MUT' => 14400,
13040                 'MVT' => 18000,
13041                 'MYT' => 28800,
13042                 'NCT' => 39600,
13043                 'NDT' => -9000,
13044                 'NFT' => 41400,
13045                 'NMIT' => 36000,
13046                 'NOVST' => 25200,
13047                 'NOVT' => 21600,
13048                 'NPT' => 20700,
13049                 'NRT' => 43200,
13050                 'NST' => -12600,
13051                 'NUT' => -39600,
13052                 'NZDT' => 46800,
13053                 'NZST' => 43200,
13054                 'OMSST' => 25200,
13055                 'OMST' => 21600,
13056                 'PDT' => -25200,
13057                 'PET' => -18000,
13058                 'PETST' => 46800,
13059                 'PETT' => 43200,
13060                 'PGT' => 36000,
13061                 'PHOT' => 46800,
13062                 'PHT' => 28800,
13063                 'PKT' => 18000,
13064                 'PMDT' => -7200,
13065                 'PMST' => -10800,
13066                 'PONT' => 39600,
13067                 'PST' => -28800,
13068                 'PWT' => 32400,
13069                 'PYST' => -10800,
13070                 'PYT' => -14400,
13071                 'RET' => 14400,
13072                 'ROTT' => -10800,
13073                 'SAMST' => 18000,
13074                 'SAMT' => 14400,
13075                 'SAST' => 7200,
13076                 'SBT' => 39600,
13077                 'SCDT' => 46800,
13078                 'SCST' => 43200,
13079                 'SCT' => 14400,
13080                 'SEST' => 3600,
13081                 'SGT' => 28800,
13082                 'SIT' => 28800,
13083                 'SRT' => -10800,
13084                 'SST' => -39600,
13085                 'SYST' => 10800,
13086                 'SYT' => 7200,
13087                 'TFT' => 18000,
13088                 'THAT' => -36000,
13089                 'TJT' => 18000,
13090                 'TKT' => -36000,
13091                 'TMT' => 18000,
13092                 'TOT' => 46800,
13093                 'TPT' => 32400,
13094                 'TRUT' => 36000,
13095                 'TVT' => 43200,
13096                 'TWT' => 28800,
13097                 'UYST' => -7200,
13098                 'UYT' => -10800,
13099                 'UZT' => 18000,
13100                 'VET' => -14400,
13101                 'VLAST' => 39600,
13102                 'VLAT' => 36000,
13103                 'VOST' => 21600,
13104                 'VUT' => 39600,
13105                 'WAST' => 7200,
13106                 'WAT' => 3600,
13107                 'WDT' => 32400,
13108                 'WEST' => 3600,
13109                 'WFT' => 43200,
13110                 'WIB' => 25200,
13111                 'WIT' => 32400,
13112                 'WITA' => 28800,
13113                 'WKST' => 18000,
13114                 'WST' => 28800,
13115                 'YAKST' => 36000,
13116                 'YAKT' => 32400,
13117                 'YAPT' => 36000,
13118                 'YEKST' => 21600,
13119                 'YEKT' => 18000,
13120         );
13121
13122         /**
13123          * Cached PCRE for SimplePie_Parse_Date::$day
13124          *
13125          * @access protected
13126          * @var string
13127          */
13128         var $day_pcre;
13129
13130         /**
13131          * Cached PCRE for SimplePie_Parse_Date::$month
13132          *
13133          * @access protected
13134          * @var string
13135          */
13136         var $month_pcre;
13137
13138         /**
13139          * Array of user-added callback methods
13140          *
13141          * @access private
13142          * @var array
13143          */
13144         var $built_in = array();
13145
13146         /**
13147          * Array of user-added callback methods
13148          *
13149          * @access private
13150          * @var array
13151          */
13152         var $user = array();
13153
13154         /**
13155          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13156          * self::month_pcre, and self::built_in
13157          *
13158          * @access private
13159          */
13160         function SimplePie_Parse_Date()
13161         {
13162                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13163                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13164
13165                 static $cache;
13166                 if (!isset($cache[get_class($this)]))
13167                 {
13168                         $all_methods = get_class_methods($this);
13169
13170                         foreach ($all_methods as $method)
13171                         {
13172                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13173                                 {
13174                                         $cache[get_class($this)][] = $method;
13175                                 }
13176                         }
13177                 }
13178
13179                 foreach ($cache[get_class($this)] as $method)
13180                 {
13181                         $this->built_in[] = $method;
13182                 }
13183         }
13184
13185         /**
13186          * Get the object
13187          *
13188          * @access public
13189          */
13190         function get()
13191         {
13192                 static $object;
13193                 if (!$object)
13194                 {
13195                         $object = new SimplePie_Parse_Date;
13196                 }
13197                 return $object;
13198         }
13199
13200         /**
13201          * Parse a date
13202          *
13203          * @final
13204          * @access public
13205          * @param string $date Date to parse
13206          * @return int Timestamp corresponding to date string, or false on failure
13207          */
13208         function parse($date)
13209         {
13210                 foreach ($this->user as $method)
13211                 {
13212                         if (($returned = call_user_func($method, $date)) !== false)
13213                         {
13214                                 return $returned;
13215                         }
13216                 }
13217
13218                 foreach ($this->built_in as $method)
13219                 {
13220                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13221                         {
13222                                 return $returned;
13223                         }
13224                 }
13225
13226                 return false;
13227         }
13228
13229         /**
13230          * Add a callback method to parse a date
13231          *
13232          * @final
13233          * @access public
13234          * @param callback $callback
13235          */
13236         function add_callback($callback)
13237         {
13238                 if (is_callable($callback))
13239                 {
13240                         $this->user[] = $callback;
13241                 }
13242                 else
13243                 {
13244                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13245                 }
13246         }
13247
13248         /**
13249          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13250          * well as allowing any of upper or lower case "T", horizontal tabs, or
13251          * spaces to be used as the time seperator (including more than one))
13252          *
13253          * @access protected
13254          * @return int Timestamp
13255          */
13256         function date_w3cdtf($date)
13257         {
13258                 static $pcre;
13259                 if (!$pcre)
13260                 {
13261                         $year = '([0-9]{4})';
13262                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13263                         $decimal = '([0-9]*)';
13264                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13265                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13266                 }
13267                 if (preg_match($pcre, $date, $match))
13268                 {
13269                         /*
13270                         Capturing subpatterns:
13271                         1: Year
13272                         2: Month
13273                         3: Day
13274                         4: Hour
13275                         5: Minute
13276                         6: Second
13277                         7: Decimal fraction of a second
13278                         8: Zulu
13279                         9: Timezone ±
13280                         10: Timezone hours
13281                         11: Timezone minutes
13282                         */
13283
13284                         // Fill in empty matches
13285                         for ($i = count($match); $i <= 3; $i++)
13286                         {
13287                                 $match[$i] = '1';
13288                         }
13289
13290                         for ($i = count($match); $i <= 7; $i++)
13291                         {
13292                                 $match[$i] = '0';
13293                         }
13294
13295                         // Numeric timezone
13296                         if (isset($match[9]) && $match[9] !== '')
13297                         {
13298                                 $timezone = $match[10] * 3600;
13299                                 $timezone += $match[11] * 60;
13300                                 if ($match[9] === '-')
13301                                 {
13302                                         $timezone = 0 - $timezone;
13303                                 }
13304                         }
13305                         else
13306                         {
13307                                 $timezone = 0;
13308                         }
13309
13310                         // Convert the number of seconds to an integer, taking decimals into account
13311                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13312
13313                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13314                 }
13315                 else
13316                 {
13317                         return false;
13318                 }
13319         }
13320
13321         /**
13322          * Remove RFC822 comments
13323          *
13324          * @access protected
13325          * @param string $data Data to strip comments from
13326          * @return string Comment stripped string
13327          */
13328         function remove_rfc2822_comments($string)
13329         {
13330                 $string = (string) $string;
13331                 $position = 0;
13332                 $length = strlen($string);
13333                 $depth = 0;
13334
13335                 $output = '';
13336
13337                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13338                 {
13339                         $output .= substr($string, $position, $pos - $position);
13340                         $position = $pos + 1;
13341                         if ($string[$pos - 1] !== '\\')
13342                         {
13343                                 $depth++;
13344                                 while ($depth && $position < $length)
13345                                 {
13346                                         $position += strcspn($string, '()', $position);
13347                                         if ($string[$position - 1] === '\\')
13348                                         {
13349                                                 $position++;
13350                                                 continue;
13351                                         }
13352                                         elseif (isset($string[$position]))
13353                                         {
13354                                                 switch ($string[$position])
13355                                                 {
13356                                                         case '(':
13357                                                                 $depth++;
13358                                                                 break;
13359
13360                                                         case ')':
13361                                                                 $depth--;
13362                                                                 break;
13363                                                 }
13364                                                 $position++;
13365                                         }
13366                                         else
13367                                         {
13368                                                 break;
13369                                         }
13370                                 }
13371                         }
13372                         else
13373                         {
13374                                 $output .= '(';
13375                         }
13376                 }
13377                 $output .= substr($string, $position);
13378
13379                 return $output;
13380         }
13381
13382         /**
13383          * Parse RFC2822's date format
13384          *
13385          * @access protected
13386          * @return int Timestamp
13387          */
13388         function date_rfc2822($date)
13389         {
13390                 static $pcre;
13391                 if (!$pcre)
13392                 {
13393                         $wsp = '[\x09\x20]';
13394                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13395                         $optional_fws = $fws . '?';
13396                         $day_name = $this->day_pcre;
13397                         $month = $this->month_pcre;
13398                         $day = '([0-9]{1,2})';
13399                         $hour = $minute = $second = '([0-9]{2})';
13400                         $year = '([0-9]{2,4})';
13401                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13402                         $character_zone = '([A-Z]{1,5})';
13403                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13404                         $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';
13405                 }
13406                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13407                 {
13408                         /*
13409                         Capturing subpatterns:
13410                         1: Day name
13411                         2: Day
13412                         3: Month
13413                         4: Year
13414                         5: Hour
13415                         6: Minute
13416                         7: Second
13417                         8: Timezone ±
13418                         9: Timezone hours
13419                         10: Timezone minutes
13420                         11: Alphabetic timezone
13421                         */
13422
13423                         // Find the month number
13424                         $month = $this->month[strtolower($match[3])];
13425
13426                         // Numeric timezone
13427                         if ($match[8] !== '')
13428                         {
13429                                 $timezone = $match[9] * 3600;
13430                                 $timezone += $match[10] * 60;
13431                                 if ($match[8] === '-')
13432                                 {
13433                                         $timezone = 0 - $timezone;
13434                                 }
13435                         }
13436                         // Character timezone
13437                         elseif (isset($this->timezone[strtoupper($match[11])]))
13438                         {
13439                                 $timezone = $this->timezone[strtoupper($match[11])];
13440                         }
13441                         // Assume everything else to be -0000
13442                         else
13443                         {
13444                                 $timezone = 0;
13445                         }
13446
13447                         // Deal with 2/3 digit years
13448                         if ($match[4] < 50)
13449                         {
13450                                 $match[4] += 2000;
13451                         }
13452                         elseif ($match[4] < 1000)
13453                         {
13454                                 $match[4] += 1900;
13455                         }
13456
13457                         // Second is optional, if it is empty set it to zero
13458                         if ($match[7] !== '')
13459                         {
13460                                 $second = $match[7];
13461                         }
13462                         else
13463                         {
13464                                 $second = 0;
13465                         }
13466
13467                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13468                 }
13469                 else
13470                 {
13471                         return false;
13472                 }
13473         }
13474
13475         /**
13476          * Parse RFC850's date format
13477          *
13478          * @access protected
13479          * @return int Timestamp
13480          */
13481         function date_rfc850($date)
13482         {
13483                 static $pcre;
13484                 if (!$pcre)
13485                 {
13486                         $space = '[\x09\x20]+';
13487                         $day_name = $this->day_pcre;
13488                         $month = $this->month_pcre;
13489                         $day = '([0-9]{1,2})';
13490                         $year = $hour = $minute = $second = '([0-9]{2})';
13491                         $zone = '([A-Z]{1,5})';
13492                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13493                 }
13494                 if (preg_match($pcre, $date, $match))
13495                 {
13496                         /*
13497                         Capturing subpatterns:
13498                         1: Day name
13499                         2: Day
13500                         3: Month
13501                         4: Year
13502                         5: Hour
13503                         6: Minute
13504                         7: Second
13505                         8: Timezone
13506                         */
13507
13508                         // Month
13509                         $month = $this->month[strtolower($match[3])];
13510
13511                         // Character timezone
13512                         if (isset($this->timezone[strtoupper($match[8])]))
13513                         {
13514                                 $timezone = $this->timezone[strtoupper($match[8])];
13515                         }
13516                         // Assume everything else to be -0000
13517                         else
13518                         {
13519                                 $timezone = 0;
13520                         }
13521
13522                         // Deal with 2 digit year
13523                         if ($match[4] < 50)
13524                         {
13525                                 $match[4] += 2000;
13526                         }
13527                         else
13528                         {
13529                                 $match[4] += 1900;
13530                         }
13531
13532                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13533                 }
13534                 else
13535                 {
13536                         return false;
13537                 }
13538         }
13539
13540         /**
13541          * Parse C99's asctime()'s date format
13542          *
13543          * @access protected
13544          * @return int Timestamp
13545          */
13546         function date_asctime($date)
13547         {
13548                 static $pcre;
13549                 if (!$pcre)
13550                 {
13551                         $space = '[\x09\x20]+';
13552                         $wday_name = $this->day_pcre;
13553                         $mon_name = $this->month_pcre;
13554                         $day = '([0-9]{1,2})';
13555                         $hour = $sec = $min = '([0-9]{2})';
13556                         $year = '([0-9]{4})';
13557                         $terminator = '\x0A?\x00?';
13558                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13559                 }
13560                 if (preg_match($pcre, $date, $match))
13561                 {
13562                         /*
13563                         Capturing subpatterns:
13564                         1: Day name
13565                         2: Month
13566                         3: Day
13567                         4: Hour
13568                         5: Minute
13569                         6: Second
13570                         7: Year
13571                         */
13572
13573                         $month = $this->month[strtolower($match[2])];
13574                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13575                 }
13576                 else
13577                 {
13578                         return false;
13579                 }
13580         }
13581
13582         /**
13583          * Parse dates using strtotime()
13584          *
13585          * @access protected
13586          * @return int Timestamp
13587          */
13588         function date_strtotime($date)
13589         {
13590                 $strtotime = strtotime($date);
13591                 if ($strtotime === -1 || $strtotime === false)
13592                 {
13593                         return false;
13594                 }
13595                 else
13596                 {
13597                         return $strtotime;
13598                 }
13599         }
13600 }
13601
13602 /**
13603  * Content-type sniffing
13604  *
13605  * @package SimplePie
13606  */
13607 class SimplePie_Content_Type_Sniffer
13608 {
13609         /**
13610          * File object
13611          *
13612          * @var SimplePie_File
13613          * @access private
13614          */
13615         var $file;
13616
13617         /**
13618          * Create an instance of the class with the input file
13619          *
13620          * @access public
13621          * @param SimplePie_Content_Type_Sniffer $file Input file
13622          */
13623         function SimplePie_Content_Type_Sniffer($file)
13624         {
13625                 $this->file = $file;
13626         }
13627
13628         /**
13629          * Get the Content-Type of the specified file
13630          *
13631          * @access public
13632          * @return string Actual Content-Type
13633          */
13634         function get_type()
13635         {
13636                 if (isset($this->file->headers['content-type']))
13637                 {
13638                         if (!isset($this->file->headers['content-encoding'])
13639                                 && ($this->file->headers['content-type'] === 'text/plain'
13640                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13641                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13642                         {
13643                                 return $this->text_or_binary();
13644                         }
13645
13646                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13647                         {
13648                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13649                         }
13650                         else
13651                         {
13652                                 $official = $this->file->headers['content-type'];
13653                         }
13654                         $official = strtolower($official);
13655
13656                         if ($official === 'unknown/unknown'
13657                                 || $official === 'application/unknown')
13658                         {
13659                                 return $this->unknown();
13660                         }
13661                         elseif (substr($official, -4) === '+xml'
13662                                 || $official === 'text/xml'
13663                                 || $official === 'application/xml')
13664                         {
13665                                 return $official;
13666                         }
13667                         elseif (substr($official, 0, 6) === 'image/')
13668                         {
13669                                 if ($return = $this->image())
13670                                 {
13671                                         return $return;
13672                                 }
13673                                 else
13674                                 {
13675                                         return $official;
13676                                 }
13677                         }
13678                         elseif ($official === 'text/html')
13679                         {
13680                                 return $this->feed_or_html();
13681                         }
13682                         else
13683                         {
13684                                 return $official;
13685                         }
13686                 }
13687                 else
13688                 {
13689                         return $this->unknown();
13690                 }
13691         }
13692
13693         /**
13694          * Sniff text or binary
13695          *
13696          * @access private
13697          * @return string Actual Content-Type
13698          */
13699         function text_or_binary()
13700         {
13701                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13702                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13703                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13704                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13705                 {
13706                         return 'text/plain';
13707                 }
13708                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13709                 {
13710                         return 'application/octect-stream';
13711                 }
13712                 else
13713                 {
13714                         return 'text/plain';
13715                 }
13716         }
13717
13718         /**
13719          * Sniff unknown
13720          *
13721          * @access private
13722          * @return string Actual Content-Type
13723          */
13724         function unknown()
13725         {
13726                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13727                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13728                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13729                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13730                 {
13731                         return 'text/html';
13732                 }
13733                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13734                 {
13735                         return 'application/pdf';
13736                 }
13737                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13738                 {
13739                         return 'application/postscript';
13740                 }
13741                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13742                         || substr($this->file->body, 0, 6) === 'GIF89a')
13743                 {
13744                         return 'image/gif';
13745                 }
13746                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13747                 {
13748                         return 'image/png';
13749                 }
13750                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13751                 {
13752                         return 'image/jpeg';
13753                 }
13754                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13755                 {
13756                         return 'image/bmp';
13757                 }
13758                 else
13759                 {
13760                         return $this->text_or_binary();
13761                 }
13762         }
13763
13764         /**
13765          * Sniff images
13766          *
13767          * @access private
13768          * @return string Actual Content-Type
13769          */
13770         function image()
13771         {
13772                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13773                         || substr($this->file->body, 0, 6) === 'GIF89a')
13774                 {
13775                         return 'image/gif';
13776                 }
13777                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13778                 {
13779                         return 'image/png';
13780                 }
13781                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13782                 {
13783                         return 'image/jpeg';
13784                 }
13785                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13786                 {
13787                         return 'image/bmp';
13788                 }
13789                 else
13790                 {
13791                         return false;
13792                 }
13793         }
13794
13795         /**
13796          * Sniff HTML
13797          *
13798          * @access private
13799          * @return string Actual Content-Type
13800          */
13801         function feed_or_html()
13802         {
13803                 $len = strlen($this->file->body);
13804                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13805
13806                 while ($pos < $len)
13807                 {
13808                         switch ($this->file->body[$pos])
13809                         {
13810                                 case "\x09":
13811                                 case "\x0A":
13812                                 case "\x0D":
13813                                 case "\x20":
13814                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13815                                         continue 2;
13816
13817                                 case '<':
13818                                         $pos++;
13819                                         break;
13820
13821                                 default:
13822                                         return 'text/html';
13823                         }
13824
13825                         if (substr($this->file->body, $pos, 3) === '!--')
13826                         {
13827                                 $pos += 3;
13828                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13829                                 {
13830                                         $pos += 3;
13831                                 }
13832                                 else
13833                                 {
13834                                         return 'text/html';
13835                                 }
13836                         }
13837                         elseif (substr($this->file->body, $pos, 1) === '!')
13838                         {
13839                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13840                                 {
13841                                         $pos++;
13842                                 }
13843                                 else
13844                                 {
13845                                         return 'text/html';
13846                                 }
13847                         }
13848                         elseif (substr($this->file->body, $pos, 1) === '?')
13849                         {
13850                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13851                                 {
13852                                         $pos += 2;
13853                                 }
13854                                 else
13855                                 {
13856                                         return 'text/html';
13857                                 }
13858                         }
13859                         elseif (substr($this->file->body, $pos, 3) === 'rss'
13860                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13861                         {
13862                                 return 'application/rss+xml';
13863                         }
13864                         elseif (substr($this->file->body, $pos, 4) === 'feed')
13865                         {
13866                                 return 'application/atom+xml';
13867                         }
13868                         else
13869                         {
13870                                 return 'text/html';
13871                         }
13872                 }
13873
13874                 return 'text/html';
13875         }
13876 }
13877
13878 /**
13879  * Parses the XML Declaration
13880  *
13881  * @package SimplePie
13882  */
13883 class SimplePie_XML_Declaration_Parser
13884 {
13885         /**
13886          * XML Version
13887          *
13888          * @access public
13889          * @var string
13890          */
13891         var $version = '1.0';
13892
13893         /**
13894          * Encoding
13895          *
13896          * @access public
13897          * @var string
13898          */
13899         var $encoding = 'UTF-8';
13900
13901         /**
13902          * Standalone
13903          *
13904          * @access public
13905          * @var bool
13906          */
13907         var $standalone = false;
13908
13909         /**
13910          * Current state of the state machine
13911          *
13912          * @access private
13913          * @var string
13914          */
13915         var $state = 'before_version_name';
13916
13917         /**
13918          * Input data
13919          *
13920          * @access private
13921          * @var string
13922          */
13923         var $data = '';
13924
13925         /**
13926          * Input data length (to avoid calling strlen() everytime this is needed)
13927          *
13928          * @access private
13929          * @var int
13930          */
13931         var $data_length = 0;
13932
13933         /**
13934          * Current position of the pointer
13935          *
13936          * @var int
13937          * @access private
13938          */
13939         var $position = 0;
13940
13941         /**
13942          * Create an instance of the class with the input data
13943          *
13944          * @access public
13945          * @param string $data Input data
13946          */
13947         function SimplePie_XML_Declaration_Parser($data)
13948         {
13949                 $this->data = $data;
13950                 $this->data_length = strlen($this->data);
13951         }
13952
13953         /**
13954          * Parse the input data
13955          *
13956          * @access public
13957          * @return bool true on success, false on failure
13958          */
13959         function parse()
13960         {
13961                 while ($this->state && $this->state !== 'emit' && $this->has_data())
13962                 {
13963                         $state = $this->state;
13964                         $this->$state();
13965                 }
13966                 $this->data = '';
13967                 if ($this->state === 'emit')
13968                 {
13969                         return true;
13970                 }
13971                 else
13972                 {
13973                         $this->version = '';
13974                         $this->encoding = '';
13975                         $this->standalone = '';
13976                         return false;
13977                 }
13978         }
13979
13980         /**
13981          * Check whether there is data beyond the pointer
13982          *
13983          * @access private
13984          * @return bool true if there is further data, false if not
13985          */
13986         function has_data()
13987         {
13988                 return (bool) ($this->position < $this->data_length);
13989         }
13990
13991         /**
13992          * Advance past any whitespace
13993          *
13994          * @return int Number of whitespace characters passed
13995          */
13996         function skip_whitespace()
13997         {
13998                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13999                 $this->position += $whitespace;
14000                 return $whitespace;
14001         }
14002
14003         /**
14004          * Read value
14005          */
14006         function get_value()
14007         {
14008                 $quote = substr($this->data, $this->position, 1);
14009                 if ($quote === '"' || $quote === "'")
14010                 {
14011                         $this->position++;
14012                         $len = strcspn($this->data, $quote, $this->position);
14013                         if ($this->has_data())
14014                         {
14015                                 $value = substr($this->data, $this->position, $len);
14016                                 $this->position += $len + 1;
14017                                 return $value;
14018                         }
14019                 }
14020                 return false;
14021         }
14022
14023         function before_version_name()
14024         {
14025                 if ($this->skip_whitespace())
14026                 {
14027                         $this->state = 'version_name';
14028                 }
14029                 else
14030                 {
14031                         $this->state = false;
14032                 }
14033         }
14034
14035         function version_name()
14036         {
14037                 if (substr($this->data, $this->position, 7) === 'version')
14038                 {
14039                         $this->position += 7;
14040                         $this->skip_whitespace();
14041                         $this->state = 'version_equals';
14042                 }
14043                 else
14044                 {
14045                         $this->state = false;
14046                 }
14047         }
14048
14049         function version_equals()
14050         {
14051                 if (substr($this->data, $this->position, 1) === '=')
14052                 {
14053                         $this->position++;
14054                         $this->skip_whitespace();
14055                         $this->state = 'version_value';
14056                 }
14057                 else
14058                 {
14059                         $this->state = false;
14060                 }
14061         }
14062
14063         function version_value()
14064         {
14065                 if ($this->version = $this->get_value())
14066                 {
14067                         $this->skip_whitespace();
14068                         if ($this->has_data())
14069                         {
14070                                 $this->state = 'encoding_name';
14071                         }
14072                         else
14073                         {
14074                                 $this->state = 'emit';
14075                         }
14076                 }
14077                 else
14078                 {
14079                         $this->state = false;
14080                 }
14081         }
14082
14083         function encoding_name()
14084         {
14085                 if (substr($this->data, $this->position, 8) === 'encoding')
14086                 {
14087                         $this->position += 8;
14088                         $this->skip_whitespace();
14089                         $this->state = 'encoding_equals';
14090                 }
14091                 else
14092                 {
14093                         $this->state = 'standalone_name';
14094                 }
14095         }
14096
14097         function encoding_equals()
14098         {
14099                 if (substr($this->data, $this->position, 1) === '=')
14100                 {
14101                         $this->position++;
14102                         $this->skip_whitespace();
14103                         $this->state = 'encoding_value';
14104                 }
14105                 else
14106                 {
14107                         $this->state = false;
14108                 }
14109         }
14110
14111         function encoding_value()
14112         {
14113                 if ($this->encoding = $this->get_value())
14114                 {
14115                         $this->skip_whitespace();
14116                         if ($this->has_data())
14117                         {
14118                                 $this->state = 'standalone_name';
14119                         }
14120                         else
14121                         {
14122                                 $this->state = 'emit';
14123                         }
14124                 }
14125                 else
14126                 {
14127                         $this->state = false;
14128                 }
14129         }
14130
14131         function standalone_name()
14132         {
14133                 if (substr($this->data, $this->position, 10) === 'standalone')
14134                 {
14135                         $this->position += 10;
14136                         $this->skip_whitespace();
14137                         $this->state = 'standalone_equals';
14138                 }
14139                 else
14140                 {
14141                         $this->state = false;
14142                 }
14143         }
14144
14145         function standalone_equals()
14146         {
14147                 if (substr($this->data, $this->position, 1) === '=')
14148                 {
14149                         $this->position++;
14150                         $this->skip_whitespace();
14151                         $this->state = 'standalone_value';
14152                 }
14153                 else
14154                 {
14155                         $this->state = false;
14156                 }
14157         }
14158
14159         function standalone_value()
14160         {
14161                 if ($standalone = $this->get_value())
14162                 {
14163                         switch ($standalone)
14164                         {
14165                                 case 'yes':
14166                                         $this->standalone = true;
14167                                         break;
14168
14169                                 case 'no':
14170                                         $this->standalone = false;
14171                                         break;
14172
14173                                 default:
14174                                         $this->state = false;
14175                                         return;
14176                         }
14177
14178                         $this->skip_whitespace();
14179                         if ($this->has_data())
14180                         {
14181                                 $this->state = false;
14182                         }
14183                         else
14184                         {
14185                                 $this->state = 'emit';
14186                         }
14187                 }
14188                 else
14189                 {
14190                         $this->state = false;
14191                 }
14192         }
14193 }
14194
14195 class SimplePie_Locator
14196 {
14197         var $useragent;
14198         var $timeout;
14199         var $file;
14200         var $local = array();
14201         var $elsewhere = array();
14202         var $file_class = 'SimplePie_File';
14203         var $cached_entities = array();
14204         var $http_base;
14205         var $base;
14206         var $base_location = 0;
14207         var $checked_feeds = 0;
14208         var $max_checked_feeds = 10;
14209         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14210
14211         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14212         {
14213                 $this->file =& $file;
14214                 $this->file_class = $file_class;
14215                 $this->useragent = $useragent;
14216                 $this->timeout = $timeout;
14217                 $this->max_checked_feeds = $max_checked_feeds;
14218                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14219         }
14220
14221         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14222         {
14223                 if ($this->is_feed($this->file))
14224                 {
14225                         return $this->file;
14226                 }
14227
14228                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14229                 {
14230                         $sniffer = new $this->content_type_sniffer_class($this->file);
14231                         if ($sniffer->get_type() !== 'text/html')
14232                         {
14233                                 return null;
14234                         }
14235                 }
14236
14237                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14238                 {
14239                         $this->get_base();
14240                 }
14241
14242                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14243                 {
14244                         return $working[0];
14245                 }
14246
14247                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14248                 {
14249                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14250                         {
14251                                 return $working;
14252                         }
14253
14254                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14255                         {
14256                                 return $working;
14257                         }
14258
14259                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14260                         {
14261                                 return $working;
14262                         }
14263
14264                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14265                         {
14266                                 return $working;
14267                         }
14268                 }
14269                 return null;
14270         }
14271
14272         function is_feed(&$file)
14273         {
14274                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14275                 {
14276                         $sniffer = new $this->content_type_sniffer_class($file);
14277                         $sniffed = $sniffer->get_type();
14278                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14279                         {
14280                                 return true;
14281                         }
14282                         else
14283                         {
14284                                 return false;
14285                         }
14286                 }
14287                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14288                 {
14289                         return true;
14290                 }
14291                 else
14292                 {
14293                         return false;
14294                 }
14295         }
14296
14297         function get_base()
14298         {
14299                 $this->http_base = $this->file->url;
14300                 $this->base = $this->http_base;
14301                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14302                 foreach ($elements as $element)
14303                 {
14304                         if ($element['attribs']['href']['data'] !== '')
14305                         {
14306                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14307                                 $this->base_location = $element['offset'];
14308                                 break;
14309                         }
14310                 }
14311         }
14312
14313         function autodiscovery()
14314         {
14315                 $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));
14316                 $done = array();
14317                 $feeds = array();
14318                 foreach ($links as $link)
14319                 {
14320                         if ($this->checked_feeds === $this->max_checked_feeds)
14321                         {
14322                                 break;
14323                         }
14324                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14325                         {
14326                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14327
14328                                 if ($this->base_location < $link['offset'])
14329                                 {
14330                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14331                                 }
14332                                 else
14333                                 {
14334                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14335                                 }
14336
14337                                 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]))
14338                                 {
14339                                         $this->checked_feeds++;
14340                                         $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14341                                         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))
14342                                         {
14343                                                 $feeds[$href] = $feed;
14344                                         }
14345                                 }
14346                                 $done[] = $href;
14347                         }
14348                 }
14349
14350                 if (!empty($feeds))
14351                 {
14352                         return array_values($feeds);
14353                 }
14354                 else {
14355                         return null;
14356                 }
14357         }
14358
14359         function get_links()
14360         {
14361                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14362                 foreach ($links as $link)
14363                 {
14364                         if (isset($link['attribs']['href']['data']))
14365                         {
14366                                 $href = trim($link['attribs']['href']['data']);
14367                                 $parsed = SimplePie_Misc::parse_url($href);
14368                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14369                                 {
14370                                         if ($this->base_location < $link['offset'])
14371                                         {
14372                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14373                                         }
14374                                         else
14375                                         {
14376                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14377                                         }
14378
14379                                         $current = SimplePie_Misc::parse_url($this->file->url);
14380
14381                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14382                                         {
14383                                                 $this->local[] = $href;
14384                                         }
14385                                         else
14386                                         {
14387                                                 $this->elsewhere[] = $href;
14388                                         }
14389                                 }
14390                         }
14391                 }
14392                 $this->local = array_unique($this->local);
14393                 $this->elsewhere = array_unique($this->elsewhere);
14394                 if (!empty($this->local) || !empty($this->elsewhere))
14395                 {
14396                         return true;
14397                 }
14398                 return null;
14399         }
14400
14401         function extension(&$array)
14402         {
14403                 foreach ($array as $key => $value)
14404                 {
14405                         if ($this->checked_feeds === $this->max_checked_feeds)
14406                         {
14407                                 break;
14408                         }
14409                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14410                         {
14411                                 $this->checked_feeds++;
14412                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14413                                 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))
14414                                 {
14415                                         return $feed;
14416                                 }
14417                                 else
14418                                 {
14419                                         unset($array[$key]);
14420                                 }
14421                         }
14422                 }
14423                 return null;
14424         }
14425
14426         function body(&$array)
14427         {
14428                 foreach ($array as $key => $value)
14429                 {
14430                         if ($this->checked_feeds === $this->max_checked_feeds)
14431                         {
14432                                 break;
14433                         }
14434                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14435                         {
14436                                 $this->checked_feeds++;
14437                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14438                                 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))
14439                                 {
14440                                         return $feed;
14441                                 }
14442                                 else
14443                                 {
14444                                         unset($array[$key]);
14445                                 }
14446                         }
14447                 }
14448                 return null;
14449         }
14450 }
14451
14452 class SimplePie_Parser
14453 {
14454         var $error_code;
14455         var $error_string;
14456         var $current_line;
14457         var $current_column;
14458         var $current_byte;
14459         var $separator = ' ';
14460         var $namespace = array('');
14461         var $element = array('');
14462         var $xml_base = array('');
14463         var $xml_base_explicit = array(false);
14464         var $xml_lang = array('');
14465         var $data = array();
14466         var $datas = array(array());
14467         var $current_xhtml_construct = -1;
14468         var $encoding;
14469
14470         function parse(&$data, $encoding)
14471         {
14472                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14473                 if (strtoupper($encoding) === 'US-ASCII')
14474                 {
14475                         $this->encoding = 'UTF-8';
14476                 }
14477                 else
14478                 {
14479                         $this->encoding = $encoding;
14480                 }
14481
14482                 // Strip BOM:
14483                 // UTF-32 Big Endian BOM
14484                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14485                 {
14486                         $data = substr($data, 4);
14487                 }
14488                 // UTF-32 Little Endian BOM
14489                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14490                 {
14491                         $data = substr($data, 4);
14492                 }
14493                 // UTF-16 Big Endian BOM
14494                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14495                 {
14496                         $data = substr($data, 2);
14497                 }
14498                 // UTF-16 Little Endian BOM
14499                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14500                 {
14501                         $data = substr($data, 2);
14502                 }
14503                 // UTF-8 BOM
14504                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14505                 {
14506                         $data = substr($data, 3);
14507                 }
14508
14509                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14510                 {
14511                         $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14512                         if ($declaration->parse())
14513                         {
14514                                 $data = substr($data, $pos + 2);
14515                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14516                         }
14517                         else
14518                         {
14519                                 $this->error_string = 'SimplePie bug! Please report this!';
14520                                 return false;
14521                         }
14522                 }
14523
14524                 $return = true;
14525
14526                 static $xml_is_sane = null;
14527                 if ($xml_is_sane === null)
14528                 {
14529                         $parser_check = xml_parser_create();
14530                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14531                         xml_parser_free($parser_check);
14532                         $xml_is_sane = isset($values[0]['value']);
14533                 }
14534
14535                 // Create the parser
14536                 if ($xml_is_sane)
14537                 {
14538                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14539                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14540                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14541                         xml_set_object($xml, $this);
14542                         xml_set_character_data_handler($xml, 'cdata');
14543                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14544
14545                         // Parse!
14546                         if (!xml_parse($xml, $data, true))
14547                         {
14548                                 $this->error_code = xml_get_error_code($xml);
14549                                 $this->error_string = xml_error_string($this->error_code);
14550                                 $return = false;
14551                         }
14552                         $this->current_line = xml_get_current_line_number($xml);
14553                         $this->current_column = xml_get_current_column_number($xml);
14554                         $this->current_byte = xml_get_current_byte_index($xml);
14555                         xml_parser_free($xml);
14556                         return $return;
14557                 }
14558                 else
14559                 {
14560                         libxml_clear_errors();
14561                         $xml = new XMLReader();
14562                         $xml->xml($data);
14563                         while (@$xml->read())
14564                         {
14565                                 switch ($xml->nodeType)
14566                                 {
14567
14568                                         case constant('XMLReader::END_ELEMENT'):
14569                                                 if ($xml->namespaceURI !== '')
14570                                                 {
14571                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14572                                                 }
14573                                                 else
14574                                                 {
14575                                                         $tagName = $xml->localName;
14576                                                 }
14577                                                 $this->tag_close(null, $tagName);
14578                                                 break;
14579                                         case constant('XMLReader::ELEMENT'):
14580                                                 $empty = $xml->isEmptyElement;
14581                                                 if ($xml->namespaceURI !== '')
14582                                                 {
14583                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14584                                                 }
14585                                                 else
14586                                                 {
14587                                                         $tagName = $xml->localName;
14588                                                 }
14589                                                 $attributes = array();
14590                                                 while ($xml->moveToNextAttribute())
14591                                                 {
14592                                                         if ($xml->namespaceURI !== '')
14593                                                         {
14594                                                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14595                                                         }
14596                                                         else
14597                                                         {
14598                                                                 $attrName = $xml->localName;
14599                                                         }
14600                                                         $attributes[$attrName] = $xml->value;
14601                                                 }
14602                                                 $this->tag_open(null, $tagName, $attributes);
14603                                                 if ($empty)
14604                                                 {
14605                                                         $this->tag_close(null, $tagName);
14606                                                 }
14607                                                 break;
14608                                         case constant('XMLReader::TEXT'):
14609
14610                                         case constant('XMLReader::CDATA'):
14611                                                 $this->cdata(null, $xml->value);
14612                                                 break;
14613                                 }
14614                         }
14615                         if ($error = libxml_get_last_error())
14616                         {
14617                                 $this->error_code = $error->code;
14618                                 $this->error_string = $error->message;
14619                                 $this->current_line = $error->line;
14620                                 $this->current_column = $error->column;
14621                                 return false;
14622                         }
14623                         else
14624                         {
14625                                 return true;
14626                         }
14627                 }
14628         }
14629
14630         function get_error_code()
14631         {
14632                 return $this->error_code;
14633         }
14634
14635         function get_error_string()
14636         {
14637                 return $this->error_string;
14638         }
14639
14640         function get_current_line()
14641         {
14642                 return $this->current_line;
14643         }
14644
14645         function get_current_column()
14646         {
14647                 return $this->current_column;
14648         }
14649
14650         function get_current_byte()
14651         {
14652                 return $this->current_byte;
14653         }
14654
14655         function get_data()
14656         {
14657                 return $this->data;
14658         }
14659
14660         function tag_open($parser, $tag, $attributes)
14661         {
14662                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14663
14664                 $attribs = array();
14665                 foreach ($attributes as $name => $value)
14666                 {
14667                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14668                         $attribs[$attrib_namespace][$attribute] = $value;
14669                 }
14670
14671                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14672                 {
14673                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14674                         $this->xml_base_explicit[] = true;
14675                 }
14676                 else
14677                 {
14678                         $this->xml_base[] = end($this->xml_base);
14679                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14680                 }
14681
14682                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14683                 {
14684                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14685                 }
14686                 else
14687                 {
14688                         $this->xml_lang[] = end($this->xml_lang);
14689                 }
14690
14691                 if ($this->current_xhtml_construct >= 0)
14692                 {
14693                         $this->current_xhtml_construct++;
14694                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14695                         {
14696                                 $this->data['data'] .= '<' . end($this->element);
14697                                 if (isset($attribs['']))
14698                                 {
14699                                         foreach ($attribs[''] as $name => $value)
14700                                         {
14701                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14702                                         }
14703                                 }
14704                                 $this->data['data'] .= '>';
14705                         }
14706                 }
14707                 else
14708                 {
14709                         $this->datas[] =& $this->data;
14710                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14711                         $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));
14712                         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')
14713                         || (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'))
14714                         {
14715                                 $this->current_xhtml_construct = 0;
14716                         }
14717                 }
14718         }
14719
14720         function cdata($parser, $cdata)
14721         {
14722                 if ($this->current_xhtml_construct >= 0)
14723                 {
14724                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14725                 }
14726                 else
14727                 {
14728                         $this->data['data'] .= $cdata;
14729                 }
14730         }
14731
14732         function tag_close($parser, $tag)
14733         {
14734                 if ($this->current_xhtml_construct >= 0)
14735                 {
14736                         $this->current_xhtml_construct--;
14737                         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')))
14738                         {
14739                                 $this->data['data'] .= '</' . end($this->element) . '>';
14740                         }
14741                 }
14742                 if ($this->current_xhtml_construct === -1)
14743                 {
14744                         $this->data =& $this->datas[count($this->datas) - 1];
14745                         array_pop($this->datas);
14746                 }
14747
14748                 array_pop($this->element);
14749                 array_pop($this->namespace);
14750                 array_pop($this->xml_base);
14751                 array_pop($this->xml_base_explicit);
14752                 array_pop($this->xml_lang);
14753         }
14754
14755         function split_ns($string)
14756         {
14757                 static $cache = array();
14758                 if (!isset($cache[$string]))
14759                 {
14760                         if ($pos = strpos($string, $this->separator))
14761                         {
14762                                 static $separator_length;
14763                                 if (!$separator_length)
14764                                 {
14765                                         $separator_length = strlen($this->separator);
14766                                 }
14767                                 $namespace = substr($string, 0, $pos);
14768                                 $local_name = substr($string, $pos + $separator_length);
14769                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14770                                 {
14771                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14772                                 }
14773
14774                                 // Normalize the Media RSS namespaces
14775                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14776                                 {
14777                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14778                                 }
14779                                 $cache[$string] = array($namespace, $local_name);
14780                         }
14781                         else
14782                         {
14783                                 $cache[$string] = array('', $string);
14784                         }
14785                 }
14786                 return $cache[$string];
14787         }
14788 }
14789
14790 /**
14791  * @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
14792  */
14793 class SimplePie_Sanitize
14794 {
14795         // Private vars
14796         var $base;
14797
14798         // Options
14799         var $remove_div = true;
14800         var $image_handler = '';
14801         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14802         var $encode_instead_of_strip = false;
14803         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14804         var $strip_comments = false;
14805         var $output_encoding = 'UTF-8';
14806         var $enable_cache = true;
14807         var $cache_location = './cache';
14808         var $cache_name_function = 'md5';
14809         var $cache_class = 'SimplePie_Cache';
14810         var $file_class = 'SimplePie_File';
14811         var $timeout = 10;
14812         var $useragent = '';
14813         var $force_fsockopen = false;
14814
14815         var $replace_url_attributes = array(
14816                 'a' => 'href',
14817                 'area' => 'href',
14818                 'blockquote' => 'cite',
14819                 'del' => 'cite',
14820                 'form' => 'action',
14821                 'img' => array('longdesc', 'src'),
14822                 'input' => 'src',
14823                 'ins' => 'cite',
14824                 'q' => 'cite'
14825         );
14826
14827         function remove_div($enable = true)
14828         {
14829                 $this->remove_div = (bool) $enable;
14830         }
14831
14832         function set_image_handler($page = false)
14833         {
14834                 if ($page)
14835                 {
14836                         $this->image_handler = (string) $page;
14837                 }
14838                 else
14839                 {
14840                         $this->image_handler = false;
14841                 }
14842         }
14843
14844         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14845         {
14846                 if (isset($enable_cache))
14847                 {
14848                         $this->enable_cache = (bool) $enable_cache;
14849                 }
14850
14851                 if ($cache_location)
14852                 {
14853                         $this->cache_location = (string) $cache_location;
14854                 }
14855
14856                 if ($cache_name_function)
14857                 {
14858                         $this->cache_name_function = (string) $cache_name_function;
14859                 }
14860
14861                 if ($cache_class)
14862                 {
14863                         $this->cache_class = (string) $cache_class;
14864                 }
14865         }
14866
14867         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14868         {
14869                 if ($file_class)
14870                 {
14871                         $this->file_class = (string) $file_class;
14872                 }
14873
14874                 if ($timeout)
14875                 {
14876                         $this->timeout = (string) $timeout;
14877                 }
14878
14879                 if ($useragent)
14880                 {
14881                         $this->useragent = (string) $useragent;
14882                 }
14883
14884                 if ($force_fsockopen)
14885                 {
14886                         $this->force_fsockopen = (string) $force_fsockopen;
14887                 }
14888         }
14889
14890         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14891         {
14892                 if ($tags)
14893                 {
14894                         if (is_array($tags))
14895                         {
14896                                 $this->strip_htmltags = $tags;
14897                         }
14898                         else
14899                         {
14900                                 $this->strip_htmltags = explode(',', $tags);
14901                         }
14902                 }
14903                 else
14904                 {
14905                         $this->strip_htmltags = false;
14906                 }
14907         }
14908
14909         function encode_instead_of_strip($encode = false)
14910         {
14911                 $this->encode_instead_of_strip = (bool) $encode;
14912         }
14913
14914         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14915         {
14916                 if ($attribs)
14917                 {
14918                         if (is_array($attribs))
14919                         {
14920                                 $this->strip_attributes = $attribs;
14921                         }
14922                         else
14923                         {
14924                                 $this->strip_attributes = explode(',', $attribs);
14925                         }
14926                 }
14927                 else
14928                 {
14929                         $this->strip_attributes = false;
14930                 }
14931         }
14932
14933         function strip_comments($strip = false)
14934         {
14935                 $this->strip_comments = (bool) $strip;
14936         }
14937
14938         function set_output_encoding($encoding = 'UTF-8')
14939         {
14940                 $this->output_encoding = (string) $encoding;
14941         }
14942
14943         /**
14944          * Set element/attribute key/value pairs of HTML attributes
14945          * containing URLs that need to be resolved relative to the feed
14946          *
14947          * @access public
14948          * @since 1.0
14949          * @param array $element_attribute Element/attribute key/value pairs
14950          */
14951         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'))
14952         {
14953                 $this->replace_url_attributes = (array) $element_attribute;
14954         }
14955
14956         function sanitize($data, $type, $base = '')
14957         {
14958                 $data = trim($data);
14959                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14960                 {
14961                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14962                         {
14963                                 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))
14964                                 {
14965                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
14966                                 }
14967                                 else
14968                                 {
14969                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14970                                 }
14971                         }
14972
14973                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14974                         {
14975                                 $data = base64_decode($data);
14976                         }
14977
14978                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14979                         {
14980                                 if ($this->remove_div)
14981                                 {
14982                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14983                                         $data = preg_replace('/<\/div>$/', '', $data);
14984                                 }
14985                                 else
14986                                 {
14987                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14988                                 }
14989                         }
14990
14991                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14992                         {
14993                                 // Strip comments
14994                                 if ($this->strip_comments)
14995                                 {
14996                                         $data = SimplePie_Misc::strip_comments($data);
14997                                 }
14998
14999                                 // Strip out HTML tags and attributes that might cause various security problems.
15000                                 // Based on recommendations by Mark Pilgrim at:
15001                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15002                                 if ($this->strip_htmltags)
15003                                 {
15004                                         foreach ($this->strip_htmltags as $tag)
15005                                         {
15006                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15007                                                 while (preg_match($pcre, $data))
15008                                                 {
15009                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15010                                                 }
15011                                         }
15012                                 }
15013
15014                                 if ($this->strip_attributes)
15015                                 {
15016                                         foreach ($this->strip_attributes as $attrib)
15017                                         {
15018                                                 $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);
15019                                         }
15020                                 }
15021
15022                                 // Replace relative URLs
15023                                 $this->base = $base;
15024                                 foreach ($this->replace_url_attributes as $element => $attributes)
15025                                 {
15026                                         $data = $this->replace_urls($data, $element, $attributes);
15027                                 }
15028
15029                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15030                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15031                                 {
15032                                         $images = SimplePie_Misc::get_element('img', $data);
15033                                         foreach ($images as $img)
15034                                         {
15035                                                 if (isset($img['attribs']['src']['data']))
15036                                                 {
15037                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15038                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15039
15040                                                         if ($cache->load())
15041                                                         {
15042                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15043                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15044                                                         }
15045                                                         else
15046                                                         {
15047                                                                 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15048                                                                 $headers = $file->headers;
15049
15050                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15051                                                                 {
15052                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15053                                                                         {
15054                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15055                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15056                                                                         }
15057                                                                         else
15058                                                                         {
15059                                                                                 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
15060                                                                         }
15061                                                                 }
15062                                                         }
15063                                                 }
15064                                         }
15065                                 }
15066
15067                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15068                                 $data = trim($data);
15069                         }
15070
15071                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15072                         {
15073                                 $data = SimplePie_Misc::absolutize_url($data, $base);
15074                         }
15075
15076                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15077                         {
15078                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15079                         }
15080
15081                         if ($this->output_encoding !== 'UTF-8')
15082                         {
15083                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15084                         }
15085                 }
15086                 return $data;
15087         }
15088
15089         function replace_urls($data, $tag, $attributes)
15090         {
15091                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15092                 {
15093                         $elements = SimplePie_Misc::get_element($tag, $data);
15094                         foreach ($elements as $element)
15095                         {
15096                                 if (is_array($attributes))
15097                                 {
15098                                         foreach ($attributes as $attribute)
15099                                         {
15100                                                 if (isset($element['attribs'][$attribute]['data']))
15101                                                 {
15102                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15103                                                         $new_element = SimplePie_Misc::element_implode($element);
15104                                                         $data = str_replace($element['full'], $new_element, $data);
15105                                                         $element['full'] = $new_element;
15106                                                 }
15107                                         }
15108                                 }
15109                                 elseif (isset($element['attribs'][$attributes]['data']))
15110                                 {
15111                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15112                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15113                                 }
15114                         }
15115                 }
15116                 return $data;
15117         }
15118
15119         function do_strip_htmltags($match)
15120         {
15121                 if ($this->encode_instead_of_strip)
15122                 {
15123                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15124                         {
15125                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15126                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15127                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15128                         }
15129                         else
15130                         {
15131                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15132                         }
15133                 }
15134                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15135                 {
15136                         return $match[4];
15137                 }
15138                 else
15139                 {
15140                         return '';
15141                 }
15142         }
15143 }
15144
15145 ?>