]> git.mxchange.org Git - friendica.git/blob - library/simplepie/simplepie.inc
Merge pull request #2185 from tobiasd/20151214-translations
[friendica.git] / library / 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', '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                                         $title = $title_parent;
5521
5522                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5523                                         if (isset($link['attribs']['']['type']))
5524                                         {
5525                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5526                                         }
5527                                         if (isset($link['attribs']['']['length']))
5528                                         {
5529                                                 $length = ceil($link['attribs']['']['length']);
5530                                         }
5531                                         if (isset($link['attribs']['']['title']))
5532                                         {
5533                                                 $title = $this->sanitize($link['attribs']['']['title'], SIMPLEPIE_CONSTRUCT_TEXT);
5534                                         }
5535
5536                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5537                                         $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, $width);
5538                                 }
5539                         }
5540
5541                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5542                         {
5543                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5544                                 {
5545                                         // Attributes
5546                                         $bitrate = null;
5547                                         $channels = null;
5548                                         $duration = null;
5549                                         $expression = null;
5550                                         $framerate = null;
5551                                         $height = null;
5552                                         $javascript = null;
5553                                         $lang = null;
5554                                         $length = null;
5555                                         $medium = null;
5556                                         $samplingrate = null;
5557                                         $type = null;
5558                                         $url = null;
5559                                         $width = null;
5560
5561                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5562                                         if (isset($link['attribs']['']['type']))
5563                                         {
5564                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5565                                         }
5566                                         if (isset($link['attribs']['']['length']))
5567                                         {
5568                                                 $length = ceil($link['attribs']['']['length']);
5569                                         }
5570
5571                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5572                                         $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);
5573                                 }
5574                         }
5575
5576                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5577                         {
5578                                 if (isset($enclosure[0]['attribs']['']['url']))
5579                                 {
5580                                         // Attributes
5581                                         $bitrate = null;
5582                                         $channels = null;
5583                                         $duration = null;
5584                                         $expression = null;
5585                                         $framerate = null;
5586                                         $height = null;
5587                                         $javascript = null;
5588                                         $lang = null;
5589                                         $length = null;
5590                                         $medium = null;
5591                                         $samplingrate = null;
5592                                         $type = null;
5593                                         $url = null;
5594                                         $width = null;
5595
5596                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5597                                         if (isset($enclosure[0]['attribs']['']['type']))
5598                                         {
5599                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5600                                         }
5601                                         if (isset($enclosure[0]['attribs']['']['length']))
5602                                         {
5603                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5604                                         }
5605
5606                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5607                                         $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);
5608                                 }
5609                         }
5610
5611                         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))
5612                         {
5613                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5614                                 $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);
5615                         }
5616
5617                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5618                 }
5619                 if (!empty($this->data['enclosures']))
5620                 {
5621                         return $this->data['enclosures'];
5622                 }
5623                 else
5624                 {
5625                         return null;
5626                 }
5627         }
5628
5629         function get_latitude()
5630         {
5631                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5632                 {
5633                         return (float) $return[0]['data'];
5634                 }
5635                 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))
5636                 {
5637                         return (float) $match[1];
5638                 }
5639                 else
5640                 {
5641                         return null;
5642                 }
5643         }
5644
5645         function get_longitude()
5646         {
5647                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5648                 {
5649                         return (float) $return[0]['data'];
5650                 }
5651                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5652                 {
5653                         return (float) $return[0]['data'];
5654                 }
5655                 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))
5656                 {
5657                         return (float) $match[2];
5658                 }
5659                 else
5660                 {
5661                         return null;
5662                 }
5663         }
5664
5665         function get_source()
5666         {
5667                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5668                 {
5669                         return new $this->feed->source_class($this, $return[0]);
5670                 }
5671                 else
5672                 {
5673                         return null;
5674                 }
5675         }
5676
5677         /**
5678          * Creates the add_to_* methods' return data
5679          *
5680          * @access private
5681          * @param string $item_url String to prefix to the item permalink
5682          * @param string $title_url String to prefix to the item title
5683          * (and suffix to the item permalink)
5684          * @return mixed URL if feed exists, false otherwise
5685          */
5686         function add_to_service($item_url, $title_url = null, $summary_url = null)
5687         {
5688                 if ($this->get_permalink() !== null)
5689                 {
5690                         $return = $item_url . rawurlencode($this->get_permalink());
5691                         if ($title_url !== null && $this->get_title() !== null)
5692                         {
5693                                 $return .= $title_url . rawurlencode($this->get_title());
5694                         }
5695                         if ($summary_url !== null && $this->get_description() !== null)
5696                         {
5697                                 $return .= $summary_url . rawurlencode($this->get_description());
5698                         }
5699                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5700                 }
5701                 else
5702                 {
5703                         return null;
5704                 }
5705         }
5706
5707         function add_to_blinklist()
5708         {
5709                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5710         }
5711
5712         function add_to_blogmarks()
5713         {
5714                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5715         }
5716
5717         function add_to_delicious()
5718         {
5719                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5720         }
5721
5722         function add_to_digg()
5723         {
5724                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5725         }
5726
5727         function add_to_furl()
5728         {
5729                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5730         }
5731
5732         function add_to_magnolia()
5733         {
5734                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5735         }
5736
5737         function add_to_myweb20()
5738         {
5739                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5740         }
5741
5742         function add_to_newsvine()
5743         {
5744                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5745         }
5746
5747         function add_to_reddit()
5748         {
5749                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5750         }
5751
5752         function add_to_segnalo()
5753         {
5754                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5755         }
5756
5757         function add_to_simpy()
5758         {
5759                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5760         }
5761
5762         function add_to_spurl()
5763         {
5764                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5765         }
5766
5767         function add_to_wists()
5768         {
5769                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5770         }
5771
5772         function search_technorati()
5773         {
5774                 return $this->add_to_service('http://www.technorati.com/search/');
5775         }
5776 }
5777
5778 class SimplePie_Source
5779 {
5780         var $item;
5781         var $data = array();
5782
5783         function SimplePie_Source($item, $data)
5784         {
5785                 $this->item = $item;
5786                 $this->data = $data;
5787         }
5788
5789         function __toString()
5790         {
5791                 return md5(serialize($this->data));
5792         }
5793
5794         function get_source_tags($namespace, $tag)
5795         {
5796                 if (isset($this->data['child'][$namespace][$tag]))
5797                 {
5798                         return $this->data['child'][$namespace][$tag];
5799                 }
5800                 else
5801                 {
5802                         return null;
5803                 }
5804         }
5805
5806         function get_base($element = array())
5807         {
5808                 return $this->item->get_base($element);
5809         }
5810
5811         function sanitize($data, $type, $base = '')
5812         {
5813                 return $this->item->sanitize($data, $type, $base);
5814         }
5815
5816         function get_item()
5817         {
5818                 return $this->item;
5819         }
5820
5821         function get_title()
5822         {
5823                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5824                 {
5825                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5826                 }
5827                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5828                 {
5829                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5830                 }
5831                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5832                 {
5833                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5834                 }
5835                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5836                 {
5837                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5838                 }
5839                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5840                 {
5841                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5842                 }
5843                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5844                 {
5845                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5846                 }
5847                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5848                 {
5849                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5850                 }
5851                 else
5852                 {
5853                         return null;
5854                 }
5855         }
5856
5857         function get_category($key = 0)
5858         {
5859                 $categories = $this->get_categories();
5860                 if (isset($categories[$key]))
5861                 {
5862                         return $categories[$key];
5863                 }
5864                 else
5865                 {
5866                         return null;
5867                 }
5868         }
5869
5870         function get_categories()
5871         {
5872                 $categories = array();
5873
5874                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5875                 {
5876                         $term = null;
5877                         $scheme = null;
5878                         $label = null;
5879                         if (isset($category['attribs']['']['term']))
5880                         {
5881                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5882                         }
5883                         if (isset($category['attribs']['']['scheme']))
5884                         {
5885                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5886                         }
5887                         if (isset($category['attribs']['']['label']))
5888                         {
5889                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5890                         }
5891                         $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5892                 }
5893                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5894                 {
5895                         // This is really the label, but keep this as the term also for BC.
5896                         // Label will also work on retrieving because that falls back to term.
5897                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5898                         if (isset($category['attribs']['']['domain']))
5899                         {
5900                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5901                         }
5902                         else
5903                         {
5904                                 $scheme = null;
5905                         }
5906                         $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5907                 }
5908                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5909                 {
5910                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5911                 }
5912                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5913                 {
5914                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5915                 }
5916
5917                 if (!empty($categories))
5918                 {
5919                         return SimplePie_Misc::array_unique($categories);
5920                 }
5921                 else
5922                 {
5923                         return null;
5924                 }
5925         }
5926
5927         function get_author($key = 0)
5928         {
5929                 $authors = $this->get_authors();
5930                 if (isset($authors[$key]))
5931                 {
5932                         return $authors[$key];
5933                 }
5934                 else
5935                 {
5936                         return null;
5937                 }
5938         }
5939
5940         function get_authors()
5941         {
5942                 $authors = array();
5943                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5944                 {
5945                         $name = null;
5946                         $uri = null;
5947                         $email = null;
5948                         $avatar = null;
5949                         $name_date = null;
5950                         $uri_date = null;
5951                         $avatar_date = null;
5952
5953                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5954                         {
5955                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5956                         }
5957                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5958                         {
5959                                 $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]));
5960                         }
5961                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5962                         {
5963                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5964                         }
5965                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
5966                         {
5967                                 $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]));
5968                         }
5969                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
5970                         {
5971                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
5972                         }
5973                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
5974                         {
5975                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
5976                         }
5977                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
5978                         {
5979                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
5980                         }
5981
5982                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
5983                         {
5984                                 $authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
5985                         }
5986                 }
5987                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5988                 {
5989                         $name = null;
5990                         $url = null;
5991                         $email = null;
5992                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5993                         {
5994                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5995                         }
5996                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5997                         {
5998                                 $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]));
5999                         }
6000                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6001                         {
6002                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6003                         }
6004                         if ($name !== null || $email !== null || $url !== null)
6005                         {
6006                                 $authors[] = new $this->item->feed->author_class($name, $url, $email);
6007                         }
6008                 }
6009                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
6010                 {
6011                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6012                 }
6013                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
6014                 {
6015                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6016                 }
6017                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
6018                 {
6019                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6020                 }
6021
6022                 if (!empty($authors))
6023                 {
6024                         return SimplePie_Misc::array_unique($authors);
6025                 }
6026                 else
6027                 {
6028                         return null;
6029                 }
6030         }
6031
6032         function get_contributor($key = 0)
6033         {
6034                 $contributors = $this->get_contributors();
6035                 if (isset($contributors[$key]))
6036                 {
6037                         return $contributors[$key];
6038                 }
6039                 else
6040                 {
6041                         return null;
6042                 }
6043         }
6044
6045         function get_contributors()
6046         {
6047                 $contributors = array();
6048                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
6049                 {
6050                         $name = null;
6051                         $uri = null;
6052                         $email = null;
6053                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6054                         {
6055                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6056                         }
6057                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6058                         {
6059                                 $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]));
6060                         }
6061                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6062                         {
6063                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6064                         }
6065                         if ($name !== null || $email !== null || $uri !== null)
6066                         {
6067                                 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
6068                         }
6069                 }
6070                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6071                 {
6072                         $name = null;
6073                         $url = null;
6074                         $email = null;
6075                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6076                         {
6077                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6078                         }
6079                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6080                         {
6081                                 $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]));
6082                         }
6083                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6084                         {
6085                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6086                         }
6087                         if ($name !== null || $email !== null || $url !== null)
6088                         {
6089                                 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
6090                         }
6091                 }
6092
6093                 if (!empty($contributors))
6094                 {
6095                         return SimplePie_Misc::array_unique($contributors);
6096                 }
6097                 else
6098                 {
6099                         return null;
6100                 }
6101         }
6102
6103         function get_link($key = 0, $rel = 'alternate')
6104         {
6105                 $links = $this->get_links($rel);
6106                 if (isset($links[$key]))
6107                 {
6108                         return $links[$key];
6109                 }
6110                 else
6111                 {
6112                         return null;
6113                 }
6114         }
6115
6116         /**
6117          * Added for parity between the parent-level and the item/entry-level.
6118          */
6119         function get_permalink()
6120         {
6121                 return $this->get_link(0);
6122         }
6123
6124         function get_links($rel = 'alternate')
6125         {
6126                 if (!isset($this->data['links']))
6127                 {
6128                         $this->data['links'] = array();
6129                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6130                         {
6131                                 foreach ($links as $link)
6132                                 {
6133                                         if (isset($link['attribs']['']['href']))
6134                                         {
6135                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6136                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6137                                         }
6138                                 }
6139                         }
6140                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6141                         {
6142                                 foreach ($links as $link)
6143                                 {
6144                                         if (isset($link['attribs']['']['href']))
6145                                         {
6146                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6147                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6148
6149                                         }
6150                                 }
6151                         }
6152                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6153                         {
6154                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6155                         }
6156                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6157                         {
6158                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6159                         }
6160                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6161                         {
6162                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6163                         }
6164
6165                         $keys = array_keys($this->data['links']);
6166                         foreach ($keys as $key)
6167                         {
6168                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6169                                 {
6170                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6171                                         {
6172                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6173                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6174                                         }
6175                                         else
6176                                         {
6177                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6178                                         }
6179                                 }
6180                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6181                                 {
6182                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6183                                 }
6184                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6185                         }
6186                 }
6187
6188                 if (isset($this->data['links'][$rel]))
6189                 {
6190                         return $this->data['links'][$rel];
6191                 }
6192                 else
6193                 {
6194                         return null;
6195                 }
6196         }
6197
6198         function get_description()
6199         {
6200                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6201                 {
6202                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6203                 }
6204                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6205                 {
6206                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6207                 }
6208                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6209                 {
6210                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6211                 }
6212                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6213                 {
6214                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6215                 }
6216                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6217                 {
6218                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6219                 }
6220                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6221                 {
6222                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6223                 }
6224                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6225                 {
6226                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6227                 }
6228                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6229                 {
6230                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6231                 }
6232                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6233                 {
6234                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6235                 }
6236                 else
6237                 {
6238                         return null;
6239                 }
6240         }
6241
6242         function get_copyright()
6243         {
6244                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6245                 {
6246                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6247                 }
6248                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6249                 {
6250                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6251                 }
6252                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6253                 {
6254                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6255                 }
6256                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6257                 {
6258                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6259                 }
6260                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6261                 {
6262                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6263                 }
6264                 else
6265                 {
6266                         return null;
6267                 }
6268         }
6269
6270         function get_language()
6271         {
6272                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6273                 {
6274                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6275                 }
6276                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6277                 {
6278                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6279                 }
6280                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6281                 {
6282                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6283                 }
6284                 elseif (isset($this->data['xml_lang']))
6285                 {
6286                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6287                 }
6288                 else
6289                 {
6290                         return null;
6291                 }
6292         }
6293
6294         function get_latitude()
6295         {
6296                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6297                 {
6298                         return (float) $return[0]['data'];
6299                 }
6300                 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))
6301                 {
6302                         return (float) $match[1];
6303                 }
6304                 else
6305                 {
6306                         return null;
6307                 }
6308         }
6309
6310         function get_longitude()
6311         {
6312                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6313                 {
6314                         return (float) $return[0]['data'];
6315                 }
6316                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6317                 {
6318                         return (float) $return[0]['data'];
6319                 }
6320                 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))
6321                 {
6322                         return (float) $match[2];
6323                 }
6324                 else
6325                 {
6326                         return null;
6327                 }
6328         }
6329
6330         function get_image_url()
6331         {
6332                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6333                 {
6334                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6335                 }
6336                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6337                 {
6338                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6339                 }
6340                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6341                 {
6342                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6343                 }
6344                 else
6345                 {
6346                         return null;
6347                 }
6348         }
6349 }
6350
6351 class SimplePie_Author
6352 {
6353         var $name;
6354         var $link;
6355         var $email;
6356         var $avatar;
6357         var $name_date;
6358         var $uri_date;
6359         var $avatar_date;
6360
6361         // Constructor, used to input the data
6362         function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null, $name_date = null, $uri_date = null, $avatar_date = null)
6363         {
6364                 $this->name = $name;
6365                 $this->link = $link;
6366                 $this->email = $email;
6367                 $this->avatar = $avatar;
6368                 $this->name_date = $name_date;
6369                 $this->uri_date = $uri_date;
6370                 $this->avatar_date = $avatar_date;
6371         }
6372
6373         function __toString()
6374         {
6375                 // There is no $this->data here
6376                 return md5(serialize($this));
6377         }
6378
6379         function get_name()
6380         {
6381                 if ($this->name !== null)
6382                 {
6383                         return $this->name;
6384                 }
6385                 else
6386                 {
6387                         return null;
6388                 }
6389         }
6390
6391         function get_link()
6392         {
6393                 if ($this->link !== null)
6394                 {
6395                         return $this->link;
6396                 }
6397                 else
6398                 {
6399                         return null;
6400                 }
6401         }
6402
6403         function get_email()
6404         {
6405                 if ($this->email !== null)
6406                 {
6407                         return $this->email;
6408                 }
6409                 else
6410                 {
6411                         return null;
6412                 }
6413         }
6414
6415         function get_avatar()
6416         {
6417                 if ($this->avatar !== null)
6418                 {
6419                         return $this->avatar;
6420                 }
6421                 else
6422                 {
6423                         return null;
6424                 }
6425         }
6426
6427         function get_name_date()
6428         {
6429                 if ($this->name_date !== null)
6430                 {
6431                         return $this->name_date;
6432                 }
6433                 else
6434                 {
6435                         return null;
6436                 }
6437         }
6438         function get_uri_date()
6439         {
6440                 if ($this->uri_date !== null)
6441                 {
6442                         return $this->uri_date;
6443                 }
6444                 else
6445                 {
6446                         return null;
6447                 }
6448         }
6449         function get_avatar_date()
6450         {
6451                 if ($this->avatar_date !== null)
6452                 {
6453                         return $this->avatar_date;
6454                 }
6455                 else
6456                 {
6457                         return null;
6458                 }
6459         }
6460
6461
6462 }
6463
6464 class SimplePie_Category
6465 {
6466         var $term;
6467         var $scheme;
6468         var $label;
6469
6470         // Constructor, used to input the data
6471         function SimplePie_Category($term = null, $scheme = null, $label = null)
6472         {
6473                 $this->term = $term;
6474                 $this->scheme = $scheme;
6475                 $this->label = $label;
6476         }
6477
6478         function __toString()
6479         {
6480                 // There is no $this->data here
6481                 return md5(serialize($this));
6482         }
6483
6484         function get_term()
6485         {
6486                 if ($this->term !== null)
6487                 {
6488                         return $this->term;
6489                 }
6490                 else
6491                 {
6492                         return null;
6493                 }
6494         }
6495
6496         function get_scheme()
6497         {
6498                 if ($this->scheme !== null)
6499                 {
6500                         return $this->scheme;
6501                 }
6502                 else
6503                 {
6504                         return null;
6505                 }
6506         }
6507
6508         function get_label()
6509         {
6510                 if ($this->label !== null)
6511                 {
6512                         return $this->label;
6513                 }
6514                 else
6515                 {
6516                         return $this->get_term();
6517                 }
6518         }
6519 }
6520
6521 class SimplePie_Enclosure
6522 {
6523         var $bitrate;
6524         var $captions;
6525         var $categories;
6526         var $channels;
6527         var $copyright;
6528         var $credits;
6529         var $description;
6530         var $duration;
6531         var $expression;
6532         var $framerate;
6533         var $handler;
6534         var $hashes;
6535         var $height;
6536         var $javascript;
6537         var $keywords;
6538         var $lang;
6539         var $length;
6540         var $link;
6541         var $medium;
6542         var $player;
6543         var $ratings;
6544         var $restrictions;
6545         var $samplingrate;
6546         var $thumbnails;
6547         var $title;
6548         var $type;
6549         var $width;
6550
6551         // Constructor, used to input the data
6552         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)
6553         {
6554                 $this->bitrate = $bitrate;
6555                 $this->captions = $captions;
6556                 $this->categories = $categories;
6557                 $this->channels = $channels;
6558                 $this->copyright = $copyright;
6559                 $this->credits = $credits;
6560                 $this->description = $description;
6561                 $this->duration = $duration;
6562                 $this->expression = $expression;
6563                 $this->framerate = $framerate;
6564                 $this->hashes = $hashes;
6565                 $this->height = $height;
6566                 $this->javascript = $javascript;
6567                 $this->keywords = $keywords;
6568                 $this->lang = $lang;
6569                 $this->length = $length;
6570                 $this->link = $link;
6571                 $this->medium = $medium;
6572                 $this->player = $player;
6573                 $this->ratings = $ratings;
6574                 $this->restrictions = $restrictions;
6575                 $this->samplingrate = $samplingrate;
6576                 $this->thumbnails = $thumbnails;
6577                 $this->title = $title;
6578                 $this->type = $type;
6579                 $this->width = $width;
6580                 if (class_exists('idna_convert'))
6581                 {
6582                         $idn = new idna_convert;
6583                         $parsed = SimplePie_Misc::parse_url($link);
6584                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6585                 }
6586                 $this->handler = $this->get_handler(); // Needs to load last
6587         }
6588
6589         function __toString()
6590         {
6591                 // There is no $this->data here
6592                 return md5(serialize($this));
6593         }
6594
6595         function get_bitrate()
6596         {
6597                 if ($this->bitrate !== null)
6598                 {
6599                         return $this->bitrate;
6600                 }
6601                 else
6602                 {
6603                         return null;
6604                 }
6605         }
6606
6607         function get_caption($key = 0)
6608         {
6609                 $captions = $this->get_captions();
6610                 if (isset($captions[$key]))
6611                 {
6612                         return $captions[$key];
6613                 }
6614                 else
6615                 {
6616                         return null;
6617                 }
6618         }
6619
6620         function get_captions()
6621         {
6622                 if ($this->captions !== null)
6623                 {
6624                         return $this->captions;
6625                 }
6626                 else
6627                 {
6628                         return null;
6629                 }
6630         }
6631
6632         function get_category($key = 0)
6633         {
6634                 $categories = $this->get_categories();
6635                 if (isset($categories[$key]))
6636                 {
6637                         return $categories[$key];
6638                 }
6639                 else
6640                 {
6641                         return null;
6642                 }
6643         }
6644
6645         function get_categories()
6646         {
6647                 if ($this->categories !== null)
6648                 {
6649                         return $this->categories;
6650                 }
6651                 else
6652                 {
6653                         return null;
6654                 }
6655         }
6656
6657         function get_channels()
6658         {
6659                 if ($this->channels !== null)
6660                 {
6661                         return $this->channels;
6662                 }
6663                 else
6664                 {
6665                         return null;
6666                 }
6667         }
6668
6669         function get_copyright()
6670         {
6671                 if ($this->copyright !== null)
6672                 {
6673                         return $this->copyright;
6674                 }
6675                 else
6676                 {
6677                         return null;
6678                 }
6679         }
6680
6681         function get_credit($key = 0)
6682         {
6683                 $credits = $this->get_credits();
6684                 if (isset($credits[$key]))
6685                 {
6686                         return $credits[$key];
6687                 }
6688                 else
6689                 {
6690                         return null;
6691                 }
6692         }
6693
6694         function get_credits()
6695         {
6696                 if ($this->credits !== null)
6697                 {
6698                         return $this->credits;
6699                 }
6700                 else
6701                 {
6702                         return null;
6703                 }
6704         }
6705
6706         function get_description()
6707         {
6708                 if ($this->description !== null)
6709                 {
6710                         return $this->description;
6711                 }
6712                 else
6713                 {
6714                         return null;
6715                 }
6716         }
6717
6718         function get_duration($convert = false)
6719         {
6720                 if ($this->duration !== null)
6721                 {
6722                         if ($convert)
6723                         {
6724                                 $time = SimplePie_Misc::time_hms($this->duration);
6725                                 return $time;
6726                         }
6727                         else
6728                         {
6729                                 return $this->duration;
6730                         }
6731                 }
6732                 else
6733                 {
6734                         return null;
6735                 }
6736         }
6737
6738         function get_expression()
6739         {
6740                 if ($this->expression !== null)
6741                 {
6742                         return $this->expression;
6743                 }
6744                 else
6745                 {
6746                         return 'full';
6747                 }
6748         }
6749
6750         function get_extension()
6751         {
6752                 if ($this->link !== null)
6753                 {
6754                         $url = SimplePie_Misc::parse_url($this->link);
6755                         if ($url['path'] !== '')
6756                         {
6757                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6758                         }
6759                 }
6760                 return null;
6761         }
6762
6763         function get_framerate()
6764         {
6765                 if ($this->framerate !== null)
6766                 {
6767                         return $this->framerate;
6768                 }
6769                 else
6770                 {
6771                         return null;
6772                 }
6773         }
6774
6775         function get_handler()
6776         {
6777                 return $this->get_real_type(true);
6778         }
6779
6780         function get_hash($key = 0)
6781         {
6782                 $hashes = $this->get_hashes();
6783                 if (isset($hashes[$key]))
6784                 {
6785                         return $hashes[$key];
6786                 }
6787                 else
6788                 {
6789                         return null;
6790                 }
6791         }
6792
6793         function get_hashes()
6794         {
6795                 if ($this->hashes !== null)
6796                 {
6797                         return $this->hashes;
6798                 }
6799                 else
6800                 {
6801                         return null;
6802                 }
6803         }
6804
6805         function get_height()
6806         {
6807                 if ($this->height !== null)
6808                 {
6809                         return $this->height;
6810                 }
6811                 else
6812                 {
6813                         return null;
6814                 }
6815         }
6816
6817         function get_language()
6818         {
6819                 if ($this->lang !== null)
6820                 {
6821                         return $this->lang;
6822                 }
6823                 else
6824                 {
6825                         return null;
6826                 }
6827         }
6828
6829         function get_keyword($key = 0)
6830         {
6831                 $keywords = $this->get_keywords();
6832                 if (isset($keywords[$key]))
6833                 {
6834                         return $keywords[$key];
6835                 }
6836                 else
6837                 {
6838                         return null;
6839                 }
6840         }
6841
6842         function get_keywords()
6843         {
6844                 if ($this->keywords !== null)
6845                 {
6846                         return $this->keywords;
6847                 }
6848                 else
6849                 {
6850                         return null;
6851                 }
6852         }
6853
6854         function get_length()
6855         {
6856                 if ($this->length !== null)
6857                 {
6858                         return $this->length;
6859                 }
6860                 else
6861                 {
6862                         return null;
6863                 }
6864         }
6865
6866         function get_link()
6867         {
6868                 if ($this->link !== null)
6869                 {
6870                         return urldecode($this->link);
6871                 }
6872                 else
6873                 {
6874                         return null;
6875                 }
6876         }
6877
6878         function get_medium()
6879         {
6880                 if ($this->medium !== null)
6881                 {
6882                         return $this->medium;
6883                 }
6884                 else
6885                 {
6886                         return null;
6887                 }
6888         }
6889
6890         function get_player()
6891         {
6892                 if ($this->player !== null)
6893                 {
6894                         return $this->player;
6895                 }
6896                 else
6897                 {
6898                         return null;
6899                 }
6900         }
6901
6902         function get_rating($key = 0)
6903         {
6904                 $ratings = $this->get_ratings();
6905                 if (isset($ratings[$key]))
6906                 {
6907                         return $ratings[$key];
6908                 }
6909                 else
6910                 {
6911                         return null;
6912                 }
6913         }
6914
6915         function get_ratings()
6916         {
6917                 if ($this->ratings !== null)
6918                 {
6919                         return $this->ratings;
6920                 }
6921                 else
6922                 {
6923                         return null;
6924                 }
6925         }
6926
6927         function get_restriction($key = 0)
6928         {
6929                 $restrictions = $this->get_restrictions();
6930                 if (isset($restrictions[$key]))
6931                 {
6932                         return $restrictions[$key];
6933                 }
6934                 else
6935                 {
6936                         return null;
6937                 }
6938         }
6939
6940         function get_restrictions()
6941         {
6942                 if ($this->restrictions !== null)
6943                 {
6944                         return $this->restrictions;
6945                 }
6946                 else
6947                 {
6948                         return null;
6949                 }
6950         }
6951
6952         function get_sampling_rate()
6953         {
6954                 if ($this->samplingrate !== null)
6955                 {
6956                         return $this->samplingrate;
6957                 }
6958                 else
6959                 {
6960                         return null;
6961                 }
6962         }
6963
6964         function get_size()
6965         {
6966                 $length = $this->get_length();
6967                 if ($length !== null)
6968                 {
6969                         return round($length/1048576, 2);
6970                 }
6971                 else
6972                 {
6973                         return null;
6974                 }
6975         }
6976
6977         function get_thumbnail($key = 0)
6978         {
6979                 $thumbnails = $this->get_thumbnails();
6980                 if (isset($thumbnails[$key]))
6981                 {
6982                         return $thumbnails[$key];
6983                 }
6984                 else
6985                 {
6986                         return null;
6987                 }
6988         }
6989
6990         function get_thumbnails()
6991         {
6992                 if ($this->thumbnails !== null)
6993                 {
6994                         return $this->thumbnails;
6995                 }
6996                 else
6997                 {
6998                         return null;
6999                 }
7000         }
7001
7002         function get_title()
7003         {
7004                 if ($this->title !== null)
7005                 {
7006                         return $this->title;
7007                 }
7008                 else
7009                 {
7010                         return null;
7011                 }
7012         }
7013
7014         function get_type()
7015         {
7016                 if ($this->type !== null)
7017                 {
7018                         return $this->type;
7019                 }
7020                 else
7021                 {
7022                         return null;
7023                 }
7024         }
7025
7026         function get_width()
7027         {
7028                 if ($this->width !== null)
7029                 {
7030                         return $this->width;
7031                 }
7032                 else
7033                 {
7034                         return null;
7035                 }
7036         }
7037
7038         function native_embed($options='')
7039         {
7040                 return $this->embed($options, true);
7041         }
7042
7043         /**
7044          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
7045          */
7046         function embed($options = '', $native = false)
7047         {
7048                 // Set up defaults
7049                 $audio = '';
7050                 $video = '';
7051                 $alt = '';
7052                 $altclass = '';
7053                 $loop = 'false';
7054                 $width = 'auto';
7055                 $height = 'auto';
7056                 $bgcolor = '#ffffff';
7057                 $mediaplayer = '';
7058                 $widescreen = false;
7059                 $handler = $this->get_handler();
7060                 $type = $this->get_real_type();
7061
7062                 // Process options and reassign values as necessary
7063                 if (is_array($options))
7064                 {
7065                         extract($options);
7066                 }
7067                 else
7068                 {
7069                         $options = explode(',', $options);
7070                         foreach($options as $option)
7071                         {
7072                                 $opt = explode(':', $option, 2);
7073                                 if (isset($opt[0], $opt[1]))
7074                                 {
7075                                         $opt[0] = trim($opt[0]);
7076                                         $opt[1] = trim($opt[1]);
7077                                         switch ($opt[0])
7078                                         {
7079                                                 case 'audio':
7080                                                         $audio = $opt[1];
7081                                                         break;
7082
7083                                                 case 'video':
7084                                                         $video = $opt[1];
7085                                                         break;
7086
7087                                                 case 'alt':
7088                                                         $alt = $opt[1];
7089                                                         break;
7090
7091                                                 case 'altclass':
7092                                                         $altclass = $opt[1];
7093                                                         break;
7094
7095                                                 case 'loop':
7096                                                         $loop = $opt[1];
7097                                                         break;
7098
7099                                                 case 'width':
7100                                                         $width = $opt[1];
7101                                                         break;
7102
7103                                                 case 'height':
7104                                                         $height = $opt[1];
7105                                                         break;
7106
7107                                                 case 'bgcolor':
7108                                                         $bgcolor = $opt[1];
7109                                                         break;
7110
7111                                                 case 'mediaplayer':
7112                                                         $mediaplayer = $opt[1];
7113                                                         break;
7114
7115                                                 case 'widescreen':
7116                                                         $widescreen = $opt[1];
7117                                                         break;
7118                                         }
7119                                 }
7120                         }
7121                 }
7122
7123                 $mime = explode('/', $type, 2);
7124                 $mime = $mime[0];
7125
7126                 // Process values for 'auto'
7127                 if ($width === 'auto')
7128                 {
7129                         if ($mime === 'video')
7130                         {
7131                                 if ($height === 'auto')
7132                                 {
7133                                         $width = 480;
7134                                 }
7135                                 elseif ($widescreen)
7136                                 {
7137                                         $width = round((intval($height)/9)*16);
7138                                 }
7139                                 else
7140                                 {
7141                                         $width = round((intval($height)/3)*4);
7142                                 }
7143                         }
7144                         else
7145                         {
7146                                 $width = '100%';
7147                         }
7148                 }
7149
7150                 if ($height === 'auto')
7151                 {
7152                         if ($mime === 'audio')
7153                         {
7154                                 $height = 0;
7155                         }
7156                         elseif ($mime === 'video')
7157                         {
7158                                 if ($width === 'auto')
7159                                 {
7160                                         if ($widescreen)
7161                                         {
7162                                                 $height = 270;
7163                                         }
7164                                         else
7165                                         {
7166                                                 $height = 360;
7167                                         }
7168                                 }
7169                                 elseif ($widescreen)
7170                                 {
7171                                         $height = round((intval($width)/16)*9);
7172                                 }
7173                                 else
7174                                 {
7175                                         $height = round((intval($width)/4)*3);
7176                                 }
7177                         }
7178                         else
7179                         {
7180                                 $height = 376;
7181                         }
7182                 }
7183                 elseif ($mime === 'audio')
7184                 {
7185                         $height = 0;
7186                 }
7187
7188                 // Set proper placeholder value
7189                 if ($mime === 'audio')
7190                 {
7191                         $placeholder = $audio;
7192                 }
7193                 elseif ($mime === 'video')
7194                 {
7195                         $placeholder = $video;
7196                 }
7197
7198                 $embed = '';
7199
7200                 // Make sure the JS library is included
7201                 if (!$native)
7202                 {
7203                         static $javascript_outputted = null;
7204                         if (!$javascript_outputted && $this->javascript)
7205                         {
7206                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7207                                 $javascript_outputted = true;
7208                         }
7209                 }
7210
7211                 // Odeo Feed MP3's
7212                 if ($handler === 'odeo')
7213                 {
7214                         if ($native)
7215                         {
7216                                 $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>';
7217                         }
7218                         else
7219                         {
7220                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7221                         }
7222                 }
7223
7224                 // Flash
7225                 elseif ($handler === 'flash')
7226                 {
7227                         if ($native)
7228                         {
7229                                 $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>";
7230                         }
7231                         else
7232                         {
7233                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7234                         }
7235                 }
7236
7237                 // Flash Media Player file types.
7238                 // Preferred handler for MP3 file types.
7239                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7240                 {
7241                         $height += 20;
7242                         if ($native)
7243                         {
7244                                 $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>";
7245                         }
7246                         else
7247                         {
7248                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7249                         }
7250                 }
7251
7252                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7253                 // Only handle MP3's if the Flash Media Player is not present.
7254                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7255                 {
7256                         $height += 16;
7257                         if ($native)
7258                         {
7259                                 if ($placeholder !== '')
7260                                 {
7261                                         $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>";
7262                                 }
7263                                 else
7264                                 {
7265                                         $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>";
7266                                 }
7267                         }
7268                         else
7269                         {
7270                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7271                         }
7272                 }
7273
7274                 // Windows Media
7275                 elseif ($handler === 'wmedia')
7276                 {
7277                         $height += 45;
7278                         if ($native)
7279                         {
7280                                 $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>";
7281                         }
7282                         else
7283                         {
7284                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7285                         }
7286                 }
7287
7288                 // Everything else
7289                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7290
7291                 return $embed;
7292         }
7293
7294         function get_real_type($find_handler = false)
7295         {
7296                 // If it's Odeo, let's get it out of the way.
7297                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7298                 {
7299                         return 'odeo';
7300                 }
7301
7302                 // Mime-types by handler.
7303                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7304                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7305                 $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
7306                 $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
7307                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7308
7309                 if ($this->get_type() !== null)
7310                 {
7311                         $type = strtolower($this->type);
7312                 }
7313                 else
7314                 {
7315                         $type = null;
7316                 }
7317
7318                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7319                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7320                 {
7321                         switch (strtolower($this->get_extension()))
7322                         {
7323                                 // Audio mime-types
7324                                 case 'aac':
7325                                 case 'adts':
7326                                         $type = 'audio/acc';
7327                                         break;
7328
7329                                 case 'aif':
7330                                 case 'aifc':
7331                                 case 'aiff':
7332                                 case 'cdda':
7333                                         $type = 'audio/aiff';
7334                                         break;
7335
7336                                 case 'bwf':
7337                                         $type = 'audio/wav';
7338                                         break;
7339
7340                                 case 'kar':
7341                                 case 'mid':
7342                                 case 'midi':
7343                                 case 'smf':
7344                                         $type = 'audio/midi';
7345                                         break;
7346
7347                                 case 'm4a':
7348                                         $type = 'audio/x-m4a';
7349                                         break;
7350
7351                                 case 'mp3':
7352                                 case 'swa':
7353                                         $type = 'audio/mp3';
7354                                         break;
7355
7356                                 case 'wav':
7357                                         $type = 'audio/wav';
7358                                         break;
7359
7360                                 case 'wax':
7361                                         $type = 'audio/x-ms-wax';
7362                                         break;
7363
7364                                 case 'wma':
7365                                         $type = 'audio/x-ms-wma';
7366                                         break;
7367
7368                                 // Video mime-types
7369                                 case '3gp':
7370                                 case '3gpp':
7371                                         $type = 'video/3gpp';
7372                                         break;
7373
7374                                 case '3g2':
7375                                 case '3gp2':
7376                                         $type = 'video/3gpp2';
7377                                         break;
7378
7379                                 case 'asf':
7380                                         $type = 'video/x-ms-asf';
7381                                         break;
7382
7383                                 case 'flv':
7384                                         $type = 'video/x-flv';
7385                                         break;
7386
7387                                 case 'm1a':
7388                                 case 'm1s':
7389                                 case 'm1v':
7390                                 case 'm15':
7391                                 case 'm75':
7392                                 case 'mp2':
7393                                 case 'mpa':
7394                                 case 'mpeg':
7395                                 case 'mpg':
7396                                 case 'mpm':
7397                                 case 'mpv':
7398                                         $type = 'video/mpeg';
7399                                         break;
7400
7401                                 case 'm4v':
7402                                         $type = 'video/x-m4v';
7403                                         break;
7404
7405                                 case 'mov':
7406                                 case 'qt':
7407                                         $type = 'video/quicktime';
7408                                         break;
7409
7410                                 case 'mp4':
7411                                 case 'mpg4':
7412                                         $type = 'video/mp4';
7413                                         break;
7414
7415                                 case 'sdv':
7416                                         $type = 'video/sd-video';
7417                                         break;
7418
7419                                 case 'wm':
7420                                         $type = 'video/x-ms-wm';
7421                                         break;
7422
7423                                 case 'wmv':
7424                                         $type = 'video/x-ms-wmv';
7425                                         break;
7426
7427                                 case 'wvx':
7428                                         $type = 'video/x-ms-wvx';
7429                                         break;
7430
7431                                 // Flash mime-types
7432                                 case 'spl':
7433                                         $type = 'application/futuresplash';
7434                                         break;
7435
7436                                 case 'swf':
7437                                         $type = 'application/x-shockwave-flash';
7438                                         break;
7439                         }
7440                 }
7441
7442                 if ($find_handler)
7443                 {
7444                         if (in_array($type, $types_flash))
7445                         {
7446                                 return 'flash';
7447                         }
7448                         elseif (in_array($type, $types_fmedia))
7449                         {
7450                                 return 'fmedia';
7451                         }
7452                         elseif (in_array($type, $types_quicktime))
7453                         {
7454                                 return 'quicktime';
7455                         }
7456                         elseif (in_array($type, $types_wmedia))
7457                         {
7458                                 return 'wmedia';
7459                         }
7460                         elseif (in_array($type, $types_mp3))
7461                         {
7462                                 return 'mp3';
7463                         }
7464                         else
7465                         {
7466                                 return null;
7467                         }
7468                 }
7469                 else
7470                 {
7471                         return $type;
7472                 }
7473         }
7474 }
7475
7476 class SimplePie_Caption
7477 {
7478         var $type;
7479         var $lang;
7480         var $startTime;
7481         var $endTime;
7482         var $text;
7483
7484         // Constructor, used to input the data
7485         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7486         {
7487                 $this->type = $type;
7488                 $this->lang = $lang;
7489                 $this->startTime = $startTime;
7490                 $this->endTime = $endTime;
7491                 $this->text = $text;
7492         }
7493
7494         function __toString()
7495         {
7496                 // There is no $this->data here
7497                 return md5(serialize($this));
7498         }
7499
7500         function get_endtime()
7501         {
7502                 if ($this->endTime !== null)
7503                 {
7504                         return $this->endTime;
7505                 }
7506                 else
7507                 {
7508                         return null;
7509                 }
7510         }
7511
7512         function get_language()
7513         {
7514                 if ($this->lang !== null)
7515                 {
7516                         return $this->lang;
7517                 }
7518                 else
7519                 {
7520                         return null;
7521                 }
7522         }
7523
7524         function get_starttime()
7525         {
7526                 if ($this->startTime !== null)
7527                 {
7528                         return $this->startTime;
7529                 }
7530                 else
7531                 {
7532                         return null;
7533                 }
7534         }
7535
7536         function get_text()
7537         {
7538                 if ($this->text !== null)
7539                 {
7540                         return $this->text;
7541                 }
7542                 else
7543                 {
7544                         return null;
7545                 }
7546         }
7547
7548         function get_type()
7549         {
7550                 if ($this->type !== null)
7551                 {
7552                         return $this->type;
7553                 }
7554                 else
7555                 {
7556                         return null;
7557                 }
7558         }
7559 }
7560
7561 class SimplePie_Credit
7562 {
7563         var $role;
7564         var $scheme;
7565         var $name;
7566
7567         // Constructor, used to input the data
7568         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7569         {
7570                 $this->role = $role;
7571                 $this->scheme = $scheme;
7572                 $this->name = $name;
7573         }
7574
7575         function __toString()
7576         {
7577                 // There is no $this->data here
7578                 return md5(serialize($this));
7579         }
7580
7581         function get_role()
7582         {
7583                 if ($this->role !== null)
7584                 {
7585                         return $this->role;
7586                 }
7587                 else
7588                 {
7589                         return null;
7590                 }
7591         }
7592
7593         function get_scheme()
7594         {
7595                 if ($this->scheme !== null)
7596                 {
7597                         return $this->scheme;
7598                 }
7599                 else
7600                 {
7601                         return null;
7602                 }
7603         }
7604
7605         function get_name()
7606         {
7607                 if ($this->name !== null)
7608                 {
7609                         return $this->name;
7610                 }
7611                 else
7612                 {
7613                         return null;
7614                 }
7615         }
7616 }
7617
7618 class SimplePie_Copyright
7619 {
7620         var $url;
7621         var $label;
7622
7623         // Constructor, used to input the data
7624         function SimplePie_Copyright($url = null, $label = null)
7625         {
7626                 $this->url = $url;
7627                 $this->label = $label;
7628         }
7629
7630         function __toString()
7631         {
7632                 // There is no $this->data here
7633                 return md5(serialize($this));
7634         }
7635
7636         function get_url()
7637         {
7638                 if ($this->url !== null)
7639                 {
7640                         return $this->url;
7641                 }
7642                 else
7643                 {
7644                         return null;
7645                 }
7646         }
7647
7648         function get_attribution()
7649         {
7650                 if ($this->label !== null)
7651                 {
7652                         return $this->label;
7653                 }
7654                 else
7655                 {
7656                         return null;
7657                 }
7658         }
7659 }
7660
7661 class SimplePie_Rating
7662 {
7663         var $scheme;
7664         var $value;
7665
7666         // Constructor, used to input the data
7667         function SimplePie_Rating($scheme = null, $value = null)
7668         {
7669                 $this->scheme = $scheme;
7670                 $this->value = $value;
7671         }
7672
7673         function __toString()
7674         {
7675                 // There is no $this->data here
7676                 return md5(serialize($this));
7677         }
7678
7679         function get_scheme()
7680         {
7681                 if ($this->scheme !== null)
7682                 {
7683                         return $this->scheme;
7684                 }
7685                 else
7686                 {
7687                         return null;
7688                 }
7689         }
7690
7691         function get_value()
7692         {
7693                 if ($this->value !== null)
7694                 {
7695                         return $this->value;
7696                 }
7697                 else
7698                 {
7699                         return null;
7700                 }
7701         }
7702 }
7703
7704 class SimplePie_Restriction
7705 {
7706         var $relationship;
7707         var $type;
7708         var $value;
7709
7710         // Constructor, used to input the data
7711         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7712         {
7713                 $this->relationship = $relationship;
7714                 $this->type = $type;
7715                 $this->value = $value;
7716         }
7717
7718         function __toString()
7719         {
7720                 // There is no $this->data here
7721                 return md5(serialize($this));
7722         }
7723
7724         function get_relationship()
7725         {
7726                 if ($this->relationship !== null)
7727                 {
7728                         return $this->relationship;
7729                 }
7730                 else
7731                 {
7732                         return null;
7733                 }
7734         }
7735
7736         function get_type()
7737         {
7738                 if ($this->type !== null)
7739                 {
7740                         return $this->type;
7741                 }
7742                 else
7743                 {
7744                         return null;
7745                 }
7746         }
7747
7748         function get_value()
7749         {
7750                 if ($this->value !== null)
7751                 {
7752                         return $this->value;
7753                 }
7754                 else
7755                 {
7756                         return null;
7757                 }
7758         }
7759 }
7760
7761 /**
7762  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7763  */
7764 class SimplePie_File
7765 {
7766         var $url;
7767         var $useragent;
7768         var $success = true;
7769         var $headers = array();
7770         var $body;
7771         var $status_code;
7772         var $redirects = 0;
7773         var $error;
7774         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7775
7776         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7777         {
7778                 if (class_exists('idna_convert'))
7779                 {
7780                         $idn = new idna_convert;
7781                         $parsed = SimplePie_Misc::parse_url($url);
7782                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7783                 }
7784                 $this->url = $url;
7785                 $this->useragent = $useragent;
7786                 if (preg_match('/^http(s)?:\/\//i', $url))
7787                 {
7788                         if ($useragent === null)
7789                         {
7790                                 $useragent = ini_get('user_agent');
7791                                 $this->useragent = $useragent;
7792                         }
7793                         if (!is_array($headers))
7794                         {
7795                                 $headers = array();
7796                         }
7797                         if (!$force_fsockopen && function_exists('curl_exec'))
7798                         {
7799                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7800                                 $fp = curl_init();
7801                                 $headers2 = array();
7802                                 foreach ($headers as $key => $value)
7803                                 {
7804                                         $headers2[] = "$key: $value";
7805                                 }
7806                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7807                                 {
7808                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7809                                 }
7810                                 curl_setopt($fp, CURLOPT_URL, $url);
7811                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7812                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7813                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7814                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7815                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7816                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7817                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7818                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7819                                 {
7820                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7821                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7822                                 }
7823
7824                                 $this->headers = curl_exec($fp);
7825                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7826                                 {
7827                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7828                                         $this->headers = curl_exec($fp);
7829                                 }
7830                                 if (curl_errno($fp))
7831                                 {
7832                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7833                                         $this->success = false;
7834                                 }
7835                                 else
7836                                 {
7837                                         $info = curl_getinfo($fp);
7838                                         curl_close($fp);
7839                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7840                                         $this->headers = array_pop($this->headers);
7841                                         $parser = new SimplePie_HTTP_Parser($this->headers);
7842                                         if ($parser->parse())
7843                                         {
7844                                                 $this->headers = $parser->headers;
7845                                                 $this->body = $parser->body;
7846                                                 $this->status_code = $parser->status_code;
7847                                                 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)
7848                                                 {
7849                                                         $this->redirects++;
7850                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7851                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7852                                                 }
7853                                         }
7854                                 }
7855                         }
7856                         else
7857                         {
7858                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7859                                 $url_parts = parse_url($url);
7860                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7861                                 {
7862                                         $url_parts['host'] = "ssl://$url_parts[host]";
7863                                         $url_parts['port'] = 443;
7864                                 }
7865                                 if (!isset($url_parts['port']))
7866                                 {
7867                                         $url_parts['port'] = 80;
7868                                 }
7869                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7870                                 if (!$fp)
7871                                 {
7872                                         $this->error = 'fsockopen error: ' . $errstr;
7873                                         $this->success = false;
7874                                 }
7875                                 else
7876                                 {
7877                                         stream_set_timeout($fp, $timeout);
7878                                         if (isset($url_parts['path']))
7879                                         {
7880                                                 if (isset($url_parts['query']))
7881                                                 {
7882                                                         $get = "$url_parts[path]?$url_parts[query]";
7883                                                 }
7884                                                 else
7885                                                 {
7886                                                         $get = $url_parts['path'];
7887                                                 }
7888                                         }
7889                                         else
7890                                         {
7891                                                 $get = '/';
7892                                         }
7893                                         $out = "GET $get HTTP/1.0\r\n";
7894                                         $out .= "Host: $url_parts[host]\r\n";
7895                                         $out .= "User-Agent: $useragent\r\n";
7896                                         if (extension_loaded('zlib'))
7897                                         {
7898                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7899                                         }
7900
7901                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7902                                         {
7903                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7904                                         }
7905                                         foreach ($headers as $key => $value)
7906                                         {
7907                                                 $out .= "$key: $value\r\n";
7908                                         }
7909                                         $out .= "Connection: Close\r\n\r\n";
7910                                         fwrite($fp, $out);
7911
7912                                         $info = stream_get_meta_data($fp);
7913
7914                                         $this->headers = '';
7915                                         while (!$info['eof'] && !$info['timed_out'])
7916                                         {
7917                                                 $this->headers .= fread($fp, 1160);
7918                                                 $info = stream_get_meta_data($fp);
7919                                         }
7920                                         if (!$info['timed_out'])
7921                                         {
7922                                                 $parser = new SimplePie_HTTP_Parser($this->headers);
7923                                                 if ($parser->parse())
7924                                                 {
7925                                                         $this->headers = $parser->headers;
7926                                                         $this->body = $parser->body;
7927                                                         $this->status_code = $parser->status_code;
7928                                                         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)
7929                                                         {
7930                                                                 $this->redirects++;
7931                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7932                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7933                                                         }
7934                                                         if (isset($this->headers['content-encoding']))
7935                                                         {
7936                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7937                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7938                                                                 {
7939                                                                         case 'gzip':
7940                                                                         case 'x-gzip':
7941                                                                                 $decoder = new SimplePie_gzdecode($this->body);
7942                                                                                 if (!$decoder->parse())
7943                                                                                 {
7944                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7945                                                                                         $this->success = false;
7946                                                                                 }
7947                                                                                 else
7948                                                                                 {
7949                                                                                         $this->body = $decoder->data;
7950                                                                                 }
7951                                                                                 break;
7952
7953                                                                         case 'deflate':
7954                                                                                 if (($body = gzuncompress($this->body)) === false)
7955                                                                                 {
7956                                                                                         if (($body = gzinflate($this->body)) === false)
7957                                                                                         {
7958                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7959                                                                                                 $this->success = false;
7960                                                                                         }
7961                                                                                 }
7962                                                                                 $this->body = $body;
7963                                                                                 break;
7964
7965                                                                         default:
7966                                                                                 $this->error = 'Unknown content coding';
7967                                                                                 $this->success = false;
7968                                                                 }
7969                                                         }
7970                                                 }
7971                                         }
7972                                         else
7973                                         {
7974                                                 $this->error = 'fsocket timed out';
7975                                                 $this->success = false;
7976                                         }
7977                                         fclose($fp);
7978                                 }
7979                         }
7980                 }
7981                 else
7982                 {
7983                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7984                         if (!$this->body = file_get_contents($url))
7985                         {
7986                                 $this->error = 'file_get_contents could not read the file';
7987                                 $this->success = false;
7988                         }
7989                 }
7990         }
7991 }
7992
7993 /**
7994  * HTTP Response Parser
7995  *
7996  * @package SimplePie
7997  */
7998 class SimplePie_HTTP_Parser
7999 {
8000         /**
8001          * HTTP Version
8002          *
8003          * @access public
8004          * @var float
8005          */
8006         var $http_version = 0.0;
8007
8008         /**
8009          * Status code
8010          *
8011          * @access public
8012          * @var int
8013          */
8014         var $status_code = 0;
8015
8016         /**
8017          * Reason phrase
8018          *
8019          * @access public
8020          * @var string
8021          */
8022         var $reason = '';
8023
8024         /**
8025          * Key/value pairs of the headers
8026          *
8027          * @access public
8028          * @var array
8029          */
8030         var $headers = array();
8031
8032         /**
8033          * Body of the response
8034          *
8035          * @access public
8036          * @var string
8037          */
8038         var $body = '';
8039
8040         /**
8041          * Current state of the state machine
8042          *
8043          * @access private
8044          * @var string
8045          */
8046         var $state = 'http_version';
8047
8048         /**
8049          * Input data
8050          *
8051          * @access private
8052          * @var string
8053          */
8054         var $data = '';
8055
8056         /**
8057          * Input data length (to avoid calling strlen() everytime this is needed)
8058          *
8059          * @access private
8060          * @var int
8061          */
8062         var $data_length = 0;
8063
8064         /**
8065          * Current position of the pointer
8066          *
8067          * @var int
8068          * @access private
8069          */
8070         var $position = 0;
8071
8072         /**
8073          * Name of the hedaer currently being parsed
8074          *
8075          * @access private
8076          * @var string
8077          */
8078         var $name = '';
8079
8080         /**
8081          * Value of the hedaer currently being parsed
8082          *
8083          * @access private
8084          * @var string
8085          */
8086         var $value = '';
8087
8088         /**
8089          * Create an instance of the class with the input data
8090          *
8091          * @access public
8092          * @param string $data Input data
8093          */
8094         function SimplePie_HTTP_Parser($data)
8095         {
8096                 $this->data = $data;
8097                 $this->data_length = strlen($this->data);
8098         }
8099
8100         /**
8101          * Parse the input data
8102          *
8103          * @access public
8104          * @return bool true on success, false on failure
8105          */
8106         function parse()
8107         {
8108                 while ($this->state && $this->state !== 'emit' && $this->has_data())
8109                 {
8110                         $state = $this->state;
8111                         $this->$state();
8112                 }
8113                 $this->data = '';
8114                 if ($this->state === 'emit' || $this->state === 'body')
8115                 {
8116                         return true;
8117                 }
8118                 else
8119                 {
8120                         $this->http_version = '';
8121                         $this->status_code = '';
8122                         $this->reason = '';
8123                         $this->headers = array();
8124                         $this->body = '';
8125                         return false;
8126                 }
8127         }
8128
8129         /**
8130          * Check whether there is data beyond the pointer
8131          *
8132          * @access private
8133          * @return bool true if there is further data, false if not
8134          */
8135         function has_data()
8136         {
8137                 return (bool) ($this->position < $this->data_length);
8138         }
8139
8140         /**
8141          * See if the next character is LWS
8142          *
8143          * @access private
8144          * @return bool true if the next character is LWS, false if not
8145          */
8146         function is_linear_whitespace()
8147         {
8148                 return (bool) ($this->data[$this->position] === "\x09"
8149                         || $this->data[$this->position] === "\x20"
8150                         || ($this->data[$this->position] === "\x0A"
8151                                 && isset($this->data[$this->position + 1])
8152                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8153         }
8154
8155         /**
8156          * Parse the HTTP version
8157          *
8158          * @access private
8159          */
8160         function http_version()
8161         {
8162                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8163                 {
8164                         $len = strspn($this->data, '0123456789.', 5);
8165                         $this->http_version = substr($this->data, 5, $len);
8166                         $this->position += 5 + $len;
8167                         if (substr_count($this->http_version, '.') <= 1)
8168                         {
8169                                 $this->http_version = (float) $this->http_version;
8170                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8171                                 $this->state = 'status';
8172                         }
8173                         else
8174                         {
8175                                 $this->state = false;
8176                         }
8177                 }
8178                 else
8179                 {
8180                         $this->state = false;
8181                 }
8182         }
8183
8184         /**
8185          * Parse the status code
8186          *
8187          * @access private
8188          */
8189         function status()
8190         {
8191                 if ($len = strspn($this->data, '0123456789', $this->position))
8192                 {
8193                         $this->status_code = (int) substr($this->data, $this->position, $len);
8194                         $this->position += $len;
8195                         $this->state = 'reason';
8196                 }
8197                 else
8198                 {
8199                         $this->state = false;
8200                 }
8201         }
8202
8203         /**
8204          * Parse the reason phrase
8205          *
8206          * @access private
8207          */
8208         function reason()
8209         {
8210                 $len = strcspn($this->data, "\x0A", $this->position);
8211                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8212                 $this->position += $len + 1;
8213                 $this->state = 'new_line';
8214         }
8215
8216         /**
8217          * Deal with a new line, shifting data around as needed
8218          *
8219          * @access private
8220          */
8221         function new_line()
8222         {
8223                 $this->value = trim($this->value, "\x0D\x20");
8224                 if ($this->name !== '' && $this->value !== '')
8225                 {
8226                         $this->name = strtolower($this->name);
8227                         if (isset($this->headers[$this->name]))
8228                         {
8229                                 $this->headers[$this->name] .= ', ' . $this->value;
8230                         }
8231                         else
8232                         {
8233                                 $this->headers[$this->name] = $this->value;
8234                         }
8235                 }
8236                 $this->name = '';
8237                 $this->value = '';
8238                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8239                 {
8240                         $this->position += 2;
8241                         $this->state = 'body';
8242                 }
8243                 elseif ($this->data[$this->position] === "\x0A")
8244                 {
8245                         $this->position++;
8246                         $this->state = 'body';
8247                 }
8248                 else
8249                 {
8250                         $this->state = 'name';
8251                 }
8252         }
8253
8254         /**
8255          * Parse a header name
8256          *
8257          * @access private
8258          */
8259         function name()
8260         {
8261                 $len = strcspn($this->data, "\x0A:", $this->position);
8262                 if (isset($this->data[$this->position + $len]))
8263                 {
8264                         if ($this->data[$this->position + $len] === "\x0A")
8265                         {
8266                                 $this->position += $len;
8267                                 $this->state = 'new_line';
8268                         }
8269                         else
8270                         {
8271                                 $this->name = substr($this->data, $this->position, $len);
8272                                 $this->position += $len + 1;
8273                                 $this->state = 'value';
8274                         }
8275                 }
8276                 else
8277                 {
8278                         $this->state = false;
8279                 }
8280         }
8281
8282         /**
8283          * Parse LWS, replacing consecutive LWS characters with a single space
8284          *
8285          * @access private
8286          */
8287         function linear_whitespace()
8288         {
8289                 do
8290                 {
8291                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8292                         {
8293                                 $this->position += 2;
8294                         }
8295                         elseif ($this->data[$this->position] === "\x0A")
8296                         {
8297                                 $this->position++;
8298                         }
8299                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8300                 } while ($this->has_data() && $this->is_linear_whitespace());
8301                 $this->value .= "\x20";
8302         }
8303
8304         /**
8305          * See what state to move to while within non-quoted header values
8306          *
8307          * @access private
8308          */
8309         function value()
8310         {
8311                 if ($this->is_linear_whitespace())
8312                 {
8313                         $this->linear_whitespace();
8314                 }
8315                 else
8316                 {
8317                         switch ($this->data[$this->position])
8318                         {
8319                                 case '"':
8320                                         $this->position++;
8321                                         $this->state = 'quote';
8322                                         break;
8323
8324                                 case "\x0A":
8325                                         $this->position++;
8326                                         $this->state = 'new_line';
8327                                         break;
8328
8329                                 default:
8330                                         $this->state = 'value_char';
8331                                         break;
8332                         }
8333                 }
8334         }
8335
8336         /**
8337          * Parse a header value while outside quotes
8338          *
8339          * @access private
8340          */
8341         function value_char()
8342         {
8343                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8344                 $this->value .= substr($this->data, $this->position, $len);
8345                 $this->position += $len;
8346                 $this->state = 'value';
8347         }
8348
8349         /**
8350          * See what state to move to while within quoted header values
8351          *
8352          * @access private
8353          */
8354         function quote()
8355         {
8356                 if ($this->is_linear_whitespace())
8357                 {
8358                         $this->linear_whitespace();
8359                 }
8360                 else
8361                 {
8362                         switch ($this->data[$this->position])
8363                         {
8364                                 case '"':
8365                                         $this->position++;
8366                                         $this->state = 'value';
8367                                         break;
8368
8369                                 case "\x0A":
8370                                         $this->position++;
8371                                         $this->state = 'new_line';
8372                                         break;
8373
8374                                 case '\\':
8375                                         $this->position++;
8376                                         $this->state = 'quote_escaped';
8377                                         break;
8378
8379                                 default:
8380                                         $this->state = 'quote_char';
8381                                         break;
8382                         }
8383                 }
8384         }
8385
8386         /**
8387          * Parse a header value while within quotes
8388          *
8389          * @access private
8390          */
8391         function quote_char()
8392         {
8393                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8394                 $this->value .= substr($this->data, $this->position, $len);
8395                 $this->position += $len;
8396                 $this->state = 'value';
8397         }
8398
8399         /**
8400          * Parse an escaped character within quotes
8401          *
8402          * @access private
8403          */
8404         function quote_escaped()
8405         {
8406                 $this->value .= $this->data[$this->position];
8407                 $this->position++;
8408                 $this->state = 'quote';
8409         }
8410
8411         /**
8412          * Parse the body
8413          *
8414          * @access private
8415          */
8416         function body()
8417         {
8418                 $this->body = substr($this->data, $this->position);
8419                 $this->state = 'emit';
8420         }
8421 }
8422
8423 /**
8424  * gzdecode
8425  *
8426  * @package SimplePie
8427  */
8428 class SimplePie_gzdecode
8429 {
8430         /**
8431          * Compressed data
8432          *
8433          * @access private
8434          * @see gzdecode::$data
8435          */
8436         var $compressed_data;
8437
8438         /**
8439          * Size of compressed data
8440          *
8441          * @access private
8442          */
8443         var $compressed_size;
8444
8445         /**
8446          * Minimum size of a valid gzip string
8447          *
8448          * @access private
8449          */
8450         var $min_compressed_size = 18;
8451
8452         /**
8453          * Current position of pointer
8454          *
8455          * @access private
8456          */
8457         var $position = 0;
8458
8459         /**
8460          * Flags (FLG)
8461          *
8462          * @access private
8463          */
8464         var $flags;
8465
8466         /**
8467          * Uncompressed data
8468          *
8469          * @access public
8470          * @see gzdecode::$compressed_data
8471          */
8472         var $data;
8473
8474         /**
8475          * Modified time
8476          *
8477          * @access public
8478          */
8479         var $MTIME;
8480
8481         /**
8482          * Extra Flags
8483          *
8484          * @access public
8485          */
8486         var $XFL;
8487
8488         /**
8489          * Operating System
8490          *
8491          * @access public
8492          */
8493         var $OS;
8494
8495         /**
8496          * Subfield ID 1
8497          *
8498          * @access public
8499          * @see gzdecode::$extra_field
8500          * @see gzdecode::$SI2
8501          */
8502         var $SI1;
8503
8504         /**
8505          * Subfield ID 2
8506          *
8507          * @access public
8508          * @see gzdecode::$extra_field
8509          * @see gzdecode::$SI1
8510          */
8511         var $SI2;
8512
8513         /**
8514          * Extra field content
8515          *
8516          * @access public
8517          * @see gzdecode::$SI1
8518          * @see gzdecode::$SI2
8519          */
8520         var $extra_field;
8521
8522         /**
8523          * Original filename
8524          *
8525          * @access public
8526          */
8527         var $filename;
8528
8529         /**
8530          * Human readable comment
8531          *
8532          * @access public
8533          */
8534         var $comment;
8535
8536         /**
8537          * Don't allow anything to be set
8538          *
8539          * @access public
8540          */
8541         function __set($name, $value)
8542         {
8543                 trigger_error("Cannot write property $name", E_USER_ERROR);
8544         }
8545
8546         /**
8547          * Set the compressed string and related properties
8548          *
8549          * @access public
8550          */
8551         function SimplePie_gzdecode($data)
8552         {
8553                 $this->compressed_data = $data;
8554                 $this->compressed_size = strlen($data);
8555         }
8556
8557         /**
8558          * Decode the GZIP stream
8559          *
8560          * @access public
8561          */
8562         function parse()
8563         {
8564                 if ($this->compressed_size >= $this->min_compressed_size)
8565                 {
8566                         // Check ID1, ID2, and CM
8567                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8568                         {
8569                                 return false;
8570                         }
8571
8572                         // Get the FLG (FLaGs)
8573                         $this->flags = ord($this->compressed_data[3]);
8574
8575                         // FLG bits above (1 << 4) are reserved
8576                         if ($this->flags > 0x1F)
8577                         {
8578                                 return false;
8579                         }
8580
8581                         // Advance the pointer after the above
8582                         $this->position += 4;
8583
8584                         // MTIME
8585                         $mtime = substr($this->compressed_data, $this->position, 4);
8586                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8587                         if (current(unpack('S', "\x00\x01")) === 1)
8588                         {
8589                                 $mtime = strrev($mtime);
8590                         }
8591                         $this->MTIME = current(unpack('l', $mtime));
8592                         $this->position += 4;
8593
8594                         // Get the XFL (eXtra FLags)
8595                         $this->XFL = ord($this->compressed_data[$this->position++]);
8596
8597                         // Get the OS (Operating System)
8598                         $this->OS = ord($this->compressed_data[$this->position++]);
8599
8600                         // Parse the FEXTRA
8601                         if ($this->flags & 4)
8602                         {
8603                                 // Read subfield IDs
8604                                 $this->SI1 = $this->compressed_data[$this->position++];
8605                                 $this->SI2 = $this->compressed_data[$this->position++];
8606
8607                                 // SI2 set to zero is reserved for future use
8608                                 if ($this->SI2 === "\x00")
8609                                 {
8610                                         return false;
8611                                 }
8612
8613                                 // Get the length of the extra field
8614                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8615                                 $position += 2;
8616
8617                                 // Check the length of the string is still valid
8618                                 $this->min_compressed_size += $len + 4;
8619                                 if ($this->compressed_size >= $this->min_compressed_size)
8620                                 {
8621                                         // Set the extra field to the given data
8622                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8623                                         $this->position += $len;
8624                                 }
8625                                 else
8626                                 {
8627                                         return false;
8628                                 }
8629                         }
8630
8631                         // Parse the FNAME
8632                         if ($this->flags & 8)
8633                         {
8634                                 // Get the length of the filename
8635                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8636
8637                                 // Check the length of the string is still valid
8638                                 $this->min_compressed_size += $len + 1;
8639                                 if ($this->compressed_size >= $this->min_compressed_size)
8640                                 {
8641                                         // Set the original filename to the given string
8642                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8643                                         $this->position += $len + 1;
8644                                 }
8645                                 else
8646                                 {
8647                                         return false;
8648                                 }
8649                         }
8650
8651                         // Parse the FCOMMENT
8652                         if ($this->flags & 16)
8653                         {
8654                                 // Get the length of the comment
8655                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8656
8657                                 // Check the length of the string is still valid
8658                                 $this->min_compressed_size += $len + 1;
8659                                 if ($this->compressed_size >= $this->min_compressed_size)
8660                                 {
8661                                         // Set the original comment to the given string
8662                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8663                                         $this->position += $len + 1;
8664                                 }
8665                                 else
8666                                 {
8667                                         return false;
8668                                 }
8669                         }
8670
8671                         // Parse the FHCRC
8672                         if ($this->flags & 2)
8673                         {
8674                                 // Check the length of the string is still valid
8675                                 $this->min_compressed_size += $len + 2;
8676                                 if ($this->compressed_size >= $this->min_compressed_size)
8677                                 {
8678                                         // Read the CRC
8679                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8680
8681                                         // Check the CRC matches
8682                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8683                                         {
8684                                                 $this->position += 2;
8685                                         }
8686                                         else
8687                                         {
8688                                                 return false;
8689                                         }
8690                                 }
8691                                 else
8692                                 {
8693                                         return false;
8694                                 }
8695                         }
8696
8697                         // Decompress the actual data
8698                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8699                         {
8700                                 return false;
8701                         }
8702                         else
8703                         {
8704                                 $this->position = $this->compressed_size - 8;
8705                         }
8706
8707                         // Check CRC of data
8708                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8709                         $this->position += 4;
8710                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8711                         {
8712                                 return false;
8713                         }*/
8714
8715                         // Check ISIZE of data
8716                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8717                         $this->position += 4;
8718                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8719                         {
8720                                 return false;
8721                         }
8722
8723                         // Wow, against all odds, we've actually got a valid gzip string
8724                         return true;
8725                 }
8726                 else
8727                 {
8728                         return false;
8729                 }
8730         }
8731 }
8732
8733 class SimplePie_Cache
8734 {
8735         /**
8736          * Don't call the constructor. Please.
8737          *
8738          * @access private
8739          */
8740         function SimplePie_Cache()
8741         {
8742                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8743         }
8744
8745         /**
8746          * Create a new SimplePie_Cache object
8747          *
8748          * @static
8749          * @access public
8750          */
8751         function create($location, $filename, $extension)
8752         {
8753                 $location_iri = new SimplePie_IRI($location);
8754                 switch ($location_iri->get_scheme())
8755                 {
8756                         case 'mysql':
8757                                 if (extension_loaded('mysql'))
8758                                 {
8759                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8760                                 }
8761                                 break;
8762
8763                         default:
8764                                 return new SimplePie_Cache_File($location, $filename, $extension);
8765                 }
8766         }
8767 }
8768
8769 class SimplePie_Cache_File
8770 {
8771         var $location;
8772         var $filename;
8773         var $extension;
8774         var $name;
8775
8776         function SimplePie_Cache_File($location, $filename, $extension)
8777         {
8778                 $this->location = $location;
8779                 $this->filename = $filename;
8780                 $this->extension = $extension;
8781                 $this->name = "$this->location/$this->filename.$this->extension";
8782         }
8783
8784         function save($data)
8785         {
8786                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8787                 {
8788                         if (is_a($data, 'SimplePie'))
8789                         {
8790                                 $data = $data->data;
8791                         }
8792
8793                         $data = serialize($data);
8794
8795                         if (function_exists('file_put_contents'))
8796                         {
8797                                 return (bool) file_put_contents($this->name, $data);
8798                         }
8799                         else
8800                         {
8801                                 $fp = fopen($this->name, 'wb');
8802                                 if ($fp)
8803                                 {
8804                                         fwrite($fp, $data);
8805                                         fclose($fp);
8806                                         return true;
8807                                 }
8808                         }
8809                 }
8810                 return false;
8811         }
8812
8813         function load()
8814         {
8815                 if (file_exists($this->name) && is_readable($this->name))
8816                 {
8817                         return unserialize(file_get_contents($this->name));
8818                 }
8819                 return false;
8820         }
8821
8822         function mtime()
8823         {
8824                 if (file_exists($this->name))
8825                 {
8826                         return filemtime($this->name);
8827                 }
8828                 return false;
8829         }
8830
8831         function touch()
8832         {
8833                 if (file_exists($this->name))
8834                 {
8835                         return touch($this->name);
8836                 }
8837                 return false;
8838         }
8839
8840         function unlink()
8841         {
8842                 if (file_exists($this->name))
8843                 {
8844                         return unlink($this->name);
8845                 }
8846                 return false;
8847         }
8848 }
8849
8850 class SimplePie_Cache_DB
8851 {
8852         function prepare_simplepie_object_for_cache($data)
8853         {
8854                 $items = $data->get_items();
8855                 $items_by_id = array();
8856
8857                 if (!empty($items))
8858                 {
8859                         foreach ($items as $item)
8860                         {
8861                                 $items_by_id[$item->get_id()] = $item;
8862                         }
8863
8864                         if (count($items_by_id) !== count($items))
8865                         {
8866                                 $items_by_id = array();
8867                                 foreach ($items as $item)
8868                                 {
8869                                         $items_by_id[$item->get_id(true)] = $item;
8870                                 }
8871                         }
8872
8873                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8874                         {
8875                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8876                         }
8877                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8878                         {
8879                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8880                         }
8881                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8882                         {
8883                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8884                         }
8885                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8886                         {
8887                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8888                         }
8889                         else
8890                         {
8891                                 $channel = null;
8892                         }
8893
8894                         if ($channel !== null)
8895                         {
8896                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8897                                 {
8898                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8899                                 }
8900                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8901                                 {
8902                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8903                                 }
8904                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8905                                 {
8906                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8907                                 }
8908                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8909                                 {
8910                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8911                                 }
8912                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8913                                 {
8914                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8915                                 }
8916                         }
8917                         if (isset($data->data['items']))
8918                         {
8919                                 unset($data->data['items']);
8920                         }
8921                         if (isset($data->data['ordered_items']))
8922                         {
8923                                 unset($data->data['ordered_items']);
8924                         }
8925                 }
8926                 return array(serialize($data->data), $items_by_id);
8927         }
8928 }
8929
8930 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8931 {
8932         var $mysql;
8933         var $options;
8934         var $id;
8935
8936         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8937         {
8938                 $host = $mysql_location->get_host();
8939                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8940                 {
8941                         $server = ':' . substr($host, 5, -1);
8942                 }
8943                 else
8944                 {
8945                         $server = $host;
8946                         if ($mysql_location->get_port() !== null)
8947                         {
8948                                 $server .= ':' . $mysql_location->get_port();
8949                         }
8950                 }
8951
8952                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8953                 {
8954                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8955                 }
8956                 else
8957                 {
8958                         $username = $mysql_location->get_userinfo();
8959                         $password = null;
8960                 }
8961
8962                 if ($this->mysql = mysql_connect($server, $username, $password))
8963                 {
8964                         $this->id = $name . $extension;
8965                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8966                         if (!isset($this->options['prefix'][0]))
8967                         {
8968                                 $this->options['prefix'][0] = '';
8969                         }
8970
8971                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8972                                 && mysql_query('SET NAMES utf8')
8973                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8974                         {
8975                                 $db = array();
8976                                 while ($row = mysql_fetch_row($query))
8977                                 {
8978                                         $db[] = $row[0];
8979                                 }
8980
8981                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8982                                 {
8983                                         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)))'))
8984                                         {
8985                                                 $this->mysql = null;
8986                                         }
8987                                 }
8988
8989                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8990                                 {
8991                                         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)))'))
8992                                         {
8993                                                 $this->mysql = null;
8994                                         }
8995                                 }
8996                         }
8997                         else
8998                         {
8999                                 $this->mysql = null;
9000                         }
9001                 }
9002         }
9003
9004         function save($data)
9005         {
9006                 if ($this->mysql)
9007                 {
9008                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
9009
9010                         if (is_a($data, 'SimplePie'))
9011                         {
9012                                 if (SIMPLEPIE_PHP5)
9013                                 {
9014                                         // This keyword needs to defy coding standards for PHP4 compatibility
9015                                         $data = clone($data);
9016                                 }
9017
9018                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
9019
9020                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9021                                 {
9022                                         if (mysql_num_rows($query))
9023                                         {
9024                                                 $items = count($prepared[1]);
9025                                                 if ($items)
9026                                                 {
9027                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9028                                                 }
9029                                                 else
9030                                                 {
9031                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9032                                                 }
9033
9034                                                 if (!mysql_query($sql, $this->mysql))
9035                                                 {
9036                                                         return false;
9037                                                 }
9038                                         }
9039                                         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))
9040                                         {
9041                                                 return false;
9042                                         }
9043
9044                                         $ids = array_keys($prepared[1]);
9045                                         if (!empty($ids))
9046                                         {
9047                                                 foreach ($ids as $id)
9048                                                 {
9049                                                         $database_ids[] = mysql_real_escape_string($id);
9050                                                 }
9051
9052                                                 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))
9053                                                 {
9054                                                         $existing_ids = array();
9055                                                         while ($row = mysql_fetch_row($query))
9056                                                         {
9057                                                                 $existing_ids[] = $row[0];
9058                                                         }
9059
9060                                                         $new_ids = array_diff($ids, $existing_ids);
9061
9062                                                         foreach ($new_ids as $new_id)
9063                                                         {
9064                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
9065                                                                 {
9066                                                                         $date = time();
9067                                                                 }
9068
9069                                                                 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))
9070                                                                 {
9071                                                                         return false;
9072                                                                 }
9073                                                         }
9074                                                         return true;
9075                                                 }
9076                                         }
9077                                         else
9078                                         {
9079                                                 return true;
9080                                         }
9081                                 }
9082                         }
9083                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9084                         {
9085                                 if (mysql_num_rows($query))
9086                                 {
9087                                         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))
9088                                         {
9089                                                 return true;
9090                                         }
9091                                 }
9092                                 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))
9093                                 {
9094                                         return true;
9095                                 }
9096                         }
9097                 }
9098                 return false;
9099         }
9100
9101         function load()
9102         {
9103                 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)))
9104                 {
9105                         $data = unserialize($row[1]);
9106
9107                         if (isset($this->options['items'][0]))
9108                         {
9109                                 $items = (int) $this->options['items'][0];
9110                         }
9111                         else
9112                         {
9113                                 $items = (int) $row[0];
9114                         }
9115
9116                         if ($items !== 0)
9117                         {
9118                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9119                                 {
9120                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9121                                 }
9122                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9123                                 {
9124                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9125                                 }
9126                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9127                                 {
9128                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9129                                 }
9130                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9131                                 {
9132                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9133                                 }
9134                                 else
9135                                 {
9136                                         $feed = null;
9137                                 }
9138
9139                                 if ($feed !== null)
9140                                 {
9141                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9142                                         if ($items > 0)
9143                                         {
9144                                                 $sql .= ' LIMIT ' . $items;
9145                                         }
9146
9147                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9148                                         {
9149                                                 while ($row = mysql_fetch_row($query))
9150                                                 {
9151                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9152                                                 }
9153                                         }
9154                                         else
9155                                         {
9156                                                 return false;
9157                                         }
9158                                 }
9159                         }
9160                         return $data;
9161                 }
9162                 return false;
9163         }
9164
9165         function mtime()
9166         {
9167                 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)))
9168                 {
9169                         return $row[0];
9170                 }
9171                 else
9172                 {
9173                         return false;
9174                 }
9175         }
9176
9177         function touch()
9178         {
9179                 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))
9180                 {
9181                         return true;
9182                 }
9183                 else
9184                 {
9185                         return false;
9186                 }
9187         }
9188
9189         function unlink()
9190         {
9191                 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)))
9192                 {
9193                         return true;
9194                 }
9195                 else
9196                 {
9197                         return false;
9198                 }
9199         }
9200 }
9201
9202 class SimplePie_Misc
9203 {
9204         function time_hms($seconds)
9205         {
9206                 $time = '';
9207
9208                 $hours = floor($seconds / 3600);
9209                 $remainder = $seconds % 3600;
9210                 if ($hours > 0)
9211                 {
9212                         $time .= $hours.':';
9213                 }
9214
9215                 $minutes = floor($remainder / 60);
9216                 $seconds = $remainder % 60;
9217                 if ($minutes < 10 && $hours > 0)
9218                 {
9219                         $minutes = '0' . $minutes;
9220                 }
9221                 if ($seconds < 10)
9222                 {
9223                         $seconds = '0' . $seconds;
9224                 }
9225
9226                 $time .= $minutes.':';
9227                 $time .= $seconds;
9228
9229                 return $time;
9230         }
9231
9232         function absolutize_url($relative, $base)
9233         {
9234 return $relative;
9235                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9236                 return $iri->get_iri();
9237         }
9238
9239         function remove_dot_segments($input)
9240         {
9241                 $output = '';
9242                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9243                 {
9244                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9245                         if (strpos($input, '../') === 0)
9246                         {
9247                                 $input = substr($input, 3);
9248                         }
9249                         elseif (strpos($input, './') === 0)
9250                         {
9251                                 $input = substr($input, 2);
9252                         }
9253                         // 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,
9254                         elseif (strpos($input, '/./') === 0)
9255                         {
9256                                 $input = substr_replace($input, '/', 0, 3);
9257                         }
9258                         elseif ($input === '/.')
9259                         {
9260                                 $input = '/';
9261                         }
9262                         // 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,
9263                         elseif (strpos($input, '/../') === 0)
9264                         {
9265                                 $input = substr_replace($input, '/', 0, 4);
9266                                 $output = substr_replace($output, '', strrpos($output, '/'));
9267                         }
9268                         elseif ($input === '/..')
9269                         {
9270                                 $input = '/';
9271                                 $output = substr_replace($output, '', strrpos($output, '/'));
9272                         }
9273                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9274                         elseif ($input === '.' || $input === '..')
9275                         {
9276                                 $input = '';
9277                         }
9278                         // 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
9279                         elseif (($pos = strpos($input, '/', 1)) !== false)
9280                         {
9281                                 $output .= substr($input, 0, $pos);
9282                                 $input = substr_replace($input, '', 0, $pos);
9283                         }
9284                         else
9285                         {
9286                                 $output .= $input;
9287                                 $input = '';
9288                         }
9289                 }
9290                 return $output . $input;
9291         }
9292
9293         function get_element($realname, $string)
9294         {
9295                 $return = array();
9296                 $name = preg_quote($realname, '/');
9297                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9298                 {
9299                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9300                         {
9301                                 $return[$i]['tag'] = $realname;
9302                                 $return[$i]['full'] = $matches[$i][0][0];
9303                                 $return[$i]['offset'] = $matches[$i][0][1];
9304                                 if (strlen($matches[$i][3][0]) <= 2)
9305                                 {
9306                                         $return[$i]['self_closing'] = true;
9307                                 }
9308                                 else
9309                                 {
9310                                         $return[$i]['self_closing'] = false;
9311                                         $return[$i]['content'] = $matches[$i][4][0];
9312                                 }
9313                                 $return[$i]['attribs'] = array();
9314                                 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))
9315                                 {
9316                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9317                                         {
9318                                                 if (count($attribs[$j]) === 2)
9319                                                 {
9320                                                         $attribs[$j][2] = $attribs[$j][1];
9321                                                 }
9322                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9323                                         }
9324                                 }
9325                         }
9326                 }
9327                 return $return;
9328         }
9329
9330         function element_implode($element)
9331         {
9332                 $full = "<$element[tag]";
9333                 foreach ($element['attribs'] as $key => $value)
9334                 {
9335                         $key = strtolower($key);
9336                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9337                 }
9338                 if ($element['self_closing'])
9339                 {
9340                         $full .= ' />';
9341                 }
9342                 else
9343                 {
9344                         $full .= ">$element[content]</$element[tag]>";
9345                 }
9346                 return $full;
9347         }
9348
9349         function error($message, $level, $file, $line)
9350         {
9351                 if ((ini_get('error_reporting') & $level) > 0)
9352                 {
9353                         switch ($level)
9354                         {
9355                                 case E_USER_ERROR:
9356                                         $note = 'PHP Error';
9357                                         break;
9358                                 case E_USER_WARNING:
9359                                         $note = 'PHP Warning';
9360                                         break;
9361                                 case E_USER_NOTICE:
9362                                         $note = 'PHP Notice';
9363                                         break;
9364                                 default:
9365                                         $note = 'Unknown Error';
9366                                         break;
9367                         }
9368
9369                         $log_error = true;
9370                         if (!function_exists('error_log'))
9371                         {
9372                                 $log_error = false;
9373                         }
9374
9375                         $log_file = @ini_get('error_log');
9376                         if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9377                         {
9378                                 $log_error = false;
9379                         }
9380
9381                         if ($log_error)
9382                         {
9383                                 @error_log("$note: $message in $file on line $line", 0);
9384                         }
9385                 }
9386
9387                 return $message;
9388         }
9389
9390         /**
9391          * If a file has been cached, retrieve and display it.
9392          *
9393          * This is most useful for caching images (get_favicon(), etc.),
9394          * however it works for all cached files.  This WILL NOT display ANY
9395          * file/image/page/whatever, but rather only display what has already
9396          * been cached by SimplePie.
9397          *
9398          * @access public
9399          * @see SimplePie::get_favicon()
9400          * @param str $identifier_url URL that is used to identify the content.
9401          * This may or may not be the actual URL of the live content.
9402          * @param str $cache_location Location of SimplePie's cache.  Defaults
9403          * to './cache'.
9404          * @param str $cache_extension The file extension that the file was
9405          * cached with.  Defaults to 'spc'.
9406          * @param str $cache_class Name of the cache-handling class being used
9407          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9408          * as-is unless you've overloaded the class.
9409          * @param str $cache_name_function Obsolete. Exists for backwards
9410          * compatibility reasons only.
9411          */
9412         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9413         {
9414                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9415
9416                 if ($file = $cache->load())
9417                 {
9418                         if (isset($file['headers']['content-type']))
9419                         {
9420                                 header('Content-type:' . $file['headers']['content-type']);
9421                         }
9422                         else
9423                         {
9424                                 header('Content-type: application/octet-stream');
9425                         }
9426                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9427                         echo $file['body'];
9428                         exit;
9429                 }
9430
9431                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9432         }
9433
9434         function fix_protocol($url, $http = 1)
9435         {
9436                 $url = SimplePie_Misc::normalize_url($url);
9437                 $parsed = SimplePie_Misc::parse_url($url);
9438                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9439                 {
9440                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9441                 }
9442
9443                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9444                 {
9445                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9446                 }
9447
9448                 if ($http === 2 && $parsed['scheme'] !== '')
9449                 {
9450                         return "feed:$url";
9451                 }
9452                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9453                 {
9454                         return substr_replace($url, 'podcast', 0, 4);
9455                 }
9456                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9457                 {
9458                         return substr_replace($url, 'itpc', 0, 4);
9459                 }
9460                 else
9461                 {
9462                         return $url;
9463                 }
9464         }
9465
9466         function parse_url($url)
9467         {
9468                 $iri = new SimplePie_IRI($url);
9469                 return array(
9470                         'scheme' => (string) $iri->get_scheme(),
9471                         'authority' => (string) $iri->get_authority(),
9472                         'path' => (string) $iri->get_path(),
9473                         'query' => (string) $iri->get_query(),
9474                         'fragment' => (string) $iri->get_fragment()
9475                 );
9476         }
9477
9478         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9479         {
9480                 $iri = new SimplePie_IRI('');
9481                 $iri->set_scheme($scheme);
9482                 $iri->set_authority($authority);
9483                 $iri->set_path($path);
9484                 $iri->set_query($query);
9485                 $iri->set_fragment($fragment);
9486                 return $iri->get_iri();
9487         }
9488
9489         function normalize_url($url)
9490         {
9491                 $iri = new SimplePie_IRI($url);
9492                 return $iri->get_iri();
9493         }
9494
9495         function percent_encoding_normalization($match)
9496         {
9497                 $integer = hexdec($match[1]);
9498                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9499                 {
9500                         return chr($integer);
9501                 }
9502                 else
9503                 {
9504                         return strtoupper($match[0]);
9505                 }
9506         }
9507
9508         /**
9509          * Remove bad UTF-8 bytes
9510          *
9511          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9512          * FAQ: Multilingual Forms (modified to include full ASCII range)
9513          *
9514          * @author Geoffrey Sneddon
9515          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9516          * @param string $str String to remove bad UTF-8 bytes from
9517          * @return string UTF-8 string
9518          */
9519         function utf8_bad_replace($str)
9520         {
9521                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9522                 {
9523                         return $return;
9524                 }
9525                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9526                 {
9527                         return $return;
9528                 }
9529                 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))
9530                 {
9531                         return implode("\xEF\xBF\xBD", $matches[0]);
9532                 }
9533                 elseif ($str !== '')
9534                 {
9535                         return "\xEF\xBF\xBD";
9536                 }
9537                 else
9538                 {
9539                         return '';
9540                 }
9541         }
9542
9543         /**
9544          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9545          *
9546          * @static
9547          * @access public
9548          * @param string $string Windows-1252 encoded string
9549          * @return string UTF-8 encoded string
9550          */
9551         function windows_1252_to_utf8($string)
9552         {
9553                 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");
9554
9555                 return strtr($string, $convert_table);
9556         }
9557
9558         function change_encoding($data, $input, $output)
9559         {
9560                 $input = SimplePie_Misc::encoding($input);
9561                 $output = SimplePie_Misc::encoding($output);
9562
9563                 // We fail to fail on non US-ASCII bytes
9564                 if ($input === 'US-ASCII')
9565                 {
9566                         static $non_ascii_octects = '';
9567                         if (!$non_ascii_octects)
9568                         {
9569                                 for ($i = 0x80; $i <= 0xFF; $i++)
9570                                 {
9571                                         $non_ascii_octects .= chr($i);
9572                                 }
9573                         }
9574                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9575                 }
9576
9577                 // This is first, as behaviour of this is completely predictable
9578                 if ($input === 'Windows-1252' && $output === 'UTF-8')
9579                 {
9580                         return SimplePie_Misc::windows_1252_to_utf8($data);
9581                 }
9582                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9583                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9584                 {
9585                         return $return;
9586                 }
9587                 // This is last, as behaviour of this varies with OS userland and PHP version
9588                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9589                 {
9590                         return $return;
9591                 }
9592                 // If we can't do anything, just fail
9593                 else
9594                 {
9595                         return false;
9596                 }
9597         }
9598
9599         function encoding($charset)
9600         {
9601                 // Normalization from UTS #22
9602                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9603                 {
9604                         case 'adobestandardencoding':
9605                         case 'csadobestandardencoding':
9606                                 return 'Adobe-Standard-Encoding';
9607
9608                         case 'adobesymbolencoding':
9609                         case 'cshppsmath':
9610                                 return 'Adobe-Symbol-Encoding';
9611
9612                         case 'ami1251':
9613                         case 'amiga1251':
9614                                 return 'Amiga-1251';
9615
9616                         case 'ansix31101983':
9617                         case 'csat5001983':
9618                         case 'csiso99naplps':
9619                         case 'isoir99':
9620                         case 'naplps':
9621                                 return 'ANSI_X3.110-1983';
9622
9623                         case 'arabic7':
9624                         case 'asmo449':
9625                         case 'csiso89asmo449':
9626                         case 'iso9036':
9627                         case 'isoir89':
9628                                 return 'ASMO_449';
9629
9630                         case 'big5':
9631                         case 'csbig5':
9632                         case 'xxbig5':
9633                                 return 'Big5';
9634
9635                         case 'big5hkscs':
9636                                 return 'Big5-HKSCS';
9637
9638                         case 'bocu1':
9639                         case 'csbocu1':
9640                                 return 'BOCU-1';
9641
9642                         case 'brf':
9643                         case 'csbrf':
9644                                 return 'BRF';
9645
9646                         case 'bs4730':
9647                         case 'csiso4unitedkingdom':
9648                         case 'gb':
9649                         case 'iso646gb':
9650                         case 'isoir4':
9651                         case 'uk':
9652                                 return 'BS_4730';
9653
9654                         case 'bsviewdata':
9655                         case 'csiso47bsviewdata':
9656                         case 'isoir47':
9657                                 return 'BS_viewdata';
9658
9659                         case 'cesu8':
9660                         case 'cscesu8':
9661                                 return 'CESU-8';
9662
9663                         case 'ca':
9664                         case 'csa71':
9665                         case 'csaz243419851':
9666                         case 'csiso121canadian1':
9667                         case 'iso646ca':
9668                         case 'isoir121':
9669                                 return 'CSA_Z243.4-1985-1';
9670
9671                         case 'csa72':
9672                         case 'csaz243419852':
9673                         case 'csiso122canadian2':
9674                         case 'iso646ca2':
9675                         case 'isoir122':
9676                                 return 'CSA_Z243.4-1985-2';
9677
9678                         case 'csaz24341985gr':
9679                         case 'csiso123csaz24341985gr':
9680                         case 'isoir123':
9681                                 return 'CSA_Z243.4-1985-gr';
9682
9683                         case 'csiso139csn369103':
9684                         case 'csn369103':
9685                         case 'isoir139':
9686                                 return 'CSN_369103';
9687
9688                         case 'csdecmcs':
9689                         case 'dec':
9690                         case 'decmcs':
9691                                 return 'DEC-MCS';
9692
9693                         case 'csiso21german':
9694                         case 'de':
9695                         case 'din66003':
9696                         case 'iso646de':
9697                         case 'isoir21':
9698                                 return 'DIN_66003';
9699
9700                         case 'csdkus':
9701                         case 'dkus':
9702                                 return 'dk-us';
9703
9704                         case 'csiso646danish':
9705                         case 'dk':
9706                         case 'ds2089':
9707                         case 'iso646dk':
9708                                 return 'DS_2089';
9709
9710                         case 'csibmebcdicatde':
9711                         case 'ebcdicatde':
9712                                 return 'EBCDIC-AT-DE';
9713
9714                         case 'csebcdicatdea':
9715                         case 'ebcdicatdea':
9716                                 return 'EBCDIC-AT-DE-A';
9717
9718                         case 'csebcdiccafr':
9719                         case 'ebcdiccafr':
9720                                 return 'EBCDIC-CA-FR';
9721
9722                         case 'csebcdicdkno':
9723                         case 'ebcdicdkno':
9724                                 return 'EBCDIC-DK-NO';
9725
9726                         case 'csebcdicdknoa':
9727                         case 'ebcdicdknoa':
9728                                 return 'EBCDIC-DK-NO-A';
9729
9730                         case 'csebcdices':
9731                         case 'ebcdices':
9732                                 return 'EBCDIC-ES';
9733
9734                         case 'csebcdicesa':
9735                         case 'ebcdicesa':
9736                                 return 'EBCDIC-ES-A';
9737
9738                         case 'csebcdicess':
9739                         case 'ebcdicess':
9740                                 return 'EBCDIC-ES-S';
9741
9742                         case 'csebcdicfise':
9743                         case 'ebcdicfise':
9744                                 return 'EBCDIC-FI-SE';
9745
9746                         case 'csebcdicfisea':
9747                         case 'ebcdicfisea':
9748                                 return 'EBCDIC-FI-SE-A';
9749
9750                         case 'csebcdicfr':
9751                         case 'ebcdicfr':
9752                                 return 'EBCDIC-FR';
9753
9754                         case 'csebcdicit':
9755                         case 'ebcdicit':
9756                                 return 'EBCDIC-IT';
9757
9758                         case 'csebcdicpt':
9759                         case 'ebcdicpt':
9760                                 return 'EBCDIC-PT';
9761
9762                         case 'csebcdicuk':
9763                         case 'ebcdicuk':
9764                                 return 'EBCDIC-UK';
9765
9766                         case 'csebcdicus':
9767                         case 'ebcdicus':
9768                                 return 'EBCDIC-US';
9769
9770                         case 'csiso111ecmacyrillic':
9771                         case 'ecmacyrillic':
9772                         case 'isoir111':
9773                         case 'koi8e':
9774                                 return 'ECMA-cyrillic';
9775
9776                         case 'csiso17spanish':
9777                         case 'es':
9778                         case 'iso646es':
9779                         case 'isoir17':
9780                                 return 'ES';
9781
9782                         case 'csiso85spanish2':
9783                         case 'es2':
9784                         case 'iso646es2':
9785                         case 'isoir85':
9786                                 return 'ES2';
9787
9788                         case 'cseucfixwidjapanese':
9789                         case 'extendedunixcodefixedwidthforjapanese':
9790                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9791
9792                         case 'cseucpkdfmtjapanese':
9793                         case 'eucjp':
9794                         case 'extendedunixcodepackedformatforjapanese':
9795                                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9796
9797                         case 'gb18030':
9798                                 return 'GB18030';
9799
9800                         case 'chinese':
9801                         case 'cp936':
9802                         case 'csgb2312':
9803                         case 'csiso58gb231280':
9804                         case 'gb2312':
9805                         case 'gb231280':
9806                         case 'gbk':
9807                         case 'isoir58':
9808                         case 'ms936':
9809                         case 'windows936':
9810                                 return 'GBK';
9811
9812                         case 'cn':
9813                         case 'csiso57gb1988':
9814                         case 'gb198880':
9815                         case 'iso646cn':
9816                         case 'isoir57':
9817                                 return 'GB_1988-80';
9818
9819                         case 'csiso153gost1976874':
9820                         case 'gost1976874':
9821                         case 'isoir153':
9822                         case 'stsev35888':
9823                                 return 'GOST_19768-74';
9824
9825                         case 'csiso150':
9826                         case 'csiso150greekccitt':
9827                         case 'greekccitt':
9828                         case 'isoir150':
9829                                 return 'greek-ccitt';
9830
9831                         case 'csiso88greek7':
9832                         case 'greek7':
9833                         case 'isoir88':
9834                                 return 'greek7';
9835
9836                         case 'csiso18greek7old':
9837                         case 'greek7old':
9838                         case 'isoir18':
9839                                 return 'greek7-old';
9840
9841                         case 'cshpdesktop':
9842                         case 'hpdesktop':
9843                                 return 'HP-DeskTop';
9844
9845                         case 'cshplegal':
9846                         case 'hplegal':
9847                                 return 'HP-Legal';
9848
9849                         case 'cshpmath8':
9850                         case 'hpmath8':
9851                                 return 'HP-Math8';
9852
9853                         case 'cshppifont':
9854                         case 'hppifont':
9855                                 return 'HP-Pi-font';
9856
9857                         case 'cshproman8':
9858                         case 'hproman8':
9859                         case 'r8':
9860                         case 'roman8':
9861                                 return 'hp-roman8';
9862
9863                         case 'hzgb2312':
9864                                 return 'HZ-GB-2312';
9865
9866                         case 'csibmsymbols':
9867                         case 'ibmsymbols':
9868                                 return 'IBM-Symbols';
9869
9870                         case 'csibmthai':
9871                         case 'ibmthai':
9872                                 return 'IBM-Thai';
9873
9874                         case 'ccsid858':
9875                         case 'cp858':
9876                         case 'ibm858':
9877                         case 'pcmultilingual850euro':
9878                                 return 'IBM00858';
9879
9880                         case 'ccsid924':
9881                         case 'cp924':
9882                         case 'ebcdiclatin9euro':
9883                         case 'ibm924':
9884                                 return 'IBM00924';
9885
9886                         case 'ccsid1140':
9887                         case 'cp1140':
9888                         case 'ebcdicus37euro':
9889                         case 'ibm1140':
9890                                 return 'IBM01140';
9891
9892                         case 'ccsid1141':
9893                         case 'cp1141':
9894                         case 'ebcdicde273euro':
9895                         case 'ibm1141':
9896                                 return 'IBM01141';
9897
9898                         case 'ccsid1142':
9899                         case 'cp1142':
9900                         case 'ebcdicdk277euro':
9901                         case 'ebcdicno277euro':
9902                         case 'ibm1142':
9903                                 return 'IBM01142';
9904
9905                         case 'ccsid1143':
9906                         case 'cp1143':
9907                         case 'ebcdicfi278euro':
9908                         case 'ebcdicse278euro':
9909                         case 'ibm1143':
9910                                 return 'IBM01143';
9911
9912                         case 'ccsid1144':
9913                         case 'cp1144':
9914                         case 'ebcdicit280euro':
9915                         case 'ibm1144':
9916                                 return 'IBM01144';
9917
9918                         case 'ccsid1145':
9919                         case 'cp1145':
9920                         case 'ebcdices284euro':
9921                         case 'ibm1145':
9922                                 return 'IBM01145';
9923
9924                         case 'ccsid1146':
9925                         case 'cp1146':
9926                         case 'ebcdicgb285euro':
9927                         case 'ibm1146':
9928                                 return 'IBM01146';
9929
9930                         case 'ccsid1147':
9931                         case 'cp1147':
9932                         case 'ebcdicfr297euro':
9933                         case 'ibm1147':
9934                                 return 'IBM01147';
9935
9936                         case 'ccsid1148':
9937                         case 'cp1148':
9938                         case 'ebcdicinternational500euro':
9939                         case 'ibm1148':
9940                                 return 'IBM01148';
9941
9942                         case 'ccsid1149':
9943                         case 'cp1149':
9944                         case 'ebcdicis871euro':
9945                         case 'ibm1149':
9946                                 return 'IBM01149';
9947
9948                         case 'cp37':
9949                         case 'csibm37':
9950                         case 'ebcdiccpca':
9951                         case 'ebcdiccpnl':
9952                         case 'ebcdiccpus':
9953                         case 'ebcdiccpwt':
9954                         case 'ibm37':
9955                                 return 'IBM037';
9956
9957                         case 'cp38':
9958                         case 'csibm38':
9959                         case 'ebcdicint':
9960                         case 'ibm38':
9961                                 return 'IBM038';
9962
9963                         case 'cp273':
9964                         case 'csibm273':
9965                         case 'ibm273':
9966                                 return 'IBM273';
9967
9968                         case 'cp274':
9969                         case 'csibm274':
9970                         case 'ebcdicbe':
9971                         case 'ibm274':
9972                                 return 'IBM274';
9973
9974                         case 'cp275':
9975                         case 'csibm275':
9976                         case 'ebcdicbr':
9977                         case 'ibm275':
9978                                 return 'IBM275';
9979
9980                         case 'csibm277':
9981                         case 'ebcdiccpdk':
9982                         case 'ebcdiccpno':
9983                         case 'ibm277':
9984                                 return 'IBM277';
9985
9986                         case 'cp278':
9987                         case 'csibm278':
9988                         case 'ebcdiccpfi':
9989                         case 'ebcdiccpse':
9990                         case 'ibm278':
9991                                 return 'IBM278';
9992
9993                         case 'cp280':
9994                         case 'csibm280':
9995                         case 'ebcdiccpit':
9996                         case 'ibm280':
9997                                 return 'IBM280';
9998
9999                         case 'cp281':
10000                         case 'csibm281':
10001                         case 'ebcdicjpe':
10002                         case 'ibm281':
10003                                 return 'IBM281';
10004
10005                         case 'cp284':
10006                         case 'csibm284':
10007                         case 'ebcdiccpes':
10008                         case 'ibm284':
10009                                 return 'IBM284';
10010
10011                         case 'cp285':
10012                         case 'csibm285':
10013                         case 'ebcdiccpgb':
10014                         case 'ibm285':
10015                                 return 'IBM285';
10016
10017                         case 'cp290':
10018                         case 'csibm290':
10019                         case 'ebcdicjpkana':
10020                         case 'ibm290':
10021                                 return 'IBM290';
10022
10023                         case 'cp297':
10024                         case 'csibm297':
10025                         case 'ebcdiccpfr':
10026                         case 'ibm297':
10027                                 return 'IBM297';
10028
10029                         case 'cp420':
10030                         case 'csibm420':
10031                         case 'ebcdiccpar1':
10032                         case 'ibm420':
10033                                 return 'IBM420';
10034
10035                         case 'cp423':
10036                         case 'csibm423':
10037                         case 'ebcdiccpgr':
10038                         case 'ibm423':
10039                                 return 'IBM423';
10040
10041                         case 'cp424':
10042                         case 'csibm424':
10043                         case 'ebcdiccphe':
10044                         case 'ibm424':
10045                                 return 'IBM424';
10046
10047                         case '437':
10048                         case 'cp437':
10049                         case 'cspc8codepage437':
10050                         case 'ibm437':
10051                                 return 'IBM437';
10052
10053                         case 'cp500':
10054                         case 'csibm500':
10055                         case 'ebcdiccpbe':
10056                         case 'ebcdiccpch':
10057                         case 'ibm500':
10058                                 return 'IBM500';
10059
10060                         case 'cp775':
10061                         case 'cspc775baltic':
10062                         case 'ibm775':
10063                                 return 'IBM775';
10064
10065                         case '850':
10066                         case 'cp850':
10067                         case 'cspc850multilingual':
10068                         case 'ibm850':
10069                                 return 'IBM850';
10070
10071                         case '851':
10072                         case 'cp851':
10073                         case 'csibm851':
10074                         case 'ibm851':
10075                                 return 'IBM851';
10076
10077                         case '852':
10078                         case 'cp852':
10079                         case 'cspcp852':
10080                         case 'ibm852':
10081                                 return 'IBM852';
10082
10083                         case '855':
10084                         case 'cp855':
10085                         case 'csibm855':
10086                         case 'ibm855':
10087                                 return 'IBM855';
10088
10089                         case '857':
10090                         case 'cp857':
10091                         case 'csibm857':
10092                         case 'ibm857':
10093                                 return 'IBM857';
10094
10095                         case '860':
10096                         case 'cp860':
10097                         case 'csibm860':
10098                         case 'ibm860':
10099                                 return 'IBM860';
10100
10101                         case '861':
10102                         case 'cp861':
10103                         case 'cpis':
10104                         case 'csibm861':
10105                         case 'ibm861':
10106                                 return 'IBM861';
10107
10108                         case '862':
10109                         case 'cp862':
10110                         case 'cspc862latinhebrew':
10111                         case 'ibm862':
10112                                 return 'IBM862';
10113
10114                         case '863':
10115                         case 'cp863':
10116                         case 'csibm863':
10117                         case 'ibm863':
10118                                 return 'IBM863';
10119
10120                         case 'cp864':
10121                         case 'csibm864':
10122                         case 'ibm864':
10123                                 return 'IBM864';
10124
10125                         case '865':
10126                         case 'cp865':
10127                         case 'csibm865':
10128                         case 'ibm865':
10129                                 return 'IBM865';
10130
10131                         case '866':
10132                         case 'cp866':
10133                         case 'csibm866':
10134                         case 'ibm866':
10135                                 return 'IBM866';
10136
10137                         case 'cp868':
10138                         case 'cpar':
10139                         case 'csibm868':
10140                         case 'ibm868':
10141                                 return 'IBM868';
10142
10143                         case '869':
10144                         case 'cp869':
10145                         case 'cpgr':
10146                         case 'csibm869':
10147                         case 'ibm869':
10148                                 return 'IBM869';
10149
10150                         case 'cp870':
10151                         case 'csibm870':
10152                         case 'ebcdiccproece':
10153                         case 'ebcdiccpyu':
10154                         case 'ibm870':
10155                                 return 'IBM870';
10156
10157                         case 'cp871':
10158                         case 'csibm871':
10159                         case 'ebcdiccpis':
10160                         case 'ibm871':
10161                                 return 'IBM871';
10162
10163                         case 'cp880':
10164                         case 'csibm880':
10165                         case 'ebcdiccyrillic':
10166                         case 'ibm880':
10167                                 return 'IBM880';
10168
10169                         case 'cp891':
10170                         case 'csibm891':
10171                         case 'ibm891':
10172                                 return 'IBM891';
10173
10174                         case 'cp903':
10175                         case 'csibm903':
10176                         case 'ibm903':
10177                                 return 'IBM903';
10178
10179                         case '904':
10180                         case 'cp904':
10181                         case 'csibbm904':
10182                         case 'ibm904':
10183                                 return 'IBM904';
10184
10185                         case 'cp905':
10186                         case 'csibm905':
10187                         case 'ebcdiccptr':
10188                         case 'ibm905':
10189                                 return 'IBM905';
10190
10191                         case 'cp918':
10192                         case 'csibm918':
10193                         case 'ebcdiccpar2':
10194                         case 'ibm918':
10195                                 return 'IBM918';
10196
10197                         case 'cp1026':
10198                         case 'csibm1026':
10199                         case 'ibm1026':
10200                                 return 'IBM1026';
10201
10202                         case 'ibm1047':
10203                                 return 'IBM1047';
10204
10205                         case 'csiso143iecp271':
10206                         case 'iecp271':
10207                         case 'isoir143':
10208                                 return 'IEC_P27-1';
10209
10210                         case 'csiso49inis':
10211                         case 'inis':
10212                         case 'isoir49':
10213                                 return 'INIS';
10214
10215                         case 'csiso50inis8':
10216                         case 'inis8':
10217                         case 'isoir50':
10218                                 return 'INIS-8';
10219
10220                         case 'csiso51iniscyrillic':
10221                         case 'iniscyrillic':
10222                         case 'isoir51':
10223                                 return 'INIS-cyrillic';
10224
10225                         case 'csinvariant':
10226                         case 'invariant':
10227                                 return 'INVARIANT';
10228
10229                         case 'iso2022cn':
10230                                 return 'ISO-2022-CN';
10231
10232                         case 'iso2022cnext':
10233                                 return 'ISO-2022-CN-EXT';
10234
10235                         case 'csiso2022jp':
10236                         case 'iso2022jp':
10237                                 return 'ISO-2022-JP';
10238
10239                         case 'csiso2022jp2':
10240                         case 'iso2022jp2':
10241                                 return 'ISO-2022-JP-2';
10242
10243                         case 'csiso2022kr':
10244                         case 'iso2022kr':
10245                                 return 'ISO-2022-KR';
10246
10247                         case 'cswindows30latin1':
10248                         case 'iso88591windows30latin1':
10249                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10250
10251                         case 'cswindows31latin1':
10252                         case 'iso88591windows31latin1':
10253                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10254
10255                         case 'csisolatin2':
10256                         case 'iso88592':
10257                         case 'iso885921987':
10258                         case 'isoir101':
10259                         case 'l2':
10260                         case 'latin2':
10261                                 return 'ISO-8859-2';
10262
10263                         case 'cswindows31latin2':
10264                         case 'iso88592windowslatin2':
10265                                 return 'ISO-8859-2-Windows-Latin-2';
10266
10267                         case 'csisolatin3':
10268                         case 'iso88593':
10269                         case 'iso885931988':
10270                         case 'isoir109':
10271                         case 'l3':
10272                         case 'latin3':
10273                                 return 'ISO-8859-3';
10274
10275                         case 'csisolatin4':
10276                         case 'iso88594':
10277                         case 'iso885941988':
10278                         case 'isoir110':
10279                         case 'l4':
10280                         case 'latin4':
10281                                 return 'ISO-8859-4';
10282
10283                         case 'csisolatincyrillic':
10284                         case 'cyrillic':
10285                         case 'iso88595':
10286                         case 'iso885951988':
10287                         case 'isoir144':
10288                                 return 'ISO-8859-5';
10289
10290                         case 'arabic':
10291                         case 'asmo708':
10292                         case 'csisolatinarabic':
10293                         case 'ecma114':
10294                         case 'iso88596':
10295                         case 'iso885961987':
10296                         case 'isoir127':
10297                                 return 'ISO-8859-6';
10298
10299                         case 'csiso88596e':
10300                         case 'iso88596e':
10301                                 return 'ISO-8859-6-E';
10302
10303                         case 'csiso88596i':
10304                         case 'iso88596i':
10305                                 return 'ISO-8859-6-I';
10306
10307                         case 'csisolatingreek':
10308                         case 'ecma118':
10309                         case 'elot928':
10310                         case 'greek':
10311                         case 'greek8':
10312                         case 'iso88597':
10313                         case 'iso885971987':
10314                         case 'isoir126':
10315                                 return 'ISO-8859-7';
10316
10317                         case 'csisolatinhebrew':
10318                         case 'hebrew':
10319                         case 'iso88598':
10320                         case 'iso885981988':
10321                         case 'isoir138':
10322                                 return 'ISO-8859-8';
10323
10324                         case 'csiso88598e':
10325                         case 'iso88598e':
10326                                 return 'ISO-8859-8-E';
10327
10328                         case 'csiso88598i':
10329                         case 'iso88598i':
10330                                 return 'ISO-8859-8-I';
10331
10332                         case 'cswindows31latin5':
10333                         case 'iso88599windowslatin5':
10334                                 return 'ISO-8859-9-Windows-Latin-5';
10335
10336                         case 'csisolatin6':
10337                         case 'iso885910':
10338                         case 'iso8859101992':
10339                         case 'isoir157':
10340                         case 'l6':
10341                         case 'latin6':
10342                                 return 'ISO-8859-10';
10343
10344                         case 'iso885913':
10345                                 return 'ISO-8859-13';
10346
10347                         case 'iso885914':
10348                         case 'iso8859141998':
10349                         case 'isoceltic':
10350                         case 'isoir199':
10351                         case 'l8':
10352                         case 'latin8':
10353                                 return 'ISO-8859-14';
10354
10355                         case 'iso885915':
10356                         case 'latin9':
10357                                 return 'ISO-8859-15';
10358
10359                         case 'iso885916':
10360                         case 'iso8859162001':
10361                         case 'isoir226':
10362                         case 'l10':
10363                         case 'latin10':
10364                                 return 'ISO-8859-16';
10365
10366                         case 'iso10646j1':
10367                                 return 'ISO-10646-J-1';
10368
10369                         case 'csunicode':
10370                         case 'iso10646ucs2':
10371                                 return 'ISO-10646-UCS-2';
10372
10373                         case 'csucs4':
10374                         case 'iso10646ucs4':
10375                                 return 'ISO-10646-UCS-4';
10376
10377                         case 'csunicodeascii':
10378                         case 'iso10646ucsbasic':
10379                                 return 'ISO-10646-UCS-Basic';
10380
10381                         case 'csunicodelatin1':
10382                         case 'iso10646':
10383                         case 'iso10646unicodelatin1':
10384                                 return 'ISO-10646-Unicode-Latin1';
10385
10386                         case 'csiso10646utf1':
10387                         case 'iso10646utf1':
10388                                 return 'ISO-10646-UTF-1';
10389
10390                         case 'csiso115481':
10391                         case 'iso115481':
10392                         case 'isotr115481':
10393                                 return 'ISO-11548-1';
10394
10395                         case 'csiso90':
10396                         case 'isoir90':
10397                                 return 'iso-ir-90';
10398
10399                         case 'csunicodeibm1261':
10400                         case 'isounicodeibm1261':
10401                                 return 'ISO-Unicode-IBM-1261';
10402
10403                         case 'csunicodeibm1264':
10404                         case 'isounicodeibm1264':
10405                                 return 'ISO-Unicode-IBM-1264';
10406
10407                         case 'csunicodeibm1265':
10408                         case 'isounicodeibm1265':
10409                                 return 'ISO-Unicode-IBM-1265';
10410
10411                         case 'csunicodeibm1268':
10412                         case 'isounicodeibm1268':
10413                                 return 'ISO-Unicode-IBM-1268';
10414
10415                         case 'csunicodeibm1276':
10416                         case 'isounicodeibm1276':
10417                                 return 'ISO-Unicode-IBM-1276';
10418
10419                         case 'csiso646basic1983':
10420                         case 'iso646basic1983':
10421                         case 'ref':
10422                                 return 'ISO_646.basic:1983';
10423
10424                         case 'csiso2intlrefversion':
10425                         case 'irv':
10426                         case 'iso646irv1983':
10427                         case 'isoir2':
10428                                 return 'ISO_646.irv:1983';
10429
10430                         case 'csiso2033':
10431                         case 'e13b':
10432                         case 'iso20331983':
10433                         case 'isoir98':
10434                                 return 'ISO_2033-1983';
10435
10436                         case 'csiso5427cyrillic':
10437                         case 'iso5427':
10438                         case 'isoir37':
10439                                 return 'ISO_5427';
10440
10441                         case 'iso5427cyrillic1981':
10442                         case 'iso54271981':
10443                         case 'isoir54':
10444                                 return 'ISO_5427:1981';
10445
10446                         case 'csiso5428greek':
10447                         case 'iso54281980':
10448                         case 'isoir55':
10449                                 return 'ISO_5428:1980';
10450
10451                         case 'csiso6937add':
10452                         case 'iso6937225':
10453                         case 'isoir152':
10454                                 return 'ISO_6937-2-25';
10455
10456                         case 'csisotextcomm':
10457                         case 'iso69372add':
10458                         case 'isoir142':
10459                                 return 'ISO_6937-2-add';
10460
10461                         case 'csiso8859supp':
10462                         case 'iso8859supp':
10463                         case 'isoir154':
10464                         case 'latin125':
10465                                 return 'ISO_8859-supp';
10466
10467                         case 'csiso10367box':
10468                         case 'iso10367box':
10469                         case 'isoir155':
10470                                 return 'ISO_10367-box';
10471
10472                         case 'csiso15italian':
10473                         case 'iso646it':
10474                         case 'isoir15':
10475                         case 'it':
10476                                 return 'IT';
10477
10478                         case 'csiso13jisc6220jp':
10479                         case 'isoir13':
10480                         case 'jisc62201969':
10481                         case 'jisc62201969jp':
10482                         case 'katakana':
10483                         case 'x2017':
10484                                 return 'JIS_C6220-1969-jp';
10485
10486                         case 'csiso14jisc6220ro':
10487                         case 'iso646jp':
10488                         case 'isoir14':
10489                         case 'jisc62201969ro':
10490                         case 'jp':
10491                                 return 'JIS_C6220-1969-ro';
10492
10493                         case 'csiso42jisc62261978':
10494                         case 'isoir42':
10495                         case 'jisc62261978':
10496                                 return 'JIS_C6226-1978';
10497
10498                         case 'csiso87jisx208':
10499                         case 'isoir87':
10500                         case 'jisc62261983':
10501                         case 'jisx2081983':
10502                         case 'x208':
10503                                 return 'JIS_C6226-1983';
10504
10505                         case 'csiso91jisc62291984a':
10506                         case 'isoir91':
10507                         case 'jisc62291984a':
10508                         case 'jpocra':
10509                                 return 'JIS_C6229-1984-a';
10510
10511                         case 'csiso92jisc62991984b':
10512                         case 'iso646jpocrb':
10513                         case 'isoir92':
10514                         case 'jisc62291984b':
10515                         case 'jpocrb':
10516                                 return 'JIS_C6229-1984-b';
10517
10518                         case 'csiso93jis62291984badd':
10519                         case 'isoir93':
10520                         case 'jisc62291984badd':
10521                         case 'jpocrbadd':
10522                                 return 'JIS_C6229-1984-b-add';
10523
10524                         case 'csiso94jis62291984hand':
10525                         case 'isoir94':
10526                         case 'jisc62291984hand':
10527                         case 'jpocrhand':
10528                                 return 'JIS_C6229-1984-hand';
10529
10530                         case 'csiso95jis62291984handadd':
10531                         case 'isoir95':
10532                         case 'jisc62291984handadd':
10533                         case 'jpocrhandadd':
10534                                 return 'JIS_C6229-1984-hand-add';
10535
10536                         case 'csiso96jisc62291984kana':
10537                         case 'isoir96':
10538                         case 'jisc62291984kana':
10539                                 return 'JIS_C6229-1984-kana';
10540
10541                         case 'csjisencoding':
10542                         case 'jisencoding':
10543                                 return 'JIS_Encoding';
10544
10545                         case 'cshalfwidthkatakana':
10546                         case 'jisx201':
10547                         case 'x201':
10548                                 return 'JIS_X0201';
10549
10550                         case 'csiso159jisx2121990':
10551                         case 'isoir159':
10552                         case 'jisx2121990':
10553                         case 'x212':
10554                                 return 'JIS_X0212-1990';
10555
10556                         case 'csiso141jusib1002':
10557                         case 'iso646yu':
10558                         case 'isoir141':
10559                         case 'js':
10560                         case 'jusib1002':
10561                         case 'yu':
10562                                 return 'JUS_I.B1.002';
10563
10564                         case 'csiso147macedonian':
10565                         case 'isoir147':
10566                         case 'jusib1003mac':
10567                         case 'macedonian':
10568                                 return 'JUS_I.B1.003-mac';
10569
10570                         case 'csiso146serbian':
10571                         case 'isoir146':
10572                         case 'jusib1003serb':
10573                         case 'serbian':
10574                                 return 'JUS_I.B1.003-serb';
10575
10576                         case 'koi7switched':
10577                                 return 'KOI7-switched';
10578
10579                         case 'cskoi8r':
10580                         case 'koi8r':
10581                                 return 'KOI8-R';
10582
10583                         case 'koi8u':
10584                                 return 'KOI8-U';
10585
10586                         case 'csksc5636':
10587                         case 'iso646kr':
10588                         case 'ksc5636':
10589                                 return 'KSC5636';
10590
10591                         case 'cskz1048':
10592                         case 'kz1048':
10593                         case 'rk1048':
10594                         case 'strk10482002':
10595                                 return 'KZ-1048';
10596
10597                         case 'csiso19latingreek':
10598                         case 'isoir19':
10599                         case 'latingreek':
10600                                 return 'latin-greek';
10601
10602                         case 'csiso27latingreek1':
10603                         case 'isoir27':
10604                         case 'latingreek1':
10605                                 return 'Latin-greek-1';
10606
10607                         case 'csiso158lap':
10608                         case 'isoir158':
10609                         case 'lap':
10610                         case 'latinlap':
10611                                 return 'latin-lap';
10612
10613                         case 'csmacintosh':
10614                         case 'mac':
10615                         case 'macintosh':
10616                                 return 'macintosh';
10617
10618                         case 'csmicrosoftpublishing':
10619                         case 'microsoftpublishing':
10620                                 return 'Microsoft-Publishing';
10621
10622                         case 'csmnem':
10623                         case 'mnem':
10624                                 return 'MNEM';
10625
10626                         case 'csmnemonic':
10627                         case 'mnemonic':
10628                                 return 'MNEMONIC';
10629
10630                         case 'csiso86hungarian':
10631                         case 'hu':
10632                         case 'iso646hu':
10633                         case 'isoir86':
10634                         case 'msz77953':
10635                                 return 'MSZ_7795.3';
10636
10637                         case 'csnatsdano':
10638                         case 'isoir91':
10639                         case 'natsdano':
10640                                 return 'NATS-DANO';
10641
10642                         case 'csnatsdanoadd':
10643                         case 'isoir92':
10644                         case 'natsdanoadd':
10645                                 return 'NATS-DANO-ADD';
10646
10647                         case 'csnatssefi':
10648                         case 'isoir81':
10649                         case 'natssefi':
10650                                 return 'NATS-SEFI';
10651
10652                         case 'csnatssefiadd':
10653                         case 'isoir82':
10654                         case 'natssefiadd':
10655                                 return 'NATS-SEFI-ADD';
10656
10657                         case 'csiso151cuba':
10658                         case 'cuba':
10659                         case 'iso646cu':
10660                         case 'isoir151':
10661                         case 'ncnc1081':
10662                                 return 'NC_NC00-10:81';
10663
10664                         case 'csiso69french':
10665                         case 'fr':
10666                         case 'iso646fr':
10667                         case 'isoir69':
10668                         case 'nfz62010':
10669                                 return 'NF_Z_62-010';
10670
10671                         case 'csiso25french':
10672                         case 'iso646fr1':
10673                         case 'isoir25':
10674                         case 'nfz620101973':
10675                                 return 'NF_Z_62-010_(1973)';
10676
10677                         case 'csiso60danishnorwegian':
10678                         case 'csiso60norwegian1':
10679                         case 'iso646no':
10680                         case 'isoir60':
10681                         case 'no':
10682                         case 'ns45511':
10683                                 return 'NS_4551-1';
10684
10685                         case 'csiso61norwegian2':
10686                         case 'iso646no2':
10687                         case 'isoir61':
10688                         case 'no2':
10689                         case 'ns45512':
10690                                 return 'NS_4551-2';
10691
10692                         case 'osdebcdicdf3irv':
10693                                 return 'OSD_EBCDIC_DF03_IRV';
10694
10695                         case 'osdebcdicdf41':
10696                                 return 'OSD_EBCDIC_DF04_1';
10697
10698                         case 'osdebcdicdf415':
10699                                 return 'OSD_EBCDIC_DF04_15';
10700
10701                         case 'cspc8danishnorwegian':
10702                         case 'pc8danishnorwegian':
10703                                 return 'PC8-Danish-Norwegian';
10704
10705                         case 'cspc8turkish':
10706                         case 'pc8turkish':
10707                                 return 'PC8-Turkish';
10708
10709                         case 'csiso16portuguese':
10710                         case 'iso646pt':
10711                         case 'isoir16':
10712                         case 'pt':
10713                                 return 'PT';
10714
10715                         case 'csiso84portuguese2':
10716                         case 'iso646pt2':
10717                         case 'isoir84':
10718                         case 'pt2':
10719                                 return 'PT2';
10720
10721                         case 'cp154':
10722                         case 'csptcp154':
10723                         case 'cyrillicasian':
10724                         case 'pt154':
10725                         case 'ptcp154':
10726                                 return 'PTCP154';
10727
10728                         case 'scsu':
10729                                 return 'SCSU';
10730
10731                         case 'csiso10swedish':
10732                         case 'fi':
10733                         case 'iso646fi':
10734                         case 'iso646se':
10735                         case 'isoir10':
10736                         case 'se':
10737                         case 'sen850200b':
10738                                 return 'SEN_850200_B';
10739
10740                         case 'csiso11swedishfornames':
10741                         case 'iso646se2':
10742                         case 'isoir11':
10743                         case 'se2':
10744                         case 'sen850200c':
10745                                 return 'SEN_850200_C';
10746
10747                         case 'csshiftjis':
10748                         case 'mskanji':
10749                         case 'shiftjis':
10750                                 return 'Shift_JIS';
10751
10752                         case 'csiso102t617bit':
10753                         case 'isoir102':
10754                         case 't617bit':
10755                                 return 'T.61-7bit';
10756
10757                         case 'csiso103t618bit':
10758                         case 'isoir103':
10759                         case 't61':
10760                         case 't618bit':
10761                                 return 'T.61-8bit';
10762
10763                         case 'csiso128t101g2':
10764                         case 'isoir128':
10765                         case 't101g2':
10766                                 return 'T.101-G2';
10767
10768                         case 'cstscii':
10769                         case 'tscii':
10770                                 return 'TSCII';
10771
10772                         case 'csunicode11':
10773                         case 'unicode11':
10774                                 return 'UNICODE-1-1';
10775
10776                         case 'csunicode11utf7':
10777                         case 'unicode11utf7':
10778                                 return 'UNICODE-1-1-UTF-7';
10779
10780                         case 'csunknown8bit':
10781                         case 'unknown8bit':
10782                                 return 'UNKNOWN-8BIT';
10783
10784                         case 'ansix341968':
10785                         case 'ansix341986':
10786                         case 'ascii':
10787                         case 'cp367':
10788                         case 'csascii':
10789                         case 'ibm367':
10790                         case 'iso646irv1991':
10791                         case 'iso646us':
10792                         case 'isoir6':
10793                         case 'us':
10794                         case 'usascii':
10795                                 return 'US-ASCII';
10796
10797                         case 'csusdk':
10798                         case 'usdk':
10799                                 return 'us-dk';
10800
10801                         case 'utf7':
10802                                 return 'UTF-7';
10803
10804                         case 'utf8':
10805                                 return 'UTF-8';
10806
10807                         case 'utf16':
10808                                 return 'UTF-16';
10809
10810                         case 'utf16be':
10811                                 return 'UTF-16BE';
10812
10813                         case 'utf16le':
10814                                 return 'UTF-16LE';
10815
10816                         case 'utf32':
10817                                 return 'UTF-32';
10818
10819                         case 'utf32be':
10820                                 return 'UTF-32BE';
10821
10822                         case 'utf32le':
10823                                 return 'UTF-32LE';
10824
10825                         case 'csventurainternational':
10826                         case 'venturainternational':
10827                                 return 'Ventura-International';
10828
10829                         case 'csventuramath':
10830                         case 'venturamath':
10831                                 return 'Ventura-Math';
10832
10833                         case 'csventuraus':
10834                         case 'venturaus':
10835                                 return 'Ventura-US';
10836
10837                         case 'csiso70videotexsupp1':
10838                         case 'isoir70':
10839                         case 'videotexsuppl':
10840                                 return 'videotex-suppl';
10841
10842                         case 'csviqr':
10843                         case 'viqr':
10844                                 return 'VIQR';
10845
10846                         case 'csviscii':
10847                         case 'viscii':
10848                                 return 'VISCII';
10849
10850                         case 'cswindows31j':
10851                         case 'windows31j':
10852                                 return 'Windows-31J';
10853
10854                         case 'iso885911':
10855                         case 'tis620':
10856                                 return 'windows-874';
10857
10858                         case 'cseuckr':
10859                         case 'csksc56011987':
10860                         case 'euckr':
10861                         case 'isoir149':
10862                         case 'korean':
10863                         case 'ksc5601':
10864                         case 'ksc56011987':
10865                         case 'ksc56011989':
10866                         case 'windows949':
10867                                 return 'windows-949';
10868
10869                         case 'windows1250':
10870                                 return 'windows-1250';
10871
10872                         case 'windows1251':
10873                                 return 'windows-1251';
10874
10875                         case 'cp819':
10876                         case 'csisolatin1':
10877                         case 'ibm819':
10878                         case 'iso88591':
10879                         case 'iso885911987':
10880                         case 'isoir100':
10881                         case 'l1':
10882                         case 'latin1':
10883                         case 'windows1252':
10884                                 return 'windows-1252';
10885
10886                         case 'windows1253':
10887                                 return 'windows-1253';
10888
10889                         case 'csisolatin5':
10890                         case 'iso88599':
10891                         case 'iso885991989':
10892                         case 'isoir148':
10893                         case 'l5':
10894                         case 'latin5':
10895                         case 'windows1254':
10896                                 return 'windows-1254';
10897
10898                         case 'windows1255':
10899                                 return 'windows-1255';
10900
10901                         case 'windows1256':
10902                                 return 'windows-1256';
10903
10904                         case 'windows1257':
10905                                 return 'windows-1257';
10906
10907                         case 'windows1258':
10908                                 return 'windows-1258';
10909
10910                         default:
10911                                 return $charset;
10912                 }
10913         }
10914
10915         function get_curl_version()
10916         {
10917                 if (is_array($curl = curl_version()))
10918                 {
10919                         $curl = $curl['version'];
10920                 }
10921                 elseif (substr($curl, 0, 5) === 'curl/')
10922                 {
10923                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10924                 }
10925                 elseif (substr($curl, 0, 8) === 'libcurl/')
10926                 {
10927                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10928                 }
10929                 else
10930                 {
10931                         $curl = 0;
10932                 }
10933                 return $curl;
10934         }
10935
10936         function is_subclass_of($class1, $class2)
10937         {
10938                 if (func_num_args() !== 2)
10939                 {
10940                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10941                 }
10942                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10943                 {
10944                         return is_subclass_of($class1, $class2);
10945                 }
10946                 elseif (is_string($class1) && is_string($class2))
10947                 {
10948                         if (class_exists($class1))
10949                         {
10950                                 if (class_exists($class2))
10951                                 {
10952                                         $class2 = strtolower($class2);
10953                                         while ($class1 = strtolower(get_parent_class($class1)))
10954                                         {
10955                                                 if ($class1 === $class2)
10956                                                 {
10957                                                         return true;
10958                                                 }
10959                                         }
10960                                 }
10961                         }
10962                         else
10963                         {
10964                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10965                         }
10966                 }
10967                 return false;
10968         }
10969
10970         /**
10971          * Strip HTML comments
10972          *
10973          * @access public
10974          * @param string $data Data to strip comments from
10975          * @return string Comment stripped string
10976          */
10977         function strip_comments($data)
10978         {
10979                 $output = '';
10980                 while (($start = strpos($data, '<!--')) !== false)
10981                 {
10982                         $output .= substr($data, 0, $start);
10983                         if (($end = strpos($data, '-->', $start)) !== false)
10984                         {
10985                                 $data = substr_replace($data, '', 0, $end + 3);
10986                         }
10987                         else
10988                         {
10989                                 $data = '';
10990                         }
10991                 }
10992                 return $output . $data;
10993         }
10994
10995         function parse_date($dt)
10996         {
10997                 $parser = SimplePie_Parse_Date::get();
10998                 return $parser->parse($dt);
10999         }
11000
11001         /**
11002          * Decode HTML entities
11003          *
11004          * @static
11005          * @access public
11006          * @param string $data Input data
11007          * @return string Output data
11008          */
11009         function entities_decode($data)
11010         {
11011                 $decoder = new SimplePie_Decode_HTML_Entities($data);
11012                 return $decoder->parse();
11013         }
11014
11015         /**
11016          * Remove RFC822 comments
11017          *
11018          * @access public
11019          * @param string $data Data to strip comments from
11020          * @return string Comment stripped string
11021          */
11022         function uncomment_rfc822($string)
11023         {
11024                 $string = (string) $string;
11025                 $position = 0;
11026                 $length = strlen($string);
11027                 $depth = 0;
11028
11029                 $output = '';
11030
11031                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11032                 {
11033                         $output .= substr($string, $position, $pos - $position);
11034                         $position = $pos + 1;
11035                         if ($string[$pos - 1] !== '\\')
11036                         {
11037                                 $depth++;
11038                                 while ($depth && $position < $length)
11039                                 {
11040                                         $position += strcspn($string, '()', $position);
11041                                         if ($string[$position - 1] === '\\')
11042                                         {
11043                                                 $position++;
11044                                                 continue;
11045                                         }
11046                                         elseif (isset($string[$position]))
11047                                         {
11048                                                 switch ($string[$position])
11049                                                 {
11050                                                         case '(':
11051                                                                 $depth++;
11052                                                                 break;
11053
11054                                                         case ')':
11055                                                                 $depth--;
11056                                                                 break;
11057                                                 }
11058                                                 $position++;
11059                                         }
11060                                         else
11061                                         {
11062                                                 break;
11063                                         }
11064                                 }
11065                         }
11066                         else
11067                         {
11068                                 $output .= '(';
11069                         }
11070                 }
11071                 $output .= substr($string, $position);
11072
11073                 return $output;
11074         }
11075
11076         function parse_mime($mime)
11077         {
11078                 if (($pos = strpos($mime, ';')) === false)
11079                 {
11080                         return trim($mime);
11081                 }
11082                 else
11083                 {
11084                         return trim(substr($mime, 0, $pos));
11085                 }
11086         }
11087
11088         function htmlspecialchars_decode($string, $quote_style)
11089         {
11090                 if (function_exists('htmlspecialchars_decode'))
11091                 {
11092                         return htmlspecialchars_decode($string, $quote_style);
11093                 }
11094                 else
11095                 {
11096                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11097                 }
11098         }
11099
11100         function atom_03_construct_type($attribs)
11101         {
11102                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11103                 {
11104                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11105                 }
11106                 else
11107                 {
11108                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
11109                 }
11110                 if (isset($attribs['']['type']))
11111                 {
11112                         switch (strtolower(trim($attribs['']['type'])))
11113                         {
11114                                 case 'text':
11115                                 case 'text/plain':
11116                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11117
11118                                 case 'html':
11119                                 case 'text/html':
11120                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11121
11122                                 case 'xhtml':
11123                                 case 'application/xhtml+xml':
11124                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11125
11126                                 default:
11127                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11128                         }
11129                 }
11130                 else
11131                 {
11132                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11133                 }
11134         }
11135
11136         function atom_10_construct_type($attribs)
11137         {
11138                 if (isset($attribs['']['type']))
11139                 {
11140                         switch (strtolower(trim($attribs['']['type'])))
11141                         {
11142                                 case 'text':
11143                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11144
11145                                 case 'html':
11146                                         return SIMPLEPIE_CONSTRUCT_HTML;
11147
11148                                 case 'xhtml':
11149                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11150
11151                                 default:
11152                                         return SIMPLEPIE_CONSTRUCT_NONE;
11153                         }
11154                 }
11155                 return SIMPLEPIE_CONSTRUCT_TEXT;
11156         }
11157
11158         function atom_10_content_construct_type($attribs)
11159         {
11160                 if (isset($attribs['']['type']))
11161                 {
11162                         $type = strtolower(trim($attribs['']['type']));
11163                         switch ($type)
11164                         {
11165                                 case 'text':
11166                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11167
11168                                 case 'html':
11169                                         return SIMPLEPIE_CONSTRUCT_HTML;
11170
11171                                 case 'xhtml':
11172                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11173                         }
11174                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11175                         {
11176                                 return SIMPLEPIE_CONSTRUCT_NONE;
11177                         }
11178                         else
11179                         {
11180                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11181                         }
11182                 }
11183                 else
11184                 {
11185                         return SIMPLEPIE_CONSTRUCT_TEXT;
11186                 }
11187         }
11188
11189         function is_isegment_nz_nc($string)
11190         {
11191                 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);
11192         }
11193
11194         function space_seperated_tokens($string)
11195         {
11196                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11197                 $string_length = strlen($string);
11198
11199                 $position = strspn($string, $space_characters);
11200                 $tokens = array();
11201
11202                 while ($position < $string_length)
11203                 {
11204                         $len = strcspn($string, $space_characters, $position);
11205                         $tokens[] = substr($string, $position, $len);
11206                         $position += $len;
11207                         $position += strspn($string, $space_characters, $position);
11208                 }
11209
11210                 return $tokens;
11211         }
11212
11213         function array_unique($array)
11214         {
11215                 if (version_compare(PHP_VERSION, '5.2', '>='))
11216                 {
11217                         return array_unique($array);
11218                 }
11219                 else
11220                 {
11221                         $array = (array) $array;
11222                         $new_array = array();
11223                         $new_array_strings = array();
11224                         foreach ($array as $key => $value)
11225                         {
11226                                 if (is_object($value))
11227                                 {
11228                                         if (method_exists($value, '__toString'))
11229                                         {
11230                                                 $cmp = $value->__toString();
11231                                         }
11232                                         else
11233                                         {
11234                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11235                                         }
11236                                 }
11237                                 elseif (is_array($value))
11238                                 {
11239                                         $cmp = (string) reset($value);
11240                                 }
11241                                 else
11242                                 {
11243                                         $cmp = (string) $value;
11244                                 }
11245                                 if (!in_array($cmp, $new_array_strings))
11246                                 {
11247                                         $new_array[$key] = $value;
11248                                         $new_array_strings[] = $cmp;
11249                                 }
11250                         }
11251                         return $new_array;
11252                 }
11253         }
11254
11255         /**
11256          * Converts a unicode codepoint to a UTF-8 character
11257          *
11258          * @static
11259          * @access public
11260          * @param int $codepoint Unicode codepoint
11261          * @return string UTF-8 character
11262          */
11263         function codepoint_to_utf8($codepoint)
11264         {
11265                 $codepoint = (int) $codepoint;
11266                 if ($codepoint < 0)
11267                 {
11268                         return false;
11269                 }
11270                 else if ($codepoint <= 0x7f)
11271                 {
11272                         return chr($codepoint);
11273                 }
11274                 else if ($codepoint <= 0x7ff)
11275                 {
11276                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11277                 }
11278                 else if ($codepoint <= 0xffff)
11279                 {
11280                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11281                 }
11282                 else if ($codepoint <= 0x10ffff)
11283                 {
11284                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11285                 }
11286                 else
11287                 {
11288                         // U+FFFD REPLACEMENT CHARACTER
11289                         return "\xEF\xBF\xBD";
11290                 }
11291         }
11292
11293         /**
11294          * Re-implementation of PHP 5's stripos()
11295          *
11296          * Returns the numeric position of the first occurrence of needle in the
11297          * haystack string.
11298          *
11299          * @static
11300          * @access string
11301          * @param object $haystack
11302          * @param string $needle Note that the needle may be a string of one or more
11303          *     characters. If needle is not a string, it is converted to an integer
11304          *     and applied as the ordinal value of a character.
11305          * @param int $offset The optional offset parameter allows you to specify which
11306          *     character in haystack to start searching. The position returned is still
11307          *     relative to the beginning of haystack.
11308          * @return bool If needle is not found, stripos() will return boolean false.
11309          */
11310         function stripos($haystack, $needle, $offset = 0)
11311         {
11312                 if (function_exists('stripos'))
11313                 {
11314                         return stripos($haystack, $needle, $offset);
11315                 }
11316                 else
11317                 {
11318                         if (is_string($needle))
11319                         {
11320                                 $needle = strtolower($needle);
11321                         }
11322                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11323                         {
11324                                 $needle = strtolower(chr($needle));
11325                         }
11326                         else
11327                         {
11328                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11329                                 return false;
11330                         }
11331
11332                         return strpos(strtolower($haystack), $needle, $offset);
11333                 }
11334         }
11335
11336         /**
11337          * Similar to parse_str()
11338          *
11339          * Returns an associative array of name/value pairs, where the value is an
11340          * array of values that have used the same name
11341          *
11342          * @static
11343          * @access string
11344          * @param string $str The input string.
11345          * @return array
11346          */
11347         function parse_str($str)
11348         {
11349                 $return = array();
11350                 $str = explode('&', $str);
11351
11352                 foreach ($str as $section)
11353                 {
11354                         if (strpos($section, '=') !== false)
11355                         {
11356                                 list($name, $value) = explode('=', $section, 2);
11357                                 $return[urldecode($name)][] = urldecode($value);
11358                         }
11359                         else
11360                         {
11361                                 $return[urldecode($section)][] = null;
11362                         }
11363                 }
11364
11365                 return $return;
11366         }
11367
11368         /**
11369          * Detect XML encoding, as per XML 1.0 Appendix F.1
11370          *
11371          * @todo Add support for EBCDIC
11372          * @param string $data XML data
11373          * @return array Possible encodings
11374          */
11375         function xml_encoding($data)
11376         {
11377                 // UTF-32 Big Endian BOM
11378                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11379                 {
11380                         $encoding[] = 'UTF-32BE';
11381                 }
11382                 // UTF-32 Little Endian BOM
11383                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11384                 {
11385                         $encoding[] = 'UTF-32LE';
11386                 }
11387                 // UTF-16 Big Endian BOM
11388                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11389                 {
11390                         $encoding[] = 'UTF-16BE';
11391                 }
11392                 // UTF-16 Little Endian BOM
11393                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11394                 {
11395                         $encoding[] = 'UTF-16LE';
11396                 }
11397                 // UTF-8 BOM
11398                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11399                 {
11400                         $encoding[] = 'UTF-8';
11401                 }
11402                 // UTF-32 Big Endian Without BOM
11403                 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")
11404                 {
11405                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11406                         {
11407                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11408                                 if ($parser->parse())
11409                                 {
11410                                         $encoding[] = $parser->encoding;
11411                                 }
11412                         }
11413                         $encoding[] = 'UTF-32BE';
11414                 }
11415                 // UTF-32 Little Endian Without BOM
11416                 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")
11417                 {
11418                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11419                         {
11420                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11421                                 if ($parser->parse())
11422                                 {
11423                                         $encoding[] = $parser->encoding;
11424                                 }
11425                         }
11426                         $encoding[] = 'UTF-32LE';
11427                 }
11428                 // UTF-16 Big Endian Without BOM
11429                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11430                 {
11431                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11432                         {
11433                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11434                                 if ($parser->parse())
11435                                 {
11436                                         $encoding[] = $parser->encoding;
11437                                 }
11438                         }
11439                         $encoding[] = 'UTF-16BE';
11440                 }
11441                 // UTF-16 Little Endian Without BOM
11442                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11443                 {
11444                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11445                         {
11446                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11447                                 if ($parser->parse())
11448                                 {
11449                                         $encoding[] = $parser->encoding;
11450                                 }
11451                         }
11452                         $encoding[] = 'UTF-16LE';
11453                 }
11454                 // US-ASCII (or superset)
11455                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11456                 {
11457                         if ($pos = strpos($data, "\x3F\x3E"))
11458                         {
11459                                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11460                                 if ($parser->parse())
11461                                 {
11462                                         $encoding[] = $parser->encoding;
11463                                 }
11464                         }
11465                         $encoding[] = 'UTF-8';
11466                 }
11467                 // Fallback to UTF-8
11468                 else
11469                 {
11470                         $encoding[] = 'UTF-8';
11471                 }
11472                 return $encoding;
11473         }
11474
11475         function output_javascript()
11476         {
11477                 if (function_exists('ob_gzhandler'))
11478                 {
11479                         ob_start('ob_gzhandler');
11480                 }
11481                 header('Content-type: text/javascript; charset: UTF-8');
11482                 header('Cache-Control: must-revalidate');
11483                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11484                 ?>
11485 function embed_odeo(link) {
11486         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>');
11487 }
11488
11489 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11490         if (placeholder != '') {
11491                 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>');
11492         }
11493         else {
11494                 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>');
11495         }
11496 }
11497
11498 function embed_flash(bgcolor, width, height, link, loop, type) {
11499         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>');
11500 }
11501
11502 function embed_flv(width, height, link, placeholder, loop, player) {
11503         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>');
11504 }
11505
11506 function embed_wmedia(width, height, link) {
11507         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11508 }
11509                 <?php
11510         }
11511 }
11512
11513 /**
11514  * Decode HTML Entities
11515  *
11516  * This implements HTML5 as of revision 967 (2007-06-28)
11517  *
11518  * @package SimplePie
11519  */
11520 class SimplePie_Decode_HTML_Entities
11521 {
11522         /**
11523          * Data to be parsed
11524          *
11525          * @access private
11526          * @var string
11527          */
11528         var $data = '';
11529
11530         /**
11531          * Currently consumed bytes
11532          *
11533          * @access private
11534          * @var string
11535          */
11536         var $consumed = '';
11537
11538         /**
11539          * Position of the current byte being parsed
11540          *
11541          * @access private
11542          * @var int
11543          */
11544         var $position = 0;
11545
11546         /**
11547          * Create an instance of the class with the input data
11548          *
11549          * @access public
11550          * @param string $data Input data
11551          */
11552         function SimplePie_Decode_HTML_Entities($data)
11553         {
11554                 $this->data = $data;
11555         }
11556
11557         /**
11558          * Parse the input data
11559          *
11560          * @access public
11561          * @return string Output data
11562          */
11563         function parse()
11564         {
11565                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11566                 {
11567                         $this->consume();
11568                         $this->entity();
11569                         $this->consumed = '';
11570                 }
11571                 return $this->data;
11572         }
11573
11574         /**
11575          * Consume the next byte
11576          *
11577          * @access private
11578          * @return mixed The next byte, or false, if there is no more data
11579          */
11580         function consume()
11581         {
11582                 if (isset($this->data[$this->position]))
11583                 {
11584                         $this->consumed .= $this->data[$this->position];
11585                         return $this->data[$this->position++];
11586                 }
11587                 else
11588                 {
11589                         return false;
11590                 }
11591         }
11592
11593         /**
11594          * Consume a range of characters
11595          *
11596          * @access private
11597          * @param string $chars Characters to consume
11598          * @return mixed A series of characters that match the range, or false
11599          */
11600         function consume_range($chars)
11601         {
11602                 if ($len = strspn($this->data, $chars, $this->position))
11603                 {
11604                         $data = substr($this->data, $this->position, $len);
11605                         $this->consumed .= $data;
11606                         $this->position += $len;
11607                         return $data;
11608                 }
11609                 else
11610                 {
11611                         return false;
11612                 }
11613         }
11614
11615         /**
11616          * Unconsume one byte
11617          *
11618          * @access private
11619          */
11620         function unconsume()
11621         {
11622                 $this->consumed = substr($this->consumed, 0, -1);
11623                 $this->position--;
11624         }
11625
11626         /**
11627          * Decode an entity
11628          *
11629          * @access private
11630          */
11631         function entity()
11632         {
11633                 switch ($this->consume())
11634                 {
11635                         case "\x09":
11636                         case "\x0A":
11637                         case "\x0B":
11638                         case "\x0B":
11639                         case "\x0C":
11640                         case "\x20":
11641                         case "\x3C":
11642                         case "\x26":
11643                         case false:
11644                                 break;
11645
11646                         case "\x23":
11647                                 switch ($this->consume())
11648                                 {
11649                                         case "\x78":
11650                                         case "\x58":
11651                                                 $range = '0123456789ABCDEFabcdef';
11652                                                 $hex = true;
11653                                                 break;
11654
11655                                         default:
11656                                                 $range = '0123456789';
11657                                                 $hex = false;
11658                                                 $this->unconsume();
11659                                                 break;
11660                                 }
11661
11662                                 if ($codepoint = $this->consume_range($range))
11663                                 {
11664                                         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");
11665
11666                                         if ($hex)
11667                                         {
11668                                                 $codepoint = hexdec($codepoint);
11669                                         }
11670                                         else
11671                                         {
11672                                                 $codepoint = intval($codepoint);
11673                                         }
11674
11675                                         if (isset($windows_1252_specials[$codepoint]))
11676                                         {
11677                                                 $replacement = $windows_1252_specials[$codepoint];
11678                                         }
11679                                         else
11680                                         {
11681                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11682                                         }
11683
11684                                         if (!in_array($this->consume(), array(';', false), true))
11685                                         {
11686                                                 $this->unconsume();
11687                                         }
11688
11689                                         $consumed_length = strlen($this->consumed);
11690                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11691                                         $this->position += strlen($replacement) - $consumed_length;
11692                                 }
11693                                 break;
11694
11695                         default:
11696                                 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");
11697
11698                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11699                                 {
11700                                         $consumed = substr($this->consumed, 1);
11701                                         if (isset($entities[$consumed]))
11702                                         {
11703                                                 $match = $consumed;
11704                                         }
11705                                 }
11706
11707                                 if ($match !== null)
11708                                 {
11709                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11710                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11711                                 }
11712                                 break;
11713                 }
11714         }
11715 }
11716
11717 /**
11718  * IRI parser/serialiser
11719  *
11720  * @package SimplePie
11721  */
11722 class SimplePie_IRI
11723 {
11724         /**
11725          * Scheme
11726          *
11727          * @access private
11728          * @var string
11729          */
11730         var $scheme;
11731
11732         /**
11733          * User Information
11734          *
11735          * @access private
11736          * @var string
11737          */
11738         var $userinfo;
11739
11740         /**
11741          * Host
11742          *
11743          * @access private
11744          * @var string
11745          */
11746         var $host;
11747
11748         /**
11749          * Port
11750          *
11751          * @access private
11752          * @var string
11753          */
11754         var $port;
11755
11756         /**
11757          * Path
11758          *
11759          * @access private
11760          * @var string
11761          */
11762         var $path;
11763
11764         /**
11765          * Query
11766          *
11767          * @access private
11768          * @var string
11769          */
11770         var $query;
11771
11772         /**
11773          * Fragment
11774          *
11775          * @access private
11776          * @var string
11777          */
11778         var $fragment;
11779
11780         /**
11781          * Whether the object represents a valid IRI
11782          *
11783          * @access private
11784          * @var array
11785          */
11786         var $valid = array();
11787
11788         /**
11789          * Return the entire IRI when you try and read the object as a string
11790          *
11791          * @access public
11792          * @return string
11793          */
11794         function __toString()
11795         {
11796                 return $this->get_iri();
11797         }
11798
11799         /**
11800          * Create a new IRI object, from a specified string
11801          *
11802          * @access public
11803          * @param string $iri
11804          * @return SimplePie_IRI
11805          */
11806         function SimplePie_IRI($iri)
11807         {
11808                 $iri = (string) $iri;
11809                 if ($iri !== '')
11810                 {
11811                         $parsed = $this->parse_iri($iri);
11812                         $this->set_scheme($parsed['scheme']);
11813                         $this->set_authority($parsed['authority']);
11814                         $this->set_path($parsed['path']);
11815                         $this->set_query($parsed['query']);
11816                         $this->set_fragment($parsed['fragment']);
11817                 }
11818         }
11819
11820         /**
11821          * Create a new IRI object by resolving a relative IRI
11822          *
11823          * @static
11824          * @access public
11825          * @param SimplePie_IRI $base Base IRI
11826          * @param string $relative Relative IRI
11827          * @return SimplePie_IRI
11828          */
11829         function absolutize($base, $relative)
11830         {
11831                 $relative = (string) $relative;
11832                 if ($relative !== '')
11833                 {
11834                         $relative = new SimplePie_IRI($relative);
11835                         if ($relative->get_scheme() !== null)
11836                         {
11837                                 $target = $relative;
11838                         }
11839                         elseif ($base->get_iri() !== null)
11840                         {
11841                                 if ($relative->get_authority() !== null)
11842                                 {
11843                                         $target = $relative;
11844                                         $target->set_scheme($base->get_scheme());
11845                                 }
11846                                 else
11847                                 {
11848                                         $target = new SimplePie_IRI('');
11849                                         $target->set_scheme($base->get_scheme());
11850                                         $target->set_userinfo($base->get_userinfo());
11851                                         $target->set_host($base->get_host());
11852                                         $target->set_port($base->get_port());
11853                                         if ($relative->get_path() !== null)
11854                                         {
11855                                                 if (strpos($relative->get_path(), '/') === 0)
11856                                                 {
11857                                                         $target->set_path($relative->get_path());
11858                                                 }
11859                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11860                                                 {
11861                                                         $target->set_path('/' . $relative->get_path());
11862                                                 }
11863                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11864                                                 {
11865                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11866                                                 }
11867                                                 else
11868                                                 {
11869                                                         $target->set_path($relative->get_path());
11870                                                 }
11871                                                 $target->set_query($relative->get_query());
11872                                         }
11873                                         else
11874                                         {
11875                                                 $target->set_path($base->get_path());
11876                                                 if ($relative->get_query() !== null)
11877                                                 {
11878                                                         $target->set_query($relative->get_query());
11879                                                 }
11880                                                 elseif ($base->get_query() !== null)
11881                                                 {
11882                                                         $target->set_query($base->get_query());
11883                                                 }
11884                                         }
11885                                 }
11886                                 $target->set_fragment($relative->get_fragment());
11887                         }
11888                         else
11889                         {
11890                                 // No base URL, just return the relative URL
11891                                 $target = $relative;
11892                         }
11893                 }
11894                 else
11895                 {
11896                         $target = $base;
11897                 }
11898                 return $target;
11899         }
11900
11901         /**
11902          * Parse an IRI into scheme/authority/path/query/fragment segments
11903          *
11904          * @access private
11905          * @param string $iri
11906          * @return array
11907          */
11908         function parse_iri($iri)
11909         {
11910                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11911                 for ($i = count($match); $i <= 9; $i++)
11912                 {
11913                         $match[$i] = '';
11914                 }
11915                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11916         }
11917
11918         /**
11919          * Remove dot segments from a path
11920          *
11921          * @access private
11922          * @param string $input
11923          * @return string
11924          */
11925         function remove_dot_segments($input)
11926         {
11927                 $output = '';
11928                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11929                 {
11930                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11931                         if (strpos($input, '../') === 0)
11932                         {
11933                                 $input = substr($input, 3);
11934                         }
11935                         elseif (strpos($input, './') === 0)
11936                         {
11937                                 $input = substr($input, 2);
11938                         }
11939                         // 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,
11940                         elseif (strpos($input, '/./') === 0)
11941                         {
11942                                 $input = substr_replace($input, '/', 0, 3);
11943                         }
11944                         elseif ($input === '/.')
11945                         {
11946                                 $input = '/';
11947                         }
11948                         // 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,
11949                         elseif (strpos($input, '/../') === 0)
11950                         {
11951                                 $input = substr_replace($input, '/', 0, 4);
11952                                 $output = substr_replace($output, '', strrpos($output, '/'));
11953                         }
11954                         elseif ($input === '/..')
11955                         {
11956                                 $input = '/';
11957                                 $output = substr_replace($output, '', strrpos($output, '/'));
11958                         }
11959                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11960                         elseif ($input === '.' || $input === '..')
11961                         {
11962                                 $input = '';
11963                         }
11964                         // 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
11965                         elseif (($pos = strpos($input, '/', 1)) !== false)
11966                         {
11967                                 $output .= substr($input, 0, $pos);
11968                                 $input = substr_replace($input, '', 0, $pos);
11969                         }
11970                         else
11971                         {
11972                                 $output .= $input;
11973                                 $input = '';
11974                         }
11975                 }
11976                 return $output . $input;
11977         }
11978
11979         /**
11980          * Replace invalid character with percent encoding
11981          *
11982          * @access private
11983          * @param string $string Input string
11984          * @param string $valid_chars Valid characters
11985          * @param int $case Normalise case
11986          * @return string
11987          */
11988         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11989         {
11990                 // Normalise case
11991                 if ($case & SIMPLEPIE_LOWERCASE)
11992                 {
11993                         $string = strtolower($string);
11994                 }
11995                 elseif ($case & SIMPLEPIE_UPPERCASE)
11996                 {
11997                         $string = strtoupper($string);
11998                 }
11999
12000                 // Store position and string length (to avoid constantly recalculating this)
12001                 $position = 0;
12002                 $strlen = strlen($string);
12003
12004                 // Loop as long as we have invalid characters, advancing the position to the next invalid character
12005                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
12006                 {
12007                         // If we have a % character
12008                         if ($string[$position] === '%')
12009                         {
12010                                 // If we have a pct-encoded section
12011                                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
12012                                 {
12013                                         // Get the the represented character
12014                                         $chr = chr(hexdec(substr($string, $position + 1, 2)));
12015
12016                                         // If the character is valid, replace the pct-encoded with the actual character while normalising case
12017                                         if (strpos($valid_chars, $chr) !== false)
12018                                         {
12019                                                 if ($case & SIMPLEPIE_LOWERCASE)
12020                                                 {
12021                                                         $chr = strtolower($chr);
12022                                                 }
12023                                                 elseif ($case & SIMPLEPIE_UPPERCASE)
12024                                                 {
12025                                                         $chr = strtoupper($chr);
12026                                                 }
12027                                                 $string = substr_replace($string, $chr, $position, 3);
12028                                                 $strlen -= 2;
12029                                                 $position++;
12030                                         }
12031
12032                                         // Otherwise just normalise the pct-encoded to uppercase
12033                                         else
12034                                         {
12035                                                 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
12036                                                 $position += 3;
12037                                         }
12038                                 }
12039                                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
12040                                 else
12041                                 {
12042                                         $string = substr_replace($string, '%25', $position, 1);
12043                                         $strlen += 2;
12044                                         $position += 3;
12045                                 }
12046                         }
12047                         // If we have an invalid character, change into its pct-encoded form
12048                         else
12049                         {
12050                                 $replacement = sprintf("%%%02X", ord($string[$position]));
12051                                 $string = str_replace($string[$position], $replacement, $string);
12052                                 $strlen = strlen($string);
12053                         }
12054                 }
12055                 return $string;
12056         }
12057
12058         /**
12059          * Check if the object represents a valid IRI
12060          *
12061          * @access public
12062          * @return bool
12063          */
12064         function is_valid()
12065         {
12066                 return array_sum($this->valid) === count($this->valid);
12067         }
12068
12069         /**
12070          * Set the scheme. Returns true on success, false on failure (if there are
12071          * any invalid characters).
12072          *
12073          * @access public
12074          * @param string $scheme
12075          * @return bool
12076          */
12077         function set_scheme($scheme)
12078         {
12079                 if ($scheme === null || $scheme === '')
12080                 {
12081                         $this->scheme = null;
12082                 }
12083                 else
12084                 {
12085                         $len = strlen($scheme);
12086                         switch (true)
12087                         {
12088                                 case $len > 1:
12089                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12090                                         {
12091                                                 $this->scheme = null;
12092                                                 $this->valid[__FUNCTION__] = false;
12093                                                 return false;
12094                                         }
12095
12096                                 case $len > 0:
12097                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12098                                         {
12099                                                 $this->scheme = null;
12100                                                 $this->valid[__FUNCTION__] = false;
12101                                                 return false;
12102                                         }
12103                         }
12104                         $this->scheme = strtolower($scheme);
12105                 }
12106                 $this->valid[__FUNCTION__] = true;
12107                 return true;
12108         }
12109
12110         /**
12111          * Set the authority. Returns true on success, false on failure (if there are
12112          * any invalid characters).
12113          *
12114          * @access public
12115          * @param string $authority
12116          * @return bool
12117          */
12118         function set_authority($authority)
12119         {
12120                 if (($userinfo_end = strrpos($authority, '@')) !== false)
12121                 {
12122                         $userinfo = substr($authority, 0, $userinfo_end);
12123                         $authority = substr($authority, $userinfo_end + 1);
12124                 }
12125                 else
12126                 {
12127                         $userinfo = null;
12128                 }
12129
12130                 if (($port_start = strpos($authority, ':')) !== false)
12131                 {
12132                         $port = substr($authority, $port_start + 1);
12133                         $authority = substr($authority, 0, $port_start);
12134                 }
12135                 else
12136                 {
12137                         $port = null;
12138                 }
12139
12140                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12141         }
12142
12143         /**
12144          * Set the userinfo.
12145          *
12146          * @access public
12147          * @param string $userinfo
12148          * @return bool
12149          */
12150         function set_userinfo($userinfo)
12151         {
12152                 if ($userinfo === null || $userinfo === '')
12153                 {
12154                         $this->userinfo = null;
12155                 }
12156                 else
12157                 {
12158                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12159                 }
12160                 $this->valid[__FUNCTION__] = true;
12161                 return true;
12162         }
12163
12164         /**
12165          * Set the host. Returns true on success, false on failure (if there are
12166          * any invalid characters).
12167          *
12168          * @access public
12169          * @param string $host
12170          * @return bool
12171          */
12172         function set_host($host)
12173         {
12174                 if ($host === null || $host === '')
12175                 {
12176                         $this->host = null;
12177                         $this->valid[__FUNCTION__] = true;
12178                         return true;
12179                 }
12180                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12181                 {
12182                         if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12183                         {
12184                                 $this->host = $host;
12185                                 $this->valid[__FUNCTION__] = true;
12186                                 return true;
12187                         }
12188                         else
12189                         {
12190                                 $this->host = null;
12191                                 $this->valid[__FUNCTION__] = false;
12192                                 return false;
12193                         }
12194                 }
12195                 else
12196                 {
12197                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12198                         $this->valid[__FUNCTION__] = true;
12199                         return true;
12200                 }
12201         }
12202
12203         /**
12204          * Set the port. Returns true on success, false on failure (if there are
12205          * any invalid characters).
12206          *
12207          * @access public
12208          * @param string $port
12209          * @return bool
12210          */
12211         function set_port($port)
12212         {
12213                 if ($port === null || $port === '')
12214                 {
12215                         $this->port = null;
12216                         $this->valid[__FUNCTION__] = true;
12217                         return true;
12218                 }
12219                 elseif (strspn($port, '0123456789') === strlen($port))
12220                 {
12221                         $this->port = (int) $port;
12222                         $this->valid[__FUNCTION__] = true;
12223                         return true;
12224                 }
12225                 else
12226                 {
12227                         $this->port = null;
12228                         $this->valid[__FUNCTION__] = false;
12229                         return false;
12230                 }
12231         }
12232
12233         /**
12234          * Set the path.
12235          *
12236          * @access public
12237          * @param string $path
12238          * @return bool
12239          */
12240         function set_path($path)
12241         {
12242                 if ($path === null || $path === '')
12243                 {
12244                         $this->path = null;
12245                         $this->valid[__FUNCTION__] = true;
12246                         return true;
12247                 }
12248                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12249                 {
12250                         $this->path = null;
12251                         $this->valid[__FUNCTION__] = false;
12252                         return false;
12253                 }
12254                 else
12255                 {
12256                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12257                         if ($this->scheme !== null)
12258                         {
12259                                 $this->path = $this->remove_dot_segments($this->path);
12260                         }
12261                         $this->valid[__FUNCTION__] = true;
12262                         return true;
12263                 }
12264         }
12265
12266         /**
12267          * Set the query.
12268          *
12269          * @access public
12270          * @param string $query
12271          * @return bool
12272          */
12273         function set_query($query)
12274         {
12275                 if ($query === null || $query === '')
12276                 {
12277                         $this->query = null;
12278                 }
12279                 else
12280                 {
12281                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
12282                 }
12283                 $this->valid[__FUNCTION__] = true;
12284                 return true;
12285         }
12286
12287         /**
12288          * Set the fragment.
12289          *
12290          * @access public
12291          * @param string $fragment
12292          * @return bool
12293          */
12294         function set_fragment($fragment)
12295         {
12296                 if ($fragment === null || $fragment === '')
12297                 {
12298                         $this->fragment = null;
12299                 }
12300                 else
12301                 {
12302                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12303                 }
12304                 $this->valid[__FUNCTION__] = true;
12305                 return true;
12306         }
12307
12308         /**
12309          * Get the complete IRI
12310          *
12311          * @access public
12312          * @return string
12313          */
12314         function get_iri()
12315         {
12316                 $iri = '';
12317                 if ($this->scheme !== null)
12318                 {
12319                         $iri .= $this->scheme . ':';
12320                 }
12321                 if (($authority = $this->get_authority()) !== null)
12322                 {
12323                         $iri .= '//' . $authority;
12324                 }
12325                 if ($this->path !== null)
12326                 {
12327                         $iri .= $this->path;
12328                 }
12329                 if ($this->query !== null)
12330                 {
12331                         $iri .= '?' . $this->query;
12332                 }
12333                 if ($this->fragment !== null)
12334                 {
12335                         $iri .= '#' . $this->fragment;
12336                 }
12337
12338                 if ($iri !== '')
12339                 {
12340                         return $iri;
12341                 }
12342                 else
12343                 {
12344                         return null;
12345                 }
12346         }
12347
12348         /**
12349          * Get the scheme
12350          *
12351          * @access public
12352          * @return string
12353          */
12354         function get_scheme()
12355         {
12356                 return $this->scheme;
12357         }
12358
12359         /**
12360          * Get the complete authority
12361          *
12362          * @access public
12363          * @return string
12364          */
12365         function get_authority()
12366         {
12367                 $authority = '';
12368                 if ($this->userinfo !== null)
12369                 {
12370                         $authority .= $this->userinfo . '@';
12371                 }
12372                 if ($this->host !== null)
12373                 {
12374                         $authority .= $this->host;
12375                 }
12376                 if ($this->port !== null)
12377                 {
12378                         $authority .= ':' . $this->port;
12379                 }
12380
12381                 if ($authority !== '')
12382                 {
12383                         return $authority;
12384                 }
12385                 else
12386                 {
12387                         return null;
12388                 }
12389         }
12390
12391         /**
12392          * Get the user information
12393          *
12394          * @access public
12395          * @return string
12396          */
12397         function get_userinfo()
12398         {
12399                 return $this->userinfo;
12400         }
12401
12402         /**
12403          * Get the host
12404          *
12405          * @access public
12406          * @return string
12407          */
12408         function get_host()
12409         {
12410                 return $this->host;
12411         }
12412
12413         /**
12414          * Get the port
12415          *
12416          * @access public
12417          * @return string
12418          */
12419         function get_port()
12420         {
12421                 return $this->port;
12422         }
12423
12424         /**
12425          * Get the path
12426          *
12427          * @access public
12428          * @return string
12429          */
12430         function get_path()
12431         {
12432                 return $this->path;
12433         }
12434
12435         /**
12436          * Get the query
12437          *
12438          * @access public
12439          * @return string
12440          */
12441         function get_query()
12442         {
12443                 return $this->query;
12444         }
12445
12446         /**
12447          * Get the fragment
12448          *
12449          * @access public
12450          * @return string
12451          */
12452         function get_fragment()
12453         {
12454                 return $this->fragment;
12455         }
12456 }
12457
12458 /**
12459  * Class to validate and to work with IPv6 addresses.
12460  *
12461  * @package SimplePie
12462  * @copyright 2003-2005 The PHP Group
12463  * @license http://www.opensource.org/licenses/bsd-license.php
12464  * @link http://pear.php.net/package/Net_IPv6
12465  * @author Alexander Merz <alexander.merz@web.de>
12466  * @author elfrink at introweb dot nl
12467  * @author Josh Peck <jmp at joshpeck dot org>
12468  * @author Geoffrey Sneddon <geoffers@gmail.com>
12469  */
12470 class SimplePie_Net_IPv6
12471 {
12472         /**
12473          * Removes a possible existing netmask specification of an IP address.
12474          *
12475          * @param string $ip the (compressed) IP as Hex representation
12476          * @return string the IP the without netmask
12477          * @since 1.1.0
12478          * @access public
12479          * @static
12480          */
12481         function removeNetmaskSpec($ip)
12482         {
12483                 if (strpos($ip, '/') !== false)
12484                 {
12485                         list($addr, $nm) = explode('/', $ip);
12486                 }
12487                 else
12488                 {
12489                         $addr = $ip;
12490                 }
12491                 return $addr;
12492         }
12493
12494         /**
12495          * Uncompresses an IPv6 address
12496          *
12497          * RFC 2373 allows you to compress zeros in an address to '::'. This
12498          * function expects an valid IPv6 address and expands the '::' to
12499          * the required zeros.
12500          *
12501          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12502          *                       ::1            ->      0:0:0:0:0:0:0:1
12503          *
12504          * @access public
12505          * @static
12506          * @param string $ip a valid IPv6-address (hex format)
12507          * @return string the uncompressed IPv6-address (hex format)
12508          */
12509         function Uncompress($ip)
12510         {
12511                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12512                 $c1 = -1;
12513                 $c2 = -1;
12514                 if (strpos($ip, '::') !== false)
12515                 {
12516                         list($ip1, $ip2) = explode('::', $ip);
12517                         if ($ip1 === '')
12518                         {
12519                                 $c1 = -1;
12520                         }
12521                         else
12522                         {
12523                                 $pos = 0;
12524                                 if (($pos = substr_count($ip1, ':')) > 0)
12525                                 {
12526                                         $c1 = $pos;
12527                                 }
12528                                 else
12529                                 {
12530                                         $c1 = 0;
12531                                 }
12532                         }
12533                         if ($ip2 === '')
12534                         {
12535                                 $c2 = -1;
12536                         }
12537                         else
12538                         {
12539                                 $pos = 0;
12540                                 if (($pos = substr_count($ip2, ':')) > 0)
12541                                 {
12542                                         $c2 = $pos;
12543                                 }
12544                                 else
12545                                 {
12546                                         $c2 = 0;
12547                                 }
12548                         }
12549                         if (strstr($ip2, '.'))
12550                         {
12551                                 $c2++;
12552                         }
12553                         // ::
12554                         if ($c1 === -1 && $c2 === -1)
12555                         {
12556                                 $uip = '0:0:0:0:0:0:0:0';
12557                         }
12558                         // ::xxx
12559                         else if ($c1 === -1)
12560                         {
12561                                 $fill = str_repeat('0:', 7 - $c2);
12562                                 $uip =  str_replace('::', $fill, $uip);
12563                         }
12564                         // xxx::
12565                         else if ($c2 === -1)
12566                         {
12567                                 $fill = str_repeat(':0', 7 - $c1);
12568                                 $uip =  str_replace('::', $fill, $uip);
12569                         }
12570                         // xxx::xxx
12571                         else
12572                         {
12573                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12574                                 $uip =  str_replace('::', $fill, $uip);
12575                                 $uip =  str_replace('::', ':', $uip);
12576                         }
12577                 }
12578                 return $uip;
12579         }
12580
12581         /**
12582          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12583          *
12584          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12585          * an IPv4 compatible address
12586          *
12587          * Example:      0:0:0:0:0:0:13.1.68.3
12588          *                       0:0:0:0:0:FFFF:129.144.52.38
12589          *
12590          * @access public
12591          * @static
12592          * @param string $ip a valid IPv6-address (hex format)
12593          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12594          */
12595         function SplitV64($ip)
12596         {
12597                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12598                 if (strstr($ip, '.'))
12599                 {
12600                         $pos = strrpos($ip, ':');
12601                         $ip[$pos] = '_';
12602                         $ipPart = explode('_', $ip);
12603                         return $ipPart;
12604                 }
12605                 else
12606                 {
12607                         return array($ip, '');
12608                 }
12609         }
12610
12611         /**
12612          * Checks an IPv6 address
12613          *
12614          * Checks if the given IP is IPv6-compatible
12615          *
12616          * @access public
12617          * @static
12618          * @param string $ip a valid IPv6-address
12619          * @return bool true if $ip is an IPv6 address
12620          */
12621         function checkIPv6($ip)
12622         {
12623                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12624                 $count = 0;
12625                 if (!empty($ipPart[0]))
12626                 {
12627                         $ipv6 = explode(':', $ipPart[0]);
12628                         for ($i = 0; $i < count($ipv6); $i++)
12629                         {
12630                                 $dec = hexdec($ipv6[$i]);
12631                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12632                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12633                                 {
12634                                         $count++;
12635                                 }
12636                         }
12637                         if ($count === 8)
12638                         {
12639                                 return true;
12640                         }
12641                         elseif ($count === 6 && !empty($ipPart[1]))
12642                         {
12643                                 $ipv4 = explode('.', $ipPart[1]);
12644                                 $count = 0;
12645                                 foreach ($ipv4 as $ipv4_part)
12646                                 {
12647                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12648                                         {
12649                                                 $count++;
12650                                         }
12651                                 }
12652                                 if ($count === 4)
12653                                 {
12654                                         return true;
12655                                 }
12656                         }
12657                         else
12658                         {
12659                                 return false;
12660                         }
12661
12662                 }
12663                 else
12664                 {
12665                         return false;
12666                 }
12667         }
12668 }
12669
12670 /**
12671  * Date Parser
12672  *
12673  * @package SimplePie
12674  */
12675 class SimplePie_Parse_Date
12676 {
12677         /**
12678          * Input data
12679          *
12680          * @access protected
12681          * @var string
12682          */
12683         var $date;
12684
12685         /**
12686          * List of days, calendar day name => ordinal day number in the week
12687          *
12688          * @access protected
12689          * @var array
12690          */
12691         var $day = array(
12692                 // English
12693                 'mon' => 1,
12694                 'monday' => 1,
12695                 'tue' => 2,
12696                 'tuesday' => 2,
12697                 'wed' => 3,
12698                 'wednesday' => 3,
12699                 'thu' => 4,
12700                 'thursday' => 4,
12701                 'fri' => 5,
12702                 'friday' => 5,
12703                 'sat' => 6,
12704                 'saturday' => 6,
12705                 'sun' => 7,
12706                 'sunday' => 7,
12707                 // Dutch
12708                 'maandag' => 1,
12709                 'dinsdag' => 2,
12710                 'woensdag' => 3,
12711                 'donderdag' => 4,
12712                 'vrijdag' => 5,
12713                 'zaterdag' => 6,
12714                 'zondag' => 7,
12715                 // French
12716                 'lundi' => 1,
12717                 'mardi' => 2,
12718                 'mercredi' => 3,
12719                 'jeudi' => 4,
12720                 'vendredi' => 5,
12721                 'samedi' => 6,
12722                 'dimanche' => 7,
12723                 // German
12724                 'montag' => 1,
12725                 'dienstag' => 2,
12726                 'mittwoch' => 3,
12727                 'donnerstag' => 4,
12728                 'freitag' => 5,
12729                 'samstag' => 6,
12730                 'sonnabend' => 6,
12731                 'sonntag' => 7,
12732                 // Italian
12733                 'lunedì' => 1,
12734                 'martedì' => 2,
12735                 'mercoledì' => 3,
12736                 'giovedì' => 4,
12737                 'venerdì' => 5,
12738                 'sabato' => 6,
12739                 'domenica' => 7,
12740                 // Spanish
12741                 'lunes' => 1,
12742                 'martes' => 2,
12743                 'miércoles' => 3,
12744                 'jueves' => 4,
12745                 'viernes' => 5,
12746                 'sábado' => 6,
12747                 'domingo' => 7,
12748                 // Finnish
12749                 'maanantai' => 1,
12750                 'tiistai' => 2,
12751                 'keskiviikko' => 3,
12752                 'torstai' => 4,
12753                 'perjantai' => 5,
12754                 'lauantai' => 6,
12755                 'sunnuntai' => 7,
12756                 // Hungarian
12757                 'hétfő' => 1,
12758                 'kedd' => 2,
12759                 'szerda' => 3,
12760                 'csütörtok' => 4,
12761                 'péntek' => 5,
12762                 'szombat' => 6,
12763                 'vasárnap' => 7,
12764                 // Greek
12765                 'Δευ' => 1,
12766                 'Τρι' => 2,
12767                 'Τετ' => 3,
12768                 'Πεμ' => 4,
12769                 'Παρ' => 5,
12770                 'Σαβ' => 6,
12771                 'Κυρ' => 7,
12772         );
12773
12774         /**
12775          * List of months, calendar month name => calendar month number
12776          *
12777          * @access protected
12778          * @var array
12779          */
12780         var $month = array(
12781                 // English
12782                 'jan' => 1,
12783                 'january' => 1,
12784                 'feb' => 2,
12785                 'february' => 2,
12786                 'mar' => 3,
12787                 'march' => 3,
12788                 'apr' => 4,
12789                 'april' => 4,
12790                 'may' => 5,
12791                 // No long form of May
12792                 'jun' => 6,
12793                 'june' => 6,
12794                 'jul' => 7,
12795                 'july' => 7,
12796                 'aug' => 8,
12797                 'august' => 8,
12798                 'sep' => 9,
12799                 'september' => 8,
12800                 'oct' => 10,
12801                 'october' => 10,
12802                 'nov' => 11,
12803                 'november' => 11,
12804                 'dec' => 12,
12805                 'december' => 12,
12806                 // Dutch
12807                 'januari' => 1,
12808                 'februari' => 2,
12809                 'maart' => 3,
12810                 'april' => 4,
12811                 'mei' => 5,
12812                 'juni' => 6,
12813                 'juli' => 7,
12814                 'augustus' => 8,
12815                 'september' => 9,
12816                 'oktober' => 10,
12817                 'november' => 11,
12818                 'december' => 12,
12819                 // French
12820                 'janvier' => 1,
12821                 'février' => 2,
12822                 'mars' => 3,
12823                 'avril' => 4,
12824                 'mai' => 5,
12825                 'juin' => 6,
12826                 'juillet' => 7,
12827                 'août' => 8,
12828                 'septembre' => 9,
12829                 'octobre' => 10,
12830                 'novembre' => 11,
12831                 'décembre' => 12,
12832                 // German
12833                 'januar' => 1,
12834                 'februar' => 2,
12835                 'märz' => 3,
12836                 'april' => 4,
12837                 'mai' => 5,
12838                 'juni' => 6,
12839                 'juli' => 7,
12840                 'august' => 8,
12841                 'september' => 9,
12842                 'oktober' => 10,
12843                 'november' => 11,
12844                 'dezember' => 12,
12845                 // Italian
12846                 'gennaio' => 1,
12847                 'febbraio' => 2,
12848                 'marzo' => 3,
12849                 'aprile' => 4,
12850                 'maggio' => 5,
12851                 'giugno' => 6,
12852                 'luglio' => 7,
12853                 'agosto' => 8,
12854                 'settembre' => 9,
12855                 'ottobre' => 10,
12856                 'novembre' => 11,
12857                 'dicembre' => 12,
12858                 // Spanish
12859                 'enero' => 1,
12860                 'febrero' => 2,
12861                 'marzo' => 3,
12862                 'abril' => 4,
12863                 'mayo' => 5,
12864                 'junio' => 6,
12865                 'julio' => 7,
12866                 'agosto' => 8,
12867                 'septiembre' => 9,
12868                 'setiembre' => 9,
12869                 'octubre' => 10,
12870                 'noviembre' => 11,
12871                 'diciembre' => 12,
12872                 // Finnish
12873                 'tammikuu' => 1,
12874                 'helmikuu' => 2,
12875                 'maaliskuu' => 3,
12876                 'huhtikuu' => 4,
12877                 'toukokuu' => 5,
12878                 'kesäkuu' => 6,
12879                 'heinäkuu' => 7,
12880                 'elokuu' => 8,
12881                 'suuskuu' => 9,
12882                 'lokakuu' => 10,
12883                 'marras' => 11,
12884                 'joulukuu' => 12,
12885                 // Hungarian
12886                 'január' => 1,
12887                 'február' => 2,
12888                 'március' => 3,
12889                 'április' => 4,
12890                 'május' => 5,
12891                 'június' => 6,
12892                 'július' => 7,
12893                 'augusztus' => 8,
12894                 'szeptember' => 9,
12895                 'október' => 10,
12896                 'november' => 11,
12897                 'december' => 12,
12898                 // Greek
12899                 'Ιαν' => 1,
12900                 'Φεβ' => 2,
12901                 'Μάώ' => 3,
12902                 'Μαώ' => 3,
12903                 'Απρ' => 4,
12904                 'Μάι' => 5,
12905                 'Μαϊ' => 5,
12906                 'Μαι' => 5,
12907                 'Ιούν' => 6,
12908                 'Ιον' => 6,
12909                 'Ιούλ' => 7,
12910                 'Ιολ' => 7,
12911                 'Αύγ' => 8,
12912                 'Αυγ' => 8,
12913                 'Σεπ' => 9,
12914                 'Οκτ' => 10,
12915                 'Νοέ' => 11,
12916                 'Δεκ' => 12,
12917         );
12918
12919         /**
12920          * List of timezones, abbreviation => offset from UTC
12921          *
12922          * @access protected
12923          * @var array
12924          */
12925         var $timezone = array(
12926                 'ACDT' => 37800,
12927                 'ACIT' => 28800,
12928                 'ACST' => 34200,
12929                 'ACT' => -18000,
12930                 'ACWDT' => 35100,
12931                 'ACWST' => 31500,
12932                 'AEDT' => 39600,
12933                 'AEST' => 36000,
12934                 'AFT' => 16200,
12935                 'AKDT' => -28800,
12936                 'AKST' => -32400,
12937                 'AMDT' => 18000,
12938                 'AMT' => -14400,
12939                 'ANAST' => 46800,
12940                 'ANAT' => 43200,
12941                 'ART' => -10800,
12942                 'AZOST' => -3600,
12943                 'AZST' => 18000,
12944                 'AZT' => 14400,
12945                 'BIOT' => 21600,
12946                 'BIT' => -43200,
12947                 'BOT' => -14400,
12948                 'BRST' => -7200,
12949                 'BRT' => -10800,
12950                 'BST' => 3600,
12951                 'BTT' => 21600,
12952                 'CAST' => 18000,
12953                 'CAT' => 7200,
12954                 'CCT' => 23400,
12955                 'CDT' => -18000,
12956                 'CEDT' => 7200,
12957                 'CET' => 3600,
12958                 'CGST' => -7200,
12959                 'CGT' => -10800,
12960                 'CHADT' => 49500,
12961                 'CHAST' => 45900,
12962                 'CIST' => -28800,
12963                 'CKT' => -36000,
12964                 'CLDT' => -10800,
12965                 'CLST' => -14400,
12966                 'COT' => -18000,
12967                 'CST' => -21600,
12968                 'CVT' => -3600,
12969                 'CXT' => 25200,
12970                 'DAVT' => 25200,
12971                 'DTAT' => 36000,
12972                 'EADT' => -18000,
12973                 'EAST' => -21600,
12974                 'EAT' => 10800,
12975                 'ECT' => -18000,
12976                 'EDT' => -14400,
12977                 'EEST' => 10800,
12978                 'EET' => 7200,
12979                 'EGT' => -3600,
12980                 'EKST' => 21600,
12981                 'EST' => -18000,
12982                 'FJT' => 43200,
12983                 'FKDT' => -10800,
12984                 'FKST' => -14400,
12985                 'FNT' => -7200,
12986                 'GALT' => -21600,
12987                 'GEDT' => 14400,
12988                 'GEST' => 10800,
12989                 'GFT' => -10800,
12990                 'GILT' => 43200,
12991                 'GIT' => -32400,
12992                 'GST' => 14400,
12993                 'GST' => -7200,
12994                 'GYT' => -14400,
12995                 'HAA' => -10800,
12996                 'HAC' => -18000,
12997                 'HADT' => -32400,
12998                 'HAE' => -14400,
12999                 'HAP' => -25200,
13000                 'HAR' => -21600,
13001                 'HAST' => -36000,
13002                 'HAT' => -9000,
13003                 'HAY' => -28800,
13004                 'HKST' => 28800,
13005                 'HMT' => 18000,
13006                 'HNA' => -14400,
13007                 'HNC' => -21600,
13008                 'HNE' => -18000,
13009                 'HNP' => -28800,
13010                 'HNR' => -25200,
13011                 'HNT' => -12600,
13012                 'HNY' => -32400,
13013                 'IRDT' => 16200,
13014                 'IRKST' => 32400,
13015                 'IRKT' => 28800,
13016                 'IRST' => 12600,
13017                 'JFDT' => -10800,
13018                 'JFST' => -14400,
13019                 'JST' => 32400,
13020                 'KGST' => 21600,
13021                 'KGT' => 18000,
13022                 'KOST' => 39600,
13023                 'KOVST' => 28800,
13024                 'KOVT' => 25200,
13025                 'KRAST' => 28800,
13026                 'KRAT' => 25200,
13027                 'KST' => 32400,
13028                 'LHDT' => 39600,
13029                 'LHST' => 37800,
13030                 'LINT' => 50400,
13031                 'LKT' => 21600,
13032                 'MAGST' => 43200,
13033                 'MAGT' => 39600,
13034                 'MAWT' => 21600,
13035                 'MDT' => -21600,
13036                 'MESZ' => 7200,
13037                 'MEZ' => 3600,
13038                 'MHT' => 43200,
13039                 'MIT' => -34200,
13040                 'MNST' => 32400,
13041                 'MSDT' => 14400,
13042                 'MSST' => 10800,
13043                 'MST' => -25200,
13044                 'MUT' => 14400,
13045                 'MVT' => 18000,
13046                 'MYT' => 28800,
13047                 'NCT' => 39600,
13048                 'NDT' => -9000,
13049                 'NFT' => 41400,
13050                 'NMIT' => 36000,
13051                 'NOVST' => 25200,
13052                 'NOVT' => 21600,
13053                 'NPT' => 20700,
13054                 'NRT' => 43200,
13055                 'NST' => -12600,
13056                 'NUT' => -39600,
13057                 'NZDT' => 46800,
13058                 'NZST' => 43200,
13059                 'OMSST' => 25200,
13060                 'OMST' => 21600,
13061                 'PDT' => -25200,
13062                 'PET' => -18000,
13063                 'PETST' => 46800,
13064                 'PETT' => 43200,
13065                 'PGT' => 36000,
13066                 'PHOT' => 46800,
13067                 'PHT' => 28800,
13068                 'PKT' => 18000,
13069                 'PMDT' => -7200,
13070                 'PMST' => -10800,
13071                 'PONT' => 39600,
13072                 'PST' => -28800,
13073                 'PWT' => 32400,
13074                 'PYST' => -10800,
13075                 'PYT' => -14400,
13076                 'RET' => 14400,
13077                 'ROTT' => -10800,
13078                 'SAMST' => 18000,
13079                 'SAMT' => 14400,
13080                 'SAST' => 7200,
13081                 'SBT' => 39600,
13082                 'SCDT' => 46800,
13083                 'SCST' => 43200,
13084                 'SCT' => 14400,
13085                 'SEST' => 3600,
13086                 'SGT' => 28800,
13087                 'SIT' => 28800,
13088                 'SRT' => -10800,
13089                 'SST' => -39600,
13090                 'SYST' => 10800,
13091                 'SYT' => 7200,
13092                 'TFT' => 18000,
13093                 'THAT' => -36000,
13094                 'TJT' => 18000,
13095                 'TKT' => -36000,
13096                 'TMT' => 18000,
13097                 'TOT' => 46800,
13098                 'TPT' => 32400,
13099                 'TRUT' => 36000,
13100                 'TVT' => 43200,
13101                 'TWT' => 28800,
13102                 'UYST' => -7200,
13103                 'UYT' => -10800,
13104                 'UZT' => 18000,
13105                 'VET' => -14400,
13106                 'VLAST' => 39600,
13107                 'VLAT' => 36000,
13108                 'VOST' => 21600,
13109                 'VUT' => 39600,
13110                 'WAST' => 7200,
13111                 'WAT' => 3600,
13112                 'WDT' => 32400,
13113                 'WEST' => 3600,
13114                 'WFT' => 43200,
13115                 'WIB' => 25200,
13116                 'WIT' => 32400,
13117                 'WITA' => 28800,
13118                 'WKST' => 18000,
13119                 'WST' => 28800,
13120                 'YAKST' => 36000,
13121                 'YAKT' => 32400,
13122                 'YAPT' => 36000,
13123                 'YEKST' => 21600,
13124                 'YEKT' => 18000,
13125         );
13126
13127         /**
13128          * Cached PCRE for SimplePie_Parse_Date::$day
13129          *
13130          * @access protected
13131          * @var string
13132          */
13133         var $day_pcre;
13134
13135         /**
13136          * Cached PCRE for SimplePie_Parse_Date::$month
13137          *
13138          * @access protected
13139          * @var string
13140          */
13141         var $month_pcre;
13142
13143         /**
13144          * Array of user-added callback methods
13145          *
13146          * @access private
13147          * @var array
13148          */
13149         var $built_in = array();
13150
13151         /**
13152          * Array of user-added callback methods
13153          *
13154          * @access private
13155          * @var array
13156          */
13157         var $user = array();
13158
13159         /**
13160          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13161          * self::month_pcre, and self::built_in
13162          *
13163          * @access private
13164          */
13165         function SimplePie_Parse_Date()
13166         {
13167                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13168                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13169
13170                 static $cache;
13171                 if (!isset($cache[get_class($this)]))
13172                 {
13173                         $all_methods = get_class_methods($this);
13174
13175                         foreach ($all_methods as $method)
13176                         {
13177                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13178                                 {
13179                                         $cache[get_class($this)][] = $method;
13180                                 }
13181                         }
13182                 }
13183
13184                 foreach ($cache[get_class($this)] as $method)
13185                 {
13186                         $this->built_in[] = $method;
13187                 }
13188         }
13189
13190         /**
13191          * Get the object
13192          *
13193          * @access public
13194          */
13195         function get()
13196         {
13197                 static $object;
13198                 if (!$object)
13199                 {
13200                         $object = new SimplePie_Parse_Date;
13201                 }
13202                 return $object;
13203         }
13204
13205         /**
13206          * Parse a date
13207          *
13208          * @final
13209          * @access public
13210          * @param string $date Date to parse
13211          * @return int Timestamp corresponding to date string, or false on failure
13212          */
13213         function parse($date)
13214         {
13215                 foreach ($this->user as $method)
13216                 {
13217                         if (($returned = call_user_func($method, $date)) !== false)
13218                         {
13219                                 return $returned;
13220                         }
13221                 }
13222
13223                 foreach ($this->built_in as $method)
13224                 {
13225                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13226                         {
13227                                 return $returned;
13228                         }
13229                 }
13230
13231                 return false;
13232         }
13233
13234         /**
13235          * Add a callback method to parse a date
13236          *
13237          * @final
13238          * @access public
13239          * @param callback $callback
13240          */
13241         function add_callback($callback)
13242         {
13243                 if (is_callable($callback))
13244                 {
13245                         $this->user[] = $callback;
13246                 }
13247                 else
13248                 {
13249                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13250                 }
13251         }
13252
13253         /**
13254          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13255          * well as allowing any of upper or lower case "T", horizontal tabs, or
13256          * spaces to be used as the time seperator (including more than one))
13257          *
13258          * @access protected
13259          * @return int Timestamp
13260          */
13261         function date_w3cdtf($date)
13262         {
13263                 static $pcre;
13264                 if (!$pcre)
13265                 {
13266                         $year = '([0-9]{4})';
13267                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13268                         $decimal = '([0-9]*)';
13269                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13270                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13271                 }
13272                 if (preg_match($pcre, $date, $match))
13273                 {
13274                         /*
13275                         Capturing subpatterns:
13276                         1: Year
13277                         2: Month
13278                         3: Day
13279                         4: Hour
13280                         5: Minute
13281                         6: Second
13282                         7: Decimal fraction of a second
13283                         8: Zulu
13284                         9: Timezone ±
13285                         10: Timezone hours
13286                         11: Timezone minutes
13287                         */
13288
13289                         // Fill in empty matches
13290                         for ($i = count($match); $i <= 3; $i++)
13291                         {
13292                                 $match[$i] = '1';
13293                         }
13294
13295                         for ($i = count($match); $i <= 7; $i++)
13296                         {
13297                                 $match[$i] = '0';
13298                         }
13299
13300                         // Numeric timezone
13301                         if (isset($match[9]) && $match[9] !== '')
13302                         {
13303                                 $timezone = $match[10] * 3600;
13304                                 $timezone += $match[11] * 60;
13305                                 if ($match[9] === '-')
13306                                 {
13307                                         $timezone = 0 - $timezone;
13308                                 }
13309                         }
13310                         else
13311                         {
13312                                 $timezone = 0;
13313                         }
13314
13315                         // Convert the number of seconds to an integer, taking decimals into account
13316                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13317
13318                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13319                 }
13320                 else
13321                 {
13322                         return false;
13323                 }
13324         }
13325
13326         /**
13327          * Remove RFC822 comments
13328          *
13329          * @access protected
13330          * @param string $data Data to strip comments from
13331          * @return string Comment stripped string
13332          */
13333         function remove_rfc2822_comments($string)
13334         {
13335                 $string = (string) $string;
13336                 $position = 0;
13337                 $length = strlen($string);
13338                 $depth = 0;
13339
13340                 $output = '';
13341
13342                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13343                 {
13344                         $output .= substr($string, $position, $pos - $position);
13345                         $position = $pos + 1;
13346                         if ($string[$pos - 1] !== '\\')
13347                         {
13348                                 $depth++;
13349                                 while ($depth && $position < $length)
13350                                 {
13351                                         $position += strcspn($string, '()', $position);
13352                                         if ($string[$position - 1] === '\\')
13353                                         {
13354                                                 $position++;
13355                                                 continue;
13356                                         }
13357                                         elseif (isset($string[$position]))
13358                                         {
13359                                                 switch ($string[$position])
13360                                                 {
13361                                                         case '(':
13362                                                                 $depth++;
13363                                                                 break;
13364
13365                                                         case ')':
13366                                                                 $depth--;
13367                                                                 break;
13368                                                 }
13369                                                 $position++;
13370                                         }
13371                                         else
13372                                         {
13373                                                 break;
13374                                         }
13375                                 }
13376                         }
13377                         else
13378                         {
13379                                 $output .= '(';
13380                         }
13381                 }
13382                 $output .= substr($string, $position);
13383
13384                 return $output;
13385         }
13386
13387         /**
13388          * Parse RFC2822's date format
13389          *
13390          * @access protected
13391          * @return int Timestamp
13392          */
13393         function date_rfc2822($date)
13394         {
13395                 static $pcre;
13396                 if (!$pcre)
13397                 {
13398                         $wsp = '[\x09\x20]';
13399                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13400                         $optional_fws = $fws . '?';
13401                         $day_name = $this->day_pcre;
13402                         $month = $this->month_pcre;
13403                         $day = '([0-9]{1,2})';
13404                         $hour = $minute = $second = '([0-9]{2})';
13405                         $year = '([0-9]{2,4})';
13406                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13407                         $character_zone = '([A-Z]{1,5})';
13408                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13409                         $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';
13410                 }
13411                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13412                 {
13413                         /*
13414                         Capturing subpatterns:
13415                         1: Day name
13416                         2: Day
13417                         3: Month
13418                         4: Year
13419                         5: Hour
13420                         6: Minute
13421                         7: Second
13422                         8: Timezone ±
13423                         9: Timezone hours
13424                         10: Timezone minutes
13425                         11: Alphabetic timezone
13426                         */
13427
13428                         // Find the month number
13429                         $month = $this->month[strtolower($match[3])];
13430
13431                         // Numeric timezone
13432                         if ($match[8] !== '')
13433                         {
13434                                 $timezone = $match[9] * 3600;
13435                                 $timezone += $match[10] * 60;
13436                                 if ($match[8] === '-')
13437                                 {
13438                                         $timezone = 0 - $timezone;
13439                                 }
13440                         }
13441                         // Character timezone
13442                         elseif (isset($this->timezone[strtoupper($match[11])]))
13443                         {
13444                                 $timezone = $this->timezone[strtoupper($match[11])];
13445                         }
13446                         // Assume everything else to be -0000
13447                         else
13448                         {
13449                                 $timezone = 0;
13450                         }
13451
13452                         // Deal with 2/3 digit years
13453                         if ($match[4] < 50)
13454                         {
13455                                 $match[4] += 2000;
13456                         }
13457                         elseif ($match[4] < 1000)
13458                         {
13459                                 $match[4] += 1900;
13460                         }
13461
13462                         // Second is optional, if it is empty set it to zero
13463                         if ($match[7] !== '')
13464                         {
13465                                 $second = $match[7];
13466                         }
13467                         else
13468                         {
13469                                 $second = 0;
13470                         }
13471
13472                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13473                 }
13474                 else
13475                 {
13476                         return false;
13477                 }
13478         }
13479
13480         /**
13481          * Parse RFC850's date format
13482          *
13483          * @access protected
13484          * @return int Timestamp
13485          */
13486         function date_rfc850($date)
13487         {
13488                 static $pcre;
13489                 if (!$pcre)
13490                 {
13491                         $space = '[\x09\x20]+';
13492                         $day_name = $this->day_pcre;
13493                         $month = $this->month_pcre;
13494                         $day = '([0-9]{1,2})';
13495                         $year = $hour = $minute = $second = '([0-9]{2})';
13496                         $zone = '([A-Z]{1,5})';
13497                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13498                 }
13499                 if (preg_match($pcre, $date, $match))
13500                 {
13501                         /*
13502                         Capturing subpatterns:
13503                         1: Day name
13504                         2: Day
13505                         3: Month
13506                         4: Year
13507                         5: Hour
13508                         6: Minute
13509                         7: Second
13510                         8: Timezone
13511                         */
13512
13513                         // Month
13514                         $month = $this->month[strtolower($match[3])];
13515
13516                         // Character timezone
13517                         if (isset($this->timezone[strtoupper($match[8])]))
13518                         {
13519                                 $timezone = $this->timezone[strtoupper($match[8])];
13520                         }
13521                         // Assume everything else to be -0000
13522                         else
13523                         {
13524                                 $timezone = 0;
13525                         }
13526
13527                         // Deal with 2 digit year
13528                         if ($match[4] < 50)
13529                         {
13530                                 $match[4] += 2000;
13531                         }
13532                         else
13533                         {
13534                                 $match[4] += 1900;
13535                         }
13536
13537                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13538                 }
13539                 else
13540                 {
13541                         return false;
13542                 }
13543         }
13544
13545         /**
13546          * Parse C99's asctime()'s date format
13547          *
13548          * @access protected
13549          * @return int Timestamp
13550          */
13551         function date_asctime($date)
13552         {
13553                 static $pcre;
13554                 if (!$pcre)
13555                 {
13556                         $space = '[\x09\x20]+';
13557                         $wday_name = $this->day_pcre;
13558                         $mon_name = $this->month_pcre;
13559                         $day = '([0-9]{1,2})';
13560                         $hour = $sec = $min = '([0-9]{2})';
13561                         $year = '([0-9]{4})';
13562                         $terminator = '\x0A?\x00?';
13563                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13564                 }
13565                 if (preg_match($pcre, $date, $match))
13566                 {
13567                         /*
13568                         Capturing subpatterns:
13569                         1: Day name
13570                         2: Month
13571                         3: Day
13572                         4: Hour
13573                         5: Minute
13574                         6: Second
13575                         7: Year
13576                         */
13577
13578                         $month = $this->month[strtolower($match[2])];
13579                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13580                 }
13581                 else
13582                 {
13583                         return false;
13584                 }
13585         }
13586
13587         /**
13588          * Parse dates using strtotime()
13589          *
13590          * @access protected
13591          * @return int Timestamp
13592          */
13593         function date_strtotime($date)
13594         {
13595                 $strtotime = strtotime($date);
13596                 if ($strtotime === -1 || $strtotime === false)
13597                 {
13598                         return false;
13599                 }
13600                 else
13601                 {
13602                         return $strtotime;
13603                 }
13604         }
13605 }
13606
13607 /**
13608  * Content-type sniffing
13609  *
13610  * @package SimplePie
13611  */
13612 class SimplePie_Content_Type_Sniffer
13613 {
13614         /**
13615          * File object
13616          *
13617          * @var SimplePie_File
13618          * @access private
13619          */
13620         var $file;
13621
13622         /**
13623          * Create an instance of the class with the input file
13624          *
13625          * @access public
13626          * @param SimplePie_Content_Type_Sniffer $file Input file
13627          */
13628         function SimplePie_Content_Type_Sniffer($file)
13629         {
13630                 $this->file = $file;
13631         }
13632
13633         /**
13634          * Get the Content-Type of the specified file
13635          *
13636          * @access public
13637          * @return string Actual Content-Type
13638          */
13639         function get_type()
13640         {
13641                 if (isset($this->file->headers['content-type']))
13642                 {
13643                         if (!isset($this->file->headers['content-encoding'])
13644                                 && ($this->file->headers['content-type'] === 'text/plain'
13645                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13646                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13647                         {
13648                                 return $this->text_or_binary();
13649                         }
13650
13651                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13652                         {
13653                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13654                         }
13655                         else
13656                         {
13657                                 $official = $this->file->headers['content-type'];
13658                         }
13659                         $official = strtolower($official);
13660
13661                         if ($official === 'unknown/unknown'
13662                                 || $official === 'application/unknown')
13663                         {
13664                                 return $this->unknown();
13665                         }
13666                         elseif (substr($official, -4) === '+xml'
13667                                 || $official === 'text/xml'
13668                                 || $official === 'application/xml')
13669                         {
13670                                 return $official;
13671                         }
13672                         elseif (substr($official, 0, 6) === 'image/')
13673                         {
13674                                 if ($return = $this->image())
13675                                 {
13676                                         return $return;
13677                                 }
13678                                 else
13679                                 {
13680                                         return $official;
13681                                 }
13682                         }
13683                         elseif ($official === 'text/html')
13684                         {
13685                                 return $this->feed_or_html();
13686                         }
13687                         else
13688                         {
13689                                 return $official;
13690                         }
13691                 }
13692                 else
13693                 {
13694                         return $this->unknown();
13695                 }
13696         }
13697
13698         /**
13699          * Sniff text or binary
13700          *
13701          * @access private
13702          * @return string Actual Content-Type
13703          */
13704         function text_or_binary()
13705         {
13706                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13707                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13708                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13709                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13710                 {
13711                         return 'text/plain';
13712                 }
13713                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13714                 {
13715                         return 'application/octect-stream';
13716                 }
13717                 else
13718                 {
13719                         return 'text/plain';
13720                 }
13721         }
13722
13723         /**
13724          * Sniff unknown
13725          *
13726          * @access private
13727          * @return string Actual Content-Type
13728          */
13729         function unknown()
13730         {
13731                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13732                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13733                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13734                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13735                 {
13736                         return 'text/html';
13737                 }
13738                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13739                 {
13740                         return 'application/pdf';
13741                 }
13742                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13743                 {
13744                         return 'application/postscript';
13745                 }
13746                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13747                         || substr($this->file->body, 0, 6) === 'GIF89a')
13748                 {
13749                         return 'image/gif';
13750                 }
13751                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13752                 {
13753                         return 'image/png';
13754                 }
13755                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13756                 {
13757                         return 'image/jpeg';
13758                 }
13759                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13760                 {
13761                         return 'image/bmp';
13762                 }
13763                 else
13764                 {
13765                         return $this->text_or_binary();
13766                 }
13767         }
13768
13769         /**
13770          * Sniff images
13771          *
13772          * @access private
13773          * @return string Actual Content-Type
13774          */
13775         function image()
13776         {
13777                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13778                         || substr($this->file->body, 0, 6) === 'GIF89a')
13779                 {
13780                         return 'image/gif';
13781                 }
13782                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13783                 {
13784                         return 'image/png';
13785                 }
13786                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13787                 {
13788                         return 'image/jpeg';
13789                 }
13790                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13791                 {
13792                         return 'image/bmp';
13793                 }
13794                 else
13795                 {
13796                         return false;
13797                 }
13798         }
13799
13800         /**
13801          * Sniff HTML
13802          *
13803          * @access private
13804          * @return string Actual Content-Type
13805          */
13806         function feed_or_html()
13807         {
13808                 $len = strlen($this->file->body);
13809                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13810
13811                 while ($pos < $len)
13812                 {
13813                         switch ($this->file->body[$pos])
13814                         {
13815                                 case "\x09":
13816                                 case "\x0A":
13817                                 case "\x0D":
13818                                 case "\x20":
13819                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13820                                         continue 2;
13821
13822                                 case '<':
13823                                         $pos++;
13824                                         break;
13825
13826                                 default:
13827                                         return 'text/html';
13828                         }
13829
13830                         if (substr($this->file->body, $pos, 3) === '!--')
13831                         {
13832                                 $pos += 3;
13833                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13834                                 {
13835                                         $pos += 3;
13836                                 }
13837                                 else
13838                                 {
13839                                         return 'text/html';
13840                                 }
13841                         }
13842                         elseif (substr($this->file->body, $pos, 1) === '!')
13843                         {
13844                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13845                                 {
13846                                         $pos++;
13847                                 }
13848                                 else
13849                                 {
13850                                         return 'text/html';
13851                                 }
13852                         }
13853                         elseif (substr($this->file->body, $pos, 1) === '?')
13854                         {
13855                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13856                                 {
13857                                         $pos += 2;
13858                                 }
13859                                 else
13860                                 {
13861                                         return 'text/html';
13862                                 }
13863                         }
13864                         elseif (substr($this->file->body, $pos, 3) === 'rss'
13865                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13866                         {
13867                                 return 'application/rss+xml';
13868                         }
13869                         elseif (substr($this->file->body, $pos, 4) === 'feed')
13870                         {
13871                                 return 'application/atom+xml';
13872                         }
13873                         else
13874                         {
13875                                 return 'text/html';
13876                         }
13877                 }
13878
13879                 return 'text/html';
13880         }
13881 }
13882
13883 /**
13884  * Parses the XML Declaration
13885  *
13886  * @package SimplePie
13887  */
13888 class SimplePie_XML_Declaration_Parser
13889 {
13890         /**
13891          * XML Version
13892          *
13893          * @access public
13894          * @var string
13895          */
13896         var $version = '1.0';
13897
13898         /**
13899          * Encoding
13900          *
13901          * @access public
13902          * @var string
13903          */
13904         var $encoding = 'UTF-8';
13905
13906         /**
13907          * Standalone
13908          *
13909          * @access public
13910          * @var bool
13911          */
13912         var $standalone = false;
13913
13914         /**
13915          * Current state of the state machine
13916          *
13917          * @access private
13918          * @var string
13919          */
13920         var $state = 'before_version_name';
13921
13922         /**
13923          * Input data
13924          *
13925          * @access private
13926          * @var string
13927          */
13928         var $data = '';
13929
13930         /**
13931          * Input data length (to avoid calling strlen() everytime this is needed)
13932          *
13933          * @access private
13934          * @var int
13935          */
13936         var $data_length = 0;
13937
13938         /**
13939          * Current position of the pointer
13940          *
13941          * @var int
13942          * @access private
13943          */
13944         var $position = 0;
13945
13946         /**
13947          * Create an instance of the class with the input data
13948          *
13949          * @access public
13950          * @param string $data Input data
13951          */
13952         function SimplePie_XML_Declaration_Parser($data)
13953         {
13954                 $this->data = $data;
13955                 $this->data_length = strlen($this->data);
13956         }
13957
13958         /**
13959          * Parse the input data
13960          *
13961          * @access public
13962          * @return bool true on success, false on failure
13963          */
13964         function parse()
13965         {
13966                 while ($this->state && $this->state !== 'emit' && $this->has_data())
13967                 {
13968                         $state = $this->state;
13969                         $this->$state();
13970                 }
13971                 $this->data = '';
13972                 if ($this->state === 'emit')
13973                 {
13974                         return true;
13975                 }
13976                 else
13977                 {
13978                         $this->version = '';
13979                         $this->encoding = '';
13980                         $this->standalone = '';
13981                         return false;
13982                 }
13983         }
13984
13985         /**
13986          * Check whether there is data beyond the pointer
13987          *
13988          * @access private
13989          * @return bool true if there is further data, false if not
13990          */
13991         function has_data()
13992         {
13993                 return (bool) ($this->position < $this->data_length);
13994         }
13995
13996         /**
13997          * Advance past any whitespace
13998          *
13999          * @return int Number of whitespace characters passed
14000          */
14001         function skip_whitespace()
14002         {
14003                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14004                 $this->position += $whitespace;
14005                 return $whitespace;
14006         }
14007
14008         /**
14009          * Read value
14010          */
14011         function get_value()
14012         {
14013                 $quote = substr($this->data, $this->position, 1);
14014                 if ($quote === '"' || $quote === "'")
14015                 {
14016                         $this->position++;
14017                         $len = strcspn($this->data, $quote, $this->position);
14018                         if ($this->has_data())
14019                         {
14020                                 $value = substr($this->data, $this->position, $len);
14021                                 $this->position += $len + 1;
14022                                 return $value;
14023                         }
14024                 }
14025                 return false;
14026         }
14027
14028         function before_version_name()
14029         {
14030                 if ($this->skip_whitespace())
14031                 {
14032                         $this->state = 'version_name';
14033                 }
14034                 else
14035                 {
14036                         $this->state = false;
14037                 }
14038         }
14039
14040         function version_name()
14041         {
14042                 if (substr($this->data, $this->position, 7) === 'version')
14043                 {
14044                         $this->position += 7;
14045                         $this->skip_whitespace();
14046                         $this->state = 'version_equals';
14047                 }
14048                 else
14049                 {
14050                         $this->state = false;
14051                 }
14052         }
14053
14054         function version_equals()
14055         {
14056                 if (substr($this->data, $this->position, 1) === '=')
14057                 {
14058                         $this->position++;
14059                         $this->skip_whitespace();
14060                         $this->state = 'version_value';
14061                 }
14062                 else
14063                 {
14064                         $this->state = false;
14065                 }
14066         }
14067
14068         function version_value()
14069         {
14070                 if ($this->version = $this->get_value())
14071                 {
14072                         $this->skip_whitespace();
14073                         if ($this->has_data())
14074                         {
14075                                 $this->state = 'encoding_name';
14076                         }
14077                         else
14078                         {
14079                                 $this->state = 'emit';
14080                         }
14081                 }
14082                 else
14083                 {
14084                         $this->state = false;
14085                 }
14086         }
14087
14088         function encoding_name()
14089         {
14090                 if (substr($this->data, $this->position, 8) === 'encoding')
14091                 {
14092                         $this->position += 8;
14093                         $this->skip_whitespace();
14094                         $this->state = 'encoding_equals';
14095                 }
14096                 else
14097                 {
14098                         $this->state = 'standalone_name';
14099                 }
14100         }
14101
14102         function encoding_equals()
14103         {
14104                 if (substr($this->data, $this->position, 1) === '=')
14105                 {
14106                         $this->position++;
14107                         $this->skip_whitespace();
14108                         $this->state = 'encoding_value';
14109                 }
14110                 else
14111                 {
14112                         $this->state = false;
14113                 }
14114         }
14115
14116         function encoding_value()
14117         {
14118                 if ($this->encoding = $this->get_value())
14119                 {
14120                         $this->skip_whitespace();
14121                         if ($this->has_data())
14122                         {
14123                                 $this->state = 'standalone_name';
14124                         }
14125                         else
14126                         {
14127                                 $this->state = 'emit';
14128                         }
14129                 }
14130                 else
14131                 {
14132                         $this->state = false;
14133                 }
14134         }
14135
14136         function standalone_name()
14137         {
14138                 if (substr($this->data, $this->position, 10) === 'standalone')
14139                 {
14140                         $this->position += 10;
14141                         $this->skip_whitespace();
14142                         $this->state = 'standalone_equals';
14143                 }
14144                 else
14145                 {
14146                         $this->state = false;
14147                 }
14148         }
14149
14150         function standalone_equals()
14151         {
14152                 if (substr($this->data, $this->position, 1) === '=')
14153                 {
14154                         $this->position++;
14155                         $this->skip_whitespace();
14156                         $this->state = 'standalone_value';
14157                 }
14158                 else
14159                 {
14160                         $this->state = false;
14161                 }
14162         }
14163
14164         function standalone_value()
14165         {
14166                 if ($standalone = $this->get_value())
14167                 {
14168                         switch ($standalone)
14169                         {
14170                                 case 'yes':
14171                                         $this->standalone = true;
14172                                         break;
14173
14174                                 case 'no':
14175                                         $this->standalone = false;
14176                                         break;
14177
14178                                 default:
14179                                         $this->state = false;
14180                                         return;
14181                         }
14182
14183                         $this->skip_whitespace();
14184                         if ($this->has_data())
14185                         {
14186                                 $this->state = false;
14187                         }
14188                         else
14189                         {
14190                                 $this->state = 'emit';
14191                         }
14192                 }
14193                 else
14194                 {
14195                         $this->state = false;
14196                 }
14197         }
14198 }
14199
14200 class SimplePie_Locator
14201 {
14202         var $useragent;
14203         var $timeout;
14204         var $file;
14205         var $local = array();
14206         var $elsewhere = array();
14207         var $file_class = 'SimplePie_File';
14208         var $cached_entities = array();
14209         var $http_base;
14210         var $base;
14211         var $base_location = 0;
14212         var $checked_feeds = 0;
14213         var $max_checked_feeds = 10;
14214         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14215
14216         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14217         {
14218                 $this->file =& $file;
14219                 $this->file_class = $file_class;
14220                 $this->useragent = $useragent;
14221                 $this->timeout = $timeout;
14222                 $this->max_checked_feeds = $max_checked_feeds;
14223                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14224         }
14225
14226         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14227         {
14228                 if ($this->is_feed($this->file))
14229                 {
14230                         return $this->file;
14231                 }
14232
14233                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14234                 {
14235                         $sniffer = new $this->content_type_sniffer_class($this->file);
14236                         if ($sniffer->get_type() !== 'text/html')
14237                         {
14238                                 return null;
14239                         }
14240                 }
14241
14242                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14243                 {
14244                         $this->get_base();
14245                 }
14246
14247                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14248                 {
14249                         return $working[0];
14250                 }
14251
14252                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14253                 {
14254                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14255                         {
14256                                 return $working;
14257                         }
14258
14259                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14260                         {
14261                                 return $working;
14262                         }
14263
14264                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14265                         {
14266                                 return $working;
14267                         }
14268
14269                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14270                         {
14271                                 return $working;
14272                         }
14273                 }
14274                 return null;
14275         }
14276
14277         function is_feed(&$file)
14278         {
14279                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14280                 {
14281                         $sniffer = new $this->content_type_sniffer_class($file);
14282                         $sniffed = $sniffer->get_type();
14283                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14284                         {
14285                                 return true;
14286                         }
14287                         else
14288                         {
14289                                 return false;
14290                         }
14291                 }
14292                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14293                 {
14294                         return true;
14295                 }
14296                 else
14297                 {
14298                         return false;
14299                 }
14300         }
14301
14302         function get_base()
14303         {
14304                 $this->http_base = $this->file->url;
14305                 $this->base = $this->http_base;
14306                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14307                 foreach ($elements as $element)
14308                 {
14309                         if ($element['attribs']['href']['data'] !== '')
14310                         {
14311                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14312                                 $this->base_location = $element['offset'];
14313                                 break;
14314                         }
14315                 }
14316         }
14317
14318         function autodiscovery()
14319         {
14320                 $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));
14321                 $done = array();
14322                 $feeds = array();
14323                 foreach ($links as $link)
14324                 {
14325                         if ($this->checked_feeds === $this->max_checked_feeds)
14326                         {
14327                                 break;
14328                         }
14329                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14330                         {
14331                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14332
14333                                 if ($this->base_location < $link['offset'])
14334                                 {
14335                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14336                                 }
14337                                 else
14338                                 {
14339                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14340                                 }
14341
14342                                 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]))
14343                                 {
14344                                         $this->checked_feeds++;
14345                                         $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14346                                         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))
14347                                         {
14348                                                 $feeds[$href] = $feed;
14349                                         }
14350                                 }
14351                                 $done[] = $href;
14352                         }
14353                 }
14354
14355                 if (!empty($feeds))
14356                 {
14357                         return array_values($feeds);
14358                 }
14359                 else {
14360                         return null;
14361                 }
14362         }
14363
14364         function get_links()
14365         {
14366                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14367                 foreach ($links as $link)
14368                 {
14369                         if (isset($link['attribs']['href']['data']))
14370                         {
14371                                 $href = trim($link['attribs']['href']['data']);
14372                                 $parsed = SimplePie_Misc::parse_url($href);
14373                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14374                                 {
14375                                         if ($this->base_location < $link['offset'])
14376                                         {
14377                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14378                                         }
14379                                         else
14380                                         {
14381                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14382                                         }
14383
14384                                         $current = SimplePie_Misc::parse_url($this->file->url);
14385
14386                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14387                                         {
14388                                                 $this->local[] = $href;
14389                                         }
14390                                         else
14391                                         {
14392                                                 $this->elsewhere[] = $href;
14393                                         }
14394                                 }
14395                         }
14396                 }
14397                 $this->local = array_unique($this->local);
14398                 $this->elsewhere = array_unique($this->elsewhere);
14399                 if (!empty($this->local) || !empty($this->elsewhere))
14400                 {
14401                         return true;
14402                 }
14403                 return null;
14404         }
14405
14406         function extension(&$array)
14407         {
14408                 foreach ($array as $key => $value)
14409                 {
14410                         if ($this->checked_feeds === $this->max_checked_feeds)
14411                         {
14412                                 break;
14413                         }
14414                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14415                         {
14416                                 $this->checked_feeds++;
14417                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14418                                 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))
14419                                 {
14420                                         return $feed;
14421                                 }
14422                                 else
14423                                 {
14424                                         unset($array[$key]);
14425                                 }
14426                         }
14427                 }
14428                 return null;
14429         }
14430
14431         function body(&$array)
14432         {
14433                 foreach ($array as $key => $value)
14434                 {
14435                         if ($this->checked_feeds === $this->max_checked_feeds)
14436                         {
14437                                 break;
14438                         }
14439                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14440                         {
14441                                 $this->checked_feeds++;
14442                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14443                                 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))
14444                                 {
14445                                         return $feed;
14446                                 }
14447                                 else
14448                                 {
14449                                         unset($array[$key]);
14450                                 }
14451                         }
14452                 }
14453                 return null;
14454         }
14455 }
14456
14457 class SimplePie_Parser
14458 {
14459         var $error_code;
14460         var $error_string;
14461         var $current_line;
14462         var $current_column;
14463         var $current_byte;
14464         var $separator = ' ';
14465         var $namespace = array('');
14466         var $element = array('');
14467         var $xml_base = array('');
14468         var $xml_base_explicit = array(false);
14469         var $xml_lang = array('');
14470         var $data = array();
14471         var $datas = array(array());
14472         var $current_xhtml_construct = -1;
14473         var $encoding;
14474
14475         function parse(&$data, $encoding)
14476         {
14477                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14478                 if (strtoupper($encoding) === 'US-ASCII')
14479                 {
14480                         $this->encoding = 'UTF-8';
14481                 }
14482                 else
14483                 {
14484                         $this->encoding = $encoding;
14485                 }
14486
14487                 // Strip BOM:
14488                 // UTF-32 Big Endian BOM
14489                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14490                 {
14491                         $data = substr($data, 4);
14492                 }
14493                 // UTF-32 Little Endian BOM
14494                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14495                 {
14496                         $data = substr($data, 4);
14497                 }
14498                 // UTF-16 Big Endian BOM
14499                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14500                 {
14501                         $data = substr($data, 2);
14502                 }
14503                 // UTF-16 Little Endian BOM
14504                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14505                 {
14506                         $data = substr($data, 2);
14507                 }
14508                 // UTF-8 BOM
14509                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14510                 {
14511                         $data = substr($data, 3);
14512                 }
14513
14514                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14515                 {
14516                         $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14517                         if ($declaration->parse())
14518                         {
14519                                 $data = substr($data, $pos + 2);
14520                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14521                         }
14522                         else
14523                         {
14524                                 $this->error_string = 'SimplePie bug! Please report this!';
14525                                 return false;
14526                         }
14527                 }
14528
14529                 $return = true;
14530
14531                 static $xml_is_sane = null;
14532                 if ($xml_is_sane === null)
14533                 {
14534                         $parser_check = xml_parser_create();
14535                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14536                         xml_parser_free($parser_check);
14537                         $xml_is_sane = isset($values[0]['value']);
14538                 }
14539
14540                 // Create the parser
14541                 if ($xml_is_sane)
14542                 {
14543                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14544                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14545                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14546                         xml_set_object($xml, $this);
14547                         xml_set_character_data_handler($xml, 'cdata');
14548                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14549
14550                         // Parse!
14551                         if (!xml_parse($xml, $data, true))
14552                         {
14553                                 $this->error_code = xml_get_error_code($xml);
14554                                 $this->error_string = xml_error_string($this->error_code);
14555                                 $return = false;
14556                         }
14557                         $this->current_line = xml_get_current_line_number($xml);
14558                         $this->current_column = xml_get_current_column_number($xml);
14559                         $this->current_byte = xml_get_current_byte_index($xml);
14560                         xml_parser_free($xml);
14561                         return $return;
14562                 }
14563                 else
14564                 {
14565                         libxml_clear_errors();
14566                         $xml = new XMLReader();
14567                         $xml->xml($data);
14568                         while (@$xml->read())
14569                         {
14570                                 switch ($xml->nodeType)
14571                                 {
14572
14573                                         case constant('XMLReader::END_ELEMENT'):
14574                                                 if ($xml->namespaceURI !== '')
14575                                                 {
14576                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14577                                                 }
14578                                                 else
14579                                                 {
14580                                                         $tagName = $xml->localName;
14581                                                 }
14582                                                 $this->tag_close(null, $tagName);
14583                                                 break;
14584                                         case constant('XMLReader::ELEMENT'):
14585                                                 $empty = $xml->isEmptyElement;
14586                                                 if ($xml->namespaceURI !== '')
14587                                                 {
14588                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14589                                                 }
14590                                                 else
14591                                                 {
14592                                                         $tagName = $xml->localName;
14593                                                 }
14594                                                 $attributes = array();
14595                                                 while ($xml->moveToNextAttribute())
14596                                                 {
14597                                                         if ($xml->namespaceURI !== '')
14598                                                         {
14599                                                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14600                                                         }
14601                                                         else
14602                                                         {
14603                                                                 $attrName = $xml->localName;
14604                                                         }
14605                                                         $attributes[$attrName] = $xml->value;
14606                                                 }
14607                                                 $this->tag_open(null, $tagName, $attributes);
14608                                                 if ($empty)
14609                                                 {
14610                                                         $this->tag_close(null, $tagName);
14611                                                 }
14612                                                 break;
14613                                         case constant('XMLReader::TEXT'):
14614
14615                                         case constant('XMLReader::CDATA'):
14616                                                 $this->cdata(null, $xml->value);
14617                                                 break;
14618                                 }
14619                         }
14620                         if ($error = libxml_get_last_error())
14621                         {
14622                                 $this->error_code = $error->code;
14623                                 $this->error_string = $error->message;
14624                                 $this->current_line = $error->line;
14625                                 $this->current_column = $error->column;
14626                                 return false;
14627                         }
14628                         else
14629                         {
14630                                 return true;
14631                         }
14632                 }
14633         }
14634
14635         function get_error_code()
14636         {
14637                 return $this->error_code;
14638         }
14639
14640         function get_error_string()
14641         {
14642                 return $this->error_string;
14643         }
14644
14645         function get_current_line()
14646         {
14647                 return $this->current_line;
14648         }
14649
14650         function get_current_column()
14651         {
14652                 return $this->current_column;
14653         }
14654
14655         function get_current_byte()
14656         {
14657                 return $this->current_byte;
14658         }
14659
14660         function get_data()
14661         {
14662                 return $this->data;
14663         }
14664
14665         function tag_open($parser, $tag, $attributes)
14666         {
14667                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14668
14669                 $attribs = array();
14670                 foreach ($attributes as $name => $value)
14671                 {
14672                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14673                         $attribs[$attrib_namespace][$attribute] = $value;
14674                 }
14675
14676                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14677                 {
14678                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14679                         $this->xml_base_explicit[] = true;
14680                 }
14681                 else
14682                 {
14683                         $this->xml_base[] = end($this->xml_base);
14684                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14685                 }
14686
14687                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14688                 {
14689                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14690                 }
14691                 else
14692                 {
14693                         $this->xml_lang[] = end($this->xml_lang);
14694                 }
14695
14696                 if ($this->current_xhtml_construct >= 0)
14697                 {
14698                         $this->current_xhtml_construct++;
14699                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14700                         {
14701                                 $this->data['data'] .= '<' . end($this->element);
14702                                 if (isset($attribs['']))
14703                                 {
14704                                         foreach ($attribs[''] as $name => $value)
14705                                         {
14706                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14707                                         }
14708                                 }
14709                                 $this->data['data'] .= '>';
14710                         }
14711                 }
14712                 else
14713                 {
14714                         $this->datas[] =& $this->data;
14715                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14716                         $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));
14717                         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')
14718                         || (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'))
14719                         {
14720                                 $this->current_xhtml_construct = 0;
14721                         }
14722                 }
14723         }
14724
14725         function cdata($parser, $cdata)
14726         {
14727                 if ($this->current_xhtml_construct >= 0)
14728                 {
14729                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14730                 }
14731                 else
14732                 {
14733                         $this->data['data'] .= $cdata;
14734                 }
14735         }
14736
14737         function tag_close($parser, $tag)
14738         {
14739                 if ($this->current_xhtml_construct >= 0)
14740                 {
14741                         $this->current_xhtml_construct--;
14742                         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')))
14743                         {
14744                                 $this->data['data'] .= '</' . end($this->element) . '>';
14745                         }
14746                 }
14747                 if ($this->current_xhtml_construct === -1)
14748                 {
14749                         $this->data =& $this->datas[count($this->datas) - 1];
14750                         array_pop($this->datas);
14751                 }
14752
14753                 array_pop($this->element);
14754                 array_pop($this->namespace);
14755                 array_pop($this->xml_base);
14756                 array_pop($this->xml_base_explicit);
14757                 array_pop($this->xml_lang);
14758         }
14759
14760         function split_ns($string)
14761         {
14762                 static $cache = array();
14763                 if (!isset($cache[$string]))
14764                 {
14765                         if ($pos = strpos($string, $this->separator))
14766                         {
14767                                 static $separator_length;
14768                                 if (!$separator_length)
14769                                 {
14770                                         $separator_length = strlen($this->separator);
14771                                 }
14772                                 $namespace = substr($string, 0, $pos);
14773                                 $local_name = substr($string, $pos + $separator_length);
14774                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14775                                 {
14776                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14777                                 }
14778
14779                                 // Normalize the Media RSS namespaces
14780                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14781                                 {
14782                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14783                                 }
14784                                 $cache[$string] = array($namespace, $local_name);
14785                         }
14786                         else
14787                         {
14788                                 $cache[$string] = array('', $string);
14789                         }
14790                 }
14791                 return $cache[$string];
14792         }
14793 }
14794
14795 /**
14796  * @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
14797  */
14798 class SimplePie_Sanitize
14799 {
14800         // Private vars
14801         var $base;
14802
14803         // Options
14804         var $remove_div = true;
14805         var $image_handler = '';
14806         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14807         var $encode_instead_of_strip = false;
14808         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14809         var $strip_comments = false;
14810         var $output_encoding = 'UTF-8';
14811         var $enable_cache = true;
14812         var $cache_location = './cache';
14813         var $cache_name_function = 'md5';
14814         var $cache_class = 'SimplePie_Cache';
14815         var $file_class = 'SimplePie_File';
14816         var $timeout = 10;
14817         var $useragent = '';
14818         var $force_fsockopen = false;
14819
14820         var $replace_url_attributes = array(
14821                 'a' => 'href',
14822                 'area' => 'href',
14823                 'blockquote' => 'cite',
14824                 'del' => 'cite',
14825                 'form' => 'action',
14826                 'img' => array('longdesc', 'src'),
14827                 'input' => 'src',
14828                 'ins' => 'cite',
14829                 'q' => 'cite'
14830         );
14831
14832         function remove_div($enable = true)
14833         {
14834                 $this->remove_div = (bool) $enable;
14835         }
14836
14837         function set_image_handler($page = false)
14838         {
14839                 if ($page)
14840                 {
14841                         $this->image_handler = (string) $page;
14842                 }
14843                 else
14844                 {
14845                         $this->image_handler = false;
14846                 }
14847         }
14848
14849         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14850         {
14851                 if (isset($enable_cache))
14852                 {
14853                         $this->enable_cache = (bool) $enable_cache;
14854                 }
14855
14856                 if ($cache_location)
14857                 {
14858                         $this->cache_location = (string) $cache_location;
14859                 }
14860
14861                 if ($cache_name_function)
14862                 {
14863                         $this->cache_name_function = (string) $cache_name_function;
14864                 }
14865
14866                 if ($cache_class)
14867                 {
14868                         $this->cache_class = (string) $cache_class;
14869                 }
14870         }
14871
14872         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14873         {
14874                 if ($file_class)
14875                 {
14876                         $this->file_class = (string) $file_class;
14877                 }
14878
14879                 if ($timeout)
14880                 {
14881                         $this->timeout = (string) $timeout;
14882                 }
14883
14884                 if ($useragent)
14885                 {
14886                         $this->useragent = (string) $useragent;
14887                 }
14888
14889                 if ($force_fsockopen)
14890                 {
14891                         $this->force_fsockopen = (string) $force_fsockopen;
14892                 }
14893         }
14894
14895         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14896         {
14897                 if ($tags)
14898                 {
14899                         if (is_array($tags))
14900                         {
14901                                 $this->strip_htmltags = $tags;
14902                         }
14903                         else
14904                         {
14905                                 $this->strip_htmltags = explode(',', $tags);
14906                         }
14907                 }
14908                 else
14909                 {
14910                         $this->strip_htmltags = false;
14911                 }
14912         }
14913
14914         function encode_instead_of_strip($encode = false)
14915         {
14916                 $this->encode_instead_of_strip = (bool) $encode;
14917         }
14918
14919         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14920         {
14921                 if ($attribs)
14922                 {
14923                         if (is_array($attribs))
14924                         {
14925                                 $this->strip_attributes = $attribs;
14926                         }
14927                         else
14928                         {
14929                                 $this->strip_attributes = explode(',', $attribs);
14930                         }
14931                 }
14932                 else
14933                 {
14934                         $this->strip_attributes = false;
14935                 }
14936         }
14937
14938         function strip_comments($strip = false)
14939         {
14940                 $this->strip_comments = (bool) $strip;
14941         }
14942
14943         function set_output_encoding($encoding = 'UTF-8')
14944         {
14945                 $this->output_encoding = (string) $encoding;
14946         }
14947
14948         /**
14949          * Set element/attribute key/value pairs of HTML attributes
14950          * containing URLs that need to be resolved relative to the feed
14951          *
14952          * @access public
14953          * @since 1.0
14954          * @param array $element_attribute Element/attribute key/value pairs
14955          */
14956         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'))
14957         {
14958                 $this->replace_url_attributes = (array) $element_attribute;
14959         }
14960
14961         function sanitize($data, $type, $base = '')
14962         {
14963                 $data = trim($data);
14964                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14965                 {
14966                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14967                         {
14968                                 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))
14969                                 {
14970                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
14971                                 }
14972                                 else
14973                                 {
14974                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14975                                 }
14976                         }
14977
14978                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14979                         {
14980                                 $data = base64_decode($data);
14981                         }
14982
14983                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14984                         {
14985                                 if ($this->remove_div)
14986                                 {
14987                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14988                                         $data = preg_replace('/<\/div>$/', '', $data);
14989                                 }
14990                                 else
14991                                 {
14992                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14993                                 }
14994                         }
14995
14996                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14997                         {
14998                                 // Strip comments
14999                                 if ($this->strip_comments)
15000                                 {
15001                                         $data = SimplePie_Misc::strip_comments($data);
15002                                 }
15003
15004                                 // Strip out HTML tags and attributes that might cause various security problems.
15005                                 // Based on recommendations by Mark Pilgrim at:
15006                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15007                                 if ($this->strip_htmltags)
15008                                 {
15009                                         foreach ($this->strip_htmltags as $tag)
15010                                         {
15011                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15012                                                 while (preg_match($pcre, $data))
15013                                                 {
15014                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15015                                                 }
15016                                         }
15017                                 }
15018
15019                                 if ($this->strip_attributes)
15020                                 {
15021                                         foreach ($this->strip_attributes as $attrib)
15022                                         {
15023                                                 $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);
15024                                         }
15025                                 }
15026
15027                                 // Replace relative URLs
15028                                 $this->base = $base;
15029                                 foreach ($this->replace_url_attributes as $element => $attributes)
15030                                 {
15031                                         $data = $this->replace_urls($data, $element, $attributes);
15032                                 }
15033
15034                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15035                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15036                                 {
15037                                         $images = SimplePie_Misc::get_element('img', $data);
15038                                         foreach ($images as $img)
15039                                         {
15040                                                 if (isset($img['attribs']['src']['data']))
15041                                                 {
15042                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15043                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15044
15045                                                         if ($cache->load())
15046                                                         {
15047                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15048                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15049                                                         }
15050                                                         else
15051                                                         {
15052                                                                 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15053                                                                 $headers = $file->headers;
15054
15055                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15056                                                                 {
15057                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15058                                                                         {
15059                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15060                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15061                                                                         }
15062                                                                         else
15063                                                                         {
15064                                                                                 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);
15065                                                                         }
15066                                                                 }
15067                                                         }
15068                                                 }
15069                                         }
15070                                 }
15071
15072                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15073                                 $data = trim($data);
15074                         }
15075
15076                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15077                         {
15078                                 $data = SimplePie_Misc::absolutize_url($data, $base);
15079                         }
15080
15081                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15082                         {
15083                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15084                         }
15085
15086                         if ($this->output_encoding !== 'UTF-8')
15087                         {
15088                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15089                         }
15090                 }
15091                 return $data;
15092         }
15093
15094         function replace_urls($data, $tag, $attributes)
15095         {
15096                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15097                 {
15098                         $elements = SimplePie_Misc::get_element($tag, $data);
15099                         foreach ($elements as $element)
15100                         {
15101                                 if (is_array($attributes))
15102                                 {
15103                                         foreach ($attributes as $attribute)
15104                                         {
15105                                                 if (isset($element['attribs'][$attribute]['data']))
15106                                                 {
15107                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15108                                                         $new_element = SimplePie_Misc::element_implode($element);
15109                                                         $data = str_replace($element['full'], $new_element, $data);
15110                                                         $element['full'] = $new_element;
15111                                                 }
15112                                         }
15113                                 }
15114                                 elseif (isset($element['attribs'][$attributes]['data']))
15115                                 {
15116                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15117                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15118                                 }
15119                         }
15120                 }
15121                 return $data;
15122         }
15123
15124         function do_strip_htmltags($match)
15125         {
15126                 if ($this->encode_instead_of_strip)
15127                 {
15128                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15129                         {
15130                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15131                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15132                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15133                         }
15134                         else
15135                         {
15136                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15137                         }
15138                 }
15139                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15140                 {
15141                         return $match[4];
15142                 }
15143                 else
15144                 {
15145                         return '';
15146                 }
15147         }
15148 }
15149
15150 ?>