]> git.mxchange.org Git - friendica.git/blob - simplepie/simplepie.inc
add owner's birthday information to feed (if allowed to)
[friendica.git] / simplepie / simplepie.inc
1 <?php
2 /**
3  * SimplePie
4  *
5  * A PHP-Based RSS and Atom Feed Framework.
6  * Takes the hard work out of managing a complete RSS/Atom solution.
7  *
8  * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification, are
12  * permitted provided that the following conditions are met:
13  *
14  *      * Redistributions of source code must retain the above copyright notice, this list of
15  *        conditions and the following disclaimer.
16  *
17  *      * Redistributions in binary form must reproduce the above copyright notice, this list
18  *        of conditions and the following disclaimer in the documentation and/or other materials
19  *        provided with the distribution.
20  *
21  *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
22  *        to endorse or promote products derived from this software without specific prior
23  *        written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * @package SimplePie
36  * @version 1.2.1-dev
37  * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
38  * @author Ryan Parman
39  * @author Geoffrey Sneddon
40  * @link http://simplepie.org/ SimplePie
41  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43  * @todo phpDoc comments
44  */
45
46 /**
47  * SimplePie Name
48  */
49 define('SIMPLEPIE_NAME', 'SimplePie');
50
51 /**
52  * SimplePie Version
53  */
54 define('SIMPLEPIE_VERSION', '1.2.1-dev');
55
56 /**
57  * SimplePie Build
58  * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
59  */
60 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
61
62 /**
63  * SimplePie Website URL
64  */
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
66
67 /**
68  * SimplePie Useragent
69  * @see SimplePie::set_useragent()
70  */
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
72
73 /**
74  * SimplePie Linkback
75  */
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
77
78 /**
79  * No Autodiscovery
80  * @see SimplePie::set_autodiscovery_level()
81  */
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
83
84 /**
85  * Feed Link Element Autodiscovery
86  * @see SimplePie::set_autodiscovery_level()
87  */
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
89
90 /**
91  * Local Feed Extension Autodiscovery
92  * @see SimplePie::set_autodiscovery_level()
93  */
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
95
96 /**
97  * Local Feed Body Autodiscovery
98  * @see SimplePie::set_autodiscovery_level()
99  */
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
101
102 /**
103  * Remote Feed Extension Autodiscovery
104  * @see SimplePie::set_autodiscovery_level()
105  */
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
107
108 /**
109  * Remote Feed Body Autodiscovery
110  * @see SimplePie::set_autodiscovery_level()
111  */
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
113
114 /**
115  * All Feed Autodiscovery
116  * @see SimplePie::set_autodiscovery_level()
117  */
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
119
120 /**
121  * No known feed type
122  */
123 define('SIMPLEPIE_TYPE_NONE', 0);
124
125 /**
126  * RSS 0.90
127  */
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
129
130 /**
131  * RSS 0.91 (Netscape)
132  */
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
134
135 /**
136  * RSS 0.91 (Userland)
137  */
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
139
140 /**
141  * RSS 0.91 (both Netscape and Userland)
142  */
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
144
145 /**
146  * RSS 0.92
147  */
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
149
150 /**
151  * RSS 0.93
152  */
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
154
155 /**
156  * RSS 0.94
157  */
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
159
160 /**
161  * RSS 1.0
162  */
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
164
165 /**
166  * RSS 2.0
167  */
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
169
170 /**
171  * RDF-based RSS
172  */
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
174
175 /**
176  * Non-RDF-based RSS (truly intended as syndication format)
177  */
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
179
180 /**
181  * All RSS
182  */
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
184
185 /**
186  * Atom 0.3
187  */
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
189
190 /**
191  * Atom 1.0
192  */
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
194
195 /**
196  * All Atom
197  */
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
199
200 /**
201  * All feed types
202  */
203 define('SIMPLEPIE_TYPE_ALL', 1023);
204
205 /**
206  * No construct
207  */
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
209
210 /**
211  * Text construct
212  */
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
214
215 /**
216  * HTML construct
217  */
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
219
220 /**
221  * XHTML construct
222  */
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
224
225 /**
226  * base64-encoded construct
227  */
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
229
230 /**
231  * IRI construct
232  */
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
234
235 /**
236  * A construct that might be HTML
237  */
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
239
240 /**
241  * All constructs
242  */
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
244
245 /**
246  * Don't change case
247  */
248 define('SIMPLEPIE_SAME_CASE', 1);
249
250 /**
251  * Change to lowercase
252  */
253 define('SIMPLEPIE_LOWERCASE', 2);
254
255 /**
256  * Change to uppercase
257  */
258 define('SIMPLEPIE_UPPERCASE', 4);
259
260 /**
261  * PCRE for HTML attributes
262  */
263 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
264
265 /**
266  * PCRE for XML attributes
267  */
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
269
270 /**
271  * XML Namespace
272  */
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
274
275 /**
276  * Atom 1.0 Namespace
277  */
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
279
280 /**
281  * Atom 0.3 Namespace
282  */
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
284
285 /**
286  * RDF Namespace
287  */
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
289
290 /**
291  * RSS 0.90 Namespace
292  */
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
294
295 /**
296  * RSS 1.0 Namespace
297  */
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
299
300 /**
301  * RSS 1.0 Content Module Namespace
302  */
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
304
305 /**
306  * RSS 2.0 Namespace
307  * (Stupid, I know, but I'm certain it will confuse people less with support.)
308  */
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
310
311 /**
312  * DC 1.0 Namespace
313  */
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
315
316 /**
317  * DC 1.1 Namespace
318  */
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
320
321 /**
322  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
323  */
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
325
326 /**
327  * GeoRSS Namespace
328  */
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
330
331 /**
332  * Media RSS Namespace
333  */
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
335
336 /**
337  * Wrong Media RSS Namespace
338  */
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
340
341 /**
342  * iTunes RSS Namespace
343  */
344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
345
346 /**
347  * XHTML Namespace
348  */
349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
350
351 /**
352  * IANA Link Relations Registry
353  */
354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
355
356 /**
357  * Whether we're running on PHP5
358  */
359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
360
361 /**
362  * No file source
363  */
364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
365
366 /**
367  * Remote file source
368  */
369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
370
371 /**
372  * Local file source
373  */
374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
375
376 /**
377  * fsockopen() file source
378  */
379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
380
381 /**
382  * cURL file source
383  */
384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
385
386 /**
387  * file_get_contents() file source
388  */
389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
390
391 /**
392  * SimplePie
393  *
394  * @package SimplePie
395  */
396 class SimplePie
397 {
398         /**
399          * @var array Raw data
400          * @access private
401          */
402         var $data = array();
403
404         /**
405          * @var mixed Error string
406          * @access private
407          */
408         var $error;
409
410         /**
411          * @var object Instance of SimplePie_Sanitize (or other class)
412          * @see SimplePie::set_sanitize_class()
413          * @access private
414          */
415         var $sanitize;
416
417         /**
418          * @var string SimplePie Useragent
419          * @see SimplePie::set_useragent()
420          * @access private
421          */
422         var $useragent = SIMPLEPIE_USERAGENT;
423
424         /**
425          * @var string Feed URL
426          * @see SimplePie::set_feed_url()
427          * @access private
428          */
429         var $feed_url;
430
431         /**
432          * @var object Instance of SimplePie_File to use as a feed
433          * @see SimplePie::set_file()
434          * @access private
435          */
436         var $file;
437
438         /**
439          * @var string Raw feed data
440          * @see SimplePie::set_raw_data()
441          * @access private
442          */
443         var $raw_data;
444
445         /**
446          * @var int Timeout for fetching remote files
447          * @see SimplePie::set_timeout()
448          * @access private
449          */
450         var $timeout = 10;
451
452         /**
453          * @var bool Forces fsockopen() to be used for remote files instead
454          * of cURL, even if a new enough version is installed
455          * @see SimplePie::force_fsockopen()
456          * @access private
457          */
458         var $force_fsockopen = false;
459
460         /**
461          * @var bool Force the given data/URL to be treated as a feed no matter what
462          * it appears like
463          * @see SimplePie::force_feed()
464          * @access private
465          */
466         var $force_feed = false;
467
468         /**
469          * @var bool Enable/Disable XML dump
470          * @see SimplePie::enable_xml_dump()
471          * @access private
472          */
473         var $xml_dump = false;
474
475         /**
476          * @var bool Enable/Disable Caching
477          * @see SimplePie::enable_cache()
478          * @access private
479          */
480         var $cache = true;
481
482         /**
483          * @var int Cache duration (in seconds)
484          * @see SimplePie::set_cache_duration()
485          * @access private
486          */
487         var $cache_duration = 3600;
488
489         /**
490          * @var int Auto-discovery cache duration (in seconds)
491          * @see SimplePie::set_autodiscovery_cache_duration()
492          * @access private
493          */
494         var $autodiscovery_cache_duration = 604800; // 7 Days.
495
496         /**
497          * @var string Cache location (relative to executing script)
498          * @see SimplePie::set_cache_location()
499          * @access private
500          */
501         var $cache_location = './cache';
502
503         /**
504          * @var string Function that creates the cache filename
505          * @see SimplePie::set_cache_name_function()
506          * @access private
507          */
508         var $cache_name_function = 'md5';
509
510         /**
511          * @var bool Reorder feed by date descending
512          * @see SimplePie::enable_order_by_date()
513          * @access private
514          */
515         var $order_by_date = true;
516
517         /**
518          * @var mixed Force input encoding to be set to the follow value
519          * (false, or anything type-cast to false, disables this feature)
520          * @see SimplePie::set_input_encoding()
521          * @access private
522          */
523         var $input_encoding = false;
524
525         /**
526          * @var int Feed Autodiscovery Level
527          * @see SimplePie::set_autodiscovery_level()
528          * @access private
529          */
530         var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
531
532         /**
533          * @var string Class used for caching feeds
534          * @see SimplePie::set_cache_class()
535          * @access private
536          */
537         var $cache_class = 'SimplePie_Cache';
538
539         /**
540          * @var string Class used for locating feeds
541          * @see SimplePie::set_locator_class()
542          * @access private
543          */
544         var $locator_class = 'SimplePie_Locator';
545
546         /**
547          * @var string Class used for parsing feeds
548          * @see SimplePie::set_parser_class()
549          * @access private
550          */
551         var $parser_class = 'SimplePie_Parser';
552
553         /**
554          * @var string Class used for fetching feeds
555          * @see SimplePie::set_file_class()
556          * @access private
557          */
558         var $file_class = 'SimplePie_File';
559
560         /**
561          * @var string Class used for items
562          * @see SimplePie::set_item_class()
563          * @access private
564          */
565         var $item_class = 'SimplePie_Item';
566
567         /**
568          * @var string Class used for authors
569          * @see SimplePie::set_author_class()
570          * @access private
571          */
572         var $author_class = 'SimplePie_Author';
573
574         /**
575          * @var string Class used for categories
576          * @see SimplePie::set_category_class()
577          * @access private
578          */
579         var $category_class = 'SimplePie_Category';
580
581         /**
582          * @var string Class used for enclosures
583          * @see SimplePie::set_enclosures_class()
584          * @access private
585          */
586         var $enclosure_class = 'SimplePie_Enclosure';
587
588         /**
589          * @var string Class used for Media RSS <media:text> captions
590          * @see SimplePie::set_caption_class()
591          * @access private
592          */
593         var $caption_class = 'SimplePie_Caption';
594
595         /**
596          * @var string Class used for Media RSS <media:copyright>
597          * @see SimplePie::set_copyright_class()
598          * @access private
599          */
600         var $copyright_class = 'SimplePie_Copyright';
601
602         /**
603          * @var string Class used for Media RSS <media:credit>
604          * @see SimplePie::set_credit_class()
605          * @access private
606          */
607         var $credit_class = 'SimplePie_Credit';
608
609         /**
610          * @var string Class used for Media RSS <media:rating>
611          * @see SimplePie::set_rating_class()
612          * @access private
613          */
614         var $rating_class = 'SimplePie_Rating';
615
616         /**
617          * @var string Class used for Media RSS <media:restriction>
618          * @see SimplePie::set_restriction_class()
619          * @access private
620          */
621         var $restriction_class = 'SimplePie_Restriction';
622
623         /**
624          * @var string Class used for content-type sniffing
625          * @see SimplePie::set_content_type_sniffer_class()
626          * @access private
627          */
628         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
629
630         /**
631          * @var string Class used for item sources.
632          * @see SimplePie::set_source_class()
633          * @access private
634          */
635         var $source_class = 'SimplePie_Source';
636
637         /**
638          * @var mixed Set javascript query string parameter (false, or
639          * anything type-cast to false, disables this feature)
640          * @see SimplePie::set_javascript()
641          * @access private
642          */
643         var $javascript = 'js';
644
645         /**
646          * @var int Maximum number of feeds to check with autodiscovery
647          * @see SimplePie::set_max_checked_feeds()
648          * @access private
649          */
650         var $max_checked_feeds = 10;
651
652         /**
653          * @var array All the feeds found during the autodiscovery process
654          * @see SimplePie::get_all_discovered_feeds()
655          * @access private
656          */
657         var $all_discovered_feeds = array();
658
659         /**
660          * @var string Web-accessible path to the handler_favicon.php file.
661          * @see SimplePie::set_favicon_handler()
662          * @access private
663          */
664         var $favicon_handler = '';
665
666         /**
667          * @var string Web-accessible path to the handler_image.php file.
668          * @see SimplePie::set_image_handler()
669          * @access private
670          */
671         var $image_handler = '';
672
673         /**
674          * @var array Stores the URLs when multiple feeds are being initialized.
675          * @see SimplePie::set_feed_url()
676          * @access private
677          */
678         var $multifeed_url = array();
679
680         /**
681          * @var array Stores SimplePie objects when multiple feeds initialized.
682          * @access private
683          */
684         var $multifeed_objects = array();
685
686         /**
687          * @var array Stores the get_object_vars() array for use with multifeeds.
688          * @see SimplePie::set_feed_url()
689          * @access private
690          */
691         var $config_settings = null;
692
693         /**
694          * @var integer Stores the number of items to return per-feed with multifeeds.
695          * @see SimplePie::set_item_limit()
696          * @access private
697          */
698         var $item_limit = 0;
699
700         /**
701          * @var array Stores the default attributes to be stripped by strip_attributes().
702          * @see SimplePie::strip_attributes()
703          * @access private
704          */
705         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
706
707         /**
708          * @var array Stores the default tags to be stripped by strip_htmltags().
709          * @see SimplePie::strip_htmltags()
710          * @access private
711          */
712         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
713
714         /**
715          * The SimplePie class contains feed level data and options
716          *
717          * There are two ways that you can create a new SimplePie object. The first
718          * is by passing a feed URL as a parameter to the SimplePie constructor
719          * (as well as optionally setting the cache location and cache expiry). This
720          * will initialise the whole feed with all of the default settings, and you
721          * can begin accessing methods and properties immediately.
722          *
723          * The second way is to create the SimplePie object with no parameters
724          * at all. This will enable you to set configuration options. After setting
725          * them, you must initialise the feed using $feed->init(). At that point the
726          * object's methods and properties will be available to you. This format is
727          * what is used throughout this documentation.
728          *
729          * @access public
730          * @since 1.0 Preview Release
731          * @param string $feed_url This is the URL you want to parse.
732          * @param string $cache_location This is where you want the cache to be stored.
733          * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
734          */
735         function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
736         {
737                 // Other objects, instances created here so we can set options on them
738                 $this->sanitize = new SimplePie_Sanitize;
739
740                 // Set options if they're passed to the constructor
741                 if ($cache_location !== null)
742                 {
743                         $this->set_cache_location($cache_location);
744                 }
745
746                 if ($cache_duration !== null)
747                 {
748                         $this->set_cache_duration($cache_duration);
749                 }
750
751                 // Only init the script if we're passed a feed URL
752                 if ($feed_url !== null)
753                 {
754                         $this->set_feed_url($feed_url);
755                         $this->init();
756                 }
757         }
758
759         /**
760          * Used for converting object to a string
761          */
762         function __toString()
763         {
764                 return md5(serialize($this->data));
765         }
766
767         /**
768          * Remove items that link back to this before destroying this object
769          */
770         function __destruct()
771         {
772                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
773                 {
774                         if (!empty($this->data['items']))
775                         {
776                                 foreach ($this->data['items'] as $item)
777                                 {
778                                         $item->__destruct();
779                                 }
780                                 unset($item, $this->data['items']);
781                         }
782                         if (!empty($this->data['ordered_items']))
783                         {
784                                 foreach ($this->data['ordered_items'] as $item)
785                                 {
786                                         $item->__destruct();
787                                 }
788                                 unset($item, $this->data['ordered_items']);
789                         }
790                 }
791         }
792
793         /**
794          * Force the given data/URL to be treated as a feed no matter what it
795          * appears like
796          *
797          * @access public
798          * @since 1.1
799          * @param bool $enable Force the given data/URL to be treated as a feed
800          */
801         function force_feed($enable = false)
802         {
803                 $this->force_feed = (bool) $enable;
804         }
805
806         /**
807          * This is the URL of the feed you want to parse.
808          *
809          * This allows you to enter the URL of the feed you want to parse, or the
810          * website you want to try to use auto-discovery on. This takes priority
811          * over any set raw data.
812          *
813          * You can set multiple feeds to mash together by passing an array instead
814          * of a string for the $url. Remember that with each additional feed comes
815          * additional processing and resources.
816          *
817          * @access public
818          * @since 1.0 Preview Release
819          * @param mixed $url This is the URL (or array of URLs) that you want to parse.
820          * @see SimplePie::set_raw_data()
821          */
822         function set_feed_url($url)
823         {
824                 if (is_array($url))
825                 {
826                         $this->multifeed_url = array();
827                         foreach ($url as $value)
828                         {
829                                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
830                         }
831                 }
832                 else
833                 {
834                         $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
835                 }
836         }
837
838         /**
839          * Provides an instance of SimplePie_File to use as a feed
840          *
841          * @access public
842          * @param object &$file Instance of SimplePie_File (or subclass)
843          * @return bool True on success, false on failure
844          */
845         function set_file(&$file)
846         {
847                 if (is_a($file, 'SimplePie_File'))
848                 {
849                         $this->feed_url = $file->url;
850                         $this->file =& $file;
851                         return true;
852                 }
853                 return false;
854         }
855
856         /**
857          * Allows you to use a string of RSS/Atom data instead of a remote feed.
858          *
859          * If you have a feed available as a string in PHP, you can tell SimplePie
860          * to parse that data string instead of a remote feed. Any set feed URL
861          * takes precedence.
862          *
863          * @access public
864          * @since 1.0 Beta 3
865          * @param string $data RSS or Atom data as a string.
866          * @see SimplePie::set_feed_url()
867          */
868         function set_raw_data($data)
869         {
870                 $this->raw_data = $data;
871         }
872
873         /**
874          * Allows you to override the default timeout for fetching remote feeds.
875          *
876          * This allows you to change the maximum time the feed's server to respond
877          * and send the feed back.
878          *
879          * @access public
880          * @since 1.0 Beta 3
881          * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
882          */
883         function set_timeout($timeout = 10)
884         {
885                 $this->timeout = (int) $timeout;
886         }
887
888         /**
889          * Forces SimplePie to use fsockopen() instead of the preferred cURL
890          * functions.
891          *
892          * @access public
893          * @since 1.0 Beta 3
894          * @param bool $enable Force fsockopen() to be used
895          */
896         function force_fsockopen($enable = false)
897         {
898                 $this->force_fsockopen = (bool) $enable;
899         }
900
901         /**
902          * Outputs the raw XML content of the feed, after it has gone through
903          * SimplePie's filters.
904          *
905          * Used only for debugging, this function will output the XML content as
906          * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
907          * before trying to parse it. Many parts of the feed are re-written in
908          * memory, and in the end, you have a parsable feed. XML dump shows you the
909          * actual XML that SimplePie tries to parse, which may or may not be very
910          * different from the original feed.
911          *
912          * @access public
913          * @since 1.0 Preview Release
914          * @param bool $enable Enable XML dump
915          */
916         function enable_xml_dump($enable = false)
917         {
918                 $this->xml_dump = (bool) $enable;
919         }
920
921         /**
922          * Enables/disables caching in SimplePie.
923          *
924          * This option allows you to disable caching all-together in SimplePie.
925          * However, disabling the cache can lead to longer load times.
926          *
927          * @access public
928          * @since 1.0 Preview Release
929          * @param bool $enable Enable caching
930          */
931         function enable_cache($enable = true)
932         {
933                 $this->cache = (bool) $enable;
934         }
935
936         /**
937          * Set the length of time (in seconds) that the contents of a feed
938          * will be cached.
939          *
940          * @access public
941          * @param int $seconds The feed content cache duration.
942          */
943         function set_cache_duration($seconds = 3600)
944         {
945                 $this->cache_duration = (int) $seconds;
946         }
947
948         /**
949          * Set the length of time (in seconds) that the autodiscovered feed
950          * URL will be cached.
951          *
952          * @access public
953          * @param int $seconds The autodiscovered feed URL cache duration.
954          */
955         function set_autodiscovery_cache_duration($seconds = 604800)
956         {
957                 $this->autodiscovery_cache_duration = (int) $seconds;
958         }
959
960         /**
961          * Set the file system location where the cached files should be stored.
962          *
963          * @access public
964          * @param string $location The file system location.
965          */
966         function set_cache_location($location = './cache')
967         {
968                 $this->cache_location = (string) $location;
969         }
970
971         /**
972          * Determines whether feed items should be sorted into reverse chronological order.
973          *
974          * @access public
975          * @param bool $enable Sort as reverse chronological order.
976          */
977         function enable_order_by_date($enable = true)
978         {
979                 $this->order_by_date = (bool) $enable;
980         }
981
982         /**
983          * Allows you to override the character encoding reported by the feed.
984          *
985          * @access public
986          * @param string $encoding Character encoding.
987          */
988         function set_input_encoding($encoding = false)
989         {
990                 if ($encoding)
991                 {
992                         $this->input_encoding = (string) $encoding;
993                 }
994                 else
995                 {
996                         $this->input_encoding = false;
997                 }
998         }
999
1000         /**
1001          * Set how much feed autodiscovery to do
1002          *
1003          * @access public
1004          * @see SIMPLEPIE_LOCATOR_NONE
1005          * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1006          * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1007          * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1008          * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1009          * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1010          * @see SIMPLEPIE_LOCATOR_ALL
1011          * @param int $level Feed Autodiscovery Level (level can be a
1012          * combination of the above constants, see bitwise OR operator)
1013          */
1014         function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1015         {
1016                 $this->autodiscovery = (int) $level;
1017         }
1018
1019         /**
1020          * Allows you to change which class SimplePie uses for caching.
1021          * Useful when you are overloading or extending SimplePie's default classes.
1022          *
1023          * @access public
1024          * @param string $class Name of custom class.
1025          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1026          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1027          */
1028         function set_cache_class($class = 'SimplePie_Cache')
1029         {
1030                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1031                 {
1032                         $this->cache_class = $class;
1033                         return true;
1034                 }
1035                 return false;
1036         }
1037
1038         /**
1039          * Allows you to change which class SimplePie uses for auto-discovery.
1040          * Useful when you are overloading or extending SimplePie's default classes.
1041          *
1042          * @access public
1043          * @param string $class Name of custom class.
1044          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1045          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1046          */
1047         function set_locator_class($class = 'SimplePie_Locator')
1048         {
1049                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1050                 {
1051                         $this->locator_class = $class;
1052                         return true;
1053                 }
1054                 return false;
1055         }
1056
1057         /**
1058          * Allows you to change which class SimplePie uses for XML parsing.
1059          * Useful when you are overloading or extending SimplePie's default classes.
1060          *
1061          * @access public
1062          * @param string $class Name of custom class.
1063          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1064          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1065          */
1066         function set_parser_class($class = 'SimplePie_Parser')
1067         {
1068                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1069                 {
1070                         $this->parser_class = $class;
1071                         return true;
1072                 }
1073                 return false;
1074         }
1075
1076         /**
1077          * Allows you to change which class SimplePie uses for remote file fetching.
1078          * Useful when you are overloading or extending SimplePie's default classes.
1079          *
1080          * @access public
1081          * @param string $class Name of custom class.
1082          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1083          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1084          */
1085         function set_file_class($class = 'SimplePie_File')
1086         {
1087                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1088                 {
1089                         $this->file_class = $class;
1090                         return true;
1091                 }
1092                 return false;
1093         }
1094
1095         /**
1096          * Allows you to change which class SimplePie uses for data sanitization.
1097          * Useful when you are overloading or extending SimplePie's default classes.
1098          *
1099          * @access public
1100          * @param string $class Name of custom class.
1101          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1102          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1103          */
1104         function set_sanitize_class($class = 'SimplePie_Sanitize')
1105         {
1106                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1107                 {
1108                         $this->sanitize = new $class;
1109                         return true;
1110                 }
1111                 return false;
1112         }
1113
1114         /**
1115          * Allows you to change which class SimplePie uses for handling feed items.
1116          * Useful when you are overloading or extending SimplePie's default classes.
1117          *
1118          * @access public
1119          * @param string $class Name of custom class.
1120          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1121          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1122          */
1123         function set_item_class($class = 'SimplePie_Item')
1124         {
1125                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1126                 {
1127                         $this->item_class = $class;
1128                         return true;
1129                 }
1130                 return false;
1131         }
1132
1133         /**
1134          * Allows you to change which class SimplePie uses for handling author data.
1135          * Useful when you are overloading or extending SimplePie's default classes.
1136          *
1137          * @access public
1138          * @param string $class Name of custom class.
1139          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1140          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1141          */
1142         function set_author_class($class = 'SimplePie_Author')
1143         {
1144                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1145                 {
1146                         $this->author_class = $class;
1147                         return true;
1148                 }
1149                 return false;
1150         }
1151
1152         /**
1153          * Allows you to change which class SimplePie uses for handling category data.
1154          * Useful when you are overloading or extending SimplePie's default classes.
1155          *
1156          * @access public
1157          * @param string $class Name of custom class.
1158          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1159          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1160          */
1161         function set_category_class($class = 'SimplePie_Category')
1162         {
1163                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1164                 {
1165                         $this->category_class = $class;
1166                         return true;
1167                 }
1168                 return false;
1169         }
1170
1171         /**
1172          * Allows you to change which class SimplePie uses for feed enclosures.
1173          * Useful when you are overloading or extending SimplePie's default classes.
1174          *
1175          * @access public
1176          * @param string $class Name of custom class.
1177          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1178          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1179          */
1180         function set_enclosure_class($class = 'SimplePie_Enclosure')
1181         {
1182                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1183                 {
1184                         $this->enclosure_class = $class;
1185                         return true;
1186                 }
1187                 return false;
1188         }
1189
1190         /**
1191          * Allows you to change which class SimplePie uses for <media:text> captions
1192          * Useful when you are overloading or extending SimplePie's default classes.
1193          *
1194          * @access public
1195          * @param string $class Name of custom class.
1196          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1197          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1198          */
1199         function set_caption_class($class = 'SimplePie_Caption')
1200         {
1201                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1202                 {
1203                         $this->caption_class = $class;
1204                         return true;
1205                 }
1206                 return false;
1207         }
1208
1209         /**
1210          * Allows you to change which class SimplePie uses for <media:copyright>
1211          * Useful when you are overloading or extending SimplePie's default classes.
1212          *
1213          * @access public
1214          * @param string $class Name of custom class.
1215          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1216          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1217          */
1218         function set_copyright_class($class = 'SimplePie_Copyright')
1219         {
1220                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1221                 {
1222                         $this->copyright_class = $class;
1223                         return true;
1224                 }
1225                 return false;
1226         }
1227
1228         /**
1229          * Allows you to change which class SimplePie uses for <media:credit>
1230          * Useful when you are overloading or extending SimplePie's default classes.
1231          *
1232          * @access public
1233          * @param string $class Name of custom class.
1234          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1235          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1236          */
1237         function set_credit_class($class = 'SimplePie_Credit')
1238         {
1239                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1240                 {
1241                         $this->credit_class = $class;
1242                         return true;
1243                 }
1244                 return false;
1245         }
1246
1247         /**
1248          * Allows you to change which class SimplePie uses for <media:rating>
1249          * Useful when you are overloading or extending SimplePie's default classes.
1250          *
1251          * @access public
1252          * @param string $class Name of custom class.
1253          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1254          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1255          */
1256         function set_rating_class($class = 'SimplePie_Rating')
1257         {
1258                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1259                 {
1260                         $this->rating_class = $class;
1261                         return true;
1262                 }
1263                 return false;
1264         }
1265
1266         /**
1267          * Allows you to change which class SimplePie uses for <media:restriction>
1268          * Useful when you are overloading or extending SimplePie's default classes.
1269          *
1270          * @access public
1271          * @param string $class Name of custom class.
1272          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1273          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1274          */
1275         function set_restriction_class($class = 'SimplePie_Restriction')
1276         {
1277                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1278                 {
1279                         $this->restriction_class = $class;
1280                         return true;
1281                 }
1282                 return false;
1283         }
1284
1285         /**
1286          * Allows you to change which class SimplePie uses for content-type sniffing.
1287          * Useful when you are overloading or extending SimplePie's default classes.
1288          *
1289          * @access public
1290          * @param string $class Name of custom class.
1291          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1292          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1293          */
1294         function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1295         {
1296                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1297                 {
1298                         $this->content_type_sniffer_class = $class;
1299                         return true;
1300                 }
1301                 return false;
1302         }
1303
1304         /**
1305          * Allows you to change which class SimplePie uses item sources.
1306          * Useful when you are overloading or extending SimplePie's default classes.
1307          *
1308          * @access public
1309          * @param string $class Name of custom class.
1310          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1311          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1312          */
1313         function set_source_class($class = 'SimplePie_Source')
1314         {
1315                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1316                 {
1317                         $this->source_class = $class;
1318                         return true;
1319                 }
1320                 return false;
1321         }
1322
1323         /**
1324          * Allows you to override the default user agent string.
1325          *
1326          * @access public
1327          * @param string $ua New user agent string.
1328          */
1329         function set_useragent($ua = SIMPLEPIE_USERAGENT)
1330         {
1331                 $this->useragent = (string) $ua;
1332         }
1333
1334         /**
1335          * Set callback function to create cache filename with
1336          *
1337          * @access public
1338          * @param mixed $function Callback function
1339          */
1340         function set_cache_name_function($function = 'md5')
1341         {
1342                 if (is_callable($function))
1343                 {
1344                         $this->cache_name_function = $function;
1345                 }
1346         }
1347
1348         /**
1349          * Set javascript query string parameter
1350          *
1351          * @access public
1352          * @param mixed $get Javascript query string parameter
1353          */
1354         function set_javascript($get = 'js')
1355         {
1356                 if ($get)
1357                 {
1358                         $this->javascript = (string) $get;
1359                 }
1360                 else
1361                 {
1362                         $this->javascript = false;
1363                 }
1364         }
1365
1366         /**
1367          * Set options to make SP as fast as possible.  Forgoes a
1368          * substantial amount of data sanitization in favor of speed.
1369          *
1370          * @access public
1371          * @param bool $set Whether to set them or not
1372          */
1373         function set_stupidly_fast($set = false)
1374         {
1375                 if ($set)
1376                 {
1377                         $this->enable_order_by_date(false);
1378                         $this->remove_div(false);
1379                         $this->strip_comments(false);
1380                         $this->strip_htmltags(false);
1381                         $this->strip_attributes(false);
1382                         $this->set_image_handler(false);
1383                 }
1384         }
1385
1386         /**
1387          * Set maximum number of feeds to check with autodiscovery
1388          *
1389          * @access public
1390          * @param int $max Maximum number of feeds to check
1391          */
1392         function set_max_checked_feeds($max = 10)
1393         {
1394                 $this->max_checked_feeds = (int) $max;
1395         }
1396
1397         function remove_div($enable = true)
1398         {
1399                 $this->sanitize->remove_div($enable);
1400         }
1401
1402         function strip_htmltags($tags = '', $encode = null)
1403         {
1404                 if ($tags === '')
1405                 {
1406                         $tags = $this->strip_htmltags;
1407                 }
1408                 $this->sanitize->strip_htmltags($tags);
1409                 if ($encode !== null)
1410                 {
1411                         $this->sanitize->encode_instead_of_strip($tags);
1412                 }
1413         }
1414
1415         function encode_instead_of_strip($enable = true)
1416         {
1417                 $this->sanitize->encode_instead_of_strip($enable);
1418         }
1419
1420         function strip_attributes($attribs = '')
1421         {
1422                 if ($attribs === '')
1423                 {
1424                         $attribs = $this->strip_attributes;
1425                 }
1426                 $this->sanitize->strip_attributes($attribs);
1427         }
1428
1429         function set_output_encoding($encoding = 'UTF-8')
1430         {
1431                 $this->sanitize->set_output_encoding($encoding);
1432         }
1433
1434         function strip_comments($strip = false)
1435         {
1436                 $this->sanitize->strip_comments($strip);
1437         }
1438
1439         /**
1440          * Set element/attribute key/value pairs of HTML attributes
1441          * containing URLs that need to be resolved relative to the feed
1442          *
1443          * @access public
1444          * @since 1.0
1445          * @param array $element_attribute Element/attribute key/value pairs
1446          */
1447         function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1448         {
1449                 $this->sanitize->set_url_replacements($element_attribute);
1450         }
1451
1452         /**
1453          * Set the handler to enable the display of cached favicons.
1454          *
1455          * @access public
1456          * @param str $page Web-accessible path to the handler_favicon.php file.
1457          * @param str $qs The query string that the value should be passed to.
1458          */
1459         function set_favicon_handler($page = false, $qs = 'i')
1460         {
1461                 if ($page !== false)
1462                 {
1463                         $this->favicon_handler = $page . '?' . $qs . '=';
1464                 }
1465                 else
1466                 {
1467                         $this->favicon_handler = '';
1468                 }
1469         }
1470
1471         /**
1472          * Set the handler to enable the display of cached images.
1473          *
1474          * @access public
1475          * @param str $page Web-accessible path to the handler_image.php file.
1476          * @param str $qs The query string that the value should be passed to.
1477          */
1478         function set_image_handler($page = false, $qs = 'i')
1479         {
1480                 if ($page !== false)
1481                 {
1482                         $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1483                 }
1484                 else
1485                 {
1486                         $this->image_handler = '';
1487                 }
1488         }
1489
1490         /**
1491          * Set the limit for items returned per-feed with multifeeds.
1492          *
1493          * @access public
1494          * @param integer $limit The maximum number of items to return.
1495          */
1496         function set_item_limit($limit = 0)
1497         {
1498                 $this->item_limit = (int) $limit;
1499         }
1500
1501         function init()
1502         {
1503                 // Check absolute bare minimum requirements.
1504                 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1505                 {
1506                         return false;
1507                 }
1508                 // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1509                 elseif (!extension_loaded('xmlreader'))
1510                 {
1511                         static $xml_is_sane = null;
1512                         if ($xml_is_sane === null)
1513                         {
1514                                 $parser_check = xml_parser_create();
1515                                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1516                                 xml_parser_free($parser_check);
1517                                 $xml_is_sane = isset($values[0]['value']);
1518                         }
1519                         if (!$xml_is_sane)
1520                         {
1521                                 return false;
1522                         }
1523                 }
1524
1525                 if (isset($_GET[$this->javascript]))
1526                 {
1527                         SimplePie_Misc::output_javascript();
1528                         exit;
1529                 }
1530
1531                 // Pass whatever was set with config options over to the sanitizer.
1532                 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1533                 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1534
1535                 if ($this->feed_url !== null || $this->raw_data !== null)
1536                 {
1537                         $this->data = array();
1538                         $this->multifeed_objects = array();
1539                         $cache = false;
1540
1541                         if ($this->feed_url !== null)
1542                         {
1543                                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1544                                 // Decide whether to enable caching
1545                                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1546                                 {
1547                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1548                                 }
1549                                 // If it's enabled and we don't want an XML dump, use the cache
1550                                 if ($cache && !$this->xml_dump)
1551                                 {
1552                                         // Load the Cache
1553                                         $this->data = $cache->load();
1554                                         if (!empty($this->data))
1555                                         {
1556                                                 // If the cache is for an outdated build of SimplePie
1557                                                 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1558                                                 {
1559                                                         $cache->unlink();
1560                                                         $this->data = array();
1561                                                 }
1562                                                 // If we've hit a collision just rerun it with caching disabled
1563                                                 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1564                                                 {
1565                                                         $cache = false;
1566                                                         $this->data = array();
1567                                                 }
1568                                                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1569                                                 elseif (isset($this->data['feed_url']))
1570                                                 {
1571                                                         // If the autodiscovery cache is still valid use it.
1572                                                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1573                                                         {
1574                                                                 // Do not need to do feed autodiscovery yet.
1575                                                                 if ($this->data['feed_url'] === $this->data['url'])
1576                                                                 {
1577                                                                         $cache->unlink();
1578                                                                         $this->data = array();
1579                                                                 }
1580                                                                 else
1581                                                                 {
1582                                                                         $this->set_feed_url($this->data['feed_url']);
1583                                                                         return $this->init();
1584                                                                 }
1585                                                         }
1586                                                 }
1587                                                 // Check if the cache has been updated
1588                                                 elseif ($cache->mtime() + $this->cache_duration < time())
1589                                                 {
1590                                                         // If we have last-modified and/or etag set
1591                                                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1592                                                         {
1593                                                                 $headers = array();
1594                                                                 if (isset($this->data['headers']['last-modified']))
1595                                                                 {
1596                                                                         $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1597                                                                 }
1598                                                                 if (isset($this->data['headers']['etag']))
1599                                                                 {
1600                                                                         $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1601                                                                 }
1602                                                                 $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1603                                                                 if ($file->success)
1604                                                                 {
1605                                                                         if ($file->status_code === 304)
1606                                                                         {
1607                                                                                 $cache->touch();
1608                                                                                 return true;
1609                                                                         }
1610                                                                         else
1611                                                                         {
1612                                                                                 $headers = $file->headers;
1613                                                                         }
1614                                                                 }
1615                                                                 else
1616                                                                 {
1617                                                                         unset($file);
1618                                                                 }
1619                                                         }
1620                                                 }
1621                                                 // If the cache is still valid, just return true
1622                                                 else
1623                                                 {
1624                                                         return true;
1625                                                 }
1626                                         }
1627                                         // If the cache is empty, delete it
1628                                         else
1629                                         {
1630                                                 $cache->unlink();
1631                                                 $this->data = array();
1632                                         }
1633                                 }
1634                                 // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
1635                                 if (!isset($file))
1636                                 {
1637                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1638                                         {
1639                                                 $file =& $this->file;
1640                                         }
1641                                         else
1642                                         {
1643                                                 $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1644                                         }
1645                                 }
1646                                 // If the file connection has an error, set SimplePie::error to that and quit
1647                                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1648                                 {
1649                                         $this->error = $file->error;
1650                                         if (!empty($this->data))
1651                                         {
1652                                                 return true;
1653                                         }
1654                                         else
1655                                         {
1656                                                 return false;
1657                                         }
1658                                 }
1659
1660                                 if (!$this->force_feed)
1661                                 {
1662                                         // Check if the supplied URL is a feed, if it isn't, look for it.
1663                                         $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1664                                         if (!$locate->is_feed($file))
1665                                         {
1666                                                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1667                                                 unset($file);
1668                                                 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1669                                                 {
1670                                                         if ($cache)
1671                                                         {
1672                                                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673                                                                 if (!$cache->save($this))
1674                                                                 {
1675                                                                         trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1676                                                                 }
1677                                                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1678                                                         }
1679                                                         $this->feed_url = $file->url;
1680                                                 }
1681                                                 else
1682                                                 {
1683                                                         $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1684                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1685                                                         return false;
1686                                                 }
1687                                         }
1688                                         $locate = null;
1689                                 }
1690
1691                                 $headers = $file->headers;
1692                                 $data = $file->body;
1693                                 $sniffer = new $this->content_type_sniffer_class($file);
1694                                 $sniffed = $sniffer->get_type();
1695                         }
1696                         else
1697                         {
1698                                 $data = $this->raw_data;
1699                         }
1700
1701                         // Set up array of possible encodings
1702                         $encodings = array();
1703
1704                         // First check to see if input has been overridden.
1705                         if ($this->input_encoding !== false)
1706                         {
1707                                 $encodings[] = $this->input_encoding;
1708                         }
1709
1710                         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1711                         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1712
1713                         // RFC 3023 (only applies to sniffed content)
1714                         if (isset($sniffed))
1715                         {
1716                                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1717                                 {
1718                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1719                                         {
1720                                                 $encodings[] = strtoupper($charset[1]);
1721                                         }
1722                                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723                                         $encodings[] = 'UTF-8';
1724                                 }
1725                                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1726                                 {
1727                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1728                                         {
1729                                                 $encodings[] = $charset[1];
1730                                         }
1731                                         $encodings[] = 'US-ASCII';
1732                                 }
1733                                 // Text MIME-type default
1734                                 elseif (substr($sniffed, 0, 5) === 'text/')
1735                                 {
1736                                         $encodings[] = 'US-ASCII';
1737                                 }
1738                         }
1739
1740                         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1741                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1742                         $encodings[] = 'UTF-8';
1743                         $encodings[] = 'ISO-8859-1';
1744
1745                         // There's no point in trying an encoding twice
1746                         $encodings = array_unique($encodings);
1747
1748                         // If we want the XML, just output that with the most likely encoding and quit
1749                         if ($this->xml_dump)
1750                         {
1751                                 header('Content-type: text/xml; charset=' . $encodings[0]);
1752                                 echo $data;
1753                                 exit;
1754                         }
1755
1756                         // Loop through each possible encoding, till we return something, or run out of possibilities
1757                         foreach ($encodings as $encoding)
1758                         {
1759                                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1760                                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1761                                 {
1762                                         // Create new parser
1763                                         $parser = new $this->parser_class();
1764
1765                                         // If it's parsed fine
1766                                         if ($parser->parse($utf8_data, 'UTF-8'))
1767                                         {
1768                                                 $this->data = $parser->get_data();
1769                                                 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1770                                                 {
1771                                                         if (isset($headers))
1772                                                         {
1773                                                                 $this->data['headers'] = $headers;
1774                                                         }
1775                                                         $this->data['build'] = SIMPLEPIE_BUILD;
1776
1777                                                         // Cache the file if caching is enabled
1778                                                         if ($cache && !$cache->save($this))
1779                                                         {
1780                                                                 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1781                                                         }
1782                                                         return true;
1783                                                 }
1784                                                 else
1785                                                 {
1786                                                         $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1787                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1788                                                         return false;
1789                                                 }
1790                                         }
1791                                 }
1792                         }
1793                         if (isset($parser))
1794                         {
1795                                 // We have an error, just set SimplePie_Misc::error to it and quit
1796                                 $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1797                         }
1798                         else
1799                         {
1800                                 $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1801                         }
1802                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1803                         return false;
1804                 }
1805                 elseif (!empty($this->multifeed_url))
1806                 {
1807                         $i = 0;
1808                         $success = 0;
1809                         $this->multifeed_objects = array();
1810                         foreach ($this->multifeed_url as $url)
1811                         {
1812                                 if (SIMPLEPIE_PHP5)
1813                                 {
1814                                         // This keyword needs to defy coding standards for PHP4 compatibility
1815                                         $this->multifeed_objects[$i] = clone($this);
1816                                 }
1817                                 else
1818                                 {
1819                                         $this->multifeed_objects[$i] = $this;
1820                                 }
1821                                 $this->multifeed_objects[$i]->set_feed_url($url);
1822                                 $success |= $this->multifeed_objects[$i]->init();
1823                                 $i++;
1824                         }
1825                         return (bool) $success;
1826                 }
1827                 else
1828                 {
1829                         return false;
1830                 }
1831         }
1832
1833         /**
1834          * Return the error message for the occured error
1835          *
1836          * @access public
1837          * @return string Error message
1838          */
1839         function error()
1840         {
1841                 return $this->error;
1842         }
1843
1844         function get_encoding()
1845         {
1846                 return $this->sanitize->output_encoding;
1847         }
1848
1849         function handle_content_type($mime = 'text/html')
1850         {
1851                 if (!headers_sent())
1852                 {
1853                         $header = "Content-type: $mime;";
1854                         if ($this->get_encoding())
1855                         {
1856                                 $header .= ' charset=' . $this->get_encoding();
1857                         }
1858                         else
1859                         {
1860                                 $header .= ' charset=UTF-8';
1861                         }
1862                         header($header);
1863                 }
1864         }
1865
1866         function get_type()
1867         {
1868                 if (!isset($this->data['type']))
1869                 {
1870                         $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1872                         {
1873                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1874                         }
1875                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1876                         {
1877                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1878                         }
1879                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1880                         {
1881                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1882                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1883                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1884                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1885                                 {
1886                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1887                                 }
1888                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1889                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1890                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1891                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1892                                 {
1893                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1894                                 }
1895                         }
1896                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1897                         {
1898                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1900                                 {
1901                                         switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1902                                         {
1903                                                 case '0.91':
1904                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1905                                                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1906                                                         {
1907                                                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1908                                                                 {
1909                                                                         case '0':
1910                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1911                                                                                 break;
1912
1913                                                                         case '24':
1914                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1915                                                                                 break;
1916                                                                 }
1917                                                         }
1918                                                         break;
1919
1920                                                 case '0.92':
1921                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1922                                                         break;
1923
1924                                                 case '0.93':
1925                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1926                                                         break;
1927
1928                                                 case '0.94':
1929                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1930                                                         break;
1931
1932                                                 case '2.0':
1933                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1934                                                         break;
1935                                         }
1936                                 }
1937                         }
1938                         else
1939                         {
1940                                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1941                         }
1942                 }
1943                 return $this->data['type'];
1944         }
1945
1946         /**
1947          * Returns the URL for the favicon of the feed's website.
1948          *
1949          * @todo Cache atom:icon
1950          * @access public
1951          * @since 1.0
1952          */
1953         function get_favicon()
1954         {
1955                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1956                 {
1957                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1958                 }
1959                 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1960                 {
1961                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1962
1963                         if ($this->cache && $this->favicon_handler)
1964                         {
1965                                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1966                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1967
1968                                 if ($cache->load())
1969                                 {
1970                                         return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1971                                 }
1972                                 else
1973                                 {
1974                                         $file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1975
1976                                         if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1977                                         {
1978                                                 $sniffer = new $this->content_type_sniffer_class($file);
1979                                                 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1980                                                 {
1981                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1982                                                         {
1983                                                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1984                                                         }
1985                                                         else
1986                                                         {
1987                                                                 trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1988                                                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1989                                                         }
1990                                                 }
1991                                                 // not an image
1992                                                 else
1993                                                 {
1994                                                         return false;
1995                                                 }
1996                                         }
1997                                 }
1998                         }
1999                         else
2000                         {
2001                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2002                         }
2003                 }
2004                 return false;
2005         }
2006
2007         /**
2008          * @todo If we have a perm redirect we should return the new URL
2009          * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2010          * @todo Also, |atom:link|@rel=self
2011          */
2012         function subscribe_url()
2013         {
2014                 if ($this->feed_url !== null)
2015                 {
2016                         return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2017                 }
2018                 else
2019                 {
2020                         return null;
2021                 }
2022         }
2023
2024         function subscribe_feed()
2025         {
2026                 if ($this->feed_url !== null)
2027                 {
2028                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2029                 }
2030                 else
2031                 {
2032                         return null;
2033                 }
2034         }
2035
2036         function subscribe_outlook()
2037         {
2038                 if ($this->feed_url !== null)
2039                 {
2040                         return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2041                 }
2042                 else
2043                 {
2044                         return null;
2045                 }
2046         }
2047
2048         function subscribe_podcast()
2049         {
2050                 if ($this->feed_url !== null)
2051                 {
2052                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2053                 }
2054                 else
2055                 {
2056                         return null;
2057                 }
2058         }
2059
2060         function subscribe_itunes()
2061         {
2062                 if ($this->feed_url !== null)
2063                 {
2064                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2065                 }
2066                 else
2067                 {
2068                         return null;
2069                 }
2070         }
2071
2072         /**
2073          * Creates the subscribe_* methods' return data
2074          *
2075          * @access private
2076          * @param string $feed_url String to prefix to the feed URL
2077          * @param string $site_url String to prefix to the site URL (and
2078          * suffix to the feed URL)
2079          * @return mixed URL if feed exists, false otherwise
2080          */
2081         function subscribe_service($feed_url, $site_url = null)
2082         {
2083                 if ($this->subscribe_url())
2084                 {
2085                         $return = $feed_url . rawurlencode($this->feed_url);
2086                         if ($site_url !== null && $this->get_link() !== null)
2087                         {
2088                                 $return .= $site_url . rawurlencode($this->get_link());
2089                         }
2090                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2091                 }
2092                 else
2093                 {
2094                         return null;
2095                 }
2096         }
2097
2098         function subscribe_aol()
2099         {
2100                 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2101         }
2102
2103         function subscribe_bloglines()
2104         {
2105                 return $this->subscribe_service('http://www.bloglines.com/sub/');
2106         }
2107
2108         function subscribe_eskobo()
2109         {
2110                 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2111         }
2112
2113         function subscribe_feedfeeds()
2114         {
2115                 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2116         }
2117
2118         function subscribe_feedster()
2119         {
2120                 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2121         }
2122
2123         function subscribe_google()
2124         {
2125                 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2126         }
2127
2128         function subscribe_gritwire()
2129         {
2130                 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2131         }
2132
2133         function subscribe_msn()
2134         {
2135                 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2136         }
2137
2138         function subscribe_netvibes()
2139         {
2140                 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2141         }
2142
2143         function subscribe_newsburst()
2144         {
2145                 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2146         }
2147
2148         function subscribe_newsgator()
2149         {
2150                 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2151         }
2152
2153         function subscribe_odeo()
2154         {
2155                 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2156         }
2157
2158         function subscribe_podnova()
2159         {
2160                 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2161         }
2162
2163         function subscribe_rojo()
2164         {
2165                 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2166         }
2167
2168         function subscribe_yahoo()
2169         {
2170                 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2171         }
2172
2173         function get_feed_tags($namespace, $tag)
2174         {
2175                 $type = $this->get_type();
2176                 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2177                 {
2178                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2179                         {
2180                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2181                         }
2182                 }
2183                 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2184                 {
2185                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2186                         {
2187                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2188                         }
2189                 }
2190                 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2191                 {
2192                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2193                         {
2194                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2195                         }
2196                 }
2197                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2198                 {
2199                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2200                         {
2201                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2202                         }
2203                 }
2204                 return null;
2205         }
2206
2207         function get_channel_tags($namespace, $tag)
2208         {
2209                 $type = $this->get_type();
2210                 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2211                 {
2212                         if ($return = $this->get_feed_tags($namespace, $tag))
2213                         {
2214                                 return $return;
2215                         }
2216                 }
2217                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2218                 {
2219                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2220                         {
2221                                 if (isset($channel[0]['child'][$namespace][$tag]))
2222                                 {
2223                                         return $channel[0]['child'][$namespace][$tag];
2224                                 }
2225                         }
2226                 }
2227                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2228                 {
2229                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2230                         {
2231                                 if (isset($channel[0]['child'][$namespace][$tag]))
2232                                 {
2233                                         return $channel[0]['child'][$namespace][$tag];
2234                                 }
2235                         }
2236                 }
2237                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2238                 {
2239                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2240                         {
2241                                 if (isset($channel[0]['child'][$namespace][$tag]))
2242                                 {
2243                                         return $channel[0]['child'][$namespace][$tag];
2244                                 }
2245                         }
2246                 }
2247                 return null;
2248         }
2249
2250         function get_image_tags($namespace, $tag)
2251         {
2252                 $type = $this->get_type();
2253                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2254                 {
2255                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2256                         {
2257                                 if (isset($image[0]['child'][$namespace][$tag]))
2258                                 {
2259                                         return $image[0]['child'][$namespace][$tag];
2260                                 }
2261                         }
2262                 }
2263                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2264                 {
2265                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2266                         {
2267                                 if (isset($image[0]['child'][$namespace][$tag]))
2268                                 {
2269                                         return $image[0]['child'][$namespace][$tag];
2270                                 }
2271                         }
2272                 }
2273                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2274                 {
2275                         if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2276                         {
2277                                 if (isset($image[0]['child'][$namespace][$tag]))
2278                                 {
2279                                         return $image[0]['child'][$namespace][$tag];
2280                                 }
2281                         }
2282                 }
2283                 return null;
2284         }
2285
2286         function get_base($element = array())
2287         {
2288                 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2289                 {
2290                         return $element['xml_base'];
2291                 }
2292                 elseif ($this->get_link() !== null)
2293                 {
2294                         return $this->get_link();
2295                 }
2296                 else
2297                 {
2298                         return $this->subscribe_url();
2299                 }
2300         }
2301
2302         function sanitize($data, $type, $base = '')
2303         {
2304                 return $this->sanitize->sanitize($data, $type, $base);
2305         }
2306
2307         function get_title()
2308         {
2309                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2310                 {
2311                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2312                 }
2313                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2314                 {
2315                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2316                 }
2317                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2318                 {
2319                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2320                 }
2321                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2322                 {
2323                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2324                 }
2325                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2326                 {
2327                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2328                 }
2329                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2330                 {
2331                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2332                 }
2333                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2334                 {
2335                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2336                 }
2337                 else
2338                 {
2339                         return null;
2340                 }
2341         }
2342
2343         function get_category($key = 0)
2344         {
2345                 $categories = $this->get_categories();
2346                 if (isset($categories[$key]))
2347                 {
2348                         return $categories[$key];
2349                 }
2350                 else
2351                 {
2352                         return null;
2353                 }
2354         }
2355
2356         function get_categories()
2357         {
2358                 $categories = array();
2359
2360                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2361                 {
2362                         $term = null;
2363                         $scheme = null;
2364                         $label = null;
2365                         if (isset($category['attribs']['']['term']))
2366                         {
2367                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2368                         }
2369                         if (isset($category['attribs']['']['scheme']))
2370                         {
2371                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2372                         }
2373                         if (isset($category['attribs']['']['label']))
2374                         {
2375                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2376                         }
2377                         $categories[] = new $this->category_class($term, $scheme, $label);
2378                 }
2379                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2380                 {
2381                         // This is really the label, but keep this as the term also for BC.
2382                         // Label will also work on retrieving because that falls back to term.
2383                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384                         if (isset($category['attribs']['']['domain']))
2385                         {
2386                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2387                         }
2388                         else
2389                         {
2390                                 $scheme = null;
2391                         }
2392                         $categories[] = new $this->category_class($term, $scheme, null);
2393                 }
2394                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2395                 {
2396                         $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2397                 }
2398                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2399                 {
2400                         $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2401                 }
2402
2403                 if (!empty($categories))
2404                 {
2405                         return SimplePie_Misc::array_unique($categories);
2406                 }
2407                 else
2408                 {
2409                         return null;
2410                 }
2411         }
2412
2413         function get_author($key = 0)
2414         {
2415                 $authors = $this->get_authors();
2416                 if (isset($authors[$key]))
2417                 {
2418                         return $authors[$key];
2419                 }
2420                 else
2421                 {
2422                         return null;
2423                 }
2424         }
2425
2426         function get_authors()
2427         {
2428                 $authors = array();
2429                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2430                 {
2431                         $name = null;
2432                         $uri = null;
2433                         $email = null;
2434                         $avatar = null;
2435                         $name_date = null;
2436                         $uri_date = null;
2437                         $avatar_date = null;
2438
2439                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2440                         {
2441                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2442                         }
2443                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2444                         {
2445                                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2446                         }
2447                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2448                         {
2449                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2450                         }
2451                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
2452                         {
2453                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
2454                         }
2455                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
2456                         {
2457                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
2458                         }
2459                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
2460                         {
2461                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
2462                         }
2463                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
2464                         {
2465                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
2466                         }
2467
2468                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
2469                         {
2470                                 $authors[] = new $this->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
2471                         }
2472                 }
2473                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2474                 {
2475                         $name = null;
2476                         $url = null;
2477                         $email = null;
2478                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2479                         {
2480                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2481                         }
2482                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2483                         {
2484                                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2485                         }
2486                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2487                         {
2488                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2489                         }
2490                         if ($name !== null || $email !== null || $url !== null)
2491                         {
2492                                 $authors[] = new $this->author_class($name, $url, $email);
2493                         }
2494                 }
2495                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2496                 {
2497                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2498                 }
2499                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2500                 {
2501                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2502                 }
2503                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2504                 {
2505                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2506                 }
2507
2508                 if (!empty($authors))
2509                 {
2510                         return SimplePie_Misc::array_unique($authors);
2511                 }
2512                 else
2513                 {
2514                         return null;
2515                 }
2516         }
2517
2518         function get_contributor($key = 0)
2519         {
2520                 $contributors = $this->get_contributors();
2521                 if (isset($contributors[$key]))
2522                 {
2523                         return $contributors[$key];
2524                 }
2525                 else
2526                 {
2527                         return null;
2528                 }
2529         }
2530
2531         function get_contributors()
2532         {
2533                 $contributors = array();
2534                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2535                 {
2536                         $name = null;
2537                         $uri = null;
2538                         $email = null;
2539                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2540                         {
2541                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2542                         }
2543                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2544                         {
2545                                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2546                         }
2547                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2548                         {
2549                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2550                         }
2551                         if ($name !== null || $email !== null || $uri !== null)
2552                         {
2553                                 $contributors[] = new $this->author_class($name, $uri, $email);
2554                         }
2555                 }
2556                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2557                 {
2558                         $name = null;
2559                         $url = null;
2560                         $email = null;
2561                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2562                         {
2563                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2564                         }
2565                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2566                         {
2567                                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2568                         }
2569                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2570                         {
2571                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2572                         }
2573                         if ($name !== null || $email !== null || $url !== null)
2574                         {
2575                                 $contributors[] = new $this->author_class($name, $url, $email);
2576                         }
2577                 }
2578
2579                 if (!empty($contributors))
2580                 {
2581                         return SimplePie_Misc::array_unique($contributors);
2582                 }
2583                 else
2584                 {
2585                         return null;
2586                 }
2587         }
2588
2589         function get_link($key = 0, $rel = 'alternate')
2590         {
2591                 $links = $this->get_links($rel);
2592                 if (isset($links[$key]))
2593                 {
2594                         return $links[$key];
2595                 }
2596                 else
2597                 {
2598                         return null;
2599                 }
2600         }
2601
2602         /**
2603          * Added for parity between the parent-level and the item/entry-level.
2604          */
2605         function get_permalink()
2606         {
2607                 return $this->get_link(0);
2608         }
2609
2610         function get_links($rel = 'alternate')
2611         {
2612                 if (!isset($this->data['links']))
2613                 {
2614                         $this->data['links'] = array();
2615                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2616                         {
2617                                 foreach ($links as $link)
2618                                 {
2619                                         if (isset($link['attribs']['']['href']))
2620                                         {
2621                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2622                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2623                                         }
2624                                 }
2625                         }
2626                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2627                         {
2628                                 foreach ($links as $link)
2629                                 {
2630                                         if (isset($link['attribs']['']['href']))
2631                                         {
2632                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2633                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2634
2635                                         }
2636                                 }
2637                         }
2638                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2639                         {
2640                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2641                         }
2642                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2643                         {
2644                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2645                         }
2646                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2647                         {
2648                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2649                         }
2650
2651                         $keys = array_keys($this->data['links']);
2652                         foreach ($keys as $key)
2653                         {
2654                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2655                                 {
2656                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2657                                         {
2658                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2659                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2660                                         }
2661                                         else
2662                                         {
2663                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2664                                         }
2665                                 }
2666                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2667                                 {
2668                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2669                                 }
2670                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2671                         }
2672                 }
2673
2674                 if (isset($this->data['links'][$rel]))
2675                 {
2676                         return $this->data['links'][$rel];
2677                 }
2678                 else
2679                 {
2680                         return null;
2681                 }
2682         }
2683
2684         function get_all_discovered_feeds()
2685         {
2686                 return $this->all_discovered_feeds;
2687         }
2688
2689         function get_description()
2690         {
2691                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2692                 {
2693                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2694                 }
2695                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2696                 {
2697                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2698                 }
2699                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2700                 {
2701                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2702                 }
2703                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2704                 {
2705                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2706                 }
2707                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2708                 {
2709                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2710                 }
2711                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2712                 {
2713                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2714                 }
2715                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2716                 {
2717                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2718                 }
2719                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2720                 {
2721                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2722                 }
2723                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2724                 {
2725                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2726                 }
2727                 else
2728                 {
2729                         return null;
2730                 }
2731         }
2732
2733         function get_copyright()
2734         {
2735                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2736                 {
2737                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2738                 }
2739                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2740                 {
2741                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2742                 }
2743                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2744                 {
2745                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2746                 }
2747                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2748                 {
2749                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2750                 }
2751                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2752                 {
2753                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2754                 }
2755                 else
2756                 {
2757                         return null;
2758                 }
2759         }
2760
2761         function get_language()
2762         {
2763                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2764                 {
2765                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2766                 }
2767                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2768                 {
2769                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2770                 }
2771                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2772                 {
2773                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2774                 }
2775                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2776                 {
2777                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2778                 }
2779                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2780                 {
2781                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2782                 }
2783                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2784                 {
2785                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2786                 }
2787                 elseif (isset($this->data['headers']['content-language']))
2788                 {
2789                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2790                 }
2791                 else
2792                 {
2793                         return null;
2794                 }
2795         }
2796
2797         function get_latitude()
2798         {
2799                 
2800                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2801                 {
2802                         return (float) $return[0]['data'];
2803                 }
2804                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2805                 {
2806                         return (float) $match[1];
2807                 }
2808                 else
2809                 {
2810                         return null;
2811                 }
2812         }
2813
2814         function get_longitude()
2815         {
2816                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2817                 {
2818                         return (float) $return[0]['data'];
2819                 }
2820                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2821                 {
2822                         return (float) $return[0]['data'];
2823                 }
2824                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2825                 {
2826                         return (float) $match[2];
2827                 }
2828                 else
2829                 {
2830                         return null;
2831                 }
2832         }
2833
2834         function get_image_title()
2835         {
2836                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2837                 {
2838                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2839                 }
2840                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2841                 {
2842                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2843                 }
2844                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2845                 {
2846                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2847                 }
2848                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2849                 {
2850                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2851                 }
2852                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2853                 {
2854                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2855                 }
2856                 else
2857                 {
2858                         return null;
2859                 }
2860         }
2861
2862         function get_image_url()
2863         {
2864                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2865                 {
2866                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2867                 }
2868                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2869                 {
2870                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2871                 }
2872                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2873                 {
2874                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2875                 }
2876                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2877                 {
2878                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879                 }
2880                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2881                 {
2882                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883                 }
2884                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2885                 {
2886                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2887                 }
2888                 else
2889                 {
2890                         return null;
2891                 }
2892         }
2893
2894         function get_image_link()
2895         {
2896                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2897                 {
2898                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2899                 }
2900                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2901                 {
2902                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2903                 }
2904                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2905                 {
2906                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2907                 }
2908                 else
2909                 {
2910                         return null;
2911                 }
2912         }
2913
2914         function get_image_width()
2915         {
2916                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2917                 {
2918                         return round($return[0]['data']);
2919                 }
2920                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2921                 {
2922                         return 88.0;
2923                 }
2924                 else
2925                 {
2926                         return null;
2927                 }
2928         }
2929
2930         function get_image_height()
2931         {
2932                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2933                 {
2934                         return round($return[0]['data']);
2935                 }
2936                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2937                 {
2938                         return 31.0;
2939                 }
2940                 else
2941                 {
2942                         return null;
2943                 }
2944         }
2945
2946         function get_item_quantity($max = 0)
2947         {
2948                 $max = (int) $max;
2949                 $qty = count($this->get_items());
2950                 if ($max === 0)
2951                 {
2952                         return $qty;
2953                 }
2954                 else
2955                 {
2956                         return ($qty > $max) ? $max : $qty;
2957                 }
2958         }
2959
2960         function get_item($key = 0)
2961         {
2962                 $items = $this->get_items();
2963                 if (isset($items[$key]))
2964                 {
2965                         return $items[$key];
2966                 }
2967                 else
2968                 {
2969                         return null;
2970                 }
2971         }
2972
2973         function get_items($start = 0, $end = 0)
2974         {
2975                 if (!isset($this->data['items']))
2976                 {
2977                         if (!empty($this->multifeed_objects))
2978                         {
2979                                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2980                         }
2981                         else
2982                         {
2983                                 $this->data['items'] = array();
2984                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2985                                 {
2986                                         $keys = array_keys($items);
2987                                         foreach ($keys as $key)
2988                                         {
2989                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2990                                         }
2991                                 }
2992                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2993                                 {
2994                                         $keys = array_keys($items);
2995                                         foreach ($keys as $key)
2996                                         {
2997                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2998                                         }
2999                                 }
3000                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
3001                                 {
3002                                         $keys = array_keys($items);
3003                                         foreach ($keys as $key)
3004                                         {
3005                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3006                                         }
3007                                 }
3008                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
3009                                 {
3010                                         $keys = array_keys($items);
3011                                         foreach ($keys as $key)
3012                                         {
3013                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3014                                         }
3015                                 }
3016                                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
3017                                 {
3018                                         $keys = array_keys($items);
3019                                         foreach ($keys as $key)
3020                                         {
3021                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3022                                         }
3023                                 }
3024                         }
3025                 }
3026
3027                 if (!empty($this->data['items']))
3028                 {
3029                         // If we want to order it by date, check if all items have a date, and then sort it
3030                         if ($this->order_by_date && empty($this->multifeed_objects))
3031                         {
3032                                 if (!isset($this->data['ordered_items']))
3033                                 {
3034                                         $do_sort = true;
3035                                         foreach ($this->data['items'] as $item)
3036                                         {
3037                                                 if (!$item->get_date('U'))
3038                                                 {
3039                                                         $do_sort = false;
3040                                                         break;
3041                                                 }
3042                                         }
3043                                         $item = null;
3044                                         $this->data['ordered_items'] = $this->data['items'];
3045                                         if ($do_sort)
3046                                         {
3047                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3048                                         }
3049                                 }
3050                                 $items = $this->data['ordered_items'];
3051                         }
3052                         else
3053                         {
3054                                 $items = $this->data['items'];
3055                         }
3056
3057                         // Slice the data as desired
3058                         if ($end === 0)
3059                         {
3060                                 return array_slice($items, $start);
3061                         }
3062                         else
3063                         {
3064                                 return array_slice($items, $start, $end);
3065                         }
3066                 }
3067                 else
3068                 {
3069                         return array();
3070                 }
3071         }
3072
3073         /**
3074          * @static
3075          */
3076         function sort_items($a, $b)
3077         {
3078                 return $a->get_date('U') <= $b->get_date('U');
3079         }
3080
3081         /**
3082          * @static
3083          */
3084         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3085         {
3086                 if (is_array($urls) && sizeof($urls) > 0)
3087                 {
3088                         $items = array();
3089                         foreach ($urls as $arg)
3090                         {
3091                                 if (is_a($arg, 'SimplePie'))
3092                                 {
3093                                         $items = array_merge($items, $arg->get_items(0, $limit));
3094                                 }
3095                                 else
3096                                 {
3097                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3098                                 }
3099                         }
3100
3101                         $do_sort = true;
3102                         foreach ($items as $item)
3103                         {
3104                                 if (!$item->get_date('U'))
3105                                 {
3106                                         $do_sort = false;
3107                                         break;
3108                                 }
3109                         }
3110                         $item = null;
3111                         if ($do_sort)
3112                         {
3113                                 usort($items, array('SimplePie', 'sort_items'));
3114                         }
3115
3116                         if ($end === 0)
3117                         {
3118                                 return array_slice($items, $start);
3119                         }
3120                         else
3121                         {
3122                                 return array_slice($items, $start, $end);
3123                         }
3124                 }
3125                 else
3126                 {
3127                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3128                         return array();
3129                 }
3130         }
3131 }
3132
3133 class SimplePie_Item
3134 {
3135         var $feed;
3136         var $data = array();
3137
3138         function SimplePie_Item($feed, $data)
3139         {
3140                 $this->feed = $feed;
3141                 $this->data = $data;
3142         }
3143
3144         function __toString()
3145         {
3146                 return md5(serialize($this->data));
3147         }
3148
3149         /**
3150          * Remove items that link back to this before destroying this object
3151          */
3152         function __destruct()
3153         {
3154                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3155                 {
3156                         unset($this->feed);
3157                 }
3158         }
3159
3160         function get_item_tags($namespace, $tag)
3161         {
3162                 if (isset($this->data['child'][$namespace][$tag]))
3163                 {
3164                         return $this->data['child'][$namespace][$tag];
3165                 }
3166                 else
3167                 {
3168                         return null;
3169                 }
3170         }
3171
3172         function get_base($element = array())
3173         {
3174                 return $this->feed->get_base($element);
3175         }
3176
3177         function sanitize($data, $type, $base = '')
3178         {
3179                 return $this->feed->sanitize($data, $type, $base);
3180         }
3181
3182         function get_feed()
3183         {
3184                 return $this->feed;
3185         }
3186
3187         function get_id($hash = false)
3188         {
3189                 if (!$hash)
3190                 {
3191                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3192                         {
3193                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3194                         }
3195                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3196                         {
3197                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3198                         }
3199                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3200                         {
3201                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3202                         }
3203                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3204                         {
3205                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3206                         }
3207                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3208                         {
3209                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3210                         }
3211                         elseif (($return = $this->get_permalink()) !== null)
3212                         {
3213                                 return $return;
3214                         }
3215                         elseif (($return = $this->get_title()) !== null)
3216                         {
3217                                 return $return;
3218                         }
3219                 }
3220                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3221                 {
3222                         return md5($this->get_permalink() . $this->get_title());
3223                 }
3224                 else
3225                 {
3226                         return md5(serialize($this->data));
3227                 }
3228         }
3229
3230         function get_title()
3231         {
3232                 if (!isset($this->data['title']))
3233                 {
3234                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3235                         {
3236                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3237                         }
3238                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3239                         {
3240                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3241                         }
3242                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3243                         {
3244                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3245                         }
3246                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3247                         {
3248                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3249                         }
3250                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3251                         {
3252                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3253                         }
3254                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3255                         {
3256                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3257                         }
3258                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3259                         {
3260                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3261                         }
3262                         else
3263                         {
3264                                 $this->data['title'] = null;
3265                         }
3266                 }
3267                 return $this->data['title'];
3268         }
3269
3270         function get_description($description_only = false)
3271         {
3272                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3273                 {
3274                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3275                 }
3276                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3277                 {
3278                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3279                 }
3280                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3281                 {
3282                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3283                 }
3284                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3285                 {
3286                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3287                 }
3288                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3289                 {
3290                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3291                 }
3292                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3293                 {
3294                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3295                 }
3296                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3297                 {
3298                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3299                 }
3300                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3301                 {
3302                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3303                 }
3304                 elseif (!$description_only)
3305                 {
3306                         return $this->get_content(true);
3307                 }
3308                 else
3309                 {
3310                         return null;
3311                 }
3312         }
3313
3314         function get_content($content_only = false)
3315         {
3316                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3317                 {
3318                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3319                 }
3320                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3321                 {
3322                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3323                 }
3324                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3325                 {
3326                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3327                 }
3328                 elseif (!$content_only)
3329                 {
3330                         return $this->get_description(true);
3331                 }
3332                 else
3333                 {
3334                         return null;
3335                 }
3336         }
3337
3338         function get_category($key = 0)
3339         {
3340                 $categories = $this->get_categories();
3341                 if (isset($categories[$key]))
3342                 {
3343                         return $categories[$key];
3344                 }
3345                 else
3346                 {
3347                         return null;
3348                 }
3349         }
3350
3351         function get_categories()
3352         {
3353                 $categories = array();
3354
3355                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3356                 {
3357                         $term = null;
3358                         $scheme = null;
3359                         $label = null;
3360                         if (isset($category['attribs']['']['term']))
3361                         {
3362                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3363                         }
3364                         if (isset($category['attribs']['']['scheme']))
3365                         {
3366                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3367                         }
3368                         if (isset($category['attribs']['']['label']))
3369                         {
3370                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3371                         }
3372                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
3373                 }
3374                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3375                 {
3376                         // This is really the label, but keep this as the term also for BC.
3377                         // Label will also work on retrieving because that falls back to term.
3378                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3379                         if (isset($category['attribs']['']['domain']))
3380                         {
3381                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3382                         }
3383                         else
3384                         {
3385                                 $scheme = null;
3386                         }
3387                         $categories[] = new $this->feed->category_class($term, $scheme, null);
3388                 }
3389                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3390                 {
3391                         $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3392                 }
3393                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3394                 {
3395                         $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3396                 }
3397
3398                 if (!empty($categories))
3399                 {
3400                         return SimplePie_Misc::array_unique($categories);
3401                 }
3402                 else
3403                 {
3404                         return null;
3405                 }
3406         }
3407
3408         function get_author($key = 0)
3409         {
3410                 $authors = $this->get_authors();
3411                 if (isset($authors[$key]))
3412                 {
3413                         return $authors[$key];
3414                 }
3415                 else
3416                 {
3417                         return null;
3418                 }
3419         }
3420
3421         function get_contributor($key = 0)
3422         {
3423                 $contributors = $this->get_contributors();
3424                 if (isset($contributors[$key]))
3425                 {
3426                         return $contributors[$key];
3427                 }
3428                 else
3429                 {
3430                         return null;
3431                 }
3432         }
3433
3434         function get_contributors()
3435         {
3436                 $contributors = array();
3437                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3438                 {
3439                         $name = null;
3440                         $uri = null;
3441                         $email = null;
3442                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3443                         {
3444                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3445                         }
3446                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3447                         {
3448                                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3449                         }
3450                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3451                         {
3452                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3453                         }
3454                         if ($name !== null || $email !== null || $uri !== null)
3455                         {
3456                                 $contributors[] = new $this->feed->author_class($name, $uri, $email);
3457                         }
3458                 }
3459                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3460                 {
3461                         $name = null;
3462                         $url = null;
3463                         $email = null;
3464                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3465                         {
3466                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3467                         }
3468                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3469                         {
3470                                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3471                         }
3472                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3473                         {
3474                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3475                         }
3476                         if ($name !== null || $email !== null || $url !== null)
3477                         {
3478                                 $contributors[] = new $this->feed->author_class($name, $url, $email);
3479                         }
3480                 }
3481
3482                 if (!empty($contributors))
3483                 {
3484                         return SimplePie_Misc::array_unique($contributors);
3485                 }
3486                 else
3487                 {
3488                         return null;
3489                 }
3490         }
3491
3492         function get_authors()
3493         {
3494                 $authors = array();
3495                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3496                 {
3497                         $name = null;
3498                         $uri = null;
3499                         $email = null;
3500                         $avatar = null;
3501                         $name_date = null;
3502                         $uri_date = null;
3503                         $avatar_date = null;
3504                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3505                         {
3506                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3507                         }
3508                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3509                         {
3510                                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3511                         }
3512                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3513                         {
3514                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3515                         }
3516                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
3517                         {
3518                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
3519                         }
3520                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
3521                         {
3522                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
3523                         }
3524                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
3525                         {
3526                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
3527                         }
3528                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
3529                         {
3530                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
3531                         }
3532
3533                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
3534                         {
3535                                 $authors[] = new $this->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
3536                         }
3537                 }
3538                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3539                 {
3540                         $name = null;
3541                         $url = null;
3542                         $email = null;
3543                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3544                         {
3545                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3546                         }
3547                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3548                         {
3549                                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3550                         }
3551                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3552                         {
3553                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3554                         }
3555                         if ($name !== null || $email !== null || $url !== null)
3556                         {
3557                                 $authors[] = new $this->feed->author_class($name, $url, $email);
3558                         }
3559                 }
3560                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3561                 {
3562                         $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3563                 }
3564                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3565                 {
3566                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3567                 }
3568                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3569                 {
3570                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3571                 }
3572                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3573                 {
3574                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3575                 }
3576
3577                 if (!empty($authors))
3578                 {
3579                         return SimplePie_Misc::array_unique($authors);
3580                 }
3581                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3582                 {
3583                         return $authors;
3584                 }
3585                 elseif ($authors = $this->feed->get_authors())
3586                 {
3587                         return $authors;
3588                 }
3589                 else
3590                 {
3591                         return null;
3592                 }
3593         }
3594
3595         function get_copyright()
3596         {
3597                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3598                 {
3599                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3600                 }
3601                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3602                 {
3603                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3604                 }
3605                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3606                 {
3607                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3608                 }
3609                 else
3610                 {
3611                         return null;
3612                 }
3613         }
3614
3615         function get_date($date_format = 'j F Y, g:i a')
3616         {
3617                 if (!isset($this->data['date']))
3618                 {
3619                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3620                         {
3621                                 $this->data['date']['raw'] = $return[0]['data'];
3622                         }
3623                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3624                         {
3625                                 $this->data['date']['raw'] = $return[0]['data'];
3626                         }
3627                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3628                         {
3629                                 $this->data['date']['raw'] = $return[0]['data'];
3630                         }
3631                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3632                         {
3633                                 $this->data['date']['raw'] = $return[0]['data'];
3634                         }
3635                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3636                         {
3637                                 $this->data['date']['raw'] = $return[0]['data'];
3638                         }
3639                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3640                         {
3641                                 $this->data['date']['raw'] = $return[0]['data'];
3642                         }
3643                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3644                         {
3645                                 $this->data['date']['raw'] = $return[0]['data'];
3646                         }
3647                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3648                         {
3649                                 $this->data['date']['raw'] = $return[0]['data'];
3650                         }
3651
3652                         if (!empty($this->data['date']['raw']))
3653                         {
3654                                 $parser = SimplePie_Parse_Date::get();
3655                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3656                         }
3657                         else
3658                         {
3659                                 $this->data['date'] = null;
3660                         }
3661                 }
3662                 if ($this->data['date'])
3663                 {
3664                         $date_format = (string) $date_format;
3665                         switch ($date_format)
3666                         {
3667                                 case '':
3668                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3669
3670                                 case 'U':
3671                                         return $this->data['date']['parsed'];
3672
3673                                 default:
3674                                         return date($date_format, $this->data['date']['parsed']);
3675                         }
3676                 }
3677                 else
3678                 {
3679                         return null;
3680                 }
3681         }
3682
3683         function get_local_date($date_format = '%c')
3684         {
3685                 if (!$date_format)
3686                 {
3687                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3688                 }
3689                 elseif (($date = $this->get_date('U')) !== null)
3690                 {
3691                         return strftime($date_format, $date);
3692                 }
3693                 else
3694                 {
3695                         return null;
3696                 }
3697         }
3698
3699         function get_permalink()
3700         {
3701                 $link = $this->get_link();
3702                 $enclosure = $this->get_enclosure(0);
3703                 if ($link !== null)
3704                 {
3705                         return $link;
3706                 }
3707                 elseif ($enclosure !== null)
3708                 {
3709                         return $enclosure->get_link();
3710                 }
3711                 else
3712                 {
3713                         return null;
3714                 }
3715         }
3716
3717         function get_link($key = 0, $rel = 'alternate')
3718         {
3719                 $links = $this->get_links($rel);
3720                 if ($links[$key] !== null)
3721                 {
3722                         return $links[$key];
3723                 }
3724                 else
3725                 {
3726                         return null;
3727                 }
3728         }
3729
3730         function get_links($rel = 'alternate')
3731         {
3732                 if (!isset($this->data['links']))
3733                 {
3734                         $this->data['links'] = array();
3735                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3736                         {
3737                                 if (isset($link['attribs']['']['href']))
3738                                 {
3739                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3740                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3741
3742                                 }
3743                         }
3744                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3745                         {
3746                                 if (isset($link['attribs']['']['href']))
3747                                 {
3748                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3749                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3750                                 }
3751                         }
3752                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3753                         {
3754                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3755                         }
3756                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3757                         {
3758                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3759                         }
3760                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3761                         {
3762                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3763                         }
3764                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3765                         {
3766                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3767                                 {
3768                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3769                                 }
3770                         }
3771
3772                         $keys = array_keys($this->data['links']);
3773                         foreach ($keys as $key)
3774                         {
3775                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3776                                 {
3777                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3778                                         {
3779                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3780                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3781                                         }
3782                                         else
3783                                         {
3784                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3785                                         }
3786                                 }
3787                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3788                                 {
3789                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3790                                 }
3791                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3792                         }
3793                 }
3794                 if (isset($this->data['links'][$rel]))
3795                 {
3796                         return $this->data['links'][$rel];
3797                 }
3798                 else
3799                 {
3800                         return null;
3801                 }
3802         }
3803
3804         /**
3805          * @todo Add ability to prefer one type of content over another (in a media group).
3806          */
3807         function get_enclosure($key = 0, $prefer = null)
3808         {
3809                 $enclosures = $this->get_enclosures();
3810                 if (isset($enclosures[$key]))
3811                 {
3812                         return $enclosures[$key];
3813                 }
3814                 else
3815                 {
3816                         return null;
3817                 }
3818         }
3819
3820         /**
3821          * Grabs all available enclosures (podcasts, etc.)
3822          *
3823          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3824          *
3825          * At this point, we're pretty much assuming that all enclosures for an item are the same content.  Anything else is too complicated to properly support.
3826          *
3827          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3828          * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
3829          */
3830         function get_enclosures()
3831         {
3832                 if (!isset($this->data['enclosures']))
3833                 {
3834                         $this->data['enclosures'] = array();
3835
3836                         // Elements
3837                         $captions_parent = null;
3838                         $categories_parent = null;
3839                         $copyrights_parent = null;
3840                         $credits_parent = null;
3841                         $description_parent = null;
3842                         $duration_parent = null;
3843                         $hashes_parent = null;
3844                         $keywords_parent = null;
3845                         $player_parent = null;
3846                         $ratings_parent = null;
3847                         $restrictions_parent = null;
3848                         $thumbnails_parent = null;
3849                         $title_parent = null;
3850
3851                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3852                         $parent = $this->get_feed();
3853
3854                         // CAPTIONS
3855                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3856                         {
3857                                 foreach ($captions as $caption)
3858                                 {
3859                                         $caption_type = null;
3860                                         $caption_lang = null;
3861                                         $caption_startTime = null;
3862                                         $caption_endTime = null;
3863                                         $caption_text = null;
3864                                         if (isset($caption['attribs']['']['type']))
3865                                         {
3866                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3867                                         }
3868                                         if (isset($caption['attribs']['']['lang']))
3869                                         {
3870                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3871                                         }
3872                                         if (isset($caption['attribs']['']['start']))
3873                                         {
3874                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3875                                         }
3876                                         if (isset($caption['attribs']['']['end']))
3877                                         {
3878                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3879                                         }
3880                                         if (isset($caption['data']))
3881                                         {
3882                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3883                                         }
3884                                         $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3885                                 }
3886                         }
3887                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3888                         {
3889                                 foreach ($captions as $caption)
3890                                 {
3891                                         $caption_type = null;
3892                                         $caption_lang = null;
3893                                         $caption_startTime = null;
3894                                         $caption_endTime = null;
3895                                         $caption_text = null;
3896                                         if (isset($caption['attribs']['']['type']))
3897                                         {
3898                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3899                                         }
3900                                         if (isset($caption['attribs']['']['lang']))
3901                                         {
3902                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3903                                         }
3904                                         if (isset($caption['attribs']['']['start']))
3905                                         {
3906                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3907                                         }
3908                                         if (isset($caption['attribs']['']['end']))
3909                                         {
3910                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3911                                         }
3912                                         if (isset($caption['data']))
3913                                         {
3914                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3915                                         }
3916                                         $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3917                                 }
3918                         }
3919                         if (is_array($captions_parent))
3920                         {
3921                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3922                         }
3923
3924                         // CATEGORIES
3925                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3926                         {
3927                                 $term = null;
3928                                 $scheme = null;
3929                                 $label = null;
3930                                 if (isset($category['data']))
3931                                 {
3932                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3933                                 }
3934                                 if (isset($category['attribs']['']['scheme']))
3935                                 {
3936                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3937                                 }
3938                                 else
3939                                 {
3940                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3941                                 }
3942                                 if (isset($category['attribs']['']['label']))
3943                                 {
3944                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3945                                 }
3946                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3947                         }
3948                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3949                         {
3950                                 $term = null;
3951                                 $scheme = null;
3952                                 $label = null;
3953                                 if (isset($category['data']))
3954                                 {
3955                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3956                                 }
3957                                 if (isset($category['attribs']['']['scheme']))
3958                                 {
3959                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3960                                 }
3961                                 else
3962                                 {
3963                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3964                                 }
3965                                 if (isset($category['attribs']['']['label']))
3966                                 {
3967                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3968                                 }
3969                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3970                         }
3971                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3972                         {
3973                                 $term = null;
3974                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3975                                 $label = null;
3976                                 if (isset($category['attribs']['']['text']))
3977                                 {
3978                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3979                                 }
3980                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3981
3982                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3983                                 {
3984                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3985                                         {
3986                                                 if (isset($subcategory['attribs']['']['text']))
3987                                                 {
3988                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3989                                                 }
3990                                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3991                                         }
3992                                 }
3993                         }
3994                         if (is_array($categories_parent))
3995                         {
3996                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3997                         }
3998
3999                         // COPYRIGHT
4000                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4001                         {
4002                                 $copyright_url = null;
4003                                 $copyright_label = null;
4004                                 if (isset($copyright[0]['attribs']['']['url']))
4005                                 {
4006                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4007                                 }
4008                                 if (isset($copyright[0]['data']))
4009                                 {
4010                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4011                                 }
4012                                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
4013                         }
4014                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4015                         {
4016                                 $copyright_url = null;
4017                                 $copyright_label = null;
4018                                 if (isset($copyright[0]['attribs']['']['url']))
4019                                 {
4020                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4021                                 }
4022                                 if (isset($copyright[0]['data']))
4023                                 {
4024                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4025                                 }
4026                                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
4027                         }
4028
4029                         // CREDITS
4030                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4031                         {
4032                                 foreach ($credits as $credit)
4033                                 {
4034                                         $credit_role = null;
4035                                         $credit_scheme = null;
4036                                         $credit_name = null;
4037                                         if (isset($credit['attribs']['']['role']))
4038                                         {
4039                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4040                                         }
4041                                         if (isset($credit['attribs']['']['scheme']))
4042                                         {
4043                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4044                                         }
4045                                         else
4046                                         {
4047                                                 $credit_scheme = 'urn:ebu';
4048                                         }
4049                                         if (isset($credit['data']))
4050                                         {
4051                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4052                                         }
4053                                         $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4054                                 }
4055                         }
4056                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4057                         {
4058                                 foreach ($credits as $credit)
4059                                 {
4060                                         $credit_role = null;
4061                                         $credit_scheme = null;
4062                                         $credit_name = null;
4063                                         if (isset($credit['attribs']['']['role']))
4064                                         {
4065                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4066                                         }
4067                                         if (isset($credit['attribs']['']['scheme']))
4068                                         {
4069                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4070                                         }
4071                                         else
4072                                         {
4073                                                 $credit_scheme = 'urn:ebu';
4074                                         }
4075                                         if (isset($credit['data']))
4076                                         {
4077                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4078                                         }
4079                                         $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4080                                 }
4081                         }
4082                         if (is_array($credits_parent))
4083                         {
4084                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4085                         }
4086
4087                         // DESCRIPTION
4088                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4089                         {
4090                                 if (isset($description_parent[0]['data']))
4091                                 {
4092                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4093                                 }
4094                         }
4095                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4096                         {
4097                                 if (isset($description_parent[0]['data']))
4098                                 {
4099                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4100                                 }
4101                         }
4102
4103                         // DURATION
4104                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4105                         {
4106                                 $seconds = null;
4107                                 $minutes = null;
4108                                 $hours = null;
4109                                 if (isset($duration_parent[0]['data']))
4110                                 {
4111                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4112                                         if (sizeof($temp) > 0)
4113                                         {
4114                                                 (int) $seconds = array_pop($temp);
4115                                         }
4116                                         if (sizeof($temp) > 0)
4117                                         {
4118                                                 (int) $minutes = array_pop($temp);
4119                                                 $seconds += $minutes * 60;
4120                                         }
4121                                         if (sizeof($temp) > 0)
4122                                         {
4123                                                 (int) $hours = array_pop($temp);
4124                                                 $seconds += $hours * 3600;
4125                                         }
4126                                         unset($temp);
4127                                         $duration_parent = $seconds;
4128                                 }
4129                         }
4130
4131                         // HASHES
4132                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4133                         {
4134                                 foreach ($hashes_iterator as $hash)
4135                                 {
4136                                         $value = null;
4137                                         $algo = null;
4138                                         if (isset($hash['data']))
4139                                         {
4140                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4141                                         }
4142                                         if (isset($hash['attribs']['']['algo']))
4143                                         {
4144                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4145                                         }
4146                                         else
4147                                         {
4148                                                 $algo = 'md5';
4149                                         }
4150                                         $hashes_parent[] = $algo.':'.$value;
4151                                 }
4152                         }
4153                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4154                         {
4155                                 foreach ($hashes_iterator as $hash)
4156                                 {
4157                                         $value = null;
4158                                         $algo = null;
4159                                         if (isset($hash['data']))
4160                                         {
4161                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4162                                         }
4163                                         if (isset($hash['attribs']['']['algo']))
4164                                         {
4165                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4166                                         }
4167                                         else
4168                                         {
4169                                                 $algo = 'md5';
4170                                         }
4171                                         $hashes_parent[] = $algo.':'.$value;
4172                                 }
4173                         }
4174                         if (is_array($hashes_parent))
4175                         {
4176                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4177                         }
4178
4179                         // KEYWORDS
4180                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4181                         {
4182                                 if (isset($keywords[0]['data']))
4183                                 {
4184                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4185                                         foreach ($temp as $word)
4186                                         {
4187                                                 $keywords_parent[] = trim($word);
4188                                         }
4189                                 }
4190                                 unset($temp);
4191                         }
4192                         elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4193                         {
4194                                 if (isset($keywords[0]['data']))
4195                                 {
4196                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4197                                         foreach ($temp as $word)
4198                                         {
4199                                                 $keywords_parent[] = trim($word);
4200                                         }
4201                                 }
4202                                 unset($temp);
4203                         }
4204                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4205                         {
4206                                 if (isset($keywords[0]['data']))
4207                                 {
4208                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4209                                         foreach ($temp as $word)
4210                                         {
4211                                                 $keywords_parent[] = trim($word);
4212                                         }
4213                                 }
4214                                 unset($temp);
4215                         }
4216                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4217                         {
4218                                 if (isset($keywords[0]['data']))
4219                                 {
4220                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4221                                         foreach ($temp as $word)
4222                                         {
4223                                                 $keywords_parent[] = trim($word);
4224                                         }
4225                                 }
4226                                 unset($temp);
4227                         }
4228                         if (is_array($keywords_parent))
4229                         {
4230                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4231                         }
4232
4233                         // PLAYER
4234                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4235                         {
4236                                 if (isset($player_parent[0]['attribs']['']['url']))
4237                                 {
4238                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4239                                 }
4240                         }
4241                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4242                         {
4243                                 if (isset($player_parent[0]['attribs']['']['url']))
4244                                 {
4245                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4246                                 }
4247                         }
4248
4249                         // RATINGS
4250                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4251                         {
4252                                 foreach ($ratings as $rating)
4253                                 {
4254                                         $rating_scheme = null;
4255                                         $rating_value = null;
4256                                         if (isset($rating['attribs']['']['scheme']))
4257                                         {
4258                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4259                                         }
4260                                         else
4261                                         {
4262                                                 $rating_scheme = 'urn:simple';
4263                                         }
4264                                         if (isset($rating['data']))
4265                                         {
4266                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4267                                         }
4268                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4269                                 }
4270                         }
4271                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4272                         {
4273                                 foreach ($ratings as $rating)
4274                                 {
4275                                         $rating_scheme = 'urn:itunes';
4276                                         $rating_value = null;
4277                                         if (isset($rating['data']))
4278                                         {
4279                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4280                                         }
4281                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4282                                 }
4283                         }
4284                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4285                         {
4286                                 foreach ($ratings as $rating)
4287                                 {
4288                                         $rating_scheme = null;
4289                                         $rating_value = null;
4290                                         if (isset($rating['attribs']['']['scheme']))
4291                                         {
4292                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4293                                         }
4294                                         else
4295                                         {
4296                                                 $rating_scheme = 'urn:simple';
4297                                         }
4298                                         if (isset($rating['data']))
4299                                         {
4300                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4301                                         }
4302                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4303                                 }
4304                         }
4305                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4306                         {
4307                                 foreach ($ratings as $rating)
4308                                 {
4309                                         $rating_scheme = 'urn:itunes';
4310                                         $rating_value = null;
4311                                         if (isset($rating['data']))
4312                                         {
4313                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4314                                         }
4315                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4316                                 }
4317                         }
4318                         if (is_array($ratings_parent))
4319                         {
4320                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4321                         }
4322
4323                         // RESTRICTIONS
4324                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4325                         {
4326                                 foreach ($restrictions as $restriction)
4327                                 {
4328                                         $restriction_relationship = null;
4329                                         $restriction_type = null;
4330                                         $restriction_value = null;
4331                                         if (isset($restriction['attribs']['']['relationship']))
4332                                         {
4333                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4334                                         }
4335                                         if (isset($restriction['attribs']['']['type']))
4336                                         {
4337                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4338                                         }
4339                                         if (isset($restriction['data']))
4340                                         {
4341                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4342                                         }
4343                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4344                                 }
4345                         }
4346                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4347                         {
4348                                 foreach ($restrictions as $restriction)
4349                                 {
4350                                         $restriction_relationship = 'allow';
4351                                         $restriction_type = null;
4352                                         $restriction_value = 'itunes';
4353                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4354                                         {
4355                                                 $restriction_relationship = 'deny';
4356                                         }
4357                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4358                                 }
4359                         }
4360                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4361                         {
4362                                 foreach ($restrictions as $restriction)
4363                                 {
4364                                         $restriction_relationship = null;
4365                                         $restriction_type = null;
4366                                         $restriction_value = null;
4367                                         if (isset($restriction['attribs']['']['relationship']))
4368                                         {
4369                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4370                                         }
4371                                         if (isset($restriction['attribs']['']['type']))
4372                                         {
4373                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4374                                         }
4375                                         if (isset($restriction['data']))
4376                                         {
4377                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4378                                         }
4379                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4380                                 }
4381                         }
4382                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4383                         {
4384                                 foreach ($restrictions as $restriction)
4385                                 {
4386                                         $restriction_relationship = 'allow';
4387                                         $restriction_type = null;
4388                                         $restriction_value = 'itunes';
4389                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4390                                         {
4391                                                 $restriction_relationship = 'deny';
4392                                         }
4393                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4394                                 }
4395                         }
4396                         if (is_array($restrictions_parent))
4397                         {
4398                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4399                         }
4400
4401                         // THUMBNAILS
4402                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4403                         {
4404                                 foreach ($thumbnails as $thumbnail)
4405                                 {
4406                                         if (isset($thumbnail['attribs']['']['url']))
4407                                         {
4408                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4409                                         }
4410                                 }
4411                         }
4412                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4413                         {
4414                                 foreach ($thumbnails as $thumbnail)
4415                                 {
4416                                         if (isset($thumbnail['attribs']['']['url']))
4417                                         {
4418                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4419                                         }
4420                                 }
4421                         }
4422
4423                         // TITLES
4424                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4425                         {
4426                                 if (isset($title_parent[0]['data']))
4427                                 {
4428                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4429                                 }
4430                         }
4431                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4432                         {
4433                                 if (isset($title_parent[0]['data']))
4434                                 {
4435                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4436                                 }
4437                         }
4438
4439                         // Clear the memory
4440                         unset($parent);
4441
4442                         // Attributes
4443                         $bitrate = null;
4444                         $channels = null;
4445                         $duration = null;
4446                         $expression = null;
4447                         $framerate = null;
4448                         $height = null;
4449                         $javascript = null;
4450                         $lang = null;
4451                         $length = null;
4452                         $medium = null;
4453                         $samplingrate = null;
4454                         $type = null;
4455                         $url = null;
4456                         $width = null;
4457
4458                         // Elements
4459                         $captions = null;
4460                         $categories = null;
4461                         $copyrights = null;
4462                         $credits = null;
4463                         $description = null;
4464                         $hashes = null;
4465                         $keywords = null;
4466                         $player = null;
4467                         $ratings = null;
4468                         $restrictions = null;
4469                         $thumbnails = null;
4470                         $title = null;
4471
4472                         // If we have media:group tags, loop through them.
4473                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4474                         {
4475                                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4476                                 {
4477                                         // If we have media:content tags, loop through them.
4478                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4479                                         {
4480                                                 if (isset($content['attribs']['']['url']))
4481                                                 {
4482                                                         // Attributes
4483                                                         $bitrate = null;
4484                                                         $channels = null;
4485                                                         $duration = null;
4486                                                         $expression = null;
4487                                                         $framerate = null;
4488                                                         $height = null;
4489                                                         $javascript = null;
4490                                                         $lang = null;
4491                                                         $length = null;
4492                                                         $medium = null;
4493                                                         $samplingrate = null;
4494                                                         $type = null;
4495                                                         $url = null;
4496                                                         $width = null;
4497
4498                                                         // Elements
4499                                                         $captions = null;
4500                                                         $categories = null;
4501                                                         $copyrights = null;
4502                                                         $credits = null;
4503                                                         $description = null;
4504                                                         $hashes = null;
4505                                                         $keywords = null;
4506                                                         $player = null;
4507                                                         $ratings = null;
4508                                                         $restrictions = null;
4509                                                         $thumbnails = null;
4510                                                         $title = null;
4511
4512                                                         // Start checking the attributes of media:content
4513                                                         if (isset($content['attribs']['']['bitrate']))
4514                                                         {
4515                                                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4516                                                         }
4517                                                         if (isset($content['attribs']['']['channels']))
4518                                                         {
4519                                                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4520                                                         }
4521                                                         if (isset($content['attribs']['']['duration']))
4522                                                         {
4523                                                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4524                                                         }
4525                                                         else
4526                                                         {
4527                                                                 $duration = $duration_parent;
4528                                                         }
4529                                                         if (isset($content['attribs']['']['expression']))
4530                                                         {
4531                                                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4532                                                         }
4533                                                         if (isset($content['attribs']['']['framerate']))
4534                                                         {
4535                                                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4536                                                         }
4537                                                         if (isset($content['attribs']['']['height']))
4538                                                         {
4539                                                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4540                                                         }
4541                                                         if (isset($content['attribs']['']['lang']))
4542                                                         {
4543                                                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4544                                                         }
4545                                                         if (isset($content['attribs']['']['fileSize']))
4546                                                         {
4547                                                                 $length = ceil($content['attribs']['']['fileSize']);
4548                                                         }
4549                                                         if (isset($content['attribs']['']['medium']))
4550                                                         {
4551                                                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4552                                                         }
4553                                                         if (isset($content['attribs']['']['samplingrate']))
4554                                                         {
4555                                                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4556                                                         }
4557                                                         if (isset($content['attribs']['']['type']))
4558                                                         {
4559                                                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4560                                                         }
4561                                                         if (isset($content['attribs']['']['width']))
4562                                                         {
4563                                                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4564                                                         }
4565                                                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4566
4567                                                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4568
4569                                                         // CAPTIONS
4570                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4571                                                         {
4572                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4573                                                                 {
4574                                                                         $caption_type = null;
4575                                                                         $caption_lang = null;
4576                                                                         $caption_startTime = null;
4577                                                                         $caption_endTime = null;
4578                                                                         $caption_text = null;
4579                                                                         if (isset($caption['attribs']['']['type']))
4580                                                                         {
4581                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4582                                                                         }
4583                                                                         if (isset($caption['attribs']['']['lang']))
4584                                                                         {
4585                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4586                                                                         }
4587                                                                         if (isset($caption['attribs']['']['start']))
4588                                                                         {
4589                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4590                                                                         }
4591                                                                         if (isset($caption['attribs']['']['end']))
4592                                                                         {
4593                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4594                                                                         }
4595                                                                         if (isset($caption['data']))
4596                                                                         {
4597                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4598                                                                         }
4599                                                                         $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4600                                                                 }
4601                                                                 if (is_array($captions))
4602                                                                 {
4603                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4604                                                                 }
4605                                                         }
4606                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4607                                                         {
4608                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4609                                                                 {
4610                                                                         $caption_type = null;
4611                                                                         $caption_lang = null;
4612                                                                         $caption_startTime = null;
4613                                                                         $caption_endTime = null;
4614                                                                         $caption_text = null;
4615                                                                         if (isset($caption['attribs']['']['type']))
4616                                                                         {
4617                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4618                                                                         }
4619                                                                         if (isset($caption['attribs']['']['lang']))
4620                                                                         {
4621                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4622                                                                         }
4623                                                                         if (isset($caption['attribs']['']['start']))
4624                                                                         {
4625                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4626                                                                         }
4627                                                                         if (isset($caption['attribs']['']['end']))
4628                                                                         {
4629                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4630                                                                         }
4631                                                                         if (isset($caption['data']))
4632                                                                         {
4633                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4634                                                                         }
4635                                                                         $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4636                                                                 }
4637                                                                 if (is_array($captions))
4638                                                                 {
4639                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4640                                                                 }
4641                                                         }
4642                                                         else
4643                                                         {
4644                                                                 $captions = $captions_parent;
4645                                                         }
4646
4647                                                         // CATEGORIES
4648                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4649                                                         {
4650                                                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4651                                                                 {
4652                                                                         $term = null;
4653                                                                         $scheme = null;
4654                                                                         $label = null;
4655                                                                         if (isset($category['data']))
4656                                                                         {
4657                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4658                                                                         }
4659                                                                         if (isset($category['attribs']['']['scheme']))
4660                                                                         {
4661                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4662                                                                         }
4663                                                                         else
4664                                                                         {
4665                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4666                                                                         }
4667                                                                         if (isset($category['attribs']['']['label']))
4668                                                                         {
4669                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4670                                                                         }
4671                                                                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
4672                                                                 }
4673                                                         }
4674                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4675                                                         {
4676                                                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4677                                                                 {
4678                                                                         $term = null;
4679                                                                         $scheme = null;
4680                                                                         $label = null;
4681                                                                         if (isset($category['data']))
4682                                                                         {
4683                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4684                                                                         }
4685                                                                         if (isset($category['attribs']['']['scheme']))
4686                                                                         {
4687                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4688                                                                         }
4689                                                                         else
4690                                                                         {
4691                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4692                                                                         }
4693                                                                         if (isset($category['attribs']['']['label']))
4694                                                                         {
4695                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4696                                                                         }
4697                                                                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
4698                                                                 }
4699                                                         }
4700                                                         if (is_array($categories) && is_array($categories_parent))
4701                                                         {
4702                                                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4703                                                         }
4704                                                         elseif (is_array($categories))
4705                                                         {
4706                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
4707                                                         }
4708                                                         elseif (is_array($categories_parent))
4709                                                         {
4710                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4711                                                         }
4712
4713                                                         // COPYRIGHTS
4714                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4715                                                         {
4716                                                                 $copyright_url = null;
4717                                                                 $copyright_label = null;
4718                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4719                                                                 {
4720                                                                         $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4721                                                                 }
4722                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4723                                                                 {
4724                                                                         $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4725                                                                 }
4726                                                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4727                                                         }
4728                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4729                                                         {
4730                                                                 $copyright_url = null;
4731                                                                 $copyright_label = null;
4732                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4733                                                                 {
4734                                                                         $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4735                                                                 }
4736                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4737                                                                 {
4738                                                                         $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4739                                                                 }
4740                                                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4741                                                         }
4742                                                         else
4743                                                         {
4744                                                                 $copyrights = $copyrights_parent;
4745                                                         }
4746
4747                                                         // CREDITS
4748                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4749                                                         {
4750                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4751                                                                 {
4752                                                                         $credit_role = null;
4753                                                                         $credit_scheme = null;
4754                                                                         $credit_name = null;
4755                                                                         if (isset($credit['attribs']['']['role']))
4756                                                                         {
4757                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4758                                                                         }
4759                                                                         if (isset($credit['attribs']['']['scheme']))
4760                                                                         {
4761                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4762                                                                         }
4763                                                                         else
4764                                                                         {
4765                                                                                 $credit_scheme = 'urn:ebu';
4766                                                                         }
4767                                                                         if (isset($credit['data']))
4768                                                                         {
4769                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4770                                                                         }
4771                                                                         $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4772                                                                 }
4773                                                                 if (is_array($credits))
4774                                                                 {
4775                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4776                                                                 }
4777                                                         }
4778                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4779                                                         {
4780                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4781                                                                 {
4782                                                                         $credit_role = null;
4783                                                                         $credit_scheme = null;
4784                                                                         $credit_name = null;
4785                                                                         if (isset($credit['attribs']['']['role']))
4786                                                                         {
4787                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4788                                                                         }
4789                                                                         if (isset($credit['attribs']['']['scheme']))
4790                                                                         {
4791                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4792                                                                         }
4793                                                                         else
4794                                                                         {
4795                                                                                 $credit_scheme = 'urn:ebu';
4796                                                                         }
4797                                                                         if (isset($credit['data']))
4798                                                                         {
4799                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4800                                                                         }
4801                                                                         $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4802                                                                 }
4803                                                                 if (is_array($credits))
4804                                                                 {
4805                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4806                                                                 }
4807                                                         }
4808                                                         else
4809                                                         {
4810                                                                 $credits = $credits_parent;
4811                                                         }
4812
4813                                                         // DESCRIPTION
4814                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4815                                                         {
4816                                                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4817                                                         }
4818                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4819                                                         {
4820                                                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4821                                                         }
4822                                                         else
4823                                                         {
4824                                                                 $description = $description_parent;
4825                                                         }
4826
4827                                                         // HASHES
4828                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4829                                                         {
4830                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4831                                                                 {
4832                                                                         $value = null;
4833                                                                         $algo = null;
4834                                                                         if (isset($hash['data']))
4835                                                                         {
4836                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4837                                                                         }
4838                                                                         if (isset($hash['attribs']['']['algo']))
4839                                                                         {
4840                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4841                                                                         }
4842                                                                         else
4843                                                                         {
4844                                                                                 $algo = 'md5';
4845                                                                         }
4846                                                                         $hashes[] = $algo.':'.$value;
4847                                                                 }
4848                                                                 if (is_array($hashes))
4849                                                                 {
4850                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4851                                                                 }
4852                                                         }
4853                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4854                                                         {
4855                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4856                                                                 {
4857                                                                         $value = null;
4858                                                                         $algo = null;
4859                                                                         if (isset($hash['data']))
4860                                                                         {
4861                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4862                                                                         }
4863                                                                         if (isset($hash['attribs']['']['algo']))
4864                                                                         {
4865                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4866                                                                         }
4867                                                                         else
4868                                                                         {
4869                                                                                 $algo = 'md5';
4870                                                                         }
4871                                                                         $hashes[] = $algo.':'.$value;
4872                                                                 }
4873                                                                 if (is_array($hashes))
4874                                                                 {
4875                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4876                                                                 }
4877                                                         }
4878                                                         else
4879                                                         {
4880                                                                 $hashes = $hashes_parent;
4881                                                         }
4882
4883                                                         // KEYWORDS
4884                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4885                                                         {
4886                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4887                                                                 {
4888                                                                         $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4889                                                                         foreach ($temp as $word)
4890                                                                         {
4891                                                                                 $keywords[] = trim($word);
4892                                                                         }
4893                                                                         unset($temp);
4894                                                                 }
4895                                                                 if (is_array($keywords))
4896                                                                 {
4897                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4898                                                                 }
4899                                                         }
4900                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4901                                                         {
4902                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4903                                                                 {
4904                                                                         $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4905                                                                         foreach ($temp as $word)
4906                                                                         {
4907                                                                                 $keywords[] = trim($word);
4908                                                                         }
4909                                                                         unset($temp);
4910                                                                 }
4911                                                                 if (is_array($keywords))
4912                                                                 {
4913                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4914                                                                 }
4915                                                         }
4916                                                         else
4917                                                         {
4918                                                                 $keywords = $keywords_parent;
4919                                                         }
4920
4921                                                         // PLAYER
4922                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4923                                                         {
4924                                                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4925                                                         }
4926                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4927                                                         {
4928                                                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4929                                                         }
4930                                                         else
4931                                                         {
4932                                                                 $player = $player_parent;
4933                                                         }
4934
4935                                                         // RATINGS
4936                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4937                                                         {
4938                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4939                                                                 {
4940                                                                         $rating_scheme = null;
4941                                                                         $rating_value = null;
4942                                                                         if (isset($rating['attribs']['']['scheme']))
4943                                                                         {
4944                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4945                                                                         }
4946                                                                         else
4947                                                                         {
4948                                                                                 $rating_scheme = 'urn:simple';
4949                                                                         }
4950                                                                         if (isset($rating['data']))
4951                                                                         {
4952                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4953                                                                         }
4954                                                                         $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4955                                                                 }
4956                                                                 if (is_array($ratings))
4957                                                                 {
4958                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4959                                                                 }
4960                                                         }
4961                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4962                                                         {
4963                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4964                                                                 {
4965                                                                         $rating_scheme = null;
4966                                                                         $rating_value = null;
4967                                                                         if (isset($rating['attribs']['']['scheme']))
4968                                                                         {
4969                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4970                                                                         }
4971                                                                         else
4972                                                                         {
4973                                                                                 $rating_scheme = 'urn:simple';
4974                                                                         }
4975                                                                         if (isset($rating['data']))
4976                                                                         {
4977                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4978                                                                         }
4979                                                                         $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4980                                                                 }
4981                                                                 if (is_array($ratings))
4982                                                                 {
4983                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4984                                                                 }
4985                                                         }
4986                                                         else
4987                                                         {
4988                                                                 $ratings = $ratings_parent;
4989                                                         }
4990
4991                                                         // RESTRICTIONS
4992                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4993                                                         {
4994                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4995                                                                 {
4996                                                                         $restriction_relationship = null;
4997                                                                         $restriction_type = null;
4998                                                                         $restriction_value = null;
4999                                                                         if (isset($restriction['attribs']['']['relationship']))
5000                                                                         {
5001                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5002                                                                         }
5003                                                                         if (isset($restriction['attribs']['']['type']))
5004                                                                         {
5005                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5006                                                                         }
5007                                                                         if (isset($restriction['data']))
5008                                                                         {
5009                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5010                                                                         }
5011                                                                         $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5012                                                                 }
5013                                                                 if (is_array($restrictions))
5014                                                                 {
5015                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5016                                                                 }
5017                                                         }
5018                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5019                                                         {
5020                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5021                                                                 {
5022                                                                         $restriction_relationship = null;
5023                                                                         $restriction_type = null;
5024                                                                         $restriction_value = null;
5025                                                                         if (isset($restriction['attribs']['']['relationship']))
5026                                                                         {
5027                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5028                                                                         }
5029                                                                         if (isset($restriction['attribs']['']['type']))
5030                                                                         {
5031                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5032                                                                         }
5033                                                                         if (isset($restriction['data']))
5034                                                                         {
5035                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5036                                                                         }
5037                                                                         $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5038                                                                 }
5039                                                                 if (is_array($restrictions))
5040                                                                 {
5041                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5042                                                                 }
5043                                                         }
5044                                                         else
5045                                                         {
5046                                                                 $restrictions = $restrictions_parent;
5047                                                         }
5048
5049                                                         // THUMBNAILS
5050                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5051                                                         {
5052                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5053                                                                 {
5054                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5055                                                                 }
5056                                                                 if (is_array($thumbnails))
5057                                                                 {
5058                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5059                                                                 }
5060                                                         }
5061                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5062                                                         {
5063                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5064                                                                 {
5065                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5066                                                                 }
5067                                                                 if (is_array($thumbnails))
5068                                                                 {
5069                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5070                                                                 }
5071                                                         }
5072                                                         else
5073                                                         {
5074                                                                 $thumbnails = $thumbnails_parent;
5075                                                         }
5076
5077                                                         // TITLES
5078                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5079                                                         {
5080                                                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5081                                                         }
5082                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5083                                                         {
5084                                                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5085                                                         }
5086                                                         else
5087                                                         {
5088                                                                 $title = $title_parent;
5089                                                         }
5090
5091                                                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5092                                                 }
5093                                         }
5094                                 }
5095                         }
5096
5097                         // If we have standalone media:content tags, loop through them.
5098                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5099                         {
5100                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5101                                 {
5102                                         if (isset($content['attribs']['']['url']))
5103                                         {
5104                                                 // Attributes
5105                                                 $bitrate = null;
5106                                                 $channels = null;
5107                                                 $duration = null;
5108                                                 $expression = null;
5109                                                 $framerate = null;
5110                                                 $height = null;
5111                                                 $javascript = null;
5112                                                 $lang = null;
5113                                                 $length = null;
5114                                                 $medium = null;
5115                                                 $samplingrate = null;
5116                                                 $type = null;
5117                                                 $url = null;
5118                                                 $width = null;
5119
5120                                                 // Elements
5121                                                 $captions = null;
5122                                                 $categories = null;
5123                                                 $copyrights = null;
5124                                                 $credits = null;
5125                                                 $description = null;
5126                                                 $hashes = null;
5127                                                 $keywords = null;
5128                                                 $player = null;
5129                                                 $ratings = null;
5130                                                 $restrictions = null;
5131                                                 $thumbnails = null;
5132                                                 $title = null;
5133
5134                                                 // Start checking the attributes of media:content
5135                                                 if (isset($content['attribs']['']['bitrate']))
5136                                                 {
5137                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5138                                                 }
5139                                                 if (isset($content['attribs']['']['channels']))
5140                                                 {
5141                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5142                                                 }
5143                                                 if (isset($content['attribs']['']['duration']))
5144                                                 {
5145                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5146                                                 }
5147                                                 else
5148                                                 {
5149                                                         $duration = $duration_parent;
5150                                                 }
5151                                                 if (isset($content['attribs']['']['expression']))
5152                                                 {
5153                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5154                                                 }
5155                                                 if (isset($content['attribs']['']['framerate']))
5156                                                 {
5157                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5158                                                 }
5159                                                 if (isset($content['attribs']['']['height']))
5160                                                 {
5161                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5162                                                 }
5163                                                 if (isset($content['attribs']['']['lang']))
5164                                                 {
5165                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5166                                                 }
5167                                                 if (isset($content['attribs']['']['fileSize']))
5168                                                 {
5169                                                         $length = ceil($content['attribs']['']['fileSize']);
5170                                                 }
5171                                                 if (isset($content['attribs']['']['medium']))
5172                                                 {
5173                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5174                                                 }
5175                                                 if (isset($content['attribs']['']['samplingrate']))
5176                                                 {
5177                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5178                                                 }
5179                                                 if (isset($content['attribs']['']['type']))
5180                                                 {
5181                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5182                                                 }
5183                                                 if (isset($content['attribs']['']['width']))
5184                                                 {
5185                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5186                                                 }
5187                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5188
5189                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5190
5191                                                 // CAPTIONS
5192                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5193                                                 {
5194                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5195                                                         {
5196                                                                 $caption_type = null;
5197                                                                 $caption_lang = null;
5198                                                                 $caption_startTime = null;
5199                                                                 $caption_endTime = null;
5200                                                                 $caption_text = null;
5201                                                                 if (isset($caption['attribs']['']['type']))
5202                                                                 {
5203                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5204                                                                 }
5205                                                                 if (isset($caption['attribs']['']['lang']))
5206                                                                 {
5207                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5208                                                                 }
5209                                                                 if (isset($caption['attribs']['']['start']))
5210                                                                 {
5211                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5212                                                                 }
5213                                                                 if (isset($caption['attribs']['']['end']))
5214                                                                 {
5215                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5216                                                                 }
5217                                                                 if (isset($caption['data']))
5218                                                                 {
5219                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5220                                                                 }
5221                                                                 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5222                                                         }
5223                                                         if (is_array($captions))
5224                                                         {
5225                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5226                                                         }
5227                                                 }
5228                                                 else
5229                                                 {
5230                                                         $captions = $captions_parent;
5231                                                 }
5232
5233                                                 // CATEGORIES
5234                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5235                                                 {
5236                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5237                                                         {
5238                                                                 $term = null;
5239                                                                 $scheme = null;
5240                                                                 $label = null;
5241                                                                 if (isset($category['data']))
5242                                                                 {
5243                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5244                                                                 }
5245                                                                 if (isset($category['attribs']['']['scheme']))
5246                                                                 {
5247                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5248                                                                 }
5249                                                                 else
5250                                                                 {
5251                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5252                                                                 }
5253                                                                 if (isset($category['attribs']['']['label']))
5254                                                                 {
5255                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5256                                                                 }
5257                                                                 $categories[] = new $this->feed->category_class($term, $scheme, $label);
5258                                                         }
5259                                                 }
5260                                                 if (is_array($categories) && is_array($categories_parent))
5261                                                 {
5262                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5263                                                 }
5264                                                 elseif (is_array($categories))
5265                                                 {
5266                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5267                                                 }
5268                                                 elseif (is_array($categories_parent))
5269                                                 {
5270                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5271                                                 }
5272                                                 else
5273                                                 {
5274                                                         $categories = null;
5275                                                 }
5276
5277                                                 // COPYRIGHTS
5278                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5279                                                 {
5280                                                         $copyright_url = null;
5281                                                         $copyright_label = null;
5282                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5283                                                         {
5284                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5285                                                         }
5286                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5287                                                         {
5288                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5289                                                         }
5290                                                         $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
5291                                                 }
5292                                                 else
5293                                                 {
5294                                                         $copyrights = $copyrights_parent;
5295                                                 }
5296
5297                                                 // CREDITS
5298                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5299                                                 {
5300                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5301                                                         {
5302                                                                 $credit_role = null;
5303                                                                 $credit_scheme = null;
5304                                                                 $credit_name = null;
5305                                                                 if (isset($credit['attribs']['']['role']))
5306                                                                 {
5307                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5308                                                                 }
5309                                                                 if (isset($credit['attribs']['']['scheme']))
5310                                                                 {
5311                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5312                                                                 }
5313                                                                 else
5314                                                                 {
5315                                                                         $credit_scheme = 'urn:ebu';
5316                                                                 }
5317                                                                 if (isset($credit['data']))
5318                                                                 {
5319                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5320                                                                 }
5321                                                                 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5322                                                         }
5323                                                         if (is_array($credits))
5324                                                         {
5325                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5326                                                         }
5327                                                 }
5328                                                 else
5329                                                 {
5330                                                         $credits = $credits_parent;
5331                                                 }
5332
5333                                                 // DESCRIPTION
5334                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5335                                                 {
5336                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5337                                                 }
5338                                                 else
5339                                                 {
5340                                                         $description = $description_parent;
5341                                                 }
5342
5343                                                 // HASHES
5344                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5345                                                 {
5346                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5347                                                         {
5348                                                                 $value = null;
5349                                                                 $algo = null;
5350                                                                 if (isset($hash['data']))
5351                                                                 {
5352                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5353                                                                 }
5354                                                                 if (isset($hash['attribs']['']['algo']))
5355                                                                 {
5356                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5357                                                                 }
5358                                                                 else
5359                                                                 {
5360                                                                         $algo = 'md5';
5361                                                                 }
5362                                                                 $hashes[] = $algo.':'.$value;
5363                                                         }
5364                                                         if (is_array($hashes))
5365                                                         {
5366                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5367                                                         }
5368                                                 }
5369                                                 else
5370                                                 {
5371                                                         $hashes = $hashes_parent;
5372                                                 }
5373
5374                                                 // KEYWORDS
5375                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5376                                                 {
5377                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5378                                                         {
5379                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5380                                                                 foreach ($temp as $word)
5381                                                                 {
5382                                                                         $keywords[] = trim($word);
5383                                                                 }
5384                                                                 unset($temp);
5385                                                         }
5386                                                         if (is_array($keywords))
5387                                                         {
5388                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5389                                                         }
5390                                                 }
5391                                                 else
5392                                                 {
5393                                                         $keywords = $keywords_parent;
5394                                                 }
5395
5396                                                 // PLAYER
5397                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5398                                                 {
5399                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5400                                                 }
5401                                                 else
5402                                                 {
5403                                                         $player = $player_parent;
5404                                                 }
5405
5406                                                 // RATINGS
5407                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5408                                                 {
5409                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5410                                                         {
5411                                                                 $rating_scheme = null;
5412                                                                 $rating_value = null;
5413                                                                 if (isset($rating['attribs']['']['scheme']))
5414                                                                 {
5415                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5416                                                                 }
5417                                                                 else
5418                                                                 {
5419                                                                         $rating_scheme = 'urn:simple';
5420                                                                 }
5421                                                                 if (isset($rating['data']))
5422                                                                 {
5423                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5424                                                                 }
5425                                                                 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
5426                                                         }
5427                                                         if (is_array($ratings))
5428                                                         {
5429                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5430                                                         }
5431                                                 }
5432                                                 else
5433                                                 {
5434                                                         $ratings = $ratings_parent;
5435                                                 }
5436
5437                                                 // RESTRICTIONS
5438                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5439                                                 {
5440                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5441                                                         {
5442                                                                 $restriction_relationship = null;
5443                                                                 $restriction_type = null;
5444                                                                 $restriction_value = null;
5445                                                                 if (isset($restriction['attribs']['']['relationship']))
5446                                                                 {
5447                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5448                                                                 }
5449                                                                 if (isset($restriction['attribs']['']['type']))
5450                                                                 {
5451                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5452                                                                 }
5453                                                                 if (isset($restriction['data']))
5454                                                                 {
5455                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5456                                                                 }
5457                                                                 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5458                                                         }
5459                                                         if (is_array($restrictions))
5460                                                         {
5461                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5462                                                         }
5463                                                 }
5464                                                 else
5465                                                 {
5466                                                         $restrictions = $restrictions_parent;
5467                                                 }
5468
5469                                                 // THUMBNAILS
5470                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5471                                                 {
5472                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5473                                                         {
5474                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5475                                                         }
5476                                                         if (is_array($thumbnails))
5477                                                         {
5478                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5479                                                         }
5480                                                 }
5481                                                 else
5482                                                 {
5483                                                         $thumbnails = $thumbnails_parent;
5484                                                 }
5485
5486                                                 // TITLES
5487                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5488                                                 {
5489                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5490                                                 }
5491                                                 else
5492                                                 {
5493                                                         $title = $title_parent;
5494                                                 }
5495
5496                                                 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5497                                         }
5498                                 }
5499                         }
5500
5501                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5502                         {
5503                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5504                                 {
5505                                         // Attributes
5506                                         $bitrate = null;
5507                                         $channels = null;
5508                                         $duration = null;
5509                                         $expression = null;
5510                                         $framerate = null;
5511                                         $height = null;
5512                                         $javascript = null;
5513                                         $lang = null;
5514                                         $length = null;
5515                                         $medium = null;
5516                                         $samplingrate = null;
5517                                         $type = null;
5518                                         $url = null;
5519                                         $width = null;
5520
5521                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5522                                         if (isset($link['attribs']['']['type']))
5523                                         {
5524                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5525                                         }
5526                                         if (isset($link['attribs']['']['length']))
5527                                         {
5528                                                 $length = ceil($link['attribs']['']['length']);
5529                                         }
5530
5531                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5532                                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5533                                 }
5534                         }
5535
5536                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5537                         {
5538                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5539                                 {
5540                                         // Attributes
5541                                         $bitrate = null;
5542                                         $channels = null;
5543                                         $duration = null;
5544                                         $expression = null;
5545                                         $framerate = null;
5546                                         $height = null;
5547                                         $javascript = null;
5548                                         $lang = null;
5549                                         $length = null;
5550                                         $medium = null;
5551                                         $samplingrate = null;
5552                                         $type = null;
5553                                         $url = null;
5554                                         $width = null;
5555
5556                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5557                                         if (isset($link['attribs']['']['type']))
5558                                         {
5559                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5560                                         }
5561                                         if (isset($link['attribs']['']['length']))
5562                                         {
5563                                                 $length = ceil($link['attribs']['']['length']);
5564                                         }
5565
5566                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5567                                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5568                                 }
5569                         }
5570
5571                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5572                         {
5573                                 if (isset($enclosure[0]['attribs']['']['url']))
5574                                 {
5575                                         // Attributes
5576                                         $bitrate = null;
5577                                         $channels = null;
5578                                         $duration = null;
5579                                         $expression = null;
5580                                         $framerate = null;
5581                                         $height = null;
5582                                         $javascript = null;
5583                                         $lang = null;
5584                                         $length = null;
5585                                         $medium = null;
5586                                         $samplingrate = null;
5587                                         $type = null;
5588                                         $url = null;
5589                                         $width = null;
5590
5591                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5592                                         if (isset($enclosure[0]['attribs']['']['type']))
5593                                         {
5594                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5595                                         }
5596                                         if (isset($enclosure[0]['attribs']['']['length']))
5597                                         {
5598                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5599                                         }
5600
5601                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5602                                         $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5603                                 }
5604                         }
5605
5606                         if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
5607                         {
5608                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5609                                 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5610                         }
5611
5612                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5613                 }
5614                 if (!empty($this->data['enclosures']))
5615                 {
5616                         return $this->data['enclosures'];
5617                 }
5618                 else
5619                 {
5620                         return null;
5621                 }
5622         }
5623
5624         function get_latitude()
5625         {
5626                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5627                 {
5628                         return (float) $return[0]['data'];
5629                 }
5630                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5631                 {
5632                         return (float) $match[1];
5633                 }
5634                 else
5635                 {
5636                         return null;
5637                 }
5638         }
5639
5640         function get_longitude()
5641         {
5642                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5643                 {
5644                         return (float) $return[0]['data'];
5645                 }
5646                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5647                 {
5648                         return (float) $return[0]['data'];
5649                 }
5650                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5651                 {
5652                         return (float) $match[2];
5653                 }
5654                 else
5655                 {
5656                         return null;
5657                 }
5658         }
5659
5660         function get_source()
5661         {
5662                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5663                 {
5664                         return new $this->feed->source_class($this, $return[0]);
5665                 }
5666                 else
5667                 {
5668                         return null;
5669                 }
5670         }
5671
5672         /**
5673          * Creates the add_to_* methods' return data
5674          *
5675          * @access private
5676          * @param string $item_url String to prefix to the item permalink
5677          * @param string $title_url String to prefix to the item title
5678          * (and suffix to the item permalink)
5679          * @return mixed URL if feed exists, false otherwise
5680          */
5681         function add_to_service($item_url, $title_url = null, $summary_url = null)
5682         {
5683                 if ($this->get_permalink() !== null)
5684                 {
5685                         $return = $item_url . rawurlencode($this->get_permalink());
5686                         if ($title_url !== null && $this->get_title() !== null)
5687                         {
5688                                 $return .= $title_url . rawurlencode($this->get_title());
5689                         }
5690                         if ($summary_url !== null && $this->get_description() !== null)
5691                         {
5692                                 $return .= $summary_url . rawurlencode($this->get_description());
5693                         }
5694                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5695                 }
5696                 else
5697                 {
5698                         return null;
5699                 }
5700         }
5701
5702         function add_to_blinklist()
5703         {
5704                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5705         }
5706
5707         function add_to_blogmarks()
5708         {
5709                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5710         }
5711
5712         function add_to_delicious()
5713         {
5714                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5715         }
5716
5717         function add_to_digg()
5718         {
5719                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5720         }
5721
5722         function add_to_furl()
5723         {
5724                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5725         }
5726
5727         function add_to_magnolia()
5728         {
5729                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5730         }
5731
5732         function add_to_myweb20()
5733         {
5734                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5735         }
5736
5737         function add_to_newsvine()
5738         {
5739                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5740         }
5741
5742         function add_to_reddit()
5743         {
5744                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5745         }
5746
5747         function add_to_segnalo()
5748         {
5749                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5750         }
5751
5752         function add_to_simpy()
5753         {
5754                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5755         }
5756
5757         function add_to_spurl()
5758         {
5759                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5760         }
5761
5762         function add_to_wists()
5763         {
5764                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5765         }
5766
5767         function search_technorati()
5768         {
5769                 return $this->add_to_service('http://www.technorati.com/search/');
5770         }
5771 }
5772
5773 class SimplePie_Source
5774 {
5775         var $item;
5776         var $data = array();
5777
5778         function SimplePie_Source($item, $data)
5779         {
5780                 $this->item = $item;
5781                 $this->data = $data;
5782         }
5783
5784         function __toString()
5785         {
5786                 return md5(serialize($this->data));
5787         }
5788
5789         function get_source_tags($namespace, $tag)
5790         {
5791                 if (isset($this->data['child'][$namespace][$tag]))
5792                 {
5793                         return $this->data['child'][$namespace][$tag];
5794                 }
5795                 else
5796                 {
5797                         return null;
5798                 }
5799         }
5800
5801         function get_base($element = array())
5802         {
5803                 return $this->item->get_base($element);
5804         }
5805
5806         function sanitize($data, $type, $base = '')
5807         {
5808                 return $this->item->sanitize($data, $type, $base);
5809         }
5810
5811         function get_item()
5812         {
5813                 return $this->item;
5814         }
5815
5816         function get_title()
5817         {
5818                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5819                 {
5820                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5821                 }
5822                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5823                 {
5824                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5825                 }
5826                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5827                 {
5828                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5829                 }
5830                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5831                 {
5832                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5833                 }
5834                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5835                 {
5836                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5837                 }
5838                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5839                 {
5840                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5841                 }
5842                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5843                 {
5844                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5845                 }
5846                 else
5847                 {
5848                         return null;
5849                 }
5850         }
5851
5852         function get_category($key = 0)
5853         {
5854                 $categories = $this->get_categories();
5855                 if (isset($categories[$key]))
5856                 {
5857                         return $categories[$key];
5858                 }
5859                 else
5860                 {
5861                         return null;
5862                 }
5863         }
5864
5865         function get_categories()
5866         {
5867                 $categories = array();
5868
5869                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5870                 {
5871                         $term = null;
5872                         $scheme = null;
5873                         $label = null;
5874                         if (isset($category['attribs']['']['term']))
5875                         {
5876                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5877                         }
5878                         if (isset($category['attribs']['']['scheme']))
5879                         {
5880                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5881                         }
5882                         if (isset($category['attribs']['']['label']))
5883                         {
5884                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5885                         }
5886                         $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5887                 }
5888                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5889                 {
5890                         // This is really the label, but keep this as the term also for BC.
5891                         // Label will also work on retrieving because that falls back to term.
5892                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5893                         if (isset($category['attribs']['']['domain']))
5894                         {
5895                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5896                         }
5897                         else
5898                         {
5899                                 $scheme = null;
5900                         }
5901                         $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5902                 }
5903                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5904                 {
5905                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5906                 }
5907                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5908                 {
5909                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5910                 }
5911
5912                 if (!empty($categories))
5913                 {
5914                         return SimplePie_Misc::array_unique($categories);
5915                 }
5916                 else
5917                 {
5918                         return null;
5919                 }
5920         }
5921
5922         function get_author($key = 0)
5923         {
5924                 $authors = $this->get_authors();
5925                 if (isset($authors[$key]))
5926                 {
5927                         return $authors[$key];
5928                 }
5929                 else
5930                 {
5931                         return null;
5932                 }
5933         }
5934
5935         function get_authors()
5936         {
5937                 $authors = array();
5938                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5939                 {
5940                         $name = null;
5941                         $uri = null;
5942                         $email = null;
5943                         $avatar = null;
5944                         $name_date = null;
5945                         $uri_date = null;
5946                         $avatar_date = null;
5947
5948                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5949                         {
5950                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5951                         }
5952                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5953                         {
5954                                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
5955                         }
5956                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5957                         {
5958                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5959                         }
5960                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
5961                         {
5962                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
5963                         }
5964                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
5965                         {
5966                                 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
5967                         }
5968                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
5969                         {
5970                                 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
5971                         }
5972                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
5973                         {
5974                                 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
5975                         }
5976
5977                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
5978                         {
5979                                 $authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
5980                         }
5981                 }
5982                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5983                 {
5984                         $name = null;
5985                         $url = null;
5986                         $email = null;
5987                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5988                         {
5989                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5990                         }
5991                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5992                         {
5993                                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
5994                         }
5995                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5996                         {
5997                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5998                         }
5999                         if ($name !== null || $email !== null || $url !== null)
6000                         {
6001                                 $authors[] = new $this->item->feed->author_class($name, $url, $email);
6002                         }
6003                 }
6004                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
6005                 {
6006                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6007                 }
6008                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
6009                 {
6010                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6011                 }
6012                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
6013                 {
6014                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6015                 }
6016
6017                 if (!empty($authors))
6018                 {
6019                         return SimplePie_Misc::array_unique($authors);
6020                 }
6021                 else
6022                 {
6023                         return null;
6024                 }
6025         }
6026
6027         function get_contributor($key = 0)
6028         {
6029                 $contributors = $this->get_contributors();
6030                 if (isset($contributors[$key]))
6031                 {
6032                         return $contributors[$key];
6033                 }
6034                 else
6035                 {
6036                         return null;
6037                 }
6038         }
6039
6040         function get_contributors()
6041         {
6042                 $contributors = array();
6043                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
6044                 {
6045                         $name = null;
6046                         $uri = null;
6047                         $email = null;
6048                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6049                         {
6050                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6051                         }
6052                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6053                         {
6054                                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
6055                         }
6056                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6057                         {
6058                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6059                         }
6060                         if ($name !== null || $email !== null || $uri !== null)
6061                         {
6062                                 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
6063                         }
6064                 }
6065                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6066                 {
6067                         $name = null;
6068                         $url = null;
6069                         $email = null;
6070                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6071                         {
6072                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6073                         }
6074                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6075                         {
6076                                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
6077                         }
6078                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6079                         {
6080                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6081                         }
6082                         if ($name !== null || $email !== null || $url !== null)
6083                         {
6084                                 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
6085                         }
6086                 }
6087
6088                 if (!empty($contributors))
6089                 {
6090                         return SimplePie_Misc::array_unique($contributors);
6091                 }
6092                 else
6093                 {
6094                         return null;
6095                 }
6096         }
6097
6098         function get_link($key = 0, $rel = 'alternate')
6099         {
6100                 $links = $this->get_links($rel);
6101                 if (isset($links[$key]))
6102                 {
6103                         return $links[$key];
6104                 }
6105                 else
6106                 {
6107                         return null;
6108                 }
6109         }
6110
6111         /**
6112          * Added for parity between the parent-level and the item/entry-level.
6113          */
6114         function get_permalink()
6115         {
6116                 return $this->get_link(0);
6117         }
6118
6119         function get_links($rel = 'alternate')
6120         {
6121                 if (!isset($this->data['links']))
6122                 {
6123                         $this->data['links'] = array();
6124                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6125                         {
6126                                 foreach ($links as $link)
6127                                 {
6128                                         if (isset($link['attribs']['']['href']))
6129                                         {
6130                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6131                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6132                                         }
6133                                 }
6134                         }
6135                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6136                         {
6137                                 foreach ($links as $link)
6138                                 {
6139                                         if (isset($link['attribs']['']['href']))
6140                                         {
6141                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6142                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6143
6144                                         }
6145                                 }
6146                         }
6147                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6148                         {
6149                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6150                         }
6151                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6152                         {
6153                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6154                         }
6155                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6156                         {
6157                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6158                         }
6159
6160                         $keys = array_keys($this->data['links']);
6161                         foreach ($keys as $key)
6162                         {
6163                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6164                                 {
6165                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6166                                         {
6167                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6168                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6169                                         }
6170                                         else
6171                                         {
6172                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6173                                         }
6174                                 }
6175                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6176                                 {
6177                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6178                                 }
6179                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6180                         }
6181                 }
6182
6183                 if (isset($this->data['links'][$rel]))
6184                 {
6185                         return $this->data['links'][$rel];
6186                 }
6187                 else
6188                 {
6189                         return null;
6190                 }
6191         }
6192
6193         function get_description()
6194         {
6195                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6196                 {
6197                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6198                 }
6199                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6200                 {
6201                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6202                 }
6203                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6204                 {
6205                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6206                 }
6207                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6208                 {
6209                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6210                 }
6211                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6212                 {
6213                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6214                 }
6215                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6216                 {
6217                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6218                 }
6219                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6220                 {
6221                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6222                 }
6223                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6224                 {
6225                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6226                 }
6227                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6228                 {
6229                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6230                 }
6231                 else
6232                 {
6233                         return null;
6234                 }
6235         }
6236
6237         function get_copyright()
6238         {
6239                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6240                 {
6241                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6242                 }
6243                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6244                 {
6245                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6246                 }
6247                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6248                 {
6249                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6250                 }
6251                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6252                 {
6253                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6254                 }
6255                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6256                 {
6257                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6258                 }
6259                 else
6260                 {
6261                         return null;
6262                 }
6263         }
6264
6265         function get_language()
6266         {
6267                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6268                 {
6269                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6270                 }
6271                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6272                 {
6273                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6274                 }
6275                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6276                 {
6277                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6278                 }
6279                 elseif (isset($this->data['xml_lang']))
6280                 {
6281                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6282                 }
6283                 else
6284                 {
6285                         return null;
6286                 }
6287         }
6288
6289         function get_latitude()
6290         {
6291                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6292                 {
6293                         return (float) $return[0]['data'];
6294                 }
6295                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6296                 {
6297                         return (float) $match[1];
6298                 }
6299                 else
6300                 {
6301                         return null;
6302                 }
6303         }
6304
6305         function get_longitude()
6306         {
6307                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6308                 {
6309                         return (float) $return[0]['data'];
6310                 }
6311                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6312                 {
6313                         return (float) $return[0]['data'];
6314                 }
6315                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6316                 {
6317                         return (float) $match[2];
6318                 }
6319                 else
6320                 {
6321                         return null;
6322                 }
6323         }
6324
6325         function get_image_url()
6326         {
6327                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6328                 {
6329                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6330                 }
6331                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6332                 {
6333                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6334                 }
6335                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6336                 {
6337                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6338                 }
6339                 else
6340                 {
6341                         return null;
6342                 }
6343         }
6344 }
6345
6346 class SimplePie_Author
6347 {
6348         var $name;
6349         var $link;
6350         var $email;
6351         var $avatar;
6352         var $name_date;
6353         var $uri_date;
6354         var $avatar_date;
6355
6356         // Constructor, used to input the data
6357         function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null, $name_date = null, $uri_date = null, $avatar_date = null)
6358         {
6359                 $this->name = $name;
6360                 $this->link = $link;
6361                 $this->email = $email;
6362                 $this->avatar = $avatar;
6363                 $this->name_date = $name_date;
6364                 $this->uri_date = $uri_date;
6365                 $this->avatar_date = $avatar_date;
6366         }
6367
6368         function __toString()
6369         {
6370                 // There is no $this->data here
6371                 return md5(serialize($this));
6372         }
6373
6374         function get_name()
6375         {
6376                 if ($this->name !== null)
6377                 {
6378                         return $this->name;
6379                 }
6380                 else
6381                 {
6382                         return null;
6383                 }
6384         }
6385
6386         function get_link()
6387         {
6388                 if ($this->link !== null)
6389                 {
6390                         return $this->link;
6391                 }
6392                 else
6393                 {
6394                         return null;
6395                 }
6396         }
6397
6398         function get_email()
6399         {
6400                 if ($this->email !== null)
6401                 {
6402                         return $this->email;
6403                 }
6404                 else
6405                 {
6406                         return null;
6407                 }
6408         }
6409
6410         function get_avatar()
6411         {
6412                 if ($this->avatar !== null)
6413                 {
6414                         return $this->avatar;
6415                 }
6416                 else
6417                 {
6418                         return null;
6419                 }
6420         }
6421
6422         function get_name_date()
6423         {
6424                 if ($this->name_date !== null)
6425                 {
6426                         return $this->name_date;
6427                 }
6428                 else
6429                 {
6430                         return null;
6431                 }
6432         }
6433         function get_uri_date()
6434         {
6435                 if ($this->uri_date !== null)
6436                 {
6437                         return $this->uri_date;
6438                 }
6439                 else
6440                 {
6441                         return null;
6442                 }
6443         }
6444         function get_avatar_date()
6445         {
6446                 if ($this->avatar_date !== null)
6447                 {
6448                         return $this->avatar_date;
6449                 }
6450                 else
6451                 {
6452                         return null;
6453                 }
6454         }
6455
6456
6457 }
6458
6459 class SimplePie_Category
6460 {
6461         var $term;
6462         var $scheme;
6463         var $label;
6464
6465         // Constructor, used to input the data
6466         function SimplePie_Category($term = null, $scheme = null, $label = null)
6467         {
6468                 $this->term = $term;
6469                 $this->scheme = $scheme;
6470                 $this->label = $label;
6471         }
6472
6473         function __toString()
6474         {
6475                 // There is no $this->data here
6476                 return md5(serialize($this));
6477         }
6478
6479         function get_term()
6480         {
6481                 if ($this->term !== null)
6482                 {
6483                         return $this->term;
6484                 }
6485                 else
6486                 {
6487                         return null;
6488                 }
6489         }
6490
6491         function get_scheme()
6492         {
6493                 if ($this->scheme !== null)
6494                 {
6495                         return $this->scheme;
6496                 }
6497                 else
6498                 {
6499                         return null;
6500                 }
6501         }
6502
6503         function get_label()
6504         {
6505                 if ($this->label !== null)
6506                 {
6507                         return $this->label;
6508                 }
6509                 else
6510                 {
6511                         return $this->get_term();
6512                 }
6513         }
6514 }
6515
6516 class SimplePie_Enclosure
6517 {
6518         var $bitrate;
6519         var $captions;
6520         var $categories;
6521         var $channels;
6522         var $copyright;
6523         var $credits;
6524         var $description;
6525         var $duration;
6526         var $expression;
6527         var $framerate;
6528         var $handler;
6529         var $hashes;
6530         var $height;
6531         var $javascript;
6532         var $keywords;
6533         var $lang;
6534         var $length;
6535         var $link;
6536         var $medium;
6537         var $player;
6538         var $ratings;
6539         var $restrictions;
6540         var $samplingrate;
6541         var $thumbnails;
6542         var $title;
6543         var $type;
6544         var $width;
6545
6546         // Constructor, used to input the data
6547         function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
6548         {
6549                 $this->bitrate = $bitrate;
6550                 $this->captions = $captions;
6551                 $this->categories = $categories;
6552                 $this->channels = $channels;
6553                 $this->copyright = $copyright;
6554                 $this->credits = $credits;
6555                 $this->description = $description;
6556                 $this->duration = $duration;
6557                 $this->expression = $expression;
6558                 $this->framerate = $framerate;
6559                 $this->hashes = $hashes;
6560                 $this->height = $height;
6561                 $this->javascript = $javascript;
6562                 $this->keywords = $keywords;
6563                 $this->lang = $lang;
6564                 $this->length = $length;
6565                 $this->link = $link;
6566                 $this->medium = $medium;
6567                 $this->player = $player;
6568                 $this->ratings = $ratings;
6569                 $this->restrictions = $restrictions;
6570                 $this->samplingrate = $samplingrate;
6571                 $this->thumbnails = $thumbnails;
6572                 $this->title = $title;
6573                 $this->type = $type;
6574                 $this->width = $width;
6575                 if (class_exists('idna_convert'))
6576                 {
6577                         $idn = new idna_convert;
6578                         $parsed = SimplePie_Misc::parse_url($link);
6579                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6580                 }
6581                 $this->handler = $this->get_handler(); // Needs to load last
6582         }
6583
6584         function __toString()
6585         {
6586                 // There is no $this->data here
6587                 return md5(serialize($this));
6588         }
6589
6590         function get_bitrate()
6591         {
6592                 if ($this->bitrate !== null)
6593                 {
6594                         return $this->bitrate;
6595                 }
6596                 else
6597                 {
6598                         return null;
6599                 }
6600         }
6601
6602         function get_caption($key = 0)
6603         {
6604                 $captions = $this->get_captions();
6605                 if (isset($captions[$key]))
6606                 {
6607                         return $captions[$key];
6608                 }
6609                 else
6610                 {
6611                         return null;
6612                 }
6613         }
6614
6615         function get_captions()
6616         {
6617                 if ($this->captions !== null)
6618                 {
6619                         return $this->captions;
6620                 }
6621                 else
6622                 {
6623                         return null;
6624                 }
6625         }
6626
6627         function get_category($key = 0)
6628         {
6629                 $categories = $this->get_categories();
6630                 if (isset($categories[$key]))
6631                 {
6632                         return $categories[$key];
6633                 }
6634                 else
6635                 {
6636                         return null;
6637                 }
6638         }
6639
6640         function get_categories()
6641         {
6642                 if ($this->categories !== null)
6643                 {
6644                         return $this->categories;
6645                 }
6646                 else
6647                 {
6648                         return null;
6649                 }
6650         }
6651
6652         function get_channels()
6653         {
6654                 if ($this->channels !== null)
6655                 {
6656                         return $this->channels;
6657                 }
6658                 else
6659                 {
6660                         return null;
6661                 }
6662         }
6663
6664         function get_copyright()
6665         {
6666                 if ($this->copyright !== null)
6667                 {
6668                         return $this->copyright;
6669                 }
6670                 else
6671                 {
6672                         return null;
6673                 }
6674         }
6675
6676         function get_credit($key = 0)
6677         {
6678                 $credits = $this->get_credits();
6679                 if (isset($credits[$key]))
6680                 {
6681                         return $credits[$key];
6682                 }
6683                 else
6684                 {
6685                         return null;
6686                 }
6687         }
6688
6689         function get_credits()
6690         {
6691                 if ($this->credits !== null)
6692                 {
6693                         return $this->credits;
6694                 }
6695                 else
6696                 {
6697                         return null;
6698                 }
6699         }
6700
6701         function get_description()
6702         {
6703                 if ($this->description !== null)
6704                 {
6705                         return $this->description;
6706                 }
6707                 else
6708                 {
6709                         return null;
6710                 }
6711         }
6712
6713         function get_duration($convert = false)
6714         {
6715                 if ($this->duration !== null)
6716                 {
6717                         if ($convert)
6718                         {
6719                                 $time = SimplePie_Misc::time_hms($this->duration);
6720                                 return $time;
6721                         }
6722                         else
6723                         {
6724                                 return $this->duration;
6725                         }
6726                 }
6727                 else
6728                 {
6729                         return null;
6730                 }
6731         }
6732
6733         function get_expression()
6734         {
6735                 if ($this->expression !== null)
6736                 {
6737                         return $this->expression;
6738                 }
6739                 else
6740                 {
6741                         return 'full';
6742                 }
6743         }
6744
6745         function get_extension()
6746         {
6747                 if ($this->link !== null)
6748                 {
6749                         $url = SimplePie_Misc::parse_url($this->link);
6750                         if ($url['path'] !== '')
6751                         {
6752                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6753                         }
6754                 }
6755                 return null;
6756         }
6757
6758         function get_framerate()
6759         {
6760                 if ($this->framerate !== null)
6761                 {
6762                         return $this->framerate;
6763                 }
6764                 else
6765                 {
6766                         return null;
6767                 }
6768         }
6769
6770         function get_handler()
6771         {
6772                 return $this->get_real_type(true);
6773         }
6774
6775         function get_hash($key = 0)
6776         {
6777                 $hashes = $this->get_hashes();
6778                 if (isset($hashes[$key]))
6779                 {
6780                         return $hashes[$key];
6781                 }
6782                 else
6783                 {
6784                         return null;
6785                 }
6786         }
6787
6788         function get_hashes()
6789         {
6790                 if ($this->hashes !== null)
6791                 {
6792                         return $this->hashes;
6793                 }
6794                 else
6795                 {
6796                         return null;
6797                 }
6798         }
6799
6800         function get_height()
6801         {
6802                 if ($this->height !== null)
6803                 {
6804                         return $this->height;
6805                 }
6806                 else
6807                 {
6808                         return null;
6809                 }
6810         }
6811
6812         function get_language()
6813         {
6814                 if ($this->lang !== null)
6815                 {
6816                         return $this->lang;
6817                 }
6818                 else
6819                 {
6820                         return null;
6821                 }
6822         }
6823
6824         function get_keyword($key = 0)
6825         {
6826                 $keywords = $this->get_keywords();
6827                 if (isset($keywords[$key]))
6828                 {
6829                         return $keywords[$key];
6830                 }
6831                 else
6832                 {
6833                         return null;
6834                 }
6835         }
6836
6837         function get_keywords()
6838         {
6839                 if ($this->keywords !== null)
6840                 {
6841                         return $this->keywords;
6842                 }
6843                 else
6844                 {
6845                         return null;
6846                 }
6847         }
6848
6849         function get_length()
6850         {
6851                 if ($this->length !== null)
6852                 {
6853                         return $this->length;
6854                 }
6855                 else
6856                 {
6857                         return null;
6858                 }
6859         }
6860
6861         function get_link()
6862         {
6863                 if ($this->link !== null)
6864                 {
6865                         return urldecode($this->link);
6866                 }
6867                 else
6868                 {
6869                         return null;
6870                 }
6871         }
6872
6873         function get_medium()
6874         {
6875                 if ($this->medium !== null)
6876                 {
6877                         return $this->medium;
6878                 }
6879                 else
6880                 {
6881                         return null;
6882                 }
6883         }
6884
6885         function get_player()
6886         {
6887                 if ($this->player !== null)
6888                 {
6889                         return $this->player;
6890                 }
6891                 else
6892                 {
6893                         return null;
6894                 }
6895         }
6896
6897         function get_rating($key = 0)
6898         {
6899                 $ratings = $this->get_ratings();
6900                 if (isset($ratings[$key]))
6901                 {
6902                         return $ratings[$key];
6903                 }
6904                 else
6905                 {
6906                         return null;
6907                 }
6908         }
6909
6910         function get_ratings()
6911         {
6912                 if ($this->ratings !== null)
6913                 {
6914                         return $this->ratings;
6915                 }
6916                 else
6917                 {
6918                         return null;
6919                 }
6920         }
6921
6922         function get_restriction($key = 0)
6923         {
6924                 $restrictions = $this->get_restrictions();
6925                 if (isset($restrictions[$key]))
6926                 {
6927                         return $restrictions[$key];
6928                 }
6929                 else
6930                 {
6931                         return null;
6932                 }
6933         }
6934
6935         function get_restrictions()
6936         {
6937                 if ($this->restrictions !== null)
6938                 {
6939                         return $this->restrictions;
6940                 }
6941                 else
6942                 {
6943                         return null;
6944                 }
6945         }
6946
6947         function get_sampling_rate()
6948         {
6949                 if ($this->samplingrate !== null)
6950                 {
6951                         return $this->samplingrate;
6952                 }
6953                 else
6954                 {
6955                         return null;
6956                 }
6957         }
6958
6959         function get_size()
6960         {
6961                 $length = $this->get_length();
6962                 if ($length !== null)
6963                 {
6964                         return round($length/1048576, 2);
6965                 }
6966                 else
6967                 {
6968                         return null;
6969                 }
6970         }
6971
6972         function get_thumbnail($key = 0)
6973         {
6974                 $thumbnails = $this->get_thumbnails();
6975                 if (isset($thumbnails[$key]))
6976                 {
6977                         return $thumbnails[$key];
6978                 }
6979                 else
6980                 {
6981                         return null;
6982                 }
6983         }
6984
6985         function get_thumbnails()
6986         {
6987                 if ($this->thumbnails !== null)
6988                 {
6989                         return $this->thumbnails;
6990                 }
6991                 else
6992                 {
6993                         return null;
6994                 }
6995         }
6996
6997         function get_title()
6998         {
6999                 if ($this->title !== null)
7000                 {
7001                         return $this->title;
7002                 }
7003                 else
7004                 {
7005                         return null;
7006                 }
7007         }
7008
7009         function get_type()
7010         {
7011                 if ($this->type !== null)
7012                 {
7013                         return $this->type;
7014                 }
7015                 else
7016                 {
7017                         return null;
7018                 }
7019         }
7020
7021         function get_width()
7022         {
7023                 if ($this->width !== null)
7024                 {
7025                         return $this->width;
7026                 }
7027                 else
7028                 {
7029                         return null;
7030                 }
7031         }
7032
7033         function native_embed($options='')
7034         {
7035                 return $this->embed($options, true);
7036         }
7037
7038         /**
7039          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
7040          */
7041         function embed($options = '', $native = false)
7042         {
7043                 // Set up defaults
7044                 $audio = '';
7045                 $video = '';
7046                 $alt = '';
7047                 $altclass = '';
7048                 $loop = 'false';
7049                 $width = 'auto';
7050                 $height = 'auto';
7051                 $bgcolor = '#ffffff';
7052                 $mediaplayer = '';
7053                 $widescreen = false;
7054                 $handler = $this->get_handler();
7055                 $type = $this->get_real_type();
7056
7057                 // Process options and reassign values as necessary
7058                 if (is_array($options))
7059                 {
7060                         extract($options);
7061                 }
7062                 else
7063                 {
7064                         $options = explode(',', $options);
7065                         foreach($options as $option)
7066                         {
7067                                 $opt = explode(':', $option, 2);
7068                                 if (isset($opt[0], $opt[1]))
7069                                 {
7070                                         $opt[0] = trim($opt[0]);
7071                                         $opt[1] = trim($opt[1]);
7072                                         switch ($opt[0])
7073                                         {
7074                                                 case 'audio':
7075                                                         $audio = $opt[1];
7076                                                         break;
7077
7078                                                 case 'video':
7079                                                         $video = $opt[1];
7080                                                         break;
7081
7082                                                 case 'alt':
7083                                                         $alt = $opt[1];
7084                                                         break;
7085
7086                                                 case 'altclass':
7087                                                         $altclass = $opt[1];
7088                                                         break;
7089
7090                                                 case 'loop':
7091                                                         $loop = $opt[1];
7092                                                         break;
7093
7094                                                 case 'width':
7095                                                         $width = $opt[1];
7096                                                         break;
7097
7098                                                 case 'height':
7099                                                         $height = $opt[1];
7100                                                         break;
7101
7102                                                 case 'bgcolor':
7103                                                         $bgcolor = $opt[1];
7104                                                         break;
7105
7106                                                 case 'mediaplayer':
7107                                                         $mediaplayer = $opt[1];
7108                                                         break;
7109
7110                                                 case 'widescreen':
7111                                                         $widescreen = $opt[1];
7112                                                         break;
7113                                         }
7114                                 }
7115                         }
7116                 }
7117
7118                 $mime = explode('/', $type, 2);
7119                 $mime = $mime[0];
7120
7121                 // Process values for 'auto'
7122                 if ($width === 'auto')
7123                 {
7124                         if ($mime === 'video')
7125                         {
7126                                 if ($height === 'auto')
7127                                 {
7128                                         $width = 480;
7129                                 }
7130                                 elseif ($widescreen)
7131                                 {
7132                                         $width = round((intval($height)/9)*16);
7133                                 }
7134                                 else
7135                                 {
7136                                         $width = round((intval($height)/3)*4);
7137                                 }
7138                         }
7139                         else
7140                         {
7141                                 $width = '100%';
7142                         }
7143                 }
7144
7145                 if ($height === 'auto')
7146                 {
7147                         if ($mime === 'audio')
7148                         {
7149                                 $height = 0;
7150                         }
7151                         elseif ($mime === 'video')
7152                         {
7153                                 if ($width === 'auto')
7154                                 {
7155                                         if ($widescreen)
7156                                         {
7157                                                 $height = 270;
7158                                         }
7159                                         else
7160                                         {
7161                                                 $height = 360;
7162                                         }
7163                                 }
7164                                 elseif ($widescreen)
7165                                 {
7166                                         $height = round((intval($width)/16)*9);
7167                                 }
7168                                 else
7169                                 {
7170                                         $height = round((intval($width)/4)*3);
7171                                 }
7172                         }
7173                         else
7174                         {
7175                                 $height = 376;
7176                         }
7177                 }
7178                 elseif ($mime === 'audio')
7179                 {
7180                         $height = 0;
7181                 }
7182
7183                 // Set proper placeholder value
7184                 if ($mime === 'audio')
7185                 {
7186                         $placeholder = $audio;
7187                 }
7188                 elseif ($mime === 'video')
7189                 {
7190                         $placeholder = $video;
7191                 }
7192
7193                 $embed = '';
7194
7195                 // Make sure the JS library is included
7196                 if (!$native)
7197                 {
7198                         static $javascript_outputted = null;
7199                         if (!$javascript_outputted && $this->javascript)
7200                         {
7201                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7202                                 $javascript_outputted = true;
7203                         }
7204                 }
7205
7206                 // Odeo Feed MP3's
7207                 if ($handler === 'odeo')
7208                 {
7209                         if ($native)
7210                         {
7211                                 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
7212                         }
7213                         else
7214                         {
7215                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7216                         }
7217                 }
7218
7219                 // Flash
7220                 elseif ($handler === 'flash')
7221                 {
7222                         if ($native)
7223                         {
7224                                 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
7225                         }
7226                         else
7227                         {
7228                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7229                         }
7230                 }
7231
7232                 // Flash Media Player file types.
7233                 // Preferred handler for MP3 file types.
7234                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7235                 {
7236                         $height += 20;
7237                         if ($native)
7238                         {
7239                                 $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
7240                         }
7241                         else
7242                         {
7243                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7244                         }
7245                 }
7246
7247                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7248                 // Only handle MP3's if the Flash Media Player is not present.
7249                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7250                 {
7251                         $height += 16;
7252                         if ($native)
7253                         {
7254                                 if ($placeholder !== '')
7255                                 {
7256                                         $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7257                                 }
7258                                 else
7259                                 {
7260                                         $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7261                                 }
7262                         }
7263                         else
7264                         {
7265                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7266                         }
7267                 }
7268
7269                 // Windows Media
7270                 elseif ($handler === 'wmedia')
7271                 {
7272                         $height += 45;
7273                         if ($native)
7274                         {
7275                                 $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
7276                         }
7277                         else
7278                         {
7279                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7280                         }
7281                 }
7282
7283                 // Everything else
7284                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7285
7286                 return $embed;
7287         }
7288
7289         function get_real_type($find_handler = false)
7290         {
7291                 // If it's Odeo, let's get it out of the way.
7292                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7293                 {
7294                         return 'odeo';
7295                 }
7296
7297                 // Mime-types by handler.
7298                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7299                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7300                 $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
7301                 $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
7302                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7303
7304                 if ($this->get_type() !== null)
7305                 {
7306                         $type = strtolower($this->type);
7307                 }
7308                 else
7309                 {
7310                         $type = null;
7311                 }
7312
7313                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7314                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7315                 {
7316                         switch (strtolower($this->get_extension()))
7317                         {
7318                                 // Audio mime-types
7319                                 case 'aac':
7320                                 case 'adts':
7321                                         $type = 'audio/acc';
7322                                         break;
7323
7324                                 case 'aif':
7325                                 case 'aifc':
7326                                 case 'aiff':
7327                                 case 'cdda':
7328                                         $type = 'audio/aiff';
7329                                         break;
7330
7331                                 case 'bwf':
7332                                         $type = 'audio/wav';
7333                                         break;
7334
7335                                 case 'kar':
7336                                 case 'mid':
7337                                 case 'midi':
7338                                 case 'smf':
7339                                         $type = 'audio/midi';
7340                                         break;
7341
7342                                 case 'm4a':
7343                                         $type = 'audio/x-m4a';
7344                                         break;
7345
7346                                 case 'mp3':
7347                                 case 'swa':
7348                                         $type = 'audio/mp3';
7349                                         break;
7350
7351                                 case 'wav':
7352                                         $type = 'audio/wav';
7353                                         break;
7354
7355                                 case 'wax':
7356                                         $type = 'audio/x-ms-wax';
7357                                         break;
7358
7359                                 case 'wma':
7360                                         $type = 'audio/x-ms-wma';
7361                                         break;
7362
7363                                 // Video mime-types
7364                                 case '3gp':
7365                                 case '3gpp':
7366                                         $type = 'video/3gpp';
7367                                         break;
7368
7369                                 case '3g2':
7370                                 case '3gp2':
7371                                         $type = 'video/3gpp2';
7372                                         break;
7373
7374                                 case 'asf':
7375                                         $type = 'video/x-ms-asf';
7376                                         break;
7377
7378                                 case 'flv':
7379                                         $type = 'video/x-flv';
7380                                         break;
7381
7382                                 case 'm1a':
7383                                 case 'm1s':
7384                                 case 'm1v':
7385                                 case 'm15':
7386                                 case 'm75':
7387                                 case 'mp2':
7388                                 case 'mpa':
7389                                 case 'mpeg':
7390                                 case 'mpg':
7391                                 case 'mpm':
7392                                 case 'mpv':
7393                                         $type = 'video/mpeg';
7394                                         break;
7395
7396                                 case 'm4v':
7397                                         $type = 'video/x-m4v';
7398                                         break;
7399
7400                                 case 'mov':
7401                                 case 'qt':
7402                                         $type = 'video/quicktime';
7403                                         break;
7404
7405                                 case 'mp4':
7406                                 case 'mpg4':
7407                                         $type = 'video/mp4';
7408                                         break;
7409
7410                                 case 'sdv':
7411                                         $type = 'video/sd-video';
7412                                         break;
7413
7414                                 case 'wm':
7415                                         $type = 'video/x-ms-wm';
7416                                         break;
7417
7418                                 case 'wmv':
7419                                         $type = 'video/x-ms-wmv';
7420                                         break;
7421
7422                                 case 'wvx':
7423                                         $type = 'video/x-ms-wvx';
7424                                         break;
7425
7426                                 // Flash mime-types
7427                                 case 'spl':
7428                                         $type = 'application/futuresplash';
7429                                         break;
7430
7431                                 case 'swf':
7432                                         $type = 'application/x-shockwave-flash';
7433                                         break;
7434                         }
7435                 }
7436
7437                 if ($find_handler)
7438                 {
7439                         if (in_array($type, $types_flash))
7440                         {
7441                                 return 'flash';
7442                         }
7443                         elseif (in_array($type, $types_fmedia))
7444                         {
7445                                 return 'fmedia';
7446                         }
7447                         elseif (in_array($type, $types_quicktime))
7448                         {
7449                                 return 'quicktime';
7450                         }
7451                         elseif (in_array($type, $types_wmedia))
7452                         {
7453                                 return 'wmedia';
7454                         }
7455                         elseif (in_array($type, $types_mp3))
7456                         {
7457                                 return 'mp3';
7458                         }
7459                         else
7460                         {
7461                                 return null;
7462                         }
7463                 }
7464                 else
7465                 {
7466                         return $type;
7467                 }
7468         }
7469 }
7470
7471 class SimplePie_Caption
7472 {
7473         var $type;
7474         var $lang;
7475         var $startTime;
7476         var $endTime;
7477         var $text;
7478
7479         // Constructor, used to input the data
7480         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7481         {
7482                 $this->type = $type;
7483                 $this->lang = $lang;
7484                 $this->startTime = $startTime;
7485                 $this->endTime = $endTime;
7486                 $this->text = $text;
7487         }
7488
7489         function __toString()
7490         {
7491                 // There is no $this->data here
7492                 return md5(serialize($this));
7493         }
7494
7495         function get_endtime()
7496         {
7497                 if ($this->endTime !== null)
7498                 {
7499                         return $this->endTime;
7500                 }
7501                 else
7502                 {
7503                         return null;
7504                 }
7505         }
7506
7507         function get_language()
7508         {
7509                 if ($this->lang !== null)
7510                 {
7511                         return $this->lang;
7512                 }
7513                 else
7514                 {
7515                         return null;
7516                 }
7517         }
7518
7519         function get_starttime()
7520         {
7521                 if ($this->startTime !== null)
7522                 {
7523                         return $this->startTime;
7524                 }
7525                 else
7526                 {
7527                         return null;
7528                 }
7529         }
7530
7531         function get_text()
7532         {
7533                 if ($this->text !== null)
7534                 {
7535                         return $this->text;
7536                 }
7537                 else
7538                 {
7539                         return null;
7540                 }
7541         }
7542
7543         function get_type()
7544         {
7545                 if ($this->type !== null)
7546                 {
7547                         return $this->type;
7548                 }
7549                 else
7550                 {
7551                         return null;
7552                 }
7553         }
7554 }
7555
7556 class SimplePie_Credit
7557 {
7558         var $role;
7559         var $scheme;
7560         var $name;
7561
7562         // Constructor, used to input the data
7563         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7564         {
7565                 $this->role = $role;
7566                 $this->scheme = $scheme;
7567                 $this->name = $name;
7568         }
7569
7570         function __toString()
7571         {
7572                 // There is no $this->data here
7573                 return md5(serialize($this));
7574         }
7575
7576         function get_role()
7577         {
7578                 if ($this->role !== null)
7579                 {
7580                         return $this->role;
7581                 }
7582                 else
7583                 {
7584                         return null;
7585                 }
7586         }
7587
7588         function get_scheme()
7589         {
7590                 if ($this->scheme !== null)
7591                 {
7592                         return $this->scheme;
7593                 }
7594                 else
7595                 {
7596                         return null;
7597                 }
7598         }
7599
7600         function get_name()
7601         {
7602                 if ($this->name !== null)
7603                 {
7604                         return $this->name;
7605                 }
7606                 else
7607                 {
7608                         return null;
7609                 }
7610         }
7611 }
7612
7613 class SimplePie_Copyright
7614 {
7615         var $url;
7616         var $label;
7617
7618         // Constructor, used to input the data
7619         function SimplePie_Copyright($url = null, $label = null)
7620         {
7621                 $this->url = $url;
7622                 $this->label = $label;
7623         }
7624
7625         function __toString()
7626         {
7627                 // There is no $this->data here
7628                 return md5(serialize($this));
7629         }
7630
7631         function get_url()
7632         {
7633                 if ($this->url !== null)
7634                 {
7635                         return $this->url;
7636                 }
7637                 else
7638                 {
7639                         return null;
7640                 }
7641         }
7642
7643         function get_attribution()
7644         {
7645                 if ($this->label !== null)
7646                 {
7647                         return $this->label;
7648                 }
7649                 else
7650                 {
7651                         return null;
7652                 }
7653         }
7654 }
7655
7656 class SimplePie_Rating
7657 {
7658         var $scheme;
7659         var $value;
7660
7661         // Constructor, used to input the data
7662         function SimplePie_Rating($scheme = null, $value = null)
7663         {
7664                 $this->scheme = $scheme;
7665                 $this->value = $value;
7666         }
7667
7668         function __toString()
7669         {
7670                 // There is no $this->data here
7671                 return md5(serialize($this));
7672         }
7673
7674         function get_scheme()
7675         {
7676                 if ($this->scheme !== null)
7677                 {
7678                         return $this->scheme;
7679                 }
7680                 else
7681                 {
7682                         return null;
7683                 }
7684         }
7685
7686         function get_value()
7687         {
7688                 if ($this->value !== null)
7689                 {
7690                         return $this->value;
7691                 }
7692                 else
7693                 {
7694                         return null;
7695                 }
7696         }
7697 }
7698
7699 class SimplePie_Restriction
7700 {
7701         var $relationship;
7702         var $type;
7703         var $value;
7704
7705         // Constructor, used to input the data
7706         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7707         {
7708                 $this->relationship = $relationship;
7709                 $this->type = $type;
7710                 $this->value = $value;
7711         }
7712
7713         function __toString()
7714         {
7715                 // There is no $this->data here
7716                 return md5(serialize($this));
7717         }
7718
7719         function get_relationship()
7720         {
7721                 if ($this->relationship !== null)
7722                 {
7723                         return $this->relationship;
7724                 }
7725                 else
7726                 {
7727                         return null;
7728                 }
7729         }
7730
7731         function get_type()
7732         {
7733                 if ($this->type !== null)
7734                 {
7735                         return $this->type;
7736                 }
7737                 else
7738                 {
7739                         return null;
7740                 }
7741         }
7742
7743         function get_value()
7744         {
7745                 if ($this->value !== null)
7746                 {
7747                         return $this->value;
7748                 }
7749                 else
7750                 {
7751                         return null;
7752                 }
7753         }
7754 }
7755
7756 /**
7757  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7758  */
7759 class SimplePie_File
7760 {
7761         var $url;
7762         var $useragent;
7763         var $success = true;
7764         var $headers = array();
7765         var $body;
7766         var $status_code;
7767         var $redirects = 0;
7768         var $error;
7769         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7770
7771         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7772         {
7773                 if (class_exists('idna_convert'))
7774                 {
7775                         $idn = new idna_convert;
7776                         $parsed = SimplePie_Misc::parse_url($url);
7777                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7778                 }
7779                 $this->url = $url;
7780                 $this->useragent = $useragent;
7781                 if (preg_match('/^http(s)?:\/\//i', $url))
7782                 {
7783                         if ($useragent === null)
7784                         {
7785                                 $useragent = ini_get('user_agent');
7786                                 $this->useragent = $useragent;
7787                         }
7788                         if (!is_array($headers))
7789                         {
7790                                 $headers = array();
7791                         }
7792                         if (!$force_fsockopen && function_exists('curl_exec'))
7793                         {
7794                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7795                                 $fp = curl_init();
7796                                 $headers2 = array();
7797                                 foreach ($headers as $key => $value)
7798                                 {
7799                                         $headers2[] = "$key: $value";
7800                                 }
7801                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7802                                 {
7803                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7804                                 }
7805                                 curl_setopt($fp, CURLOPT_URL, $url);
7806                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7807                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7808                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7809                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7810                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7811                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7812                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7813                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7814                                 {
7815                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7816                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7817                                 }
7818
7819                                 $this->headers = curl_exec($fp);
7820                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7821                                 {
7822                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7823                                         $this->headers = curl_exec($fp);
7824                                 }
7825                                 if (curl_errno($fp))
7826                                 {
7827                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7828                                         $this->success = false;
7829                                 }
7830                                 else
7831                                 {
7832                                         $info = curl_getinfo($fp);
7833                                         curl_close($fp);
7834                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7835                                         $this->headers = array_pop($this->headers);
7836                                         $parser = new SimplePie_HTTP_Parser($this->headers);
7837                                         if ($parser->parse())
7838                                         {
7839                                                 $this->headers = $parser->headers;
7840                                                 $this->body = $parser->body;
7841                                                 $this->status_code = $parser->status_code;
7842                                                 if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7843                                                 {
7844                                                         $this->redirects++;
7845                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7846                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7847                                                 }
7848                                         }
7849                                 }
7850                         }
7851                         else
7852                         {
7853                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7854                                 $url_parts = parse_url($url);
7855                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7856                                 {
7857                                         $url_parts['host'] = "ssl://$url_parts[host]";
7858                                         $url_parts['port'] = 443;
7859                                 }
7860                                 if (!isset($url_parts['port']))
7861                                 {
7862                                         $url_parts['port'] = 80;
7863                                 }
7864                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7865                                 if (!$fp)
7866                                 {
7867                                         $this->error = 'fsockopen error: ' . $errstr;
7868                                         $this->success = false;
7869                                 }
7870                                 else
7871                                 {
7872                                         stream_set_timeout($fp, $timeout);
7873                                         if (isset($url_parts['path']))
7874                                         {
7875                                                 if (isset($url_parts['query']))
7876                                                 {
7877                                                         $get = "$url_parts[path]?$url_parts[query]";
7878                                                 }
7879                                                 else
7880                                                 {
7881                                                         $get = $url_parts['path'];
7882                                                 }
7883                                         }
7884                                         else
7885                                         {
7886                                                 $get = '/';
7887                                         }
7888                                         $out = "GET $get HTTP/1.0\r\n";
7889                                         $out .= "Host: $url_parts[host]\r\n";
7890                                         $out .= "User-Agent: $useragent\r\n";
7891                                         if (extension_loaded('zlib'))
7892                                         {
7893                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7894                                         }
7895
7896                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7897                                         {
7898                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7899                                         }
7900                                         foreach ($headers as $key => $value)
7901                                         {
7902                                                 $out .= "$key: $value\r\n";
7903                                         }
7904                                         $out .= "Connection: Close\r\n\r\n";
7905                                         fwrite($fp, $out);
7906
7907                                         $info = stream_get_meta_data($fp);
7908
7909                                         $this->headers = '';
7910                                         while (!$info['eof'] && !$info['timed_out'])
7911                                         {
7912                                                 $this->headers .= fread($fp, 1160);
7913                                                 $info = stream_get_meta_data($fp);
7914                                         }
7915                                         if (!$info['timed_out'])
7916                                         {
7917                                                 $parser = new SimplePie_HTTP_Parser($this->headers);
7918                                                 if ($parser->parse())
7919                                                 {
7920                                                         $this->headers = $parser->headers;
7921                                                         $this->body = $parser->body;
7922                                                         $this->status_code = $parser->status_code;
7923                                                         if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7924                                                         {
7925                                                                 $this->redirects++;
7926                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7927                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7928                                                         }
7929                                                         if (isset($this->headers['content-encoding']))
7930                                                         {
7931                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7932                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7933                                                                 {
7934                                                                         case 'gzip':
7935                                                                         case 'x-gzip':
7936                                                                                 $decoder = new SimplePie_gzdecode($this->body);
7937                                                                                 if (!$decoder->parse())
7938                                                                                 {
7939                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7940                                                                                         $this->success = false;
7941                                                                                 }
7942                                                                                 else
7943                                                                                 {
7944                                                                                         $this->body = $decoder->data;
7945                                                                                 }
7946                                                                                 break;
7947
7948                                                                         case 'deflate':
7949                                                                                 if (($body = gzuncompress($this->body)) === false)
7950                                                                                 {
7951                                                                                         if (($body = gzinflate($this->body)) === false)
7952                                                                                         {
7953                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7954                                                                                                 $this->success = false;
7955                                                                                         }
7956                                                                                 }
7957                                                                                 $this->body = $body;
7958                                                                                 break;
7959
7960                                                                         default:
7961                                                                                 $this->error = 'Unknown content coding';
7962                                                                                 $this->success = false;
7963                                                                 }
7964                                                         }
7965                                                 }
7966                                         }
7967                                         else
7968                                         {
7969                                                 $this->error = 'fsocket timed out';
7970                                                 $this->success = false;
7971                                         }
7972                                         fclose($fp);
7973                                 }
7974                         }
7975                 }
7976                 else
7977                 {
7978                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7979                         if (!$this->body = file_get_contents($url))
7980                         {
7981                                 $this->error = 'file_get_contents could not read the file';
7982                                 $this->success = false;
7983                         }
7984                 }
7985         }
7986 }
7987
7988 /**
7989  * HTTP Response Parser
7990  *
7991  * @package SimplePie
7992  */
7993 class SimplePie_HTTP_Parser
7994 {
7995         /**
7996          * HTTP Version
7997          *
7998          * @access public
7999          * @var float
8000          */
8001         var $http_version = 0.0;
8002
8003         /**
8004          * Status code
8005          *
8006          * @access public
8007          * @var int
8008          */
8009         var $status_code = 0;
8010
8011         /**
8012          * Reason phrase
8013          *
8014          * @access public
8015          * @var string
8016          */
8017         var $reason = '';
8018
8019         /**
8020          * Key/value pairs of the headers
8021          *
8022          * @access public
8023          * @var array
8024          */
8025         var $headers = array();
8026
8027         /**
8028          * Body of the response
8029          *
8030          * @access public
8031          * @var string
8032          */
8033         var $body = '';
8034
8035         /**
8036          * Current state of the state machine
8037          *
8038          * @access private
8039          * @var string
8040          */
8041         var $state = 'http_version';
8042
8043         /**
8044          * Input data
8045          *
8046          * @access private
8047          * @var string
8048          */
8049         var $data = '';
8050
8051         /**
8052          * Input data length (to avoid calling strlen() everytime this is needed)
8053          *
8054          * @access private
8055          * @var int
8056          */
8057         var $data_length = 0;
8058
8059         /**
8060          * Current position of the pointer
8061          *
8062          * @var int
8063          * @access private
8064          */
8065         var $position = 0;
8066
8067         /**
8068          * Name of the hedaer currently being parsed
8069          *
8070          * @access private
8071          * @var string
8072          */
8073         var $name = '';
8074
8075         /**
8076          * Value of the hedaer currently being parsed
8077          *
8078          * @access private
8079          * @var string
8080          */
8081         var $value = '';
8082
8083         /**
8084          * Create an instance of the class with the input data
8085          *
8086          * @access public
8087          * @param string $data Input data
8088          */
8089         function SimplePie_HTTP_Parser($data)
8090         {
8091                 $this->data = $data;
8092                 $this->data_length = strlen($this->data);
8093         }
8094
8095         /**
8096          * Parse the input data
8097          *
8098          * @access public
8099          * @return bool true on success, false on failure
8100          */
8101         function parse()
8102         {
8103                 while ($this->state && $this->state !== 'emit' && $this->has_data())
8104                 {
8105                         $state = $this->state;
8106                         $this->$state();
8107                 }
8108                 $this->data = '';
8109                 if ($this->state === 'emit' || $this->state === 'body')
8110                 {
8111                         return true;
8112                 }
8113                 else
8114                 {
8115                         $this->http_version = '';
8116                         $this->status_code = '';
8117                         $this->reason = '';
8118                         $this->headers = array();
8119                         $this->body = '';
8120                         return false;
8121                 }
8122         }
8123
8124         /**
8125          * Check whether there is data beyond the pointer
8126          *
8127          * @access private
8128          * @return bool true if there is further data, false if not
8129          */
8130         function has_data()
8131         {
8132                 return (bool) ($this->position < $this->data_length);
8133         }
8134
8135         /**
8136          * See if the next character is LWS
8137          *
8138          * @access private
8139          * @return bool true if the next character is LWS, false if not
8140          */
8141         function is_linear_whitespace()
8142         {
8143                 return (bool) ($this->data[$this->position] === "\x09"
8144                         || $this->data[$this->position] === "\x20"
8145                         || ($this->data[$this->position] === "\x0A"
8146                                 && isset($this->data[$this->position + 1])
8147                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8148         }
8149
8150         /**
8151          * Parse the HTTP version
8152          *
8153          * @access private
8154          */
8155         function http_version()
8156         {
8157                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8158                 {
8159                         $len = strspn($this->data, '0123456789.', 5);
8160                         $this->http_version = substr($this->data, 5, $len);
8161                         $this->position += 5 + $len;
8162                         if (substr_count($this->http_version, '.') <= 1)
8163                         {
8164                                 $this->http_version = (float) $this->http_version;
8165                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8166                                 $this->state = 'status';
8167                         }
8168                         else
8169                         {
8170                                 $this->state = false;
8171                         }
8172                 }
8173                 else
8174                 {
8175                         $this->state = false;
8176                 }
8177         }
8178
8179         /**
8180          * Parse the status code
8181          *
8182          * @access private
8183          */
8184         function status()
8185         {
8186                 if ($len = strspn($this->data, '0123456789', $this->position))
8187                 {
8188                         $this->status_code = (int) substr($this->data, $this->position, $len);
8189                         $this->position += $len;
8190                         $this->state = 'reason';
8191                 }
8192                 else
8193                 {
8194                         $this->state = false;
8195                 }
8196         }
8197
8198         /**
8199          * Parse the reason phrase
8200          *
8201          * @access private
8202          */
8203         function reason()
8204         {
8205                 $len = strcspn($this->data, "\x0A", $this->position);
8206                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8207                 $this->position += $len + 1;
8208                 $this->state = 'new_line';
8209         }
8210
8211         /**
8212          * Deal with a new line, shifting data around as needed
8213          *
8214          * @access private
8215          */
8216         function new_line()
8217         {
8218                 $this->value = trim($this->value, "\x0D\x20");
8219                 if ($this->name !== '' && $this->value !== '')
8220                 {
8221                         $this->name = strtolower($this->name);
8222                         if (isset($this->headers[$this->name]))
8223                         {
8224                                 $this->headers[$this->name] .= ', ' . $this->value;
8225                         }
8226                         else
8227                         {
8228                                 $this->headers[$this->name] = $this->value;
8229                         }
8230                 }
8231                 $this->name = '';
8232                 $this->value = '';
8233                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8234                 {
8235                         $this->position += 2;
8236                         $this->state = 'body';
8237                 }
8238                 elseif ($this->data[$this->position] === "\x0A")
8239                 {
8240                         $this->position++;
8241                         $this->state = 'body';
8242                 }
8243                 else
8244                 {
8245                         $this->state = 'name';
8246                 }
8247         }
8248
8249         /**
8250          * Parse a header name
8251          *
8252          * @access private
8253          */
8254         function name()
8255         {
8256                 $len = strcspn($this->data, "\x0A:", $this->position);
8257                 if (isset($this->data[$this->position + $len]))
8258                 {
8259                         if ($this->data[$this->position + $len] === "\x0A")
8260                         {
8261                                 $this->position += $len;
8262                                 $this->state = 'new_line';
8263                         }
8264                         else
8265                         {
8266                                 $this->name = substr($this->data, $this->position, $len);
8267                                 $this->position += $len + 1;
8268                                 $this->state = 'value';
8269                         }
8270                 }
8271                 else
8272                 {
8273                         $this->state = false;
8274                 }
8275         }
8276
8277         /**
8278          * Parse LWS, replacing consecutive LWS characters with a single space
8279          *
8280          * @access private
8281          */
8282         function linear_whitespace()
8283         {
8284                 do
8285                 {
8286                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8287                         {
8288                                 $this->position += 2;
8289                         }
8290                         elseif ($this->data[$this->position] === "\x0A")
8291                         {
8292                                 $this->position++;
8293                         }
8294                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8295                 } while ($this->has_data() && $this->is_linear_whitespace());
8296                 $this->value .= "\x20";
8297         }
8298
8299         /**
8300          * See what state to move to while within non-quoted header values
8301          *
8302          * @access private
8303          */
8304         function value()
8305         {
8306                 if ($this->is_linear_whitespace())
8307                 {
8308                         $this->linear_whitespace();
8309                 }
8310                 else
8311                 {
8312                         switch ($this->data[$this->position])
8313                         {
8314                                 case '"':
8315                                         $this->position++;
8316                                         $this->state = 'quote';
8317                                         break;
8318
8319                                 case "\x0A":
8320                                         $this->position++;
8321                                         $this->state = 'new_line';
8322                                         break;
8323
8324                                 default:
8325                                         $this->state = 'value_char';
8326                                         break;
8327                         }
8328                 }
8329         }
8330
8331         /**
8332          * Parse a header value while outside quotes
8333          *
8334          * @access private
8335          */
8336         function value_char()
8337         {
8338                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8339                 $this->value .= substr($this->data, $this->position, $len);
8340                 $this->position += $len;
8341                 $this->state = 'value';
8342         }
8343
8344         /**
8345          * See what state to move to while within quoted header values
8346          *
8347          * @access private
8348          */
8349         function quote()
8350         {
8351                 if ($this->is_linear_whitespace())
8352                 {
8353                         $this->linear_whitespace();
8354                 }
8355                 else
8356                 {
8357                         switch ($this->data[$this->position])
8358                         {
8359                                 case '"':
8360                                         $this->position++;
8361                                         $this->state = 'value';
8362                                         break;
8363
8364                                 case "\x0A":
8365                                         $this->position++;
8366                                         $this->state = 'new_line';
8367                                         break;
8368
8369                                 case '\\':
8370                                         $this->position++;
8371                                         $this->state = 'quote_escaped';
8372                                         break;
8373
8374                                 default:
8375                                         $this->state = 'quote_char';
8376                                         break;
8377                         }
8378                 }
8379         }
8380
8381         /**
8382          * Parse a header value while within quotes
8383          *
8384          * @access private
8385          */
8386         function quote_char()
8387         {
8388                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8389                 $this->value .= substr($this->data, $this->position, $len);
8390                 $this->position += $len;
8391                 $this->state = 'value';
8392         }
8393
8394         /**
8395          * Parse an escaped character within quotes
8396          *
8397          * @access private
8398          */
8399         function quote_escaped()
8400         {
8401                 $this->value .= $this->data[$this->position];
8402                 $this->position++;
8403                 $this->state = 'quote';
8404         }
8405
8406         /**
8407          * Parse the body
8408          *
8409          * @access private
8410          */
8411         function body()
8412         {
8413                 $this->body = substr($this->data, $this->position);
8414                 $this->state = 'emit';
8415         }
8416 }
8417
8418 /**
8419  * gzdecode
8420  *
8421  * @package SimplePie
8422  */
8423 class SimplePie_gzdecode
8424 {
8425         /**
8426          * Compressed data
8427          *
8428          * @access private
8429          * @see gzdecode::$data
8430          */
8431         var $compressed_data;
8432
8433         /**
8434          * Size of compressed data
8435          *
8436          * @access private
8437          */
8438         var $compressed_size;
8439
8440         /**
8441          * Minimum size of a valid gzip string
8442          *
8443          * @access private
8444          */
8445         var $min_compressed_size = 18;
8446
8447         /**
8448          * Current position of pointer
8449          *
8450          * @access private
8451          */
8452         var $position = 0;
8453
8454         /**
8455          * Flags (FLG)
8456          *
8457          * @access private
8458          */
8459         var $flags;
8460
8461         /**
8462          * Uncompressed data
8463          *
8464          * @access public
8465          * @see gzdecode::$compressed_data
8466          */
8467         var $data;
8468
8469         /**
8470          * Modified time
8471          *
8472          * @access public
8473          */
8474         var $MTIME;
8475
8476         /**
8477          * Extra Flags
8478          *
8479          * @access public
8480          */
8481         var $XFL;
8482
8483         /**
8484          * Operating System
8485          *
8486          * @access public
8487          */
8488         var $OS;
8489
8490         /**
8491          * Subfield ID 1
8492          *
8493          * @access public
8494          * @see gzdecode::$extra_field
8495          * @see gzdecode::$SI2
8496          */
8497         var $SI1;
8498
8499         /**
8500          * Subfield ID 2
8501          *
8502          * @access public
8503          * @see gzdecode::$extra_field
8504          * @see gzdecode::$SI1
8505          */
8506         var $SI2;
8507
8508         /**
8509          * Extra field content
8510          *
8511          * @access public
8512          * @see gzdecode::$SI1
8513          * @see gzdecode::$SI2
8514          */
8515         var $extra_field;
8516
8517         /**
8518          * Original filename
8519          *
8520          * @access public
8521          */
8522         var $filename;
8523
8524         /**
8525          * Human readable comment
8526          *
8527          * @access public
8528          */
8529         var $comment;
8530
8531         /**
8532          * Don't allow anything to be set
8533          *
8534          * @access public
8535          */
8536         function __set($name, $value)
8537         {
8538                 trigger_error("Cannot write property $name", E_USER_ERROR);
8539         }
8540
8541         /**
8542          * Set the compressed string and related properties
8543          *
8544          * @access public
8545          */
8546         function SimplePie_gzdecode($data)
8547         {
8548                 $this->compressed_data = $data;
8549                 $this->compressed_size = strlen($data);
8550         }
8551
8552         /**
8553          * Decode the GZIP stream
8554          *
8555          * @access public
8556          */
8557         function parse()
8558         {
8559                 if ($this->compressed_size >= $this->min_compressed_size)
8560                 {
8561                         // Check ID1, ID2, and CM
8562                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8563                         {
8564                                 return false;
8565                         }
8566
8567                         // Get the FLG (FLaGs)
8568                         $this->flags = ord($this->compressed_data[3]);
8569
8570                         // FLG bits above (1 << 4) are reserved
8571                         if ($this->flags > 0x1F)
8572                         {
8573                                 return false;
8574                         }
8575
8576                         // Advance the pointer after the above
8577                         $this->position += 4;
8578
8579                         // MTIME
8580                         $mtime = substr($this->compressed_data, $this->position, 4);
8581                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8582                         if (current(unpack('S', "\x00\x01")) === 1)
8583                         {
8584                                 $mtime = strrev($mtime);
8585                         }
8586                         $this->MTIME = current(unpack('l', $mtime));
8587                         $this->position += 4;
8588
8589                         // Get the XFL (eXtra FLags)
8590                         $this->XFL = ord($this->compressed_data[$this->position++]);
8591
8592                         // Get the OS (Operating System)
8593                         $this->OS = ord($this->compressed_data[$this->position++]);
8594
8595                         // Parse the FEXTRA
8596                         if ($this->flags & 4)
8597                         {
8598                                 // Read subfield IDs
8599                                 $this->SI1 = $this->compressed_data[$this->position++];
8600                                 $this->SI2 = $this->compressed_data[$this->position++];
8601
8602                                 // SI2 set to zero is reserved for future use
8603                                 if ($this->SI2 === "\x00")
8604                                 {
8605                                         return false;
8606                                 }
8607
8608                                 // Get the length of the extra field
8609                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8610                                 $position += 2;
8611
8612                                 // Check the length of the string is still valid
8613                                 $this->min_compressed_size += $len + 4;
8614                                 if ($this->compressed_size >= $this->min_compressed_size)
8615                                 {
8616                                         // Set the extra field to the given data
8617                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8618                                         $this->position += $len;
8619                                 }
8620                                 else
8621                                 {
8622                                         return false;
8623                                 }
8624                         }
8625
8626                         // Parse the FNAME
8627                         if ($this->flags & 8)
8628                         {
8629                                 // Get the length of the filename
8630                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8631
8632                                 // Check the length of the string is still valid
8633                                 $this->min_compressed_size += $len + 1;
8634                                 if ($this->compressed_size >= $this->min_compressed_size)
8635                                 {
8636                                         // Set the original filename to the given string
8637                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8638                                         $this->position += $len + 1;
8639                                 }
8640                                 else
8641                                 {
8642                                         return false;
8643                                 }
8644                         }
8645
8646                         // Parse the FCOMMENT
8647                         if ($this->flags & 16)
8648                         {
8649                                 // Get the length of the comment
8650                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8651
8652                                 // Check the length of the string is still valid
8653                                 $this->min_compressed_size += $len + 1;
8654                                 if ($this->compressed_size >= $this->min_compressed_size)
8655                                 {
8656                                         // Set the original comment to the given string
8657                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8658                                         $this->position += $len + 1;
8659                                 }
8660                                 else
8661                                 {
8662                                         return false;
8663                                 }
8664                         }
8665
8666                         // Parse the FHCRC
8667                         if ($this->flags & 2)
8668                         {
8669                                 // Check the length of the string is still valid
8670                                 $this->min_compressed_size += $len + 2;
8671                                 if ($this->compressed_size >= $this->min_compressed_size)
8672                                 {
8673                                         // Read the CRC
8674                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8675
8676                                         // Check the CRC matches
8677                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8678                                         {
8679                                                 $this->position += 2;
8680                                         }
8681                                         else
8682                                         {
8683                                                 return false;
8684                                         }
8685                                 }
8686                                 else
8687                                 {
8688                                         return false;
8689                                 }
8690                         }
8691
8692                         // Decompress the actual data
8693                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8694                         {
8695                                 return false;
8696                         }
8697                         else
8698                         {
8699                                 $this->position = $this->compressed_size - 8;
8700                         }
8701
8702                         // Check CRC of data
8703                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8704                         $this->position += 4;
8705                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8706                         {
8707                                 return false;
8708                         }*/
8709
8710                         // Check ISIZE of data
8711                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8712                         $this->position += 4;
8713                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8714                         {
8715                                 return false;
8716                         }
8717
8718                         // Wow, against all odds, we've actually got a valid gzip string
8719                         return true;
8720                 }
8721                 else
8722                 {
8723                         return false;
8724                 }
8725         }
8726 }
8727
8728 class SimplePie_Cache
8729 {
8730         /**
8731          * Don't call the constructor. Please.
8732          *
8733          * @access private
8734          */
8735         function SimplePie_Cache()
8736         {
8737                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8738         }
8739
8740         /**
8741          * Create a new SimplePie_Cache object
8742          *
8743          * @static
8744          * @access public
8745          */
8746         function create($location, $filename, $extension)
8747         {
8748                 $location_iri = new SimplePie_IRI($location);
8749                 switch ($location_iri->get_scheme())
8750                 {
8751                         case 'mysql':
8752                                 if (extension_loaded('mysql'))
8753                                 {
8754                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8755                                 }
8756                                 break;
8757
8758                         default:
8759                                 return new SimplePie_Cache_File($location, $filename, $extension);
8760                 }
8761         }
8762 }
8763
8764 class SimplePie_Cache_File
8765 {
8766         var $location;
8767         var $filename;
8768         var $extension;
8769         var $name;
8770
8771         function SimplePie_Cache_File($location, $filename, $extension)
8772         {
8773                 $this->location = $location;
8774                 $this->filename = $filename;
8775                 $this->extension = $extension;
8776                 $this->name = "$this->location/$this->filename.$this->extension";
8777         }
8778
8779         function save($data)
8780         {
8781                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8782                 {
8783                         if (is_a($data, 'SimplePie'))
8784                         {
8785                                 $data = $data->data;
8786                         }
8787
8788                         $data = serialize($data);
8789
8790                         if (function_exists('file_put_contents'))
8791                         {
8792                                 return (bool) file_put_contents($this->name, $data);
8793                         }
8794                         else
8795                         {
8796                                 $fp = fopen($this->name, 'wb');
8797                                 if ($fp)
8798                                 {
8799                                         fwrite($fp, $data);
8800                                         fclose($fp);
8801                                         return true;
8802                                 }
8803                         }
8804                 }
8805                 return false;
8806         }
8807
8808         function load()
8809         {
8810                 if (file_exists($this->name) && is_readable($this->name))
8811                 {
8812                         return unserialize(file_get_contents($this->name));
8813                 }
8814                 return false;
8815         }
8816
8817         function mtime()
8818         {
8819                 if (file_exists($this->name))
8820                 {
8821                         return filemtime($this->name);
8822                 }
8823                 return false;
8824         }
8825
8826         function touch()
8827         {
8828                 if (file_exists($this->name))
8829                 {
8830                         return touch($this->name);
8831                 }
8832                 return false;
8833         }
8834
8835         function unlink()
8836         {
8837                 if (file_exists($this->name))
8838                 {
8839                         return unlink($this->name);
8840                 }
8841                 return false;
8842         }
8843 }
8844
8845 class SimplePie_Cache_DB
8846 {
8847         function prepare_simplepie_object_for_cache($data)
8848         {
8849                 $items = $data->get_items();
8850                 $items_by_id = array();
8851
8852                 if (!empty($items))
8853                 {
8854                         foreach ($items as $item)
8855                         {
8856                                 $items_by_id[$item->get_id()] = $item;
8857                         }
8858
8859                         if (count($items_by_id) !== count($items))
8860                         {
8861                                 $items_by_id = array();
8862                                 foreach ($items as $item)
8863                                 {
8864                                         $items_by_id[$item->get_id(true)] = $item;
8865                                 }
8866                         }
8867
8868                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8869                         {
8870                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8871                         }
8872                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8873                         {
8874                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8875                         }
8876                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8877                         {
8878                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8879                         }
8880                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8881                         {
8882                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8883                         }
8884                         else
8885                         {
8886                                 $channel = null;
8887                         }
8888
8889                         if ($channel !== null)
8890                         {
8891                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8892                                 {
8893                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8894                                 }
8895                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8896                                 {
8897                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8898                                 }
8899                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8900                                 {
8901                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8902                                 }
8903                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8904                                 {
8905                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8906                                 }
8907                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8908                                 {
8909                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8910                                 }
8911                         }
8912                         if (isset($data->data['items']))
8913                         {
8914                                 unset($data->data['items']);
8915                         }
8916                         if (isset($data->data['ordered_items']))
8917                         {
8918                                 unset($data->data['ordered_items']);
8919                         }
8920                 }
8921                 return array(serialize($data->data), $items_by_id);
8922         }
8923 }
8924
8925 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8926 {
8927         var $mysql;
8928         var $options;
8929         var $id;
8930
8931         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8932         {
8933                 $host = $mysql_location->get_host();
8934                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8935                 {
8936                         $server = ':' . substr($host, 5, -1);
8937                 }
8938                 else
8939                 {
8940                         $server = $host;
8941                         if ($mysql_location->get_port() !== null)
8942                         {
8943                                 $server .= ':' . $mysql_location->get_port();
8944                         }
8945                 }
8946
8947                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8948                 {
8949                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8950                 }
8951                 else
8952                 {
8953                         $username = $mysql_location->get_userinfo();
8954                         $password = null;
8955                 }
8956
8957                 if ($this->mysql = mysql_connect($server, $username, $password))
8958                 {
8959                         $this->id = $name . $extension;
8960                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8961                         if (!isset($this->options['prefix'][0]))
8962                         {
8963                                 $this->options['prefix'][0] = '';
8964                         }
8965
8966                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8967                                 && mysql_query('SET NAMES utf8')
8968                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8969                         {
8970                                 $db = array();
8971                                 while ($row = mysql_fetch_row($query))
8972                                 {
8973                                         $db[] = $row[0];
8974                                 }
8975
8976                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8977                                 {
8978                                         if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
8979                                         {
8980                                                 $this->mysql = null;
8981                                         }
8982                                 }
8983
8984                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8985                                 {
8986                                         if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
8987                                         {
8988                                                 $this->mysql = null;
8989                                         }
8990                                 }
8991                         }
8992                         else
8993                         {
8994                                 $this->mysql = null;
8995                         }
8996                 }
8997         }
8998
8999         function save($data)
9000         {
9001                 if ($this->mysql)
9002                 {
9003                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
9004
9005                         if (is_a($data, 'SimplePie'))
9006                         {
9007                                 if (SIMPLEPIE_PHP5)
9008                                 {
9009                                         // This keyword needs to defy coding standards for PHP4 compatibility
9010                                         $data = clone($data);
9011                                 }
9012
9013                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
9014
9015                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9016                                 {
9017                                         if (mysql_num_rows($query))
9018                                         {
9019                                                 $items = count($prepared[1]);
9020                                                 if ($items)
9021                                                 {
9022                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9023                                                 }
9024                                                 else
9025                                                 {
9026                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9027                                                 }
9028
9029                                                 if (!mysql_query($sql, $this->mysql))
9030                                                 {
9031                                                         return false;
9032                                                 }
9033                                         }
9034                                         elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
9035                                         {
9036                                                 return false;
9037                                         }
9038
9039                                         $ids = array_keys($prepared[1]);
9040                                         if (!empty($ids))
9041                                         {
9042                                                 foreach ($ids as $id)
9043                                                 {
9044                                                         $database_ids[] = mysql_real_escape_string($id);
9045                                                 }
9046
9047                                                 if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
9048                                                 {
9049                                                         $existing_ids = array();
9050                                                         while ($row = mysql_fetch_row($query))
9051                                                         {
9052                                                                 $existing_ids[] = $row[0];
9053                                                         }
9054
9055                                                         $new_ids = array_diff($ids, $existing_ids);
9056
9057                                                         foreach ($new_ids as $new_id)
9058                                                         {
9059                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
9060                                                                 {
9061                                                                         $date = time();
9062                                                                 }
9063
9064                                                                 if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
9065                                                                 {
9066                                                                         return false;
9067                                                                 }
9068                                                         }
9069                                                         return true;
9070                                                 }
9071                                         }
9072                                         else
9073                                         {
9074                                                 return true;
9075                                         }
9076                                 }
9077                         }
9078                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9079                         {
9080                                 if (mysql_num_rows($query))
9081                                 {
9082                                         if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
9083                                         {
9084                                                 return true;
9085                                         }
9086                                 }
9087                                 elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
9088                                 {
9089                                         return true;
9090                                 }
9091                         }
9092                 }
9093                 return false;
9094         }
9095
9096         function load()
9097         {
9098                 if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9099                 {
9100                         $data = unserialize($row[1]);
9101
9102                         if (isset($this->options['items'][0]))
9103                         {
9104                                 $items = (int) $this->options['items'][0];
9105                         }
9106                         else
9107                         {
9108                                 $items = (int) $row[0];
9109                         }
9110
9111                         if ($items !== 0)
9112                         {
9113                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9114                                 {
9115                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9116                                 }
9117                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9118                                 {
9119                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9120                                 }
9121                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9122                                 {
9123                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9124                                 }
9125                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9126                                 {
9127                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9128                                 }
9129                                 else
9130                                 {
9131                                         $feed = null;
9132                                 }
9133
9134                                 if ($feed !== null)
9135                                 {
9136                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9137                                         if ($items > 0)
9138                                         {
9139                                                 $sql .= ' LIMIT ' . $items;
9140                                         }
9141
9142                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9143                                         {
9144                                                 while ($row = mysql_fetch_row($query))
9145                                                 {
9146                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9147                                                 }
9148                                         }
9149                                         else
9150                                         {
9151                                                 return false;
9152                                         }
9153                                 }
9154                         }
9155                         return $data;
9156                 }
9157                 return false;
9158         }
9159
9160         function mtime()
9161         {
9162                 if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9163                 {
9164                         return $row[0];
9165                 }
9166                 else
9167                 {
9168                         return false;
9169                 }
9170         }
9171
9172         function touch()
9173         {
9174                 if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
9175                 {
9176                         return true;
9177                 }
9178                 else
9179                 {
9180                         return false;
9181                 }
9182         }
9183
9184         function unlink()
9185         {
9186                 if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
9187                 {
9188                         return true;
9189                 }
9190                 else
9191                 {
9192                         return false;
9193                 }
9194         }
9195 }
9196
9197 class SimplePie_Misc
9198 {
9199         function time_hms($seconds)
9200         {
9201                 $time = '';
9202
9203                 $hours = floor($seconds / 3600);
9204                 $remainder = $seconds % 3600;
9205                 if ($hours > 0)
9206                 {
9207                         $time .= $hours.':';
9208                 }
9209
9210                 $minutes = floor($remainder / 60);
9211                 $seconds = $remainder % 60;
9212                 if ($minutes < 10 && $hours > 0)
9213                 {
9214                         $minutes = '0' . $minutes;
9215                 }
9216                 if ($seconds < 10)
9217                 {
9218                         $seconds = '0' . $seconds;
9219                 }
9220
9221                 $time .= $minutes.':';
9222                 $time .= $seconds;
9223
9224                 return $time;
9225         }
9226
9227         function absolutize_url($relative, $base)
9228         {
9229                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9230                 return $iri->get_iri();
9231         }
9232
9233         function remove_dot_segments($input)
9234         {
9235                 $output = '';
9236                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9237                 {
9238                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9239                         if (strpos($input, '../') === 0)
9240                         {
9241                                 $input = substr($input, 3);
9242                         }
9243                         elseif (strpos($input, './') === 0)
9244                         {
9245                                 $input = substr($input, 2);
9246                         }
9247                         // 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,
9248                         elseif (strpos($input, '/./') === 0)
9249                         {
9250                                 $input = substr_replace($input, '/', 0, 3);
9251                         }
9252                         elseif ($input === '/.')
9253                         {
9254                                 $input = '/';
9255                         }
9256                         // 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,
9257                         elseif (strpos($input, '/../') === 0)
9258                         {
9259                                 $input = substr_replace($input, '/', 0, 4);
9260                                 $output = substr_replace($output, '', strrpos($output, '/'));
9261                         }
9262                         elseif ($input === '/..')
9263                         {
9264                                 $input = '/';
9265                                 $output = substr_replace($output, '', strrpos($output, '/'));
9266                         }
9267                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9268                         elseif ($input === '.' || $input === '..')
9269                         {
9270                                 $input = '';
9271                         }
9272                         // 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
9273                         elseif (($pos = strpos($input, '/', 1)) !== false)
9274                         {
9275                                 $output .= substr($input, 0, $pos);
9276                                 $input = substr_replace($input, '', 0, $pos);
9277                         }
9278                         else
9279                         {
9280                                 $output .= $input;
9281                                 $input = '';
9282                         }
9283                 }
9284                 return $output . $input;
9285         }
9286
9287         function get_element($realname, $string)
9288         {
9289                 $return = array();
9290                 $name = preg_quote($realname, '/');
9291                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9292                 {
9293                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9294                         {
9295                                 $return[$i]['tag'] = $realname;
9296                                 $return[$i]['full'] = $matches[$i][0][0];
9297                                 $return[$i]['offset'] = $matches[$i][0][1];
9298                                 if (strlen($matches[$i][3][0]) <= 2)
9299                                 {
9300                                         $return[$i]['self_closing'] = true;
9301                                 }
9302                                 else
9303                                 {
9304                                         $return[$i]['self_closing'] = false;
9305                                         $return[$i]['content'] = $matches[$i][4][0];
9306                                 }
9307                                 $return[$i]['attribs'] = array();
9308                                 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))
9309                                 {
9310                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9311                                         {
9312                                                 if (count($attribs[$j]) === 2)
9313                                                 {
9314                                                         $attribs[$j][2] = $attribs[$j][1];
9315                                                 }
9316                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9317                                         }
9318                                 }
9319                         }
9320                 }
9321                 return $return;
9322         }
9323
9324         function element_implode($element)
9325         {
9326                 $full = "<$element[tag]";
9327                 foreach ($element['attribs'] as $key => $value)
9328                 {
9329                         $key = strtolower($key);
9330                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9331                 }
9332                 if ($element['self_closing'])
9333                 {
9334                         $full .= ' />';
9335                 }
9336                 else
9337                 {
9338                         $full .= ">$element[content]</$element[tag]>";
9339                 }
9340                 return $full;
9341         }
9342
9343         function error($message, $level, $file, $line)
9344         {
9345                 if ((ini_get('error_reporting') & $level) > 0)
9346                 {
9347                         switch ($level)
9348                         {
9349                                 case E_USER_ERROR:
9350                                         $note = 'PHP Error';
9351                                         break;
9352                                 case E_USER_WARNING:
9353                                         $note = 'PHP Warning';
9354                                         break;
9355                                 case E_USER_NOTICE:
9356                                         $note = 'PHP Notice';
9357                                         break;
9358                                 default:
9359                                         $note = 'Unknown Error';
9360                                         break;
9361                         }
9362
9363                         $log_error = true;
9364                         if (!function_exists('error_log'))
9365                         {
9366                                 $log_error = false;
9367                         }
9368
9369                         $log_file = @ini_get('error_log');
9370                         if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9371                         {
9372                                 $log_error = false;
9373                         }
9374
9375                         if ($log_error)
9376                         {
9377                                 @error_log("$note: $message in $file on line $line", 0);
9378                         }
9379                 }
9380
9381                 return $message;
9382         }
9383
9384         /**
9385          * If a file has been cached, retrieve and display it.
9386          *
9387          * This is most useful for caching images (get_favicon(), etc.),
9388          * however it works for all cached files.  This WILL NOT display ANY
9389          * file/image/page/whatever, but rather only display what has already
9390          * been cached by SimplePie.
9391          *
9392          * @access public
9393          * @see SimplePie::get_favicon()
9394          * @param str $identifier_url URL that is used to identify the content.
9395          * This may or may not be the actual URL of the live content.
9396          * @param str $cache_location Location of SimplePie's cache.  Defaults
9397          * to './cache'.
9398          * @param str $cache_extension The file extension that the file was
9399          * cached with.  Defaults to 'spc'.
9400          * @param str $cache_class Name of the cache-handling class being used
9401          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9402          * as-is unless you've overloaded the class.
9403          * @param str $cache_name_function Obsolete. Exists for backwards
9404          * compatibility reasons only.
9405          */
9406         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9407         {
9408                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9409
9410                 if ($file = $cache->load())
9411                 {
9412                         if (isset($file['headers']['content-type']))
9413                         {
9414                                 header('Content-type:' . $file['headers']['content-type']);
9415                         }
9416                         else
9417                         {
9418                                 header('Content-type: application/octet-stream');
9419                         }
9420                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9421                         echo $file['body'];
9422                         exit;
9423                 }
9424
9425                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9426         }
9427
9428         function fix_protocol($url, $http = 1)
9429         {
9430                 $url = SimplePie_Misc::normalize_url($url);
9431                 $parsed = SimplePie_Misc::parse_url($url);
9432                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9433                 {
9434                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9435                 }
9436
9437                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9438                 {
9439                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9440                 }
9441
9442                 if ($http === 2 && $parsed['scheme'] !== '')
9443                 {
9444                         return "feed:$url";
9445                 }
9446                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9447                 {
9448                         return substr_replace($url, 'podcast', 0, 4);
9449                 }
9450                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9451                 {
9452                         return substr_replace($url, 'itpc', 0, 4);
9453                 }
9454                 else
9455                 {
9456                         return $url;
9457                 }
9458         }
9459
9460         function parse_url($url)
9461         {
9462                 $iri = new SimplePie_IRI($url);
9463                 return array(
9464                         'scheme' => (string) $iri->get_scheme(),
9465                         'authority' => (string) $iri->get_authority(),
9466                         'path' => (string) $iri->get_path(),
9467                         'query' => (string) $iri->get_query(),
9468                         'fragment' => (string) $iri->get_fragment()
9469                 );
9470         }
9471
9472         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9473         {
9474                 $iri = new SimplePie_IRI('');
9475                 $iri->set_scheme($scheme);
9476                 $iri->set_authority($authority);
9477                 $iri->set_path($path);
9478                 $iri->set_query($query);
9479                 $iri->set_fragment($fragment);
9480                 return $iri->get_iri();
9481         }
9482
9483         function normalize_url($url)
9484         {
9485                 $iri = new SimplePie_IRI($url);
9486                 return $iri->get_iri();
9487         }
9488
9489         function percent_encoding_normalization($match)
9490         {
9491                 $integer = hexdec($match[1]);
9492                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9493                 {
9494                         return chr($integer);
9495                 }
9496                 else
9497                 {
9498                         return strtoupper($match[0]);
9499                 }
9500         }
9501
9502         /**
9503          * Remove bad UTF-8 bytes
9504          *
9505          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9506          * FAQ: Multilingual Forms (modified to include full ASCII range)
9507          *
9508          * @author Geoffrey Sneddon
9509          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9510          * @param string $str String to remove bad UTF-8 bytes from
9511          * @return string UTF-8 string
9512          */
9513         function utf8_bad_replace($str)
9514         {
9515                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9516                 {
9517                         return $return;
9518                 }
9519                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9520                 {
9521                         return $return;
9522                 }
9523                 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))
9524                 {
9525                         return implode("\xEF\xBF\xBD", $matches[0]);
9526                 }
9527                 elseif ($str !== '')
9528                 {
9529                         return "\xEF\xBF\xBD";
9530                 }
9531                 else
9532                 {
9533                         return '';
9534                 }
9535         }
9536
9537         /**
9538          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9539          *
9540          * @static
9541          * @access public
9542          * @param string $string Windows-1252 encoded string
9543          * @return string UTF-8 encoded string
9544          */
9545         function windows_1252_to_utf8($string)
9546         {
9547                 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");
9548
9549                 return strtr($string, $convert_table);
9550         }
9551
9552         function change_encoding($data, $input, $output)
9553         {
9554                 $input = SimplePie_Misc::encoding($input);
9555                 $output = SimplePie_Misc::encoding($output);
9556
9557                 // We fail to fail on non US-ASCII bytes
9558                 if ($input === 'US-ASCII')
9559                 {
9560                         static $non_ascii_octects = '';
9561                         if (!$non_ascii_octects)
9562                         {
9563                                 for ($i = 0x80; $i <= 0xFF; $i++)
9564                                 {
9565                                         $non_ascii_octects .= chr($i);
9566                                 }
9567                         }
9568                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9569                 }
9570
9571                 // This is first, as behaviour of this is completely predictable
9572                 if ($input === 'Windows-1252' && $output === 'UTF-8')
9573                 {
9574                         return SimplePie_Misc::windows_1252_to_utf8($data);
9575                 }
9576                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9577                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9578                 {
9579                         return $return;
9580                 }
9581                 // This is last, as behaviour of this varies with OS userland and PHP version
9582                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9583                 {
9584                         return $return;
9585                 }
9586                 // If we can't do anything, just fail
9587                 else
9588                 {
9589                         return false;
9590                 }
9591         }
9592
9593         function encoding($charset)
9594         {
9595                 // Normalization from UTS #22
9596                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9597                 {
9598                         case 'adobestandardencoding':
9599                         case 'csadobestandardencoding':
9600                                 return 'Adobe-Standard-Encoding';
9601
9602                         case 'adobesymbolencoding':
9603                         case 'cshppsmath':
9604                                 return 'Adobe-Symbol-Encoding';
9605
9606                         case 'ami1251':
9607                         case 'amiga1251':
9608                                 return 'Amiga-1251';
9609
9610                         case 'ansix31101983':
9611                         case 'csat5001983':
9612                         case 'csiso99naplps':
9613                         case 'isoir99':
9614                         case 'naplps':
9615                                 return 'ANSI_X3.110-1983';
9616
9617                         case 'arabic7':
9618                         case 'asmo449':
9619                         case 'csiso89asmo449':
9620                         case 'iso9036':
9621                         case 'isoir89':
9622                                 return 'ASMO_449';
9623
9624                         case 'big5':
9625                         case 'csbig5':
9626                         case 'xxbig5':
9627                                 return 'Big5';
9628
9629                         case 'big5hkscs':
9630                                 return 'Big5-HKSCS';
9631
9632                         case 'bocu1':
9633                         case 'csbocu1':
9634                                 return 'BOCU-1';
9635
9636                         case 'brf':
9637                         case 'csbrf':
9638                                 return 'BRF';
9639
9640                         case 'bs4730':
9641                         case 'csiso4unitedkingdom':
9642                         case 'gb':
9643                         case 'iso646gb':
9644                         case 'isoir4':
9645                         case 'uk':
9646                                 return 'BS_4730';
9647
9648                         case 'bsviewdata':
9649                         case 'csiso47bsviewdata':
9650                         case 'isoir47':
9651                                 return 'BS_viewdata';
9652
9653                         case 'cesu8':
9654                         case 'cscesu8':
9655                                 return 'CESU-8';
9656
9657                         case 'ca':
9658                         case 'csa71':
9659                         case 'csaz243419851':
9660                         case 'csiso121canadian1':
9661                         case 'iso646ca':
9662                         case 'isoir121':
9663                                 return 'CSA_Z243.4-1985-1';
9664
9665                         case 'csa72':
9666                         case 'csaz243419852':
9667                         case 'csiso122canadian2':
9668                         case 'iso646ca2':
9669                         case 'isoir122':
9670                                 return 'CSA_Z243.4-1985-2';
9671
9672                         case 'csaz24341985gr':
9673                         case 'csiso123csaz24341985gr':
9674                         case 'isoir123':
9675                                 return 'CSA_Z243.4-1985-gr';
9676
9677                         case 'csiso139csn369103':
9678                         case 'csn369103':
9679                         case 'isoir139':
9680                                 return 'CSN_369103';
9681
9682                         case 'csdecmcs':
9683                         case 'dec':
9684                         case 'decmcs':
9685                                 return 'DEC-MCS';
9686
9687                         case 'csiso21german':
9688                         case 'de':
9689                         case 'din66003':
9690                         case 'iso646de':
9691                         case 'isoir21':
9692                                 return 'DIN_66003';
9693
9694                         case 'csdkus':
9695                         case 'dkus':
9696                                 return 'dk-us';
9697
9698                         case 'csiso646danish':
9699                         case 'dk':
9700                         case 'ds2089':
9701                         case 'iso646dk':
9702                                 return 'DS_2089';
9703
9704                         case 'csibmebcdicatde':
9705                         case 'ebcdicatde':
9706                                 return 'EBCDIC-AT-DE';
9707
9708                         case 'csebcdicatdea':
9709                         case 'ebcdicatdea':
9710                                 return 'EBCDIC-AT-DE-A';
9711
9712                         case 'csebcdiccafr':
9713                         case 'ebcdiccafr':
9714                                 return 'EBCDIC-CA-FR';
9715
9716                         case 'csebcdicdkno':
9717                         case 'ebcdicdkno':
9718                                 return 'EBCDIC-DK-NO';
9719
9720                         case 'csebcdicdknoa':
9721                         case 'ebcdicdknoa':
9722                                 return 'EBCDIC-DK-NO-A';
9723
9724                         case 'csebcdices':
9725                         case 'ebcdices':
9726                                 return 'EBCDIC-ES';
9727
9728                         case 'csebcdicesa':
9729                         case 'ebcdicesa':
9730                                 return 'EBCDIC-ES-A';
9731
9732                         case 'csebcdicess':
9733                         case 'ebcdicess':
9734                                 return 'EBCDIC-ES-S';
9735
9736                         case 'csebcdicfise':
9737                         case 'ebcdicfise':
9738                                 return 'EBCDIC-FI-SE';
9739
9740                         case 'csebcdicfisea':
9741                         case 'ebcdicfisea':
9742                                 return 'EBCDIC-FI-SE-A';
9743
9744                         case 'csebcdicfr':
9745                         case 'ebcdicfr':
9746                                 return 'EBCDIC-FR';
9747
9748                         case 'csebcdicit':
9749                         case 'ebcdicit':
9750                                 return 'EBCDIC-IT';
9751
9752                         case 'csebcdicpt':
9753                         case 'ebcdicpt':
9754                                 return 'EBCDIC-PT';
9755
9756                         case 'csebcdicuk':
9757                         case 'ebcdicuk':
9758                                 return 'EBCDIC-UK';
9759
9760                         case 'csebcdicus':
9761                         case 'ebcdicus':
9762                                 return 'EBCDIC-US';
9763
9764                         case 'csiso111ecmacyrillic':
9765                         case 'ecmacyrillic':
9766                         case 'isoir111':
9767                         case 'koi8e':
9768                                 return 'ECMA-cyrillic';
9769
9770                         case 'csiso17spanish':
9771                         case 'es':
9772                         case 'iso646es':
9773                         case 'isoir17':
9774                                 return 'ES';
9775
9776                         case 'csiso85spanish2':
9777                         case 'es2':
9778                         case 'iso646es2':
9779                         case 'isoir85':
9780                                 return 'ES2';
9781
9782                         case 'cseucfixwidjapanese':
9783                         case 'extendedunixcodefixedwidthforjapanese':
9784                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9785
9786                         case 'cseucpkdfmtjapanese':
9787                         case 'eucjp':
9788                         case 'extendedunixcodepackedformatforjapanese':
9789                                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9790
9791                         case 'gb18030':
9792                                 return 'GB18030';
9793
9794                         case 'chinese':
9795                         case 'cp936':
9796                         case 'csgb2312':
9797                         case 'csiso58gb231280':
9798                         case 'gb2312':
9799                         case 'gb231280':
9800                         case 'gbk':
9801                         case 'isoir58':
9802                         case 'ms936':
9803                         case 'windows936':
9804                                 return 'GBK';
9805
9806                         case 'cn':
9807                         case 'csiso57gb1988':
9808                         case 'gb198880':
9809                         case 'iso646cn':
9810                         case 'isoir57':
9811                                 return 'GB_1988-80';
9812
9813                         case 'csiso153gost1976874':
9814                         case 'gost1976874':
9815                         case 'isoir153':
9816                         case 'stsev35888':
9817                                 return 'GOST_19768-74';
9818
9819                         case 'csiso150':
9820                         case 'csiso150greekccitt':
9821                         case 'greekccitt':
9822                         case 'isoir150':
9823                                 return 'greek-ccitt';
9824
9825                         case 'csiso88greek7':
9826                         case 'greek7':
9827                         case 'isoir88':
9828                                 return 'greek7';
9829
9830                         case 'csiso18greek7old':
9831                         case 'greek7old':
9832                         case 'isoir18':
9833                                 return 'greek7-old';
9834
9835                         case 'cshpdesktop':
9836                         case 'hpdesktop':
9837                                 return 'HP-DeskTop';
9838
9839                         case 'cshplegal':
9840                         case 'hplegal':
9841                                 return 'HP-Legal';
9842
9843                         case 'cshpmath8':
9844                         case 'hpmath8':
9845                                 return 'HP-Math8';
9846
9847                         case 'cshppifont':
9848                         case 'hppifont':
9849                                 return 'HP-Pi-font';
9850
9851                         case 'cshproman8':
9852                         case 'hproman8':
9853                         case 'r8':
9854                         case 'roman8':
9855                                 return 'hp-roman8';
9856
9857                         case 'hzgb2312':
9858                                 return 'HZ-GB-2312';
9859
9860                         case 'csibmsymbols':
9861                         case 'ibmsymbols':
9862                                 return 'IBM-Symbols';
9863
9864                         case 'csibmthai':
9865                         case 'ibmthai':
9866                                 return 'IBM-Thai';
9867
9868                         case 'ccsid858':
9869                         case 'cp858':
9870                         case 'ibm858':
9871                         case 'pcmultilingual850euro':
9872                                 return 'IBM00858';
9873
9874                         case 'ccsid924':
9875                         case 'cp924':
9876                         case 'ebcdiclatin9euro':
9877                         case 'ibm924':
9878                                 return 'IBM00924';
9879
9880                         case 'ccsid1140':
9881                         case 'cp1140':
9882                         case 'ebcdicus37euro':
9883                         case 'ibm1140':
9884                                 return 'IBM01140';
9885
9886                         case 'ccsid1141':
9887                         case 'cp1141':
9888                         case 'ebcdicde273euro':
9889                         case 'ibm1141':
9890                                 return 'IBM01141';
9891
9892                         case 'ccsid1142':
9893                         case 'cp1142':
9894                         case 'ebcdicdk277euro':
9895                         case 'ebcdicno277euro':
9896                         case 'ibm1142':
9897                                 return 'IBM01142';
9898
9899                         case 'ccsid1143':
9900                         case 'cp1143':
9901                         case 'ebcdicfi278euro':
9902                         case 'ebcdicse278euro':
9903                         case 'ibm1143':
9904                                 return 'IBM01143';
9905
9906                         case 'ccsid1144':
9907                         case 'cp1144':
9908                         case 'ebcdicit280euro':
9909                         case 'ibm1144':
9910                                 return 'IBM01144';
9911
9912                         case 'ccsid1145':
9913                         case 'cp1145':
9914                         case 'ebcdices284euro':
9915                         case 'ibm1145':
9916                                 return 'IBM01145';
9917
9918                         case 'ccsid1146':
9919                         case 'cp1146':
9920                         case 'ebcdicgb285euro':
9921                         case 'ibm1146':
9922                                 return 'IBM01146';
9923
9924                         case 'ccsid1147':
9925                         case 'cp1147':
9926                         case 'ebcdicfr297euro':
9927                         case 'ibm1147':
9928                                 return 'IBM01147';
9929
9930                         case 'ccsid1148':
9931                         case 'cp1148':
9932                         case 'ebcdicinternational500euro':
9933                         case 'ibm1148':
9934                                 return 'IBM01148';
9935
9936                         case 'ccsid1149':
9937                         case 'cp1149':
9938                         case 'ebcdicis871euro':
9939                         case 'ibm1149':
9940                                 return 'IBM01149';
9941
9942                         case 'cp37':
9943                         case 'csibm37':
9944                         case 'ebcdiccpca':
9945                         case 'ebcdiccpnl':
9946                         case 'ebcdiccpus':
9947                         case 'ebcdiccpwt':
9948                         case 'ibm37':
9949                                 return 'IBM037';
9950
9951                         case 'cp38':
9952                         case 'csibm38':
9953                         case 'ebcdicint':
9954                         case 'ibm38':
9955                                 return 'IBM038';
9956
9957                         case 'cp273':
9958                         case 'csibm273':
9959                         case 'ibm273':
9960                                 return 'IBM273';
9961
9962                         case 'cp274':
9963                         case 'csibm274':
9964                         case 'ebcdicbe':
9965                         case 'ibm274':
9966                                 return 'IBM274';
9967
9968                         case 'cp275':
9969                         case 'csibm275':
9970                         case 'ebcdicbr':
9971                         case 'ibm275':
9972                                 return 'IBM275';
9973
9974                         case 'csibm277':
9975                         case 'ebcdiccpdk':
9976                         case 'ebcdiccpno':
9977                         case 'ibm277':
9978                                 return 'IBM277';
9979
9980                         case 'cp278':
9981                         case 'csibm278':
9982                         case 'ebcdiccpfi':
9983                         case 'ebcdiccpse':
9984                         case 'ibm278':
9985                                 return 'IBM278';
9986
9987                         case 'cp280':
9988                         case 'csibm280':
9989                         case 'ebcdiccpit':
9990                         case 'ibm280':
9991                                 return 'IBM280';
9992
9993                         case 'cp281':
9994                         case 'csibm281':
9995                         case 'ebcdicjpe':
9996                         case 'ibm281':
9997                                 return 'IBM281';
9998
9999                         case 'cp284':
10000                         case 'csibm284':
10001                         case 'ebcdiccpes':
10002                         case 'ibm284':
10003                                 return 'IBM284';
10004
10005                         case 'cp285':
10006                         case 'csibm285':
10007                         case 'ebcdiccpgb':
10008                         case 'ibm285':
10009                                 return 'IBM285';
10010
10011                         case 'cp290':
10012                         case 'csibm290':
10013                         case 'ebcdicjpkana':
10014                         case 'ibm290':
10015                                 return 'IBM290';
10016
10017                         case 'cp297':
10018                         case 'csibm297':
10019                         case 'ebcdiccpfr':
10020                         case 'ibm297':
10021                                 return 'IBM297';
10022
10023                         case 'cp420':
10024                         case 'csibm420':
10025                         case 'ebcdiccpar1':
10026                         case 'ibm420':
10027                                 return 'IBM420';
10028
10029                         case 'cp423':
10030                         case 'csibm423':
10031                         case 'ebcdiccpgr':
10032                         case 'ibm423':
10033                                 return 'IBM423';
10034
10035                         case 'cp424':
10036                         case 'csibm424':
10037                         case 'ebcdiccphe':
10038                         case 'ibm424':
10039                                 return 'IBM424';
10040
10041                         case '437':
10042                         case 'cp437':
10043                         case 'cspc8codepage437':
10044                         case 'ibm437':
10045                                 return 'IBM437';
10046
10047                         case 'cp500':
10048                         case 'csibm500':
10049                         case 'ebcdiccpbe':
10050                         case 'ebcdiccpch':
10051                         case 'ibm500':
10052                                 return 'IBM500';
10053
10054                         case 'cp775':
10055                         case 'cspc775baltic':
10056                         case 'ibm775':
10057                                 return 'IBM775';
10058
10059                         case '850':
10060                         case 'cp850':
10061                         case 'cspc850multilingual':
10062                         case 'ibm850':
10063                                 return 'IBM850';
10064
10065                         case '851':
10066                         case 'cp851':
10067                         case 'csibm851':
10068                         case 'ibm851':
10069                                 return 'IBM851';
10070
10071                         case '852':
10072                         case 'cp852':
10073                         case 'cspcp852':
10074                         case 'ibm852':
10075                                 return 'IBM852';
10076
10077                         case '855':
10078                         case 'cp855':
10079                         case 'csibm855':
10080                         case 'ibm855':
10081                                 return 'IBM855';
10082
10083                         case '857':
10084                         case 'cp857':
10085                         case 'csibm857':
10086                         case 'ibm857':
10087                                 return 'IBM857';
10088
10089                         case '860':
10090                         case 'cp860':
10091                         case 'csibm860':
10092                         case 'ibm860':
10093                                 return 'IBM860';
10094
10095                         case '861':
10096                         case 'cp861':
10097                         case 'cpis':
10098                         case 'csibm861':
10099                         case 'ibm861':
10100                                 return 'IBM861';
10101
10102                         case '862':
10103                         case 'cp862':
10104                         case 'cspc862latinhebrew':
10105                         case 'ibm862':
10106                                 return 'IBM862';
10107
10108                         case '863':
10109                         case 'cp863':
10110                         case 'csibm863':
10111                         case 'ibm863':
10112                                 return 'IBM863';
10113
10114                         case 'cp864':
10115                         case 'csibm864':
10116                         case 'ibm864':
10117                                 return 'IBM864';
10118
10119                         case '865':
10120                         case 'cp865':
10121                         case 'csibm865':
10122                         case 'ibm865':
10123                                 return 'IBM865';
10124
10125                         case '866':
10126                         case 'cp866':
10127                         case 'csibm866':
10128                         case 'ibm866':
10129                                 return 'IBM866';
10130
10131                         case 'cp868':
10132                         case 'cpar':
10133                         case 'csibm868':
10134                         case 'ibm868':
10135                                 return 'IBM868';
10136
10137                         case '869':
10138                         case 'cp869':
10139                         case 'cpgr':
10140                         case 'csibm869':
10141                         case 'ibm869':
10142                                 return 'IBM869';
10143
10144                         case 'cp870':
10145                         case 'csibm870':
10146                         case 'ebcdiccproece':
10147                         case 'ebcdiccpyu':
10148                         case 'ibm870':
10149                                 return 'IBM870';
10150
10151                         case 'cp871':
10152                         case 'csibm871':
10153                         case 'ebcdiccpis':
10154                         case 'ibm871':
10155                                 return 'IBM871';
10156
10157                         case 'cp880':
10158                         case 'csibm880':
10159                         case 'ebcdiccyrillic':
10160                         case 'ibm880':
10161                                 return 'IBM880';
10162
10163                         case 'cp891':
10164                         case 'csibm891':
10165                         case 'ibm891':
10166                                 return 'IBM891';
10167
10168                         case 'cp903':
10169                         case 'csibm903':
10170                         case 'ibm903':
10171                                 return 'IBM903';
10172
10173                         case '904':
10174                         case 'cp904':
10175                         case 'csibbm904':
10176                         case 'ibm904':
10177                                 return 'IBM904';
10178
10179                         case 'cp905':
10180                         case 'csibm905':
10181                         case 'ebcdiccptr':
10182                         case 'ibm905':
10183                                 return 'IBM905';
10184
10185                         case 'cp918':
10186                         case 'csibm918':
10187                         case 'ebcdiccpar2':
10188                         case 'ibm918':
10189                                 return 'IBM918';
10190
10191                         case 'cp1026':
10192                         case 'csibm1026':
10193                         case 'ibm1026':
10194                                 return 'IBM1026';
10195
10196                         case 'ibm1047':
10197                                 return 'IBM1047';
10198
10199                         case 'csiso143iecp271':
10200                         case 'iecp271':
10201                         case 'isoir143':
10202                                 return 'IEC_P27-1';
10203
10204                         case 'csiso49inis':
10205                         case 'inis':
10206                         case 'isoir49':
10207                                 return 'INIS';
10208
10209                         case 'csiso50inis8':
10210                         case 'inis8':
10211                         case 'isoir50':
10212                                 return 'INIS-8';
10213
10214                         case 'csiso51iniscyrillic':
10215                         case 'iniscyrillic':
10216                         case 'isoir51':
10217                                 return 'INIS-cyrillic';
10218
10219                         case 'csinvariant':
10220                         case 'invariant':
10221                                 return 'INVARIANT';
10222
10223                         case 'iso2022cn':
10224                                 return 'ISO-2022-CN';
10225
10226                         case 'iso2022cnext':
10227                                 return 'ISO-2022-CN-EXT';
10228
10229                         case 'csiso2022jp':
10230                         case 'iso2022jp':
10231                                 return 'ISO-2022-JP';
10232
10233                         case 'csiso2022jp2':
10234                         case 'iso2022jp2':
10235                                 return 'ISO-2022-JP-2';
10236
10237                         case 'csiso2022kr':
10238                         case 'iso2022kr':
10239                                 return 'ISO-2022-KR';
10240
10241                         case 'cswindows30latin1':
10242                         case 'iso88591windows30latin1':
10243                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10244
10245                         case 'cswindows31latin1':
10246                         case 'iso88591windows31latin1':
10247                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10248
10249                         case 'csisolatin2':
10250                         case 'iso88592':
10251                         case 'iso885921987':
10252                         case 'isoir101':
10253                         case 'l2':
10254                         case 'latin2':
10255                                 return 'ISO-8859-2';
10256
10257                         case 'cswindows31latin2':
10258                         case 'iso88592windowslatin2':
10259                                 return 'ISO-8859-2-Windows-Latin-2';
10260
10261                         case 'csisolatin3':
10262                         case 'iso88593':
10263                         case 'iso885931988':
10264                         case 'isoir109':
10265                         case 'l3':
10266                         case 'latin3':
10267                                 return 'ISO-8859-3';
10268
10269                         case 'csisolatin4':
10270                         case 'iso88594':
10271                         case 'iso885941988':
10272                         case 'isoir110':
10273                         case 'l4':
10274                         case 'latin4':
10275                                 return 'ISO-8859-4';
10276
10277                         case 'csisolatincyrillic':
10278                         case 'cyrillic':
10279                         case 'iso88595':
10280                         case 'iso885951988':
10281                         case 'isoir144':
10282                                 return 'ISO-8859-5';
10283
10284                         case 'arabic':
10285                         case 'asmo708':
10286                         case 'csisolatinarabic':
10287                         case 'ecma114':
10288                         case 'iso88596':
10289                         case 'iso885961987':
10290                         case 'isoir127':
10291                                 return 'ISO-8859-6';
10292
10293                         case 'csiso88596e':
10294                         case 'iso88596e':
10295                                 return 'ISO-8859-6-E';
10296
10297                         case 'csiso88596i':
10298                         case 'iso88596i':
10299                                 return 'ISO-8859-6-I';
10300
10301                         case 'csisolatingreek':
10302                         case 'ecma118':
10303                         case 'elot928':
10304                         case 'greek':
10305                         case 'greek8':
10306                         case 'iso88597':
10307                         case 'iso885971987':
10308                         case 'isoir126':
10309                                 return 'ISO-8859-7';
10310
10311                         case 'csisolatinhebrew':
10312                         case 'hebrew':
10313                         case 'iso88598':
10314                         case 'iso885981988':
10315                         case 'isoir138':
10316                                 return 'ISO-8859-8';
10317
10318                         case 'csiso88598e':
10319                         case 'iso88598e':
10320                                 return 'ISO-8859-8-E';
10321
10322                         case 'csiso88598i':
10323                         case 'iso88598i':
10324                                 return 'ISO-8859-8-I';
10325
10326                         case 'cswindows31latin5':
10327                         case 'iso88599windowslatin5':
10328                                 return 'ISO-8859-9-Windows-Latin-5';
10329
10330                         case 'csisolatin6':
10331                         case 'iso885910':
10332                         case 'iso8859101992':
10333                         case 'isoir157':
10334                         case 'l6':
10335                         case 'latin6':
10336                                 return 'ISO-8859-10';
10337
10338                         case 'iso885913':
10339                                 return 'ISO-8859-13';
10340
10341                         case 'iso885914':
10342                         case 'iso8859141998':
10343                         case 'isoceltic':
10344                         case 'isoir199':
10345                         case 'l8':
10346                         case 'latin8':
10347                                 return 'ISO-8859-14';
10348
10349                         case 'iso885915':
10350                         case 'latin9':
10351                                 return 'ISO-8859-15';
10352
10353                         case 'iso885916':
10354                         case 'iso8859162001':
10355                         case 'isoir226':
10356                         case 'l10':
10357                         case 'latin10':
10358                                 return 'ISO-8859-16';
10359
10360                         case 'iso10646j1':
10361                                 return 'ISO-10646-J-1';
10362
10363                         case 'csunicode':
10364                         case 'iso10646ucs2':
10365                                 return 'ISO-10646-UCS-2';
10366
10367                         case 'csucs4':
10368                         case 'iso10646ucs4':
10369                                 return 'ISO-10646-UCS-4';
10370
10371                         case 'csunicodeascii':
10372                         case 'iso10646ucsbasic':
10373                                 return 'ISO-10646-UCS-Basic';
10374
10375                         case 'csunicodelatin1':
10376                         case 'iso10646':
10377                         case 'iso10646unicodelatin1':
10378                                 return 'ISO-10646-Unicode-Latin1';
10379
10380                         case 'csiso10646utf1':
10381                         case 'iso10646utf1':
10382                                 return 'ISO-10646-UTF-1';
10383
10384                         case 'csiso115481':
10385                         case 'iso115481':
10386                         case 'isotr115481':
10387                                 return 'ISO-11548-1';
10388
10389                         case 'csiso90':
10390                         case 'isoir90':
10391                                 return 'iso-ir-90';
10392
10393                         case 'csunicodeibm1261':
10394                         case 'isounicodeibm1261':
10395                                 return 'ISO-Unicode-IBM-1261';
10396
10397                         case 'csunicodeibm1264':
10398                         case 'isounicodeibm1264':
10399                                 return 'ISO-Unicode-IBM-1264';
10400
10401                         case 'csunicodeibm1265':
10402                         case 'isounicodeibm1265':
10403                                 return 'ISO-Unicode-IBM-1265';
10404
10405                         case 'csunicodeibm1268':
10406                         case 'isounicodeibm1268':
10407                                 return 'ISO-Unicode-IBM-1268';
10408
10409                         case 'csunicodeibm1276':
10410                         case 'isounicodeibm1276':
10411                                 return 'ISO-Unicode-IBM-1276';
10412
10413                         case 'csiso646basic1983':
10414                         case 'iso646basic1983':
10415                         case 'ref':
10416                                 return 'ISO_646.basic:1983';
10417
10418                         case 'csiso2intlrefversion':
10419                         case 'irv':
10420                         case 'iso646irv1983':
10421                         case 'isoir2':
10422                                 return 'ISO_646.irv:1983';
10423
10424                         case 'csiso2033':
10425                         case 'e13b':
10426                         case 'iso20331983':
10427                         case 'isoir98':
10428                                 return 'ISO_2033-1983';
10429
10430                         case 'csiso5427cyrillic':
10431                         case 'iso5427':
10432                         case 'isoir37':
10433                                 return 'ISO_5427';
10434
10435                         case 'iso5427cyrillic1981':
10436                         case 'iso54271981':
10437                         case 'isoir54':
10438                                 return 'ISO_5427:1981';
10439
10440                         case 'csiso5428greek':
10441                         case 'iso54281980':
10442                         case 'isoir55':
10443                                 return 'ISO_5428:1980';
10444
10445                         case 'csiso6937add':
10446                         case 'iso6937225':
10447                         case 'isoir152':
10448                                 return 'ISO_6937-2-25';
10449
10450                         case 'csisotextcomm':
10451                         case 'iso69372add':
10452                         case 'isoir142':
10453                                 return 'ISO_6937-2-add';
10454
10455                         case 'csiso8859supp':
10456                         case 'iso8859supp':
10457                         case 'isoir154':
10458                         case 'latin125':
10459                                 return 'ISO_8859-supp';
10460
10461                         case 'csiso10367box':
10462                         case 'iso10367box':
10463                         case 'isoir155':
10464                                 return 'ISO_10367-box';
10465
10466                         case 'csiso15italian':
10467                         case 'iso646it':
10468                         case 'isoir15':
10469                         case 'it':
10470                                 return 'IT';
10471
10472                         case 'csiso13jisc6220jp':
10473                         case 'isoir13':
10474                         case 'jisc62201969':
10475                         case 'jisc62201969jp':
10476                         case 'katakana':
10477                         case 'x2017':
10478                                 return 'JIS_C6220-1969-jp';
10479
10480                         case 'csiso14jisc6220ro':
10481                         case 'iso646jp':
10482                         case 'isoir14':
10483                         case 'jisc62201969ro':
10484                         case 'jp':
10485                                 return 'JIS_C6220-1969-ro';
10486
10487                         case 'csiso42jisc62261978':
10488                         case 'isoir42':
10489                         case 'jisc62261978':
10490                                 return 'JIS_C6226-1978';
10491
10492                         case 'csiso87jisx208':
10493                         case 'isoir87':
10494                         case 'jisc62261983':
10495                         case 'jisx2081983':
10496                         case 'x208':
10497                                 return 'JIS_C6226-1983';
10498
10499                         case 'csiso91jisc62291984a':
10500                         case 'isoir91':
10501                         case 'jisc62291984a':
10502                         case 'jpocra':
10503                                 return 'JIS_C6229-1984-a';
10504
10505                         case 'csiso92jisc62991984b':
10506                         case 'iso646jpocrb':
10507                         case 'isoir92':
10508                         case 'jisc62291984b':
10509                         case 'jpocrb':
10510                                 return 'JIS_C6229-1984-b';
10511
10512                         case 'csiso93jis62291984badd':
10513                         case 'isoir93':
10514                         case 'jisc62291984badd':
10515                         case 'jpocrbadd':
10516                                 return 'JIS_C6229-1984-b-add';
10517
10518                         case 'csiso94jis62291984hand':
10519                         case 'isoir94':
10520                         case 'jisc62291984hand':
10521                         case 'jpocrhand':
10522                                 return 'JIS_C6229-1984-hand';
10523
10524                         case 'csiso95jis62291984handadd':
10525                         case 'isoir95':
10526                         case 'jisc62291984handadd':
10527                         case 'jpocrhandadd':
10528                                 return 'JIS_C6229-1984-hand-add';
10529
10530                         case 'csiso96jisc62291984kana':
10531                         case 'isoir96':
10532                         case 'jisc62291984kana':
10533                                 return 'JIS_C6229-1984-kana';
10534
10535                         case 'csjisencoding':
10536                         case 'jisencoding':
10537                                 return 'JIS_Encoding';
10538
10539                         case 'cshalfwidthkatakana':
10540                         case 'jisx201':
10541                         case 'x201':
10542                                 return 'JIS_X0201';
10543
10544                         case 'csiso159jisx2121990':
10545                         case 'isoir159':
10546                         case 'jisx2121990':
10547                         case 'x212':
10548                                 return 'JIS_X0212-1990';
10549
10550                         case 'csiso141jusib1002':
10551                         case 'iso646yu':
10552                         case 'isoir141':
10553                         case 'js':
10554                         case 'jusib1002':
10555                         case 'yu':
10556                                 return 'JUS_I.B1.002';
10557
10558                         case 'csiso147macedonian':
10559                         case 'isoir147':
10560                         case 'jusib1003mac':
10561                         case 'macedonian':
10562                                 return 'JUS_I.B1.003-mac';
10563
10564                         case 'csiso146serbian':
10565                         case 'isoir146':
10566                         case 'jusib1003serb':
10567                         case 'serbian':
10568                                 return 'JUS_I.B1.003-serb';
10569
10570                         case 'koi7switched':
10571                                 return 'KOI7-switched';
10572
10573                         case 'cskoi8r':
10574                         case 'koi8r':
10575                                 return 'KOI8-R';
10576
10577                         case 'koi8u':
10578                                 return 'KOI8-U';
10579
10580                         case 'csksc5636':
10581                         case 'iso646kr':
10582                         case 'ksc5636':
10583                                 return 'KSC5636';
10584
10585                         case 'cskz1048':
10586                         case 'kz1048':
10587                         case 'rk1048':
10588                         case 'strk10482002':
10589                                 return 'KZ-1048';
10590
10591                         case 'csiso19latingreek':
10592                         case 'isoir19':
10593                         case 'latingreek':
10594                                 return 'latin-greek';
10595
10596                         case 'csiso27latingreek1':
10597                         case 'isoir27':
10598                         case 'latingreek1':
10599                                 return 'Latin-greek-1';
10600
10601                         case 'csiso158lap':
10602                         case 'isoir158':
10603                         case 'lap':
10604                         case 'latinlap':
10605                                 return 'latin-lap';
10606
10607                         case 'csmacintosh':
10608                         case 'mac':
10609                         case 'macintosh':
10610                                 return 'macintosh';
10611
10612                         case 'csmicrosoftpublishing':
10613                         case 'microsoftpublishing':
10614                                 return 'Microsoft-Publishing';
10615
10616                         case 'csmnem':
10617                         case 'mnem':
10618                                 return 'MNEM';
10619
10620                         case 'csmnemonic':
10621                         case 'mnemonic':
10622                                 return 'MNEMONIC';
10623
10624                         case 'csiso86hungarian':
10625                         case 'hu':
10626                         case 'iso646hu':
10627                         case 'isoir86':
10628                         case 'msz77953':
10629                                 return 'MSZ_7795.3';
10630
10631                         case 'csnatsdano':
10632                         case 'isoir91':
10633                         case 'natsdano':
10634                                 return 'NATS-DANO';
10635
10636                         case 'csnatsdanoadd':
10637                         case 'isoir92':
10638                         case 'natsdanoadd':
10639                                 return 'NATS-DANO-ADD';
10640
10641                         case 'csnatssefi':
10642                         case 'isoir81':
10643                         case 'natssefi':
10644                                 return 'NATS-SEFI';
10645
10646                         case 'csnatssefiadd':
10647                         case 'isoir82':
10648                         case 'natssefiadd':
10649                                 return 'NATS-SEFI-ADD';
10650
10651                         case 'csiso151cuba':
10652                         case 'cuba':
10653                         case 'iso646cu':
10654                         case 'isoir151':
10655                         case 'ncnc1081':
10656                                 return 'NC_NC00-10:81';
10657
10658                         case 'csiso69french':
10659                         case 'fr':
10660                         case 'iso646fr':
10661                         case 'isoir69':
10662                         case 'nfz62010':
10663                                 return 'NF_Z_62-010';
10664
10665                         case 'csiso25french':
10666                         case 'iso646fr1':
10667                         case 'isoir25':
10668                         case 'nfz620101973':
10669                                 return 'NF_Z_62-010_(1973)';
10670
10671                         case 'csiso60danishnorwegian':
10672                         case 'csiso60norwegian1':
10673                         case 'iso646no':
10674                         case 'isoir60':
10675                         case 'no':
10676                         case 'ns45511':
10677                                 return 'NS_4551-1';
10678
10679                         case 'csiso61norwegian2':
10680                         case 'iso646no2':
10681                         case 'isoir61':
10682                         case 'no2':
10683                         case 'ns45512':
10684                                 return 'NS_4551-2';
10685
10686                         case 'osdebcdicdf3irv':
10687                                 return 'OSD_EBCDIC_DF03_IRV';
10688
10689                         case 'osdebcdicdf41':
10690                                 return 'OSD_EBCDIC_DF04_1';
10691
10692                         case 'osdebcdicdf415':
10693                                 return 'OSD_EBCDIC_DF04_15';
10694
10695                         case 'cspc8danishnorwegian':
10696                         case 'pc8danishnorwegian':
10697                                 return 'PC8-Danish-Norwegian';
10698
10699                         case 'cspc8turkish':
10700                         case 'pc8turkish':
10701                                 return 'PC8-Turkish';
10702
10703                         case 'csiso16portuguese':
10704                         case 'iso646pt':
10705                         case 'isoir16':
10706                         case 'pt':
10707                                 return 'PT';
10708
10709                         case 'csiso84portuguese2':
10710                         case 'iso646pt2':
10711                         case 'isoir84':
10712                         case 'pt2':
10713                                 return 'PT2';
10714
10715                         case 'cp154':
10716                         case 'csptcp154':
10717                         case 'cyrillicasian':
10718                         case 'pt154':
10719                         case 'ptcp154':
10720                                 return 'PTCP154';
10721
10722                         case 'scsu':
10723                                 return 'SCSU';
10724
10725                         case 'csiso10swedish':
10726                         case 'fi':
10727                         case 'iso646fi':
10728                         case 'iso646se':
10729                         case 'isoir10':
10730                         case 'se':
10731                         case 'sen850200b':
10732                                 return 'SEN_850200_B';
10733
10734                         case 'csiso11swedishfornames':
10735                         case 'iso646se2':
10736                         case 'isoir11':
10737                         case 'se2':
10738                         case 'sen850200c':
10739                                 return 'SEN_850200_C';
10740
10741                         case 'csshiftjis':
10742                         case 'mskanji':
10743                         case 'shiftjis':
10744                                 return 'Shift_JIS';
10745
10746                         case 'csiso102t617bit':
10747                         case 'isoir102':
10748                         case 't617bit':
10749                                 return 'T.61-7bit';
10750
10751                         case 'csiso103t618bit':
10752                         case 'isoir103':
10753                         case 't61':
10754                         case 't618bit':
10755                                 return 'T.61-8bit';
10756
10757                         case 'csiso128t101g2':
10758                         case 'isoir128':
10759                         case 't101g2':
10760                                 return 'T.101-G2';
10761
10762                         case 'cstscii':
10763                         case 'tscii':
10764                                 return 'TSCII';
10765
10766                         case 'csunicode11':
10767                         case 'unicode11':
10768                                 return 'UNICODE-1-1';
10769
10770                         case 'csunicode11utf7':
10771                         case 'unicode11utf7':
10772                                 return 'UNICODE-1-1-UTF-7';
10773
10774                         case 'csunknown8bit':
10775                         case 'unknown8bit':
10776                                 return 'UNKNOWN-8BIT';
10777
10778                         case 'ansix341968':
10779                         case 'ansix341986':
10780                         case 'ascii':
10781                         case 'cp367':
10782                         case 'csascii':
10783                         case 'ibm367':
10784                         case 'iso646irv1991':
10785                         case 'iso646us':
10786                         case 'isoir6':
10787                         case 'us':
10788                         case 'usascii':
10789                                 return 'US-ASCII';
10790
10791                         case 'csusdk':
10792                         case 'usdk':
10793                                 return 'us-dk';
10794
10795                         case 'utf7':
10796                                 return 'UTF-7';
10797
10798                         case 'utf8':
10799                                 return 'UTF-8';
10800
10801                         case 'utf16':
10802                                 return 'UTF-16';
10803
10804                         case 'utf16be':
10805                                 return 'UTF-16BE';
10806
10807                         case 'utf16le':
10808                                 return 'UTF-16LE';
10809
10810                         case 'utf32':
10811                                 return 'UTF-32';
10812
10813                         case 'utf32be':
10814                                 return 'UTF-32BE';
10815
10816                         case 'utf32le':
10817                                 return 'UTF-32LE';
10818
10819                         case 'csventurainternational':
10820                         case 'venturainternational':
10821                                 return 'Ventura-International';
10822
10823                         case 'csventuramath':
10824                         case 'venturamath':
10825                                 return 'Ventura-Math';
10826
10827                         case 'csventuraus':
10828                         case 'venturaus':
10829                                 return 'Ventura-US';
10830
10831                         case 'csiso70videotexsupp1':
10832                         case 'isoir70':
10833                         case 'videotexsuppl':
10834                                 return 'videotex-suppl';
10835
10836                         case 'csviqr':
10837                         case 'viqr':
10838                                 return 'VIQR';
10839
10840                         case 'csviscii':
10841                         case 'viscii':
10842                                 return 'VISCII';
10843
10844                         case 'cswindows31j':
10845                         case 'windows31j':
10846                                 return 'Windows-31J';
10847
10848                         case 'iso885911':
10849                         case 'tis620':
10850                                 return 'windows-874';
10851
10852                         case 'cseuckr':
10853                         case 'csksc56011987':
10854                         case 'euckr':
10855                         case 'isoir149':
10856                         case 'korean':
10857                         case 'ksc5601':
10858                         case 'ksc56011987':
10859                         case 'ksc56011989':
10860                         case 'windows949':
10861                                 return 'windows-949';
10862
10863                         case 'windows1250':
10864                                 return 'windows-1250';
10865
10866                         case 'windows1251':
10867                                 return 'windows-1251';
10868
10869                         case 'cp819':
10870                         case 'csisolatin1':
10871                         case 'ibm819':
10872                         case 'iso88591':
10873                         case 'iso885911987':
10874                         case 'isoir100':
10875                         case 'l1':
10876                         case 'latin1':
10877                         case 'windows1252':
10878                                 return 'windows-1252';
10879
10880                         case 'windows1253':
10881                                 return 'windows-1253';
10882
10883                         case 'csisolatin5':
10884                         case 'iso88599':
10885                         case 'iso885991989':
10886                         case 'isoir148':
10887                         case 'l5':
10888                         case 'latin5':
10889                         case 'windows1254':
10890                                 return 'windows-1254';
10891
10892                         case 'windows1255':
10893                                 return 'windows-1255';
10894
10895                         case 'windows1256':
10896                                 return 'windows-1256';
10897
10898                         case 'windows1257':
10899                                 return 'windows-1257';
10900
10901                         case 'windows1258':
10902                                 return 'windows-1258';
10903
10904                         default:
10905                                 return $charset;
10906                 }
10907         }
10908
10909         function get_curl_version()
10910         {
10911                 if (is_array($curl = curl_version()))
10912                 {
10913                         $curl = $curl['version'];
10914                 }
10915                 elseif (substr($curl, 0, 5) === 'curl/')
10916                 {
10917                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10918                 }
10919                 elseif (substr($curl, 0, 8) === 'libcurl/')
10920                 {
10921                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10922                 }
10923                 else
10924                 {
10925                         $curl = 0;
10926                 }
10927                 return $curl;
10928         }
10929
10930         function is_subclass_of($class1, $class2)
10931         {
10932                 if (func_num_args() !== 2)
10933                 {
10934                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10935                 }
10936                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10937                 {
10938                         return is_subclass_of($class1, $class2);
10939                 }
10940                 elseif (is_string($class1) && is_string($class2))
10941                 {
10942                         if (class_exists($class1))
10943                         {
10944                                 if (class_exists($class2))
10945                                 {
10946                                         $class2 = strtolower($class2);
10947                                         while ($class1 = strtolower(get_parent_class($class1)))
10948                                         {
10949                                                 if ($class1 === $class2)
10950                                                 {
10951                                                         return true;
10952                                                 }
10953                                         }
10954                                 }
10955                         }
10956                         else
10957                         {
10958                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10959                         }
10960                 }
10961                 return false;
10962         }
10963
10964         /**
10965          * Strip HTML comments
10966          *
10967          * @access public
10968          * @param string $data Data to strip comments from
10969          * @return string Comment stripped string
10970          */
10971         function strip_comments($data)
10972         {
10973                 $output = '';
10974                 while (($start = strpos($data, '<!--')) !== false)
10975                 {
10976                         $output .= substr($data, 0, $start);
10977                         if (($end = strpos($data, '-->', $start)) !== false)
10978                         {
10979                                 $data = substr_replace($data, '', 0, $end + 3);
10980                         }
10981                         else
10982                         {
10983                                 $data = '';
10984                         }
10985                 }
10986                 return $output . $data;
10987         }
10988
10989         function parse_date($dt)
10990         {
10991                 $parser = SimplePie_Parse_Date::get();
10992                 return $parser->parse($dt);
10993         }
10994
10995         /**
10996          * Decode HTML entities
10997          *
10998          * @static
10999          * @access public
11000          * @param string $data Input data
11001          * @return string Output data
11002          */
11003         function entities_decode($data)
11004         {
11005                 $decoder = new SimplePie_Decode_HTML_Entities($data);
11006                 return $decoder->parse();
11007         }
11008
11009         /**
11010          * Remove RFC822 comments
11011          *
11012          * @access public
11013          * @param string $data Data to strip comments from
11014          * @return string Comment stripped string
11015          */
11016         function uncomment_rfc822($string)
11017         {
11018                 $string = (string) $string;
11019                 $position = 0;
11020                 $length = strlen($string);
11021                 $depth = 0;
11022
11023                 $output = '';
11024
11025                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11026                 {
11027                         $output .= substr($string, $position, $pos - $position);
11028                         $position = $pos + 1;
11029                         if ($string[$pos - 1] !== '\\')
11030                         {
11031                                 $depth++;
11032                                 while ($depth && $position < $length)
11033                                 {
11034                                         $position += strcspn($string, '()', $position);
11035                                         if ($string[$position - 1] === '\\')
11036                                         {
11037                                                 $position++;
11038                                                 continue;
11039                                         }
11040                                         elseif (isset($string[$position]))
11041                                         {
11042                                                 switch ($string[$position])
11043                                                 {
11044                                                         case '(':
11045                                                                 $depth++;
11046                                                                 break;
11047
11048                                                         case ')':
11049                                                                 $depth--;
11050                                                                 break;
11051                                                 }
11052                                                 $position++;
11053                                         }
11054                                         else
11055                                         {
11056                                                 break;
11057                                         }
11058                                 }
11059                         }
11060                         else
11061                         {
11062                                 $output .= '(';
11063                         }
11064                 }
11065                 $output .= substr($string, $position);
11066
11067                 return $output;
11068         }
11069
11070         function parse_mime($mime)
11071         {
11072                 if (($pos = strpos($mime, ';')) === false)
11073                 {
11074                         return trim($mime);
11075                 }
11076                 else
11077                 {
11078                         return trim(substr($mime, 0, $pos));
11079                 }
11080         }
11081
11082         function htmlspecialchars_decode($string, $quote_style)
11083         {
11084                 if (function_exists('htmlspecialchars_decode'))
11085                 {
11086                         return htmlspecialchars_decode($string, $quote_style);
11087                 }
11088                 else
11089                 {
11090                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11091                 }
11092         }
11093
11094         function atom_03_construct_type($attribs)
11095         {
11096                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11097                 {
11098                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11099                 }
11100                 else
11101                 {
11102                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
11103                 }
11104                 if (isset($attribs['']['type']))
11105                 {
11106                         switch (strtolower(trim($attribs['']['type'])))
11107                         {
11108                                 case 'text':
11109                                 case 'text/plain':
11110                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11111
11112                                 case 'html':
11113                                 case 'text/html':
11114                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11115
11116                                 case 'xhtml':
11117                                 case 'application/xhtml+xml':
11118                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11119
11120                                 default:
11121                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11122                         }
11123                 }
11124                 else
11125                 {
11126                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11127                 }
11128         }
11129
11130         function atom_10_construct_type($attribs)
11131         {
11132                 if (isset($attribs['']['type']))
11133                 {
11134                         switch (strtolower(trim($attribs['']['type'])))
11135                         {
11136                                 case 'text':
11137                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11138
11139                                 case 'html':
11140                                         return SIMPLEPIE_CONSTRUCT_HTML;
11141
11142                                 case 'xhtml':
11143                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11144
11145                                 default:
11146                                         return SIMPLEPIE_CONSTRUCT_NONE;
11147                         }
11148                 }
11149                 return SIMPLEPIE_CONSTRUCT_TEXT;
11150         }
11151
11152         function atom_10_content_construct_type($attribs)
11153         {
11154                 if (isset($attribs['']['type']))
11155                 {
11156                         $type = strtolower(trim($attribs['']['type']));
11157                         switch ($type)
11158                         {
11159                                 case 'text':
11160                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11161
11162                                 case 'html':
11163                                         return SIMPLEPIE_CONSTRUCT_HTML;
11164
11165                                 case 'xhtml':
11166                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11167                         }
11168                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11169                         {
11170                                 return SIMPLEPIE_CONSTRUCT_NONE;
11171                         }
11172                         else
11173                         {
11174                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11175                         }
11176                 }
11177                 else
11178                 {
11179                         return SIMPLEPIE_CONSTRUCT_TEXT;
11180                 }
11181         }
11182
11183         function is_isegment_nz_nc($string)
11184         {
11185                 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);
11186         }
11187
11188         function space_seperated_tokens($string)
11189         {
11190                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11191                 $string_length = strlen($string);
11192
11193                 $position = strspn($string, $space_characters);
11194                 $tokens = array();
11195
11196                 while ($position < $string_length)
11197                 {
11198                         $len = strcspn($string, $space_characters, $position);
11199                         $tokens[] = substr($string, $position, $len);
11200                         $position += $len;
11201                         $position += strspn($string, $space_characters, $position);
11202                 }
11203
11204                 return $tokens;
11205         }
11206
11207         function array_unique($array)
11208         {
11209                 if (version_compare(PHP_VERSION, '5.2', '>='))
11210                 {
11211                         return array_unique($array);
11212                 }
11213                 else
11214                 {
11215                         $array = (array) $array;
11216                         $new_array = array();
11217                         $new_array_strings = array();
11218                         foreach ($array as $key => $value)
11219                         {
11220                                 if (is_object($value))
11221                                 {
11222                                         if (method_exists($value, '__toString'))
11223                                         {
11224                                                 $cmp = $value->__toString();
11225                                         }
11226                                         else
11227                                         {
11228                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11229                                         }
11230                                 }
11231                                 elseif (is_array($value))
11232                                 {
11233                                         $cmp = (string) reset($value);
11234                                 }
11235                                 else
11236                                 {
11237                                         $cmp = (string) $value;
11238                                 }
11239                                 if (!in_array($cmp, $new_array_strings))
11240                                 {
11241                                         $new_array[$key] = $value;
11242                                         $new_array_strings[] = $cmp;
11243                                 }
11244                         }
11245                         return $new_array;
11246                 }
11247         }
11248
11249         /**
11250          * Converts a unicode codepoint to a UTF-8 character
11251          *
11252          * @static
11253          * @access public
11254          * @param int $codepoint Unicode codepoint
11255          * @return string UTF-8 character
11256          */
11257         function codepoint_to_utf8($codepoint)
11258         {
11259                 $codepoint = (int) $codepoint;
11260                 if ($codepoint < 0)
11261                 {
11262                         return false;
11263                 }
11264                 else if ($codepoint <= 0x7f)
11265                 {
11266                         return chr($codepoint);
11267                 }
11268                 else if ($codepoint <= 0x7ff)
11269                 {
11270                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11271                 }
11272                 else if ($codepoint <= 0xffff)
11273                 {
11274                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11275                 }
11276                 else if ($codepoint <= 0x10ffff)
11277                 {
11278                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11279                 }
11280                 else
11281                 {
11282                         // U+FFFD REPLACEMENT CHARACTER
11283                         return "\xEF\xBF\xBD";
11284                 }
11285         }
11286
11287         /**
11288          * Re-implementation of PHP 5's stripos()
11289          *
11290          * Returns the numeric position of the first occurrence of needle in the
11291          * haystack string.
11292          *
11293          * @static
11294          * @access string
11295          * @param object $haystack
11296          * @param string $needle Note that the needle may be a string of one or more
11297          *     characters. If needle is not a string, it is converted to an integer
11298          *     and applied as the ordinal value of a character.
11299          * @param int $offset The optional offset parameter allows you to specify which
11300          *     character in haystack to start searching. The position returned is still
11301          *     relative to the beginning of haystack.
11302          * @return bool If needle is not found, stripos() will return boolean false.
11303          */
11304         function stripos($haystack, $needle, $offset = 0)
11305         {
11306                 if (function_exists('stripos'))
11307                 {
11308                         return stripos($haystack, $needle, $offset);
11309                 }
11310                 else
11311                 {
11312                         if (is_string($needle))
11313                         {
11314                                 $needle = strtolower($needle);
11315                         }
11316                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11317                         {
11318                                 $needle = strtolower(chr($needle));
11319                         }
11320                         else
11321                         {
11322                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11323                                 return false;
11324                         }
11325
11326                         return strpos(strtolower($haystack), $needle, $offset);
11327                 }
11328         }
11329
11330         /**
11331          * Similar to parse_str()
11332          *
11333          * Returns an associative array of name/value pairs, where the value is an
11334          * array of values that have used the same name
11335          *
11336          * @static
11337          * @access string
11338          * @param string $str The input string.
11339          * @return array
11340          */
11341         function parse_str($str)
11342         {
11343                 $return = array();
11344                 $str = explode('&', $str);
11345
11346                 foreach ($str as $section)
11347                 {
11348                         if (strpos($section, '=') !== false)
11349                         {
11350                                 list($name, $value) = explode('=', $section, 2);
11351                                 $return[urldecode($name)][] = urldecode($value);
11352                         }
11353                         else
11354                         {
11355                                 $return[urldecode($section)][] = null;
11356                         }
11357                 }
11358
11359                 return $return;
11360         }
11361
11362         /**
11363          * Detect XML encoding, as per XML 1.0 Appendix F.1
11364          *
11365          * @todo Add support for EBCDIC
11366          * @param string $data XML data
11367          * @return array Possible encodings
11368          */
11369         function xml_encoding($data)
11370         {
11371                 // UTF-32 Big Endian BOM
11372                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11373                 {
11374                         $encoding[] = 'UTF-32BE';
11375                 }
11376                 // UTF-32 Little Endian BOM
11377                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11378                 {
11379                         $encoding[] = 'UTF-32LE';
11380                 }
11381                 // UTF-16 Big Endian BOM
11382                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11383                 {
11384                         $encoding[] = 'UTF-16BE';
11385                 }
11386                 // UTF-16 Little Endian BOM
11387                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11388                 {
11389                         $encoding[] = 'UTF-16LE';
11390                 }
11391                 // UTF-8 BOM
11392                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11393                 {
11394                         $encoding[] = 'UTF-8';
11395                 }
11396                 // UTF-32 Big Endian Without BOM
11397                 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")
11398                 {
11399                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11400                         {
11401                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11402                                 if ($parser->parse())
11403                                 {
11404                                         $encoding[] = $parser->encoding;
11405                                 }
11406                         }
11407                         $encoding[] = 'UTF-32BE';
11408                 }
11409                 // UTF-32 Little Endian Without BOM
11410                 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")
11411                 {
11412                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11413                         {
11414                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11415                                 if ($parser->parse())
11416                                 {
11417                                         $encoding[] = $parser->encoding;
11418                                 }
11419                         }
11420                         $encoding[] = 'UTF-32LE';
11421                 }
11422                 // UTF-16 Big Endian Without BOM
11423                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11424                 {
11425                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11426                         {
11427                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11428                                 if ($parser->parse())
11429                                 {
11430                                         $encoding[] = $parser->encoding;
11431                                 }
11432                         }
11433                         $encoding[] = 'UTF-16BE';
11434                 }
11435                 // UTF-16 Little Endian Without BOM
11436                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11437                 {
11438                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11439                         {
11440                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11441                                 if ($parser->parse())
11442                                 {
11443                                         $encoding[] = $parser->encoding;
11444                                 }
11445                         }
11446                         $encoding[] = 'UTF-16LE';
11447                 }
11448                 // US-ASCII (or superset)
11449                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11450                 {
11451                         if ($pos = strpos($data, "\x3F\x3E"))
11452                         {
11453                                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11454                                 if ($parser->parse())
11455                                 {
11456                                         $encoding[] = $parser->encoding;
11457                                 }
11458                         }
11459                         $encoding[] = 'UTF-8';
11460                 }
11461                 // Fallback to UTF-8
11462                 else
11463                 {
11464                         $encoding[] = 'UTF-8';
11465                 }
11466                 return $encoding;
11467         }
11468
11469         function output_javascript()
11470         {
11471                 if (function_exists('ob_gzhandler'))
11472                 {
11473                         ob_start('ob_gzhandler');
11474                 }
11475                 header('Content-type: text/javascript; charset: UTF-8');
11476                 header('Cache-Control: must-revalidate');
11477                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11478                 ?>
11479 function embed_odeo(link) {
11480         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>');
11481 }
11482
11483 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11484         if (placeholder != '') {
11485                 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>');
11486         }
11487         else {
11488                 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>');
11489         }
11490 }
11491
11492 function embed_flash(bgcolor, width, height, link, loop, type) {
11493         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>');
11494 }
11495
11496 function embed_flv(width, height, link, placeholder, loop, player) {
11497         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>');
11498 }
11499
11500 function embed_wmedia(width, height, link) {
11501         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11502 }
11503                 <?php
11504         }
11505 }
11506
11507 /**
11508  * Decode HTML Entities
11509  *
11510  * This implements HTML5 as of revision 967 (2007-06-28)
11511  *
11512  * @package SimplePie
11513  */
11514 class SimplePie_Decode_HTML_Entities
11515 {
11516         /**
11517          * Data to be parsed
11518          *
11519          * @access private
11520          * @var string
11521          */
11522         var $data = '';
11523
11524         /**
11525          * Currently consumed bytes
11526          *
11527          * @access private
11528          * @var string
11529          */
11530         var $consumed = '';
11531
11532         /**
11533          * Position of the current byte being parsed
11534          *
11535          * @access private
11536          * @var int
11537          */
11538         var $position = 0;
11539
11540         /**
11541          * Create an instance of the class with the input data
11542          *
11543          * @access public
11544          * @param string $data Input data
11545          */
11546         function SimplePie_Decode_HTML_Entities($data)
11547         {
11548                 $this->data = $data;
11549         }
11550
11551         /**
11552          * Parse the input data
11553          *
11554          * @access public
11555          * @return string Output data
11556          */
11557         function parse()
11558         {
11559                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11560                 {
11561                         $this->consume();
11562                         $this->entity();
11563                         $this->consumed = '';
11564                 }
11565                 return $this->data;
11566         }
11567
11568         /**
11569          * Consume the next byte
11570          *
11571          * @access private
11572          * @return mixed The next byte, or false, if there is no more data
11573          */
11574         function consume()
11575         {
11576                 if (isset($this->data[$this->position]))
11577                 {
11578                         $this->consumed .= $this->data[$this->position];
11579                         return $this->data[$this->position++];
11580                 }
11581                 else
11582                 {
11583                         return false;
11584                 }
11585         }
11586
11587         /**
11588          * Consume a range of characters
11589          *
11590          * @access private
11591          * @param string $chars Characters to consume
11592          * @return mixed A series of characters that match the range, or false
11593          */
11594         function consume_range($chars)
11595         {
11596                 if ($len = strspn($this->data, $chars, $this->position))
11597                 {
11598                         $data = substr($this->data, $this->position, $len);
11599                         $this->consumed .= $data;
11600                         $this->position += $len;
11601                         return $data;
11602                 }
11603                 else
11604                 {
11605                         return false;
11606                 }
11607         }
11608
11609         /**
11610          * Unconsume one byte
11611          *
11612          * @access private
11613          */
11614         function unconsume()
11615         {
11616                 $this->consumed = substr($this->consumed, 0, -1);
11617                 $this->position--;
11618         }
11619
11620         /**
11621          * Decode an entity
11622          *
11623          * @access private
11624          */
11625         function entity()
11626         {
11627                 switch ($this->consume())
11628                 {
11629                         case "\x09":
11630                         case "\x0A":
11631                         case "\x0B":
11632                         case "\x0B":
11633                         case "\x0C":
11634                         case "\x20":
11635                         case "\x3C":
11636                         case "\x26":
11637                         case false:
11638                                 break;
11639
11640                         case "\x23":
11641                                 switch ($this->consume())
11642                                 {
11643                                         case "\x78":
11644                                         case "\x58":
11645                                                 $range = '0123456789ABCDEFabcdef';
11646                                                 $hex = true;
11647                                                 break;
11648
11649                                         default:
11650                                                 $range = '0123456789';
11651                                                 $hex = false;
11652                                                 $this->unconsume();
11653                                                 break;
11654                                 }
11655
11656                                 if ($codepoint = $this->consume_range($range))
11657                                 {
11658                                         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");
11659
11660                                         if ($hex)
11661                                         {
11662                                                 $codepoint = hexdec($codepoint);
11663                                         }
11664                                         else
11665                                         {
11666                                                 $codepoint = intval($codepoint);
11667                                         }
11668
11669                                         if (isset($windows_1252_specials[$codepoint]))
11670                                         {
11671                                                 $replacement = $windows_1252_specials[$codepoint];
11672                                         }
11673                                         else
11674                                         {
11675                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11676                                         }
11677
11678                                         if (!in_array($this->consume(), array(';', false), true))
11679                                         {
11680                                                 $this->unconsume();
11681                                         }
11682
11683                                         $consumed_length = strlen($this->consumed);
11684                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11685                                         $this->position += strlen($replacement) - $consumed_length;
11686                                 }
11687                                 break;
11688
11689                         default:
11690                                 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");
11691
11692                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11693                                 {
11694                                         $consumed = substr($this->consumed, 1);
11695                                         if (isset($entities[$consumed]))
11696                                         {
11697                                                 $match = $consumed;
11698                                         }
11699                                 }
11700
11701                                 if ($match !== null)
11702                                 {
11703                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11704                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11705                                 }
11706                                 break;
11707                 }
11708         }
11709 }
11710
11711 /**
11712  * IRI parser/serialiser
11713  *
11714  * @package SimplePie
11715  */
11716 class SimplePie_IRI
11717 {
11718         /**
11719          * Scheme
11720          *
11721          * @access private
11722          * @var string
11723          */
11724         var $scheme;
11725
11726         /**
11727          * User Information
11728          *
11729          * @access private
11730          * @var string
11731          */
11732         var $userinfo;
11733
11734         /**
11735          * Host
11736          *
11737          * @access private
11738          * @var string
11739          */
11740         var $host;
11741
11742         /**
11743          * Port
11744          *
11745          * @access private
11746          * @var string
11747          */
11748         var $port;
11749
11750         /**
11751          * Path
11752          *
11753          * @access private
11754          * @var string
11755          */
11756         var $path;
11757
11758         /**
11759          * Query
11760          *
11761          * @access private
11762          * @var string
11763          */
11764         var $query;
11765
11766         /**
11767          * Fragment
11768          *
11769          * @access private
11770          * @var string
11771          */
11772         var $fragment;
11773
11774         /**
11775          * Whether the object represents a valid IRI
11776          *
11777          * @access private
11778          * @var array
11779          */
11780         var $valid = array();
11781
11782         /**
11783          * Return the entire IRI when you try and read the object as a string
11784          *
11785          * @access public
11786          * @return string
11787          */
11788         function __toString()
11789         {
11790                 return $this->get_iri();
11791         }
11792
11793         /**
11794          * Create a new IRI object, from a specified string
11795          *
11796          * @access public
11797          * @param string $iri
11798          * @return SimplePie_IRI
11799          */
11800         function SimplePie_IRI($iri)
11801         {
11802                 $iri = (string) $iri;
11803                 if ($iri !== '')
11804                 {
11805                         $parsed = $this->parse_iri($iri);
11806                         $this->set_scheme($parsed['scheme']);
11807                         $this->set_authority($parsed['authority']);
11808                         $this->set_path($parsed['path']);
11809                         $this->set_query($parsed['query']);
11810                         $this->set_fragment($parsed['fragment']);
11811                 }
11812         }
11813
11814         /**
11815          * Create a new IRI object by resolving a relative IRI
11816          *
11817          * @static
11818          * @access public
11819          * @param SimplePie_IRI $base Base IRI
11820          * @param string $relative Relative IRI
11821          * @return SimplePie_IRI
11822          */
11823         function absolutize($base, $relative)
11824         {
11825                 $relative = (string) $relative;
11826                 if ($relative !== '')
11827                 {
11828                         $relative = new SimplePie_IRI($relative);
11829                         if ($relative->get_scheme() !== null)
11830                         {
11831                                 $target = $relative;
11832                         }
11833                         elseif ($base->get_iri() !== null)
11834                         {
11835                                 if ($relative->get_authority() !== null)
11836                                 {
11837                                         $target = $relative;
11838                                         $target->set_scheme($base->get_scheme());
11839                                 }
11840                                 else
11841                                 {
11842                                         $target = new SimplePie_IRI('');
11843                                         $target->set_scheme($base->get_scheme());
11844                                         $target->set_userinfo($base->get_userinfo());
11845                                         $target->set_host($base->get_host());
11846                                         $target->set_port($base->get_port());
11847                                         if ($relative->get_path() !== null)
11848                                         {
11849                                                 if (strpos($relative->get_path(), '/') === 0)
11850                                                 {
11851                                                         $target->set_path($relative->get_path());
11852                                                 }
11853                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11854                                                 {
11855                                                         $target->set_path('/' . $relative->get_path());
11856                                                 }
11857                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11858                                                 {
11859                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11860                                                 }
11861                                                 else
11862                                                 {
11863                                                         $target->set_path($relative->get_path());
11864                                                 }
11865                                                 $target->set_query($relative->get_query());
11866                                         }
11867                                         else
11868                                         {
11869                                                 $target->set_path($base->get_path());
11870                                                 if ($relative->get_query() !== null)
11871                                                 {
11872                                                         $target->set_query($relative->get_query());
11873                                                 }
11874                                                 elseif ($base->get_query() !== null)
11875                                                 {
11876                                                         $target->set_query($base->get_query());
11877                                                 }
11878                                         }
11879                                 }
11880                                 $target->set_fragment($relative->get_fragment());
11881                         }
11882                         else
11883                         {
11884                                 // No base URL, just return the relative URL
11885                                 $target = $relative;
11886                         }
11887                 }
11888                 else
11889                 {
11890                         $target = $base;
11891                 }
11892                 return $target;
11893         }
11894
11895         /**
11896          * Parse an IRI into scheme/authority/path/query/fragment segments
11897          *
11898          * @access private
11899          * @param string $iri
11900          * @return array
11901          */
11902         function parse_iri($iri)
11903         {
11904                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11905                 for ($i = count($match); $i <= 9; $i++)
11906                 {
11907                         $match[$i] = '';
11908                 }
11909                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11910         }
11911
11912         /**
11913          * Remove dot segments from a path
11914          *
11915          * @access private
11916          * @param string $input
11917          * @return string
11918          */
11919         function remove_dot_segments($input)
11920         {
11921                 $output = '';
11922                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11923                 {
11924                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11925                         if (strpos($input, '../') === 0)
11926                         {
11927                                 $input = substr($input, 3);
11928                         }
11929                         elseif (strpos($input, './') === 0)
11930                         {
11931                                 $input = substr($input, 2);
11932                         }
11933                         // 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,
11934                         elseif (strpos($input, '/./') === 0)
11935                         {
11936                                 $input = substr_replace($input, '/', 0, 3);
11937                         }
11938                         elseif ($input === '/.')
11939                         {
11940                                 $input = '/';
11941                         }
11942                         // 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,
11943                         elseif (strpos($input, '/../') === 0)
11944                         {
11945                                 $input = substr_replace($input, '/', 0, 4);
11946                                 $output = substr_replace($output, '', strrpos($output, '/'));
11947                         }
11948                         elseif ($input === '/..')
11949                         {
11950                                 $input = '/';
11951                                 $output = substr_replace($output, '', strrpos($output, '/'));
11952                         }
11953                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11954                         elseif ($input === '.' || $input === '..')
11955                         {
11956                                 $input = '';
11957                         }
11958                         // 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
11959                         elseif (($pos = strpos($input, '/', 1)) !== false)
11960                         {
11961                                 $output .= substr($input, 0, $pos);
11962                                 $input = substr_replace($input, '', 0, $pos);
11963                         }
11964                         else
11965                         {
11966                                 $output .= $input;
11967                                 $input = '';
11968                         }
11969                 }
11970                 return $output . $input;
11971         }
11972
11973         /**
11974          * Replace invalid character with percent encoding
11975          *
11976          * @access private
11977          * @param string $string Input string
11978          * @param string $valid_chars Valid characters
11979          * @param int $case Normalise case
11980          * @return string
11981          */
11982         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11983         {
11984                 // Normalise case
11985                 if ($case & SIMPLEPIE_LOWERCASE)
11986                 {
11987                         $string = strtolower($string);
11988                 }
11989                 elseif ($case & SIMPLEPIE_UPPERCASE)
11990                 {
11991                         $string = strtoupper($string);
11992                 }
11993
11994                 // Store position and string length (to avoid constantly recalculating this)
11995                 $position = 0;
11996                 $strlen = strlen($string);
11997
11998                 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11999                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
12000                 {
12001                         // If we have a % character
12002                         if ($string[$position] === '%')
12003                         {
12004                                 // If we have a pct-encoded section
12005                                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
12006                                 {
12007                                         // Get the the represented character
12008                                         $chr = chr(hexdec(substr($string, $position + 1, 2)));
12009
12010                                         // If the character is valid, replace the pct-encoded with the actual character while normalising case
12011                                         if (strpos($valid_chars, $chr) !== false)
12012                                         {
12013                                                 if ($case & SIMPLEPIE_LOWERCASE)
12014                                                 {
12015                                                         $chr = strtolower($chr);
12016                                                 }
12017                                                 elseif ($case & SIMPLEPIE_UPPERCASE)
12018                                                 {
12019                                                         $chr = strtoupper($chr);
12020                                                 }
12021                                                 $string = substr_replace($string, $chr, $position, 3);
12022                                                 $strlen -= 2;
12023                                                 $position++;
12024                                         }
12025
12026                                         // Otherwise just normalise the pct-encoded to uppercase
12027                                         else
12028                                         {
12029                                                 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
12030                                                 $position += 3;
12031                                         }
12032                                 }
12033                                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
12034                                 else
12035                                 {
12036                                         $string = substr_replace($string, '%25', $position, 1);
12037                                         $strlen += 2;
12038                                         $position += 3;
12039                                 }
12040                         }
12041                         // If we have an invalid character, change into its pct-encoded form
12042                         else
12043                         {
12044                                 $replacement = sprintf("%%%02X", ord($string[$position]));
12045                                 $string = str_replace($string[$position], $replacement, $string);
12046                                 $strlen = strlen($string);
12047                         }
12048                 }
12049                 return $string;
12050         }
12051
12052         /**
12053          * Check if the object represents a valid IRI
12054          *
12055          * @access public
12056          * @return bool
12057          */
12058         function is_valid()
12059         {
12060                 return array_sum($this->valid) === count($this->valid);
12061         }
12062
12063         /**
12064          * Set the scheme. Returns true on success, false on failure (if there are
12065          * any invalid characters).
12066          *
12067          * @access public
12068          * @param string $scheme
12069          * @return bool
12070          */
12071         function set_scheme($scheme)
12072         {
12073                 if ($scheme === null || $scheme === '')
12074                 {
12075                         $this->scheme = null;
12076                 }
12077                 else
12078                 {
12079                         $len = strlen($scheme);
12080                         switch (true)
12081                         {
12082                                 case $len > 1:
12083                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12084                                         {
12085                                                 $this->scheme = null;
12086                                                 $this->valid[__FUNCTION__] = false;
12087                                                 return false;
12088                                         }
12089
12090                                 case $len > 0:
12091                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12092                                         {
12093                                                 $this->scheme = null;
12094                                                 $this->valid[__FUNCTION__] = false;
12095                                                 return false;
12096                                         }
12097                         }
12098                         $this->scheme = strtolower($scheme);
12099                 }
12100                 $this->valid[__FUNCTION__] = true;
12101                 return true;
12102         }
12103
12104         /**
12105          * Set the authority. Returns true on success, false on failure (if there are
12106          * any invalid characters).
12107          *
12108          * @access public
12109          * @param string $authority
12110          * @return bool
12111          */
12112         function set_authority($authority)
12113         {
12114                 if (($userinfo_end = strrpos($authority, '@')) !== false)
12115                 {
12116                         $userinfo = substr($authority, 0, $userinfo_end);
12117                         $authority = substr($authority, $userinfo_end + 1);
12118                 }
12119                 else
12120                 {
12121                         $userinfo = null;
12122                 }
12123
12124                 if (($port_start = strpos($authority, ':')) !== false)
12125                 {
12126                         $port = substr($authority, $port_start + 1);
12127                         $authority = substr($authority, 0, $port_start);
12128                 }
12129                 else
12130                 {
12131                         $port = null;
12132                 }
12133
12134                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12135         }
12136
12137         /**
12138          * Set the userinfo.
12139          *
12140          * @access public
12141          * @param string $userinfo
12142          * @return bool
12143          */
12144         function set_userinfo($userinfo)
12145         {
12146                 if ($userinfo === null || $userinfo === '')
12147                 {
12148                         $this->userinfo = null;
12149                 }
12150                 else
12151                 {
12152                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12153                 }
12154                 $this->valid[__FUNCTION__] = true;
12155                 return true;
12156         }
12157
12158         /**
12159          * Set the host. Returns true on success, false on failure (if there are
12160          * any invalid characters).
12161          *
12162          * @access public
12163          * @param string $host
12164          * @return bool
12165          */
12166         function set_host($host)
12167         {
12168                 if ($host === null || $host === '')
12169                 {
12170                         $this->host = null;
12171                         $this->valid[__FUNCTION__] = true;
12172                         return true;
12173                 }
12174                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12175                 {
12176                         if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12177                         {
12178                                 $this->host = $host;
12179                                 $this->valid[__FUNCTION__] = true;
12180                                 return true;
12181                         }
12182                         else
12183                         {
12184                                 $this->host = null;
12185                                 $this->valid[__FUNCTION__] = false;
12186                                 return false;
12187                         }
12188                 }
12189                 else
12190                 {
12191                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12192                         $this->valid[__FUNCTION__] = true;
12193                         return true;
12194                 }
12195         }
12196
12197         /**
12198          * Set the port. Returns true on success, false on failure (if there are
12199          * any invalid characters).
12200          *
12201          * @access public
12202          * @param string $port
12203          * @return bool
12204          */
12205         function set_port($port)
12206         {
12207                 if ($port === null || $port === '')
12208                 {
12209                         $this->port = null;
12210                         $this->valid[__FUNCTION__] = true;
12211                         return true;
12212                 }
12213                 elseif (strspn($port, '0123456789') === strlen($port))
12214                 {
12215                         $this->port = (int) $port;
12216                         $this->valid[__FUNCTION__] = true;
12217                         return true;
12218                 }
12219                 else
12220                 {
12221                         $this->port = null;
12222                         $this->valid[__FUNCTION__] = false;
12223                         return false;
12224                 }
12225         }
12226
12227         /**
12228          * Set the path.
12229          *
12230          * @access public
12231          * @param string $path
12232          * @return bool
12233          */
12234         function set_path($path)
12235         {
12236                 if ($path === null || $path === '')
12237                 {
12238                         $this->path = null;
12239                         $this->valid[__FUNCTION__] = true;
12240                         return true;
12241                 }
12242                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12243                 {
12244                         $this->path = null;
12245                         $this->valid[__FUNCTION__] = false;
12246                         return false;
12247                 }
12248                 else
12249                 {
12250                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12251                         if ($this->scheme !== null)
12252                         {
12253                                 $this->path = $this->remove_dot_segments($this->path);
12254                         }
12255                         $this->valid[__FUNCTION__] = true;
12256                         return true;
12257                 }
12258         }
12259
12260         /**
12261          * Set the query.
12262          *
12263          * @access public
12264          * @param string $query
12265          * @return bool
12266          */
12267         function set_query($query)
12268         {
12269                 if ($query === null || $query === '')
12270                 {
12271                         $this->query = null;
12272                 }
12273                 else
12274                 {
12275                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
12276                 }
12277                 $this->valid[__FUNCTION__] = true;
12278                 return true;
12279         }
12280
12281         /**
12282          * Set the fragment.
12283          *
12284          * @access public
12285          * @param string $fragment
12286          * @return bool
12287          */
12288         function set_fragment($fragment)
12289         {
12290                 if ($fragment === null || $fragment === '')
12291                 {
12292                         $this->fragment = null;
12293                 }
12294                 else
12295                 {
12296                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12297                 }
12298                 $this->valid[__FUNCTION__] = true;
12299                 return true;
12300         }
12301
12302         /**
12303          * Get the complete IRI
12304          *
12305          * @access public
12306          * @return string
12307          */
12308         function get_iri()
12309         {
12310                 $iri = '';
12311                 if ($this->scheme !== null)
12312                 {
12313                         $iri .= $this->scheme . ':';
12314                 }
12315                 if (($authority = $this->get_authority()) !== null)
12316                 {
12317                         $iri .= '//' . $authority;
12318                 }
12319                 if ($this->path !== null)
12320                 {
12321                         $iri .= $this->path;
12322                 }
12323                 if ($this->query !== null)
12324                 {
12325                         $iri .= '?' . $this->query;
12326                 }
12327                 if ($this->fragment !== null)
12328                 {
12329                         $iri .= '#' . $this->fragment;
12330                 }
12331
12332                 if ($iri !== '')
12333                 {
12334                         return $iri;
12335                 }
12336                 else
12337                 {
12338                         return null;
12339                 }
12340         }
12341
12342         /**
12343          * Get the scheme
12344          *
12345          * @access public
12346          * @return string
12347          */
12348         function get_scheme()
12349         {
12350                 return $this->scheme;
12351         }
12352
12353         /**
12354          * Get the complete authority
12355          *
12356          * @access public
12357          * @return string
12358          */
12359         function get_authority()
12360         {
12361                 $authority = '';
12362                 if ($this->userinfo !== null)
12363                 {
12364                         $authority .= $this->userinfo . '@';
12365                 }
12366                 if ($this->host !== null)
12367                 {
12368                         $authority .= $this->host;
12369                 }
12370                 if ($this->port !== null)
12371                 {
12372                         $authority .= ':' . $this->port;
12373                 }
12374
12375                 if ($authority !== '')
12376                 {
12377                         return $authority;
12378                 }
12379                 else
12380                 {
12381                         return null;
12382                 }
12383         }
12384
12385         /**
12386          * Get the user information
12387          *
12388          * @access public
12389          * @return string
12390          */
12391         function get_userinfo()
12392         {
12393                 return $this->userinfo;
12394         }
12395
12396         /**
12397          * Get the host
12398          *
12399          * @access public
12400          * @return string
12401          */
12402         function get_host()
12403         {
12404                 return $this->host;
12405         }
12406
12407         /**
12408          * Get the port
12409          *
12410          * @access public
12411          * @return string
12412          */
12413         function get_port()
12414         {
12415                 return $this->port;
12416         }
12417
12418         /**
12419          * Get the path
12420          *
12421          * @access public
12422          * @return string
12423          */
12424         function get_path()
12425         {
12426                 return $this->path;
12427         }
12428
12429         /**
12430          * Get the query
12431          *
12432          * @access public
12433          * @return string
12434          */
12435         function get_query()
12436         {
12437                 return $this->query;
12438         }
12439
12440         /**
12441          * Get the fragment
12442          *
12443          * @access public
12444          * @return string
12445          */
12446         function get_fragment()
12447         {
12448                 return $this->fragment;
12449         }
12450 }
12451
12452 /**
12453  * Class to validate and to work with IPv6 addresses.
12454  *
12455  * @package SimplePie
12456  * @copyright 2003-2005 The PHP Group
12457  * @license http://www.opensource.org/licenses/bsd-license.php
12458  * @link http://pear.php.net/package/Net_IPv6
12459  * @author Alexander Merz <alexander.merz@web.de>
12460  * @author elfrink at introweb dot nl
12461  * @author Josh Peck <jmp at joshpeck dot org>
12462  * @author Geoffrey Sneddon <geoffers@gmail.com>
12463  */
12464 class SimplePie_Net_IPv6
12465 {
12466         /**
12467          * Removes a possible existing netmask specification of an IP address.
12468          *
12469          * @param string $ip the (compressed) IP as Hex representation
12470          * @return string the IP the without netmask
12471          * @since 1.1.0
12472          * @access public
12473          * @static
12474          */
12475         function removeNetmaskSpec($ip)
12476         {
12477                 if (strpos($ip, '/') !== false)
12478                 {
12479                         list($addr, $nm) = explode('/', $ip);
12480                 }
12481                 else
12482                 {
12483                         $addr = $ip;
12484                 }
12485                 return $addr;
12486         }
12487
12488         /**
12489          * Uncompresses an IPv6 address
12490          *
12491          * RFC 2373 allows you to compress zeros in an address to '::'. This
12492          * function expects an valid IPv6 address and expands the '::' to
12493          * the required zeros.
12494          *
12495          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12496          *                       ::1            ->      0:0:0:0:0:0:0:1
12497          *
12498          * @access public
12499          * @static
12500          * @param string $ip a valid IPv6-address (hex format)
12501          * @return string the uncompressed IPv6-address (hex format)
12502          */
12503         function Uncompress($ip)
12504         {
12505                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12506                 $c1 = -1;
12507                 $c2 = -1;
12508                 if (strpos($ip, '::') !== false)
12509                 {
12510                         list($ip1, $ip2) = explode('::', $ip);
12511                         if ($ip1 === '')
12512                         {
12513                                 $c1 = -1;
12514                         }
12515                         else
12516                         {
12517                                 $pos = 0;
12518                                 if (($pos = substr_count($ip1, ':')) > 0)
12519                                 {
12520                                         $c1 = $pos;
12521                                 }
12522                                 else
12523                                 {
12524                                         $c1 = 0;
12525                                 }
12526                         }
12527                         if ($ip2 === '')
12528                         {
12529                                 $c2 = -1;
12530                         }
12531                         else
12532                         {
12533                                 $pos = 0;
12534                                 if (($pos = substr_count($ip2, ':')) > 0)
12535                                 {
12536                                         $c2 = $pos;
12537                                 }
12538                                 else
12539                                 {
12540                                         $c2 = 0;
12541                                 }
12542                         }
12543                         if (strstr($ip2, '.'))
12544                         {
12545                                 $c2++;
12546                         }
12547                         // ::
12548                         if ($c1 === -1 && $c2 === -1)
12549                         {
12550                                 $uip = '0:0:0:0:0:0:0:0';
12551                         }
12552                         // ::xxx
12553                         else if ($c1 === -1)
12554                         {
12555                                 $fill = str_repeat('0:', 7 - $c2);
12556                                 $uip =  str_replace('::', $fill, $uip);
12557                         }
12558                         // xxx::
12559                         else if ($c2 === -1)
12560                         {
12561                                 $fill = str_repeat(':0', 7 - $c1);
12562                                 $uip =  str_replace('::', $fill, $uip);
12563                         }
12564                         // xxx::xxx
12565                         else
12566                         {
12567                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12568                                 $uip =  str_replace('::', $fill, $uip);
12569                                 $uip =  str_replace('::', ':', $uip);
12570                         }
12571                 }
12572                 return $uip;
12573         }
12574
12575         /**
12576          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12577          *
12578          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12579          * an IPv4 compatible address
12580          *
12581          * Example:      0:0:0:0:0:0:13.1.68.3
12582          *                       0:0:0:0:0:FFFF:129.144.52.38
12583          *
12584          * @access public
12585          * @static
12586          * @param string $ip a valid IPv6-address (hex format)
12587          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12588          */
12589         function SplitV64($ip)
12590         {
12591                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12592                 if (strstr($ip, '.'))
12593                 {
12594                         $pos = strrpos($ip, ':');
12595                         $ip[$pos] = '_';
12596                         $ipPart = explode('_', $ip);
12597                         return $ipPart;
12598                 }
12599                 else
12600                 {
12601                         return array($ip, '');
12602                 }
12603         }
12604
12605         /**
12606          * Checks an IPv6 address
12607          *
12608          * Checks if the given IP is IPv6-compatible
12609          *
12610          * @access public
12611          * @static
12612          * @param string $ip a valid IPv6-address
12613          * @return bool true if $ip is an IPv6 address
12614          */
12615         function checkIPv6($ip)
12616         {
12617                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12618                 $count = 0;
12619                 if (!empty($ipPart[0]))
12620                 {
12621                         $ipv6 = explode(':', $ipPart[0]);
12622                         for ($i = 0; $i < count($ipv6); $i++)
12623                         {
12624                                 $dec = hexdec($ipv6[$i]);
12625                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12626                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12627                                 {
12628                                         $count++;
12629                                 }
12630                         }
12631                         if ($count === 8)
12632                         {
12633                                 return true;
12634                         }
12635                         elseif ($count === 6 && !empty($ipPart[1]))
12636                         {
12637                                 $ipv4 = explode('.', $ipPart[1]);
12638                                 $count = 0;
12639                                 foreach ($ipv4 as $ipv4_part)
12640                                 {
12641                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12642                                         {
12643                                                 $count++;
12644                                         }
12645                                 }
12646                                 if ($count === 4)
12647                                 {
12648                                         return true;
12649                                 }
12650                         }
12651                         else
12652                         {
12653                                 return false;
12654                         }
12655
12656                 }
12657                 else
12658                 {
12659                         return false;
12660                 }
12661         }
12662 }
12663
12664 /**
12665  * Date Parser
12666  *
12667  * @package SimplePie
12668  */
12669 class SimplePie_Parse_Date
12670 {
12671         /**
12672          * Input data
12673          *
12674          * @access protected
12675          * @var string
12676          */
12677         var $date;
12678
12679         /**
12680          * List of days, calendar day name => ordinal day number in the week
12681          *
12682          * @access protected
12683          * @var array
12684          */
12685         var $day = array(
12686                 // English
12687                 'mon' => 1,
12688                 'monday' => 1,
12689                 'tue' => 2,
12690                 'tuesday' => 2,
12691                 'wed' => 3,
12692                 'wednesday' => 3,
12693                 'thu' => 4,
12694                 'thursday' => 4,
12695                 'fri' => 5,
12696                 'friday' => 5,
12697                 'sat' => 6,
12698                 'saturday' => 6,
12699                 'sun' => 7,
12700                 'sunday' => 7,
12701                 // Dutch
12702                 'maandag' => 1,
12703                 'dinsdag' => 2,
12704                 'woensdag' => 3,
12705                 'donderdag' => 4,
12706                 'vrijdag' => 5,
12707                 'zaterdag' => 6,
12708                 'zondag' => 7,
12709                 // French
12710                 'lundi' => 1,
12711                 'mardi' => 2,
12712                 'mercredi' => 3,
12713                 'jeudi' => 4,
12714                 'vendredi' => 5,
12715                 'samedi' => 6,
12716                 'dimanche' => 7,
12717                 // German
12718                 'montag' => 1,
12719                 'dienstag' => 2,
12720                 'mittwoch' => 3,
12721                 'donnerstag' => 4,
12722                 'freitag' => 5,
12723                 'samstag' => 6,
12724                 'sonnabend' => 6,
12725                 'sonntag' => 7,
12726                 // Italian
12727                 'lunedì' => 1,
12728                 'martedì' => 2,
12729                 'mercoledì' => 3,
12730                 'giovedì' => 4,
12731                 'venerdì' => 5,
12732                 'sabato' => 6,
12733                 'domenica' => 7,
12734                 // Spanish
12735                 'lunes' => 1,
12736                 'martes' => 2,
12737                 'miércoles' => 3,
12738                 'jueves' => 4,
12739                 'viernes' => 5,
12740                 'sábado' => 6,
12741                 'domingo' => 7,
12742                 // Finnish
12743                 'maanantai' => 1,
12744                 'tiistai' => 2,
12745                 'keskiviikko' => 3,
12746                 'torstai' => 4,
12747                 'perjantai' => 5,
12748                 'lauantai' => 6,
12749                 'sunnuntai' => 7,
12750                 // Hungarian
12751                 'hétfő' => 1,
12752                 'kedd' => 2,
12753                 'szerda' => 3,
12754                 'csütörtok' => 4,
12755                 'péntek' => 5,
12756                 'szombat' => 6,
12757                 'vasárnap' => 7,
12758                 // Greek
12759                 'Δευ' => 1,
12760                 'Τρι' => 2,
12761                 'Τετ' => 3,
12762                 'Πεμ' => 4,
12763                 'Παρ' => 5,
12764                 'Σαβ' => 6,
12765                 'Κυρ' => 7,
12766         );
12767
12768         /**
12769          * List of months, calendar month name => calendar month number
12770          *
12771          * @access protected
12772          * @var array
12773          */
12774         var $month = array(
12775                 // English
12776                 'jan' => 1,
12777                 'january' => 1,
12778                 'feb' => 2,
12779                 'february' => 2,
12780                 'mar' => 3,
12781                 'march' => 3,
12782                 'apr' => 4,
12783                 'april' => 4,
12784                 'may' => 5,
12785                 // No long form of May
12786                 'jun' => 6,
12787                 'june' => 6,
12788                 'jul' => 7,
12789                 'july' => 7,
12790                 'aug' => 8,
12791                 'august' => 8,
12792                 'sep' => 9,
12793                 'september' => 8,
12794                 'oct' => 10,
12795                 'october' => 10,
12796                 'nov' => 11,
12797                 'november' => 11,
12798                 'dec' => 12,
12799                 'december' => 12,
12800                 // Dutch
12801                 'januari' => 1,
12802                 'februari' => 2,
12803                 'maart' => 3,
12804                 'april' => 4,
12805                 'mei' => 5,
12806                 'juni' => 6,
12807                 'juli' => 7,
12808                 'augustus' => 8,
12809                 'september' => 9,
12810                 'oktober' => 10,
12811                 'november' => 11,
12812                 'december' => 12,
12813                 // French
12814                 'janvier' => 1,
12815                 'février' => 2,
12816                 'mars' => 3,
12817                 'avril' => 4,
12818                 'mai' => 5,
12819                 'juin' => 6,
12820                 'juillet' => 7,
12821                 'août' => 8,
12822                 'septembre' => 9,
12823                 'octobre' => 10,
12824                 'novembre' => 11,
12825                 'décembre' => 12,
12826                 // German
12827                 'januar' => 1,
12828                 'februar' => 2,
12829                 'märz' => 3,
12830                 'april' => 4,
12831                 'mai' => 5,
12832                 'juni' => 6,
12833                 'juli' => 7,
12834                 'august' => 8,
12835                 'september' => 9,
12836                 'oktober' => 10,
12837                 'november' => 11,
12838                 'dezember' => 12,
12839                 // Italian
12840                 'gennaio' => 1,
12841                 'febbraio' => 2,
12842                 'marzo' => 3,
12843                 'aprile' => 4,
12844                 'maggio' => 5,
12845                 'giugno' => 6,
12846                 'luglio' => 7,
12847                 'agosto' => 8,
12848                 'settembre' => 9,
12849                 'ottobre' => 10,
12850                 'novembre' => 11,
12851                 'dicembre' => 12,
12852                 // Spanish
12853                 'enero' => 1,
12854                 'febrero' => 2,
12855                 'marzo' => 3,
12856                 'abril' => 4,
12857                 'mayo' => 5,
12858                 'junio' => 6,
12859                 'julio' => 7,
12860                 'agosto' => 8,
12861                 'septiembre' => 9,
12862                 'setiembre' => 9,
12863                 'octubre' => 10,
12864                 'noviembre' => 11,
12865                 'diciembre' => 12,
12866                 // Finnish
12867                 'tammikuu' => 1,
12868                 'helmikuu' => 2,
12869                 'maaliskuu' => 3,
12870                 'huhtikuu' => 4,
12871                 'toukokuu' => 5,
12872                 'kesäkuu' => 6,
12873                 'heinäkuu' => 7,
12874                 'elokuu' => 8,
12875                 'suuskuu' => 9,
12876                 'lokakuu' => 10,
12877                 'marras' => 11,
12878                 'joulukuu' => 12,
12879                 // Hungarian
12880                 'január' => 1,
12881                 'február' => 2,
12882                 'március' => 3,
12883                 'április' => 4,
12884                 'május' => 5,
12885                 'június' => 6,
12886                 'július' => 7,
12887                 'augusztus' => 8,
12888                 'szeptember' => 9,
12889                 'október' => 10,
12890                 'november' => 11,
12891                 'december' => 12,
12892                 // Greek
12893                 'Ιαν' => 1,
12894                 'Φεβ' => 2,
12895                 'Μάώ' => 3,
12896                 'Μαώ' => 3,
12897                 'Απρ' => 4,
12898                 'Μάι' => 5,
12899                 'Μαϊ' => 5,
12900                 'Μαι' => 5,
12901                 'Ιούν' => 6,
12902                 'Ιον' => 6,
12903                 'Ιούλ' => 7,
12904                 'Ιολ' => 7,
12905                 'Αύγ' => 8,
12906                 'Αυγ' => 8,
12907                 'Σεπ' => 9,
12908                 'Οκτ' => 10,
12909                 'Νοέ' => 11,
12910                 'Δεκ' => 12,
12911         );
12912
12913         /**
12914          * List of timezones, abbreviation => offset from UTC
12915          *
12916          * @access protected
12917          * @var array
12918          */
12919         var $timezone = array(
12920                 'ACDT' => 37800,
12921                 'ACIT' => 28800,
12922                 'ACST' => 34200,
12923                 'ACT' => -18000,
12924                 'ACWDT' => 35100,
12925                 'ACWST' => 31500,
12926                 'AEDT' => 39600,
12927                 'AEST' => 36000,
12928                 'AFT' => 16200,
12929                 'AKDT' => -28800,
12930                 'AKST' => -32400,
12931                 'AMDT' => 18000,
12932                 'AMT' => -14400,
12933                 'ANAST' => 46800,
12934                 'ANAT' => 43200,
12935                 'ART' => -10800,
12936                 'AZOST' => -3600,
12937                 'AZST' => 18000,
12938                 'AZT' => 14400,
12939                 'BIOT' => 21600,
12940                 'BIT' => -43200,
12941                 'BOT' => -14400,
12942                 'BRST' => -7200,
12943                 'BRT' => -10800,
12944                 'BST' => 3600,
12945                 'BTT' => 21600,
12946                 'CAST' => 18000,
12947                 'CAT' => 7200,
12948                 'CCT' => 23400,
12949                 'CDT' => -18000,
12950                 'CEDT' => 7200,
12951                 'CET' => 3600,
12952                 'CGST' => -7200,
12953                 'CGT' => -10800,
12954                 'CHADT' => 49500,
12955                 'CHAST' => 45900,
12956                 'CIST' => -28800,
12957                 'CKT' => -36000,
12958                 'CLDT' => -10800,
12959                 'CLST' => -14400,
12960                 'COT' => -18000,
12961                 'CST' => -21600,
12962                 'CVT' => -3600,
12963                 'CXT' => 25200,
12964                 'DAVT' => 25200,
12965                 'DTAT' => 36000,
12966                 'EADT' => -18000,
12967                 'EAST' => -21600,
12968                 'EAT' => 10800,
12969                 'ECT' => -18000,
12970                 'EDT' => -14400,
12971                 'EEST' => 10800,
12972                 'EET' => 7200,
12973                 'EGT' => -3600,
12974                 'EKST' => 21600,
12975                 'EST' => -18000,
12976                 'FJT' => 43200,
12977                 'FKDT' => -10800,
12978                 'FKST' => -14400,
12979                 'FNT' => -7200,
12980                 'GALT' => -21600,
12981                 'GEDT' => 14400,
12982                 'GEST' => 10800,
12983                 'GFT' => -10800,
12984                 'GILT' => 43200,
12985                 'GIT' => -32400,
12986                 'GST' => 14400,
12987                 'GST' => -7200,
12988                 'GYT' => -14400,
12989                 'HAA' => -10800,
12990                 'HAC' => -18000,
12991                 'HADT' => -32400,
12992                 'HAE' => -14400,
12993                 'HAP' => -25200,
12994                 'HAR' => -21600,
12995                 'HAST' => -36000,
12996                 'HAT' => -9000,
12997                 'HAY' => -28800,
12998                 'HKST' => 28800,
12999                 'HMT' => 18000,
13000                 'HNA' => -14400,
13001                 'HNC' => -21600,
13002                 'HNE' => -18000,
13003                 'HNP' => -28800,
13004                 'HNR' => -25200,
13005                 'HNT' => -12600,
13006                 'HNY' => -32400,
13007                 'IRDT' => 16200,
13008                 'IRKST' => 32400,
13009                 'IRKT' => 28800,
13010                 'IRST' => 12600,
13011                 'JFDT' => -10800,
13012                 'JFST' => -14400,
13013                 'JST' => 32400,
13014                 'KGST' => 21600,
13015                 'KGT' => 18000,
13016                 'KOST' => 39600,
13017                 'KOVST' => 28800,
13018                 'KOVT' => 25200,
13019                 'KRAST' => 28800,
13020                 'KRAT' => 25200,
13021                 'KST' => 32400,
13022                 'LHDT' => 39600,
13023                 'LHST' => 37800,
13024                 'LINT' => 50400,
13025                 'LKT' => 21600,
13026                 'MAGST' => 43200,
13027                 'MAGT' => 39600,
13028                 'MAWT' => 21600,
13029                 'MDT' => -21600,
13030                 'MESZ' => 7200,
13031                 'MEZ' => 3600,
13032                 'MHT' => 43200,
13033                 'MIT' => -34200,
13034                 'MNST' => 32400,
13035                 'MSDT' => 14400,
13036                 'MSST' => 10800,
13037                 'MST' => -25200,
13038                 'MUT' => 14400,
13039                 'MVT' => 18000,
13040                 'MYT' => 28800,
13041                 'NCT' => 39600,
13042                 'NDT' => -9000,
13043                 'NFT' => 41400,
13044                 'NMIT' => 36000,
13045                 'NOVST' => 25200,
13046                 'NOVT' => 21600,
13047                 'NPT' => 20700,
13048                 'NRT' => 43200,
13049                 'NST' => -12600,
13050                 'NUT' => -39600,
13051                 'NZDT' => 46800,
13052                 'NZST' => 43200,
13053                 'OMSST' => 25200,
13054                 'OMST' => 21600,
13055                 'PDT' => -25200,
13056                 'PET' => -18000,
13057                 'PETST' => 46800,
13058                 'PETT' => 43200,
13059                 'PGT' => 36000,
13060                 'PHOT' => 46800,
13061                 'PHT' => 28800,
13062                 'PKT' => 18000,
13063                 'PMDT' => -7200,
13064                 'PMST' => -10800,
13065                 'PONT' => 39600,
13066                 'PST' => -28800,
13067                 'PWT' => 32400,
13068                 'PYST' => -10800,
13069                 'PYT' => -14400,
13070                 'RET' => 14400,
13071                 'ROTT' => -10800,
13072                 'SAMST' => 18000,
13073                 'SAMT' => 14400,
13074                 'SAST' => 7200,
13075                 'SBT' => 39600,
13076                 'SCDT' => 46800,
13077                 'SCST' => 43200,
13078                 'SCT' => 14400,
13079                 'SEST' => 3600,
13080                 'SGT' => 28800,
13081                 'SIT' => 28800,
13082                 'SRT' => -10800,
13083                 'SST' => -39600,
13084                 'SYST' => 10800,
13085                 'SYT' => 7200,
13086                 'TFT' => 18000,
13087                 'THAT' => -36000,
13088                 'TJT' => 18000,
13089                 'TKT' => -36000,
13090                 'TMT' => 18000,
13091                 'TOT' => 46800,
13092                 'TPT' => 32400,
13093                 'TRUT' => 36000,
13094                 'TVT' => 43200,
13095                 'TWT' => 28800,
13096                 'UYST' => -7200,
13097                 'UYT' => -10800,
13098                 'UZT' => 18000,
13099                 'VET' => -14400,
13100                 'VLAST' => 39600,
13101                 'VLAT' => 36000,
13102                 'VOST' => 21600,
13103                 'VUT' => 39600,
13104                 'WAST' => 7200,
13105                 'WAT' => 3600,
13106                 'WDT' => 32400,
13107                 'WEST' => 3600,
13108                 'WFT' => 43200,
13109                 'WIB' => 25200,
13110                 'WIT' => 32400,
13111                 'WITA' => 28800,
13112                 'WKST' => 18000,
13113                 'WST' => 28800,
13114                 'YAKST' => 36000,
13115                 'YAKT' => 32400,
13116                 'YAPT' => 36000,
13117                 'YEKST' => 21600,
13118                 'YEKT' => 18000,
13119         );
13120
13121         /**
13122          * Cached PCRE for SimplePie_Parse_Date::$day
13123          *
13124          * @access protected
13125          * @var string
13126          */
13127         var $day_pcre;
13128
13129         /**
13130          * Cached PCRE for SimplePie_Parse_Date::$month
13131          *
13132          * @access protected
13133          * @var string
13134          */
13135         var $month_pcre;
13136
13137         /**
13138          * Array of user-added callback methods
13139          *
13140          * @access private
13141          * @var array
13142          */
13143         var $built_in = array();
13144
13145         /**
13146          * Array of user-added callback methods
13147          *
13148          * @access private
13149          * @var array
13150          */
13151         var $user = array();
13152
13153         /**
13154          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13155          * self::month_pcre, and self::built_in
13156          *
13157          * @access private
13158          */
13159         function SimplePie_Parse_Date()
13160         {
13161                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13162                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13163
13164                 static $cache;
13165                 if (!isset($cache[get_class($this)]))
13166                 {
13167                         $all_methods = get_class_methods($this);
13168
13169                         foreach ($all_methods as $method)
13170                         {
13171                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13172                                 {
13173                                         $cache[get_class($this)][] = $method;
13174                                 }
13175                         }
13176                 }
13177
13178                 foreach ($cache[get_class($this)] as $method)
13179                 {
13180                         $this->built_in[] = $method;
13181                 }
13182         }
13183
13184         /**
13185          * Get the object
13186          *
13187          * @access public
13188          */
13189         function get()
13190         {
13191                 static $object;
13192                 if (!$object)
13193                 {
13194                         $object = new SimplePie_Parse_Date;
13195                 }
13196                 return $object;
13197         }
13198
13199         /**
13200          * Parse a date
13201          *
13202          * @final
13203          * @access public
13204          * @param string $date Date to parse
13205          * @return int Timestamp corresponding to date string, or false on failure
13206          */
13207         function parse($date)
13208         {
13209                 foreach ($this->user as $method)
13210                 {
13211                         if (($returned = call_user_func($method, $date)) !== false)
13212                         {
13213                                 return $returned;
13214                         }
13215                 }
13216
13217                 foreach ($this->built_in as $method)
13218                 {
13219                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13220                         {
13221                                 return $returned;
13222                         }
13223                 }
13224
13225                 return false;
13226         }
13227
13228         /**
13229          * Add a callback method to parse a date
13230          *
13231          * @final
13232          * @access public
13233          * @param callback $callback
13234          */
13235         function add_callback($callback)
13236         {
13237                 if (is_callable($callback))
13238                 {
13239                         $this->user[] = $callback;
13240                 }
13241                 else
13242                 {
13243                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13244                 }
13245         }
13246
13247         /**
13248          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13249          * well as allowing any of upper or lower case "T", horizontal tabs, or
13250          * spaces to be used as the time seperator (including more than one))
13251          *
13252          * @access protected
13253          * @return int Timestamp
13254          */
13255         function date_w3cdtf($date)
13256         {
13257                 static $pcre;
13258                 if (!$pcre)
13259                 {
13260                         $year = '([0-9]{4})';
13261                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13262                         $decimal = '([0-9]*)';
13263                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13264                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13265                 }
13266                 if (preg_match($pcre, $date, $match))
13267                 {
13268                         /*
13269                         Capturing subpatterns:
13270                         1: Year
13271                         2: Month
13272                         3: Day
13273                         4: Hour
13274                         5: Minute
13275                         6: Second
13276                         7: Decimal fraction of a second
13277                         8: Zulu
13278                         9: Timezone ±
13279                         10: Timezone hours
13280                         11: Timezone minutes
13281                         */
13282
13283                         // Fill in empty matches
13284                         for ($i = count($match); $i <= 3; $i++)
13285                         {
13286                                 $match[$i] = '1';
13287                         }
13288
13289                         for ($i = count($match); $i <= 7; $i++)
13290                         {
13291                                 $match[$i] = '0';
13292                         }
13293
13294                         // Numeric timezone
13295                         if (isset($match[9]) && $match[9] !== '')
13296                         {
13297                                 $timezone = $match[10] * 3600;
13298                                 $timezone += $match[11] * 60;
13299                                 if ($match[9] === '-')
13300                                 {
13301                                         $timezone = 0 - $timezone;
13302                                 }
13303                         }
13304                         else
13305                         {
13306                                 $timezone = 0;
13307                         }
13308
13309                         // Convert the number of seconds to an integer, taking decimals into account
13310                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13311
13312                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13313                 }
13314                 else
13315                 {
13316                         return false;
13317                 }
13318         }
13319
13320         /**
13321          * Remove RFC822 comments
13322          *
13323          * @access protected
13324          * @param string $data Data to strip comments from
13325          * @return string Comment stripped string
13326          */
13327         function remove_rfc2822_comments($string)
13328         {
13329                 $string = (string) $string;
13330                 $position = 0;
13331                 $length = strlen($string);
13332                 $depth = 0;
13333
13334                 $output = '';
13335
13336                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13337                 {
13338                         $output .= substr($string, $position, $pos - $position);
13339                         $position = $pos + 1;
13340                         if ($string[$pos - 1] !== '\\')
13341                         {
13342                                 $depth++;
13343                                 while ($depth && $position < $length)
13344                                 {
13345                                         $position += strcspn($string, '()', $position);
13346                                         if ($string[$position - 1] === '\\')
13347                                         {
13348                                                 $position++;
13349                                                 continue;
13350                                         }
13351                                         elseif (isset($string[$position]))
13352                                         {
13353                                                 switch ($string[$position])
13354                                                 {
13355                                                         case '(':
13356                                                                 $depth++;
13357                                                                 break;
13358
13359                                                         case ')':
13360                                                                 $depth--;
13361                                                                 break;
13362                                                 }
13363                                                 $position++;
13364                                         }
13365                                         else
13366                                         {
13367                                                 break;
13368                                         }
13369                                 }
13370                         }
13371                         else
13372                         {
13373                                 $output .= '(';
13374                         }
13375                 }
13376                 $output .= substr($string, $position);
13377
13378                 return $output;
13379         }
13380
13381         /**
13382          * Parse RFC2822's date format
13383          *
13384          * @access protected
13385          * @return int Timestamp
13386          */
13387         function date_rfc2822($date)
13388         {
13389                 static $pcre;
13390                 if (!$pcre)
13391                 {
13392                         $wsp = '[\x09\x20]';
13393                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13394                         $optional_fws = $fws . '?';
13395                         $day_name = $this->day_pcre;
13396                         $month = $this->month_pcre;
13397                         $day = '([0-9]{1,2})';
13398                         $hour = $minute = $second = '([0-9]{2})';
13399                         $year = '([0-9]{2,4})';
13400                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13401                         $character_zone = '([A-Z]{1,5})';
13402                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13403                         $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';
13404                 }
13405                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13406                 {
13407                         /*
13408                         Capturing subpatterns:
13409                         1: Day name
13410                         2: Day
13411                         3: Month
13412                         4: Year
13413                         5: Hour
13414                         6: Minute
13415                         7: Second
13416                         8: Timezone ±
13417                         9: Timezone hours
13418                         10: Timezone minutes
13419                         11: Alphabetic timezone
13420                         */
13421
13422                         // Find the month number
13423                         $month = $this->month[strtolower($match[3])];
13424
13425                         // Numeric timezone
13426                         if ($match[8] !== '')
13427                         {
13428                                 $timezone = $match[9] * 3600;
13429                                 $timezone += $match[10] * 60;
13430                                 if ($match[8] === '-')
13431                                 {
13432                                         $timezone = 0 - $timezone;
13433                                 }
13434                         }
13435                         // Character timezone
13436                         elseif (isset($this->timezone[strtoupper($match[11])]))
13437                         {
13438                                 $timezone = $this->timezone[strtoupper($match[11])];
13439                         }
13440                         // Assume everything else to be -0000
13441                         else
13442                         {
13443                                 $timezone = 0;
13444                         }
13445
13446                         // Deal with 2/3 digit years
13447                         if ($match[4] < 50)
13448                         {
13449                                 $match[4] += 2000;
13450                         }
13451                         elseif ($match[4] < 1000)
13452                         {
13453                                 $match[4] += 1900;
13454                         }
13455
13456                         // Second is optional, if it is empty set it to zero
13457                         if ($match[7] !== '')
13458                         {
13459                                 $second = $match[7];
13460                         }
13461                         else
13462                         {
13463                                 $second = 0;
13464                         }
13465
13466                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13467                 }
13468                 else
13469                 {
13470                         return false;
13471                 }
13472         }
13473
13474         /**
13475          * Parse RFC850's date format
13476          *
13477          * @access protected
13478          * @return int Timestamp
13479          */
13480         function date_rfc850($date)
13481         {
13482                 static $pcre;
13483                 if (!$pcre)
13484                 {
13485                         $space = '[\x09\x20]+';
13486                         $day_name = $this->day_pcre;
13487                         $month = $this->month_pcre;
13488                         $day = '([0-9]{1,2})';
13489                         $year = $hour = $minute = $second = '([0-9]{2})';
13490                         $zone = '([A-Z]{1,5})';
13491                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13492                 }
13493                 if (preg_match($pcre, $date, $match))
13494                 {
13495                         /*
13496                         Capturing subpatterns:
13497                         1: Day name
13498                         2: Day
13499                         3: Month
13500                         4: Year
13501                         5: Hour
13502                         6: Minute
13503                         7: Second
13504                         8: Timezone
13505                         */
13506
13507                         // Month
13508                         $month = $this->month[strtolower($match[3])];
13509
13510                         // Character timezone
13511                         if (isset($this->timezone[strtoupper($match[8])]))
13512                         {
13513                                 $timezone = $this->timezone[strtoupper($match[8])];
13514                         }
13515                         // Assume everything else to be -0000
13516                         else
13517                         {
13518                                 $timezone = 0;
13519                         }
13520
13521                         // Deal with 2 digit year
13522                         if ($match[4] < 50)
13523                         {
13524                                 $match[4] += 2000;
13525                         }
13526                         else
13527                         {
13528                                 $match[4] += 1900;
13529                         }
13530
13531                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13532                 }
13533                 else
13534                 {
13535                         return false;
13536                 }
13537         }
13538
13539         /**
13540          * Parse C99's asctime()'s date format
13541          *
13542          * @access protected
13543          * @return int Timestamp
13544          */
13545         function date_asctime($date)
13546         {
13547                 static $pcre;
13548                 if (!$pcre)
13549                 {
13550                         $space = '[\x09\x20]+';
13551                         $wday_name = $this->day_pcre;
13552                         $mon_name = $this->month_pcre;
13553                         $day = '([0-9]{1,2})';
13554                         $hour = $sec = $min = '([0-9]{2})';
13555                         $year = '([0-9]{4})';
13556                         $terminator = '\x0A?\x00?';
13557                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13558                 }
13559                 if (preg_match($pcre, $date, $match))
13560                 {
13561                         /*
13562                         Capturing subpatterns:
13563                         1: Day name
13564                         2: Month
13565                         3: Day
13566                         4: Hour
13567                         5: Minute
13568                         6: Second
13569                         7: Year
13570                         */
13571
13572                         $month = $this->month[strtolower($match[2])];
13573                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13574                 }
13575                 else
13576                 {
13577                         return false;
13578                 }
13579         }
13580
13581         /**
13582          * Parse dates using strtotime()
13583          *
13584          * @access protected
13585          * @return int Timestamp
13586          */
13587         function date_strtotime($date)
13588         {
13589                 $strtotime = strtotime($date);
13590                 if ($strtotime === -1 || $strtotime === false)
13591                 {
13592                         return false;
13593                 }
13594                 else
13595                 {
13596                         return $strtotime;
13597                 }
13598         }
13599 }
13600
13601 /**
13602  * Content-type sniffing
13603  *
13604  * @package SimplePie
13605  */
13606 class SimplePie_Content_Type_Sniffer
13607 {
13608         /**
13609          * File object
13610          *
13611          * @var SimplePie_File
13612          * @access private
13613          */
13614         var $file;
13615
13616         /**
13617          * Create an instance of the class with the input file
13618          *
13619          * @access public
13620          * @param SimplePie_Content_Type_Sniffer $file Input file
13621          */
13622         function SimplePie_Content_Type_Sniffer($file)
13623         {
13624                 $this->file = $file;
13625         }
13626
13627         /**
13628          * Get the Content-Type of the specified file
13629          *
13630          * @access public
13631          * @return string Actual Content-Type
13632          */
13633         function get_type()
13634         {
13635                 if (isset($this->file->headers['content-type']))
13636                 {
13637                         if (!isset($this->file->headers['content-encoding'])
13638                                 && ($this->file->headers['content-type'] === 'text/plain'
13639                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13640                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13641                         {
13642                                 return $this->text_or_binary();
13643                         }
13644
13645                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13646                         {
13647                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13648                         }
13649                         else
13650                         {
13651                                 $official = $this->file->headers['content-type'];
13652                         }
13653                         $official = strtolower($official);
13654
13655                         if ($official === 'unknown/unknown'
13656                                 || $official === 'application/unknown')
13657                         {
13658                                 return $this->unknown();
13659                         }
13660                         elseif (substr($official, -4) === '+xml'
13661                                 || $official === 'text/xml'
13662                                 || $official === 'application/xml')
13663                         {
13664                                 return $official;
13665                         }
13666                         elseif (substr($official, 0, 6) === 'image/')
13667                         {
13668                                 if ($return = $this->image())
13669                                 {
13670                                         return $return;
13671                                 }
13672                                 else
13673                                 {
13674                                         return $official;
13675                                 }
13676                         }
13677                         elseif ($official === 'text/html')
13678                         {
13679                                 return $this->feed_or_html();
13680                         }
13681                         else
13682                         {
13683                                 return $official;
13684                         }
13685                 }
13686                 else
13687                 {
13688                         return $this->unknown();
13689                 }
13690         }
13691
13692         /**
13693          * Sniff text or binary
13694          *
13695          * @access private
13696          * @return string Actual Content-Type
13697          */
13698         function text_or_binary()
13699         {
13700                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13701                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13702                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13703                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13704                 {
13705                         return 'text/plain';
13706                 }
13707                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13708                 {
13709                         return 'application/octect-stream';
13710                 }
13711                 else
13712                 {
13713                         return 'text/plain';
13714                 }
13715         }
13716
13717         /**
13718          * Sniff unknown
13719          *
13720          * @access private
13721          * @return string Actual Content-Type
13722          */
13723         function unknown()
13724         {
13725                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13726                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13727                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13728                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13729                 {
13730                         return 'text/html';
13731                 }
13732                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13733                 {
13734                         return 'application/pdf';
13735                 }
13736                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13737                 {
13738                         return 'application/postscript';
13739                 }
13740                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13741                         || substr($this->file->body, 0, 6) === 'GIF89a')
13742                 {
13743                         return 'image/gif';
13744                 }
13745                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13746                 {
13747                         return 'image/png';
13748                 }
13749                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13750                 {
13751                         return 'image/jpeg';
13752                 }
13753                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13754                 {
13755                         return 'image/bmp';
13756                 }
13757                 else
13758                 {
13759                         return $this->text_or_binary();
13760                 }
13761         }
13762
13763         /**
13764          * Sniff images
13765          *
13766          * @access private
13767          * @return string Actual Content-Type
13768          */
13769         function image()
13770         {
13771                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13772                         || substr($this->file->body, 0, 6) === 'GIF89a')
13773                 {
13774                         return 'image/gif';
13775                 }
13776                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13777                 {
13778                         return 'image/png';
13779                 }
13780                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13781                 {
13782                         return 'image/jpeg';
13783                 }
13784                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13785                 {
13786                         return 'image/bmp';
13787                 }
13788                 else
13789                 {
13790                         return false;
13791                 }
13792         }
13793
13794         /**
13795          * Sniff HTML
13796          *
13797          * @access private
13798          * @return string Actual Content-Type
13799          */
13800         function feed_or_html()
13801         {
13802                 $len = strlen($this->file->body);
13803                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13804
13805                 while ($pos < $len)
13806                 {
13807                         switch ($this->file->body[$pos])
13808                         {
13809                                 case "\x09":
13810                                 case "\x0A":
13811                                 case "\x0D":
13812                                 case "\x20":
13813                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13814                                         continue 2;
13815
13816                                 case '<':
13817                                         $pos++;
13818                                         break;
13819
13820                                 default:
13821                                         return 'text/html';
13822                         }
13823
13824                         if (substr($this->file->body, $pos, 3) === '!--')
13825                         {
13826                                 $pos += 3;
13827                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13828                                 {
13829                                         $pos += 3;
13830                                 }
13831                                 else
13832                                 {
13833                                         return 'text/html';
13834                                 }
13835                         }
13836                         elseif (substr($this->file->body, $pos, 1) === '!')
13837                         {
13838                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13839                                 {
13840                                         $pos++;
13841                                 }
13842                                 else
13843                                 {
13844                                         return 'text/html';
13845                                 }
13846                         }
13847                         elseif (substr($this->file->body, $pos, 1) === '?')
13848                         {
13849                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13850                                 {
13851                                         $pos += 2;
13852                                 }
13853                                 else
13854                                 {
13855                                         return 'text/html';
13856                                 }
13857                         }
13858                         elseif (substr($this->file->body, $pos, 3) === 'rss'
13859                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13860                         {
13861                                 return 'application/rss+xml';
13862                         }
13863                         elseif (substr($this->file->body, $pos, 4) === 'feed')
13864                         {
13865                                 return 'application/atom+xml';
13866                         }
13867                         else
13868                         {
13869                                 return 'text/html';
13870                         }
13871                 }
13872
13873                 return 'text/html';
13874         }
13875 }
13876
13877 /**
13878  * Parses the XML Declaration
13879  *
13880  * @package SimplePie
13881  */
13882 class SimplePie_XML_Declaration_Parser
13883 {
13884         /**
13885          * XML Version
13886          *
13887          * @access public
13888          * @var string
13889          */
13890         var $version = '1.0';
13891
13892         /**
13893          * Encoding
13894          *
13895          * @access public
13896          * @var string
13897          */
13898         var $encoding = 'UTF-8';
13899
13900         /**
13901          * Standalone
13902          *
13903          * @access public
13904          * @var bool
13905          */
13906         var $standalone = false;
13907
13908         /**
13909          * Current state of the state machine
13910          *
13911          * @access private
13912          * @var string
13913          */
13914         var $state = 'before_version_name';
13915
13916         /**
13917          * Input data
13918          *
13919          * @access private
13920          * @var string
13921          */
13922         var $data = '';
13923
13924         /**
13925          * Input data length (to avoid calling strlen() everytime this is needed)
13926          *
13927          * @access private
13928          * @var int
13929          */
13930         var $data_length = 0;
13931
13932         /**
13933          * Current position of the pointer
13934          *
13935          * @var int
13936          * @access private
13937          */
13938         var $position = 0;
13939
13940         /**
13941          * Create an instance of the class with the input data
13942          *
13943          * @access public
13944          * @param string $data Input data
13945          */
13946         function SimplePie_XML_Declaration_Parser($data)
13947         {
13948                 $this->data = $data;
13949                 $this->data_length = strlen($this->data);
13950         }
13951
13952         /**
13953          * Parse the input data
13954          *
13955          * @access public
13956          * @return bool true on success, false on failure
13957          */
13958         function parse()
13959         {
13960                 while ($this->state && $this->state !== 'emit' && $this->has_data())
13961                 {
13962                         $state = $this->state;
13963                         $this->$state();
13964                 }
13965                 $this->data = '';
13966                 if ($this->state === 'emit')
13967                 {
13968                         return true;
13969                 }
13970                 else
13971                 {
13972                         $this->version = '';
13973                         $this->encoding = '';
13974                         $this->standalone = '';
13975                         return false;
13976                 }
13977         }
13978
13979         /**
13980          * Check whether there is data beyond the pointer
13981          *
13982          * @access private
13983          * @return bool true if there is further data, false if not
13984          */
13985         function has_data()
13986         {
13987                 return (bool) ($this->position < $this->data_length);
13988         }
13989
13990         /**
13991          * Advance past any whitespace
13992          *
13993          * @return int Number of whitespace characters passed
13994          */
13995         function skip_whitespace()
13996         {
13997                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13998                 $this->position += $whitespace;
13999                 return $whitespace;
14000         }
14001
14002         /**
14003          * Read value
14004          */
14005         function get_value()
14006         {
14007                 $quote = substr($this->data, $this->position, 1);
14008                 if ($quote === '"' || $quote === "'")
14009                 {
14010                         $this->position++;
14011                         $len = strcspn($this->data, $quote, $this->position);
14012                         if ($this->has_data())
14013                         {
14014                                 $value = substr($this->data, $this->position, $len);
14015                                 $this->position += $len + 1;
14016                                 return $value;
14017                         }
14018                 }
14019                 return false;
14020         }
14021
14022         function before_version_name()
14023         {
14024                 if ($this->skip_whitespace())
14025                 {
14026                         $this->state = 'version_name';
14027                 }
14028                 else
14029                 {
14030                         $this->state = false;
14031                 }
14032         }
14033
14034         function version_name()
14035         {
14036                 if (substr($this->data, $this->position, 7) === 'version')
14037                 {
14038                         $this->position += 7;
14039                         $this->skip_whitespace();
14040                         $this->state = 'version_equals';
14041                 }
14042                 else
14043                 {
14044                         $this->state = false;
14045                 }
14046         }
14047
14048         function version_equals()
14049         {
14050                 if (substr($this->data, $this->position, 1) === '=')
14051                 {
14052                         $this->position++;
14053                         $this->skip_whitespace();
14054                         $this->state = 'version_value';
14055                 }
14056                 else
14057                 {
14058                         $this->state = false;
14059                 }
14060         }
14061
14062         function version_value()
14063         {
14064                 if ($this->version = $this->get_value())
14065                 {
14066                         $this->skip_whitespace();
14067                         if ($this->has_data())
14068                         {
14069                                 $this->state = 'encoding_name';
14070                         }
14071                         else
14072                         {
14073                                 $this->state = 'emit';
14074                         }
14075                 }
14076                 else
14077                 {
14078                         $this->state = false;
14079                 }
14080         }
14081
14082         function encoding_name()
14083         {
14084                 if (substr($this->data, $this->position, 8) === 'encoding')
14085                 {
14086                         $this->position += 8;
14087                         $this->skip_whitespace();
14088                         $this->state = 'encoding_equals';
14089                 }
14090                 else
14091                 {
14092                         $this->state = 'standalone_name';
14093                 }
14094         }
14095
14096         function encoding_equals()
14097         {
14098                 if (substr($this->data, $this->position, 1) === '=')
14099                 {
14100                         $this->position++;
14101                         $this->skip_whitespace();
14102                         $this->state = 'encoding_value';
14103                 }
14104                 else
14105                 {
14106                         $this->state = false;
14107                 }
14108         }
14109
14110         function encoding_value()
14111         {
14112                 if ($this->encoding = $this->get_value())
14113                 {
14114                         $this->skip_whitespace();
14115                         if ($this->has_data())
14116                         {
14117                                 $this->state = 'standalone_name';
14118                         }
14119                         else
14120                         {
14121                                 $this->state = 'emit';
14122                         }
14123                 }
14124                 else
14125                 {
14126                         $this->state = false;
14127                 }
14128         }
14129
14130         function standalone_name()
14131         {
14132                 if (substr($this->data, $this->position, 10) === 'standalone')
14133                 {
14134                         $this->position += 10;
14135                         $this->skip_whitespace();
14136                         $this->state = 'standalone_equals';
14137                 }
14138                 else
14139                 {
14140                         $this->state = false;
14141                 }
14142         }
14143
14144         function standalone_equals()
14145         {
14146                 if (substr($this->data, $this->position, 1) === '=')
14147                 {
14148                         $this->position++;
14149                         $this->skip_whitespace();
14150                         $this->state = 'standalone_value';
14151                 }
14152                 else
14153                 {
14154                         $this->state = false;
14155                 }
14156         }
14157
14158         function standalone_value()
14159         {
14160                 if ($standalone = $this->get_value())
14161                 {
14162                         switch ($standalone)
14163                         {
14164                                 case 'yes':
14165                                         $this->standalone = true;
14166                                         break;
14167
14168                                 case 'no':
14169                                         $this->standalone = false;
14170                                         break;
14171
14172                                 default:
14173                                         $this->state = false;
14174                                         return;
14175                         }
14176
14177                         $this->skip_whitespace();
14178                         if ($this->has_data())
14179                         {
14180                                 $this->state = false;
14181                         }
14182                         else
14183                         {
14184                                 $this->state = 'emit';
14185                         }
14186                 }
14187                 else
14188                 {
14189                         $this->state = false;
14190                 }
14191         }
14192 }
14193
14194 class SimplePie_Locator
14195 {
14196         var $useragent;
14197         var $timeout;
14198         var $file;
14199         var $local = array();
14200         var $elsewhere = array();
14201         var $file_class = 'SimplePie_File';
14202         var $cached_entities = array();
14203         var $http_base;
14204         var $base;
14205         var $base_location = 0;
14206         var $checked_feeds = 0;
14207         var $max_checked_feeds = 10;
14208         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14209
14210         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14211         {
14212                 $this->file =& $file;
14213                 $this->file_class = $file_class;
14214                 $this->useragent = $useragent;
14215                 $this->timeout = $timeout;
14216                 $this->max_checked_feeds = $max_checked_feeds;
14217                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14218         }
14219
14220         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14221         {
14222                 if ($this->is_feed($this->file))
14223                 {
14224                         return $this->file;
14225                 }
14226
14227                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14228                 {
14229                         $sniffer = new $this->content_type_sniffer_class($this->file);
14230                         if ($sniffer->get_type() !== 'text/html')
14231                         {
14232                                 return null;
14233                         }
14234                 }
14235
14236                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14237                 {
14238                         $this->get_base();
14239                 }
14240
14241                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14242                 {
14243                         return $working[0];
14244                 }
14245
14246                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14247                 {
14248                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14249                         {
14250                                 return $working;
14251                         }
14252
14253                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14254                         {
14255                                 return $working;
14256                         }
14257
14258                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14259                         {
14260                                 return $working;
14261                         }
14262
14263                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14264                         {
14265                                 return $working;
14266                         }
14267                 }
14268                 return null;
14269         }
14270
14271         function is_feed(&$file)
14272         {
14273                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14274                 {
14275                         $sniffer = new $this->content_type_sniffer_class($file);
14276                         $sniffed = $sniffer->get_type();
14277                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14278                         {
14279                                 return true;
14280                         }
14281                         else
14282                         {
14283                                 return false;
14284                         }
14285                 }
14286                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14287                 {
14288                         return true;
14289                 }
14290                 else
14291                 {
14292                         return false;
14293                 }
14294         }
14295
14296         function get_base()
14297         {
14298                 $this->http_base = $this->file->url;
14299                 $this->base = $this->http_base;
14300                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14301                 foreach ($elements as $element)
14302                 {
14303                         if ($element['attribs']['href']['data'] !== '')
14304                         {
14305                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14306                                 $this->base_location = $element['offset'];
14307                                 break;
14308                         }
14309                 }
14310         }
14311
14312         function autodiscovery()
14313         {
14314                 $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));
14315                 $done = array();
14316                 $feeds = array();
14317                 foreach ($links as $link)
14318                 {
14319                         if ($this->checked_feeds === $this->max_checked_feeds)
14320                         {
14321                                 break;
14322                         }
14323                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14324                         {
14325                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14326
14327                                 if ($this->base_location < $link['offset'])
14328                                 {
14329                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14330                                 }
14331                                 else
14332                                 {
14333                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14334                                 }
14335
14336                                 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]))
14337                                 {
14338                                         $this->checked_feeds++;
14339                                         $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14340                                         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))
14341                                         {
14342                                                 $feeds[$href] = $feed;
14343                                         }
14344                                 }
14345                                 $done[] = $href;
14346                         }
14347                 }
14348
14349                 if (!empty($feeds))
14350                 {
14351                         return array_values($feeds);
14352                 }
14353                 else {
14354                         return null;
14355                 }
14356         }
14357
14358         function get_links()
14359         {
14360                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14361                 foreach ($links as $link)
14362                 {
14363                         if (isset($link['attribs']['href']['data']))
14364                         {
14365                                 $href = trim($link['attribs']['href']['data']);
14366                                 $parsed = SimplePie_Misc::parse_url($href);
14367                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14368                                 {
14369                                         if ($this->base_location < $link['offset'])
14370                                         {
14371                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14372                                         }
14373                                         else
14374                                         {
14375                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14376                                         }
14377
14378                                         $current = SimplePie_Misc::parse_url($this->file->url);
14379
14380                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14381                                         {
14382                                                 $this->local[] = $href;
14383                                         }
14384                                         else
14385                                         {
14386                                                 $this->elsewhere[] = $href;
14387                                         }
14388                                 }
14389                         }
14390                 }
14391                 $this->local = array_unique($this->local);
14392                 $this->elsewhere = array_unique($this->elsewhere);
14393                 if (!empty($this->local) || !empty($this->elsewhere))
14394                 {
14395                         return true;
14396                 }
14397                 return null;
14398         }
14399
14400         function extension(&$array)
14401         {
14402                 foreach ($array as $key => $value)
14403                 {
14404                         if ($this->checked_feeds === $this->max_checked_feeds)
14405                         {
14406                                 break;
14407                         }
14408                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14409                         {
14410                                 $this->checked_feeds++;
14411                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14412                                 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))
14413                                 {
14414                                         return $feed;
14415                                 }
14416                                 else
14417                                 {
14418                                         unset($array[$key]);
14419                                 }
14420                         }
14421                 }
14422                 return null;
14423         }
14424
14425         function body(&$array)
14426         {
14427                 foreach ($array as $key => $value)
14428                 {
14429                         if ($this->checked_feeds === $this->max_checked_feeds)
14430                         {
14431                                 break;
14432                         }
14433                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14434                         {
14435                                 $this->checked_feeds++;
14436                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14437                                 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))
14438                                 {
14439                                         return $feed;
14440                                 }
14441                                 else
14442                                 {
14443                                         unset($array[$key]);
14444                                 }
14445                         }
14446                 }
14447                 return null;
14448         }
14449 }
14450
14451 class SimplePie_Parser
14452 {
14453         var $error_code;
14454         var $error_string;
14455         var $current_line;
14456         var $current_column;
14457         var $current_byte;
14458         var $separator = ' ';
14459         var $namespace = array('');
14460         var $element = array('');
14461         var $xml_base = array('');
14462         var $xml_base_explicit = array(false);
14463         var $xml_lang = array('');
14464         var $data = array();
14465         var $datas = array(array());
14466         var $current_xhtml_construct = -1;
14467         var $encoding;
14468
14469         function parse(&$data, $encoding)
14470         {
14471                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14472                 if (strtoupper($encoding) === 'US-ASCII')
14473                 {
14474                         $this->encoding = 'UTF-8';
14475                 }
14476                 else
14477                 {
14478                         $this->encoding = $encoding;
14479                 }
14480
14481                 // Strip BOM:
14482                 // UTF-32 Big Endian BOM
14483                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14484                 {
14485                         $data = substr($data, 4);
14486                 }
14487                 // UTF-32 Little Endian BOM
14488                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14489                 {
14490                         $data = substr($data, 4);
14491                 }
14492                 // UTF-16 Big Endian BOM
14493                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14494                 {
14495                         $data = substr($data, 2);
14496                 }
14497                 // UTF-16 Little Endian BOM
14498                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14499                 {
14500                         $data = substr($data, 2);
14501                 }
14502                 // UTF-8 BOM
14503                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14504                 {
14505                         $data = substr($data, 3);
14506                 }
14507
14508                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14509                 {
14510                         $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14511                         if ($declaration->parse())
14512                         {
14513                                 $data = substr($data, $pos + 2);
14514                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14515                         }
14516                         else
14517                         {
14518                                 $this->error_string = 'SimplePie bug! Please report this!';
14519                                 return false;
14520                         }
14521                 }
14522
14523                 $return = true;
14524
14525                 static $xml_is_sane = null;
14526                 if ($xml_is_sane === null)
14527                 {
14528                         $parser_check = xml_parser_create();
14529                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14530                         xml_parser_free($parser_check);
14531                         $xml_is_sane = isset($values[0]['value']);
14532                 }
14533
14534                 // Create the parser
14535                 if ($xml_is_sane)
14536                 {
14537                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14538                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14539                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14540                         xml_set_object($xml, $this);
14541                         xml_set_character_data_handler($xml, 'cdata');
14542                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14543
14544                         // Parse!
14545                         if (!xml_parse($xml, $data, true))
14546                         {
14547                                 $this->error_code = xml_get_error_code($xml);
14548                                 $this->error_string = xml_error_string($this->error_code);
14549                                 $return = false;
14550                         }
14551                         $this->current_line = xml_get_current_line_number($xml);
14552                         $this->current_column = xml_get_current_column_number($xml);
14553                         $this->current_byte = xml_get_current_byte_index($xml);
14554                         xml_parser_free($xml);
14555                         return $return;
14556                 }
14557                 else
14558                 {
14559                         libxml_clear_errors();
14560                         $xml = new XMLReader();
14561                         $xml->xml($data);
14562                         while (@$xml->read())
14563                         {
14564                                 switch ($xml->nodeType)
14565                                 {
14566
14567                                         case constant('XMLReader::END_ELEMENT'):
14568                                                 if ($xml->namespaceURI !== '')
14569                                                 {
14570                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14571                                                 }
14572                                                 else
14573                                                 {
14574                                                         $tagName = $xml->localName;
14575                                                 }
14576                                                 $this->tag_close(null, $tagName);
14577                                                 break;
14578                                         case constant('XMLReader::ELEMENT'):
14579                                                 $empty = $xml->isEmptyElement;
14580                                                 if ($xml->namespaceURI !== '')
14581                                                 {
14582                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14583                                                 }
14584                                                 else
14585                                                 {
14586                                                         $tagName = $xml->localName;
14587                                                 }
14588                                                 $attributes = array();
14589                                                 while ($xml->moveToNextAttribute())
14590                                                 {
14591                                                         if ($xml->namespaceURI !== '')
14592                                                         {
14593                                                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14594                                                         }
14595                                                         else
14596                                                         {
14597                                                                 $attrName = $xml->localName;
14598                                                         }
14599                                                         $attributes[$attrName] = $xml->value;
14600                                                 }
14601                                                 $this->tag_open(null, $tagName, $attributes);
14602                                                 if ($empty)
14603                                                 {
14604                                                         $this->tag_close(null, $tagName);
14605                                                 }
14606                                                 break;
14607                                         case constant('XMLReader::TEXT'):
14608
14609                                         case constant('XMLReader::CDATA'):
14610                                                 $this->cdata(null, $xml->value);
14611                                                 break;
14612                                 }
14613                         }
14614                         if ($error = libxml_get_last_error())
14615                         {
14616                                 $this->error_code = $error->code;
14617                                 $this->error_string = $error->message;
14618                                 $this->current_line = $error->line;
14619                                 $this->current_column = $error->column;
14620                                 return false;
14621                         }
14622                         else
14623                         {
14624                                 return true;
14625                         }
14626                 }
14627         }
14628
14629         function get_error_code()
14630         {
14631                 return $this->error_code;
14632         }
14633
14634         function get_error_string()
14635         {
14636                 return $this->error_string;
14637         }
14638
14639         function get_current_line()
14640         {
14641                 return $this->current_line;
14642         }
14643
14644         function get_current_column()
14645         {
14646                 return $this->current_column;
14647         }
14648
14649         function get_current_byte()
14650         {
14651                 return $this->current_byte;
14652         }
14653
14654         function get_data()
14655         {
14656                 return $this->data;
14657         }
14658
14659         function tag_open($parser, $tag, $attributes)
14660         {
14661                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14662
14663                 $attribs = array();
14664                 foreach ($attributes as $name => $value)
14665                 {
14666                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14667                         $attribs[$attrib_namespace][$attribute] = $value;
14668                 }
14669
14670                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14671                 {
14672                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14673                         $this->xml_base_explicit[] = true;
14674                 }
14675                 else
14676                 {
14677                         $this->xml_base[] = end($this->xml_base);
14678                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14679                 }
14680
14681                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14682                 {
14683                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14684                 }
14685                 else
14686                 {
14687                         $this->xml_lang[] = end($this->xml_lang);
14688                 }
14689
14690                 if ($this->current_xhtml_construct >= 0)
14691                 {
14692                         $this->current_xhtml_construct++;
14693                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14694                         {
14695                                 $this->data['data'] .= '<' . end($this->element);
14696                                 if (isset($attribs['']))
14697                                 {
14698                                         foreach ($attribs[''] as $name => $value)
14699                                         {
14700                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14701                                         }
14702                                 }
14703                                 $this->data['data'] .= '>';
14704                         }
14705                 }
14706                 else
14707                 {
14708                         $this->datas[] =& $this->data;
14709                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14710                         $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));
14711                         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')
14712                         || (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'))
14713                         {
14714                                 $this->current_xhtml_construct = 0;
14715                         }
14716                 }
14717         }
14718
14719         function cdata($parser, $cdata)
14720         {
14721                 if ($this->current_xhtml_construct >= 0)
14722                 {
14723                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14724                 }
14725                 else
14726                 {
14727                         $this->data['data'] .= $cdata;
14728                 }
14729         }
14730
14731         function tag_close($parser, $tag)
14732         {
14733                 if ($this->current_xhtml_construct >= 0)
14734                 {
14735                         $this->current_xhtml_construct--;
14736                         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')))
14737                         {
14738                                 $this->data['data'] .= '</' . end($this->element) . '>';
14739                         }
14740                 }
14741                 if ($this->current_xhtml_construct === -1)
14742                 {
14743                         $this->data =& $this->datas[count($this->datas) - 1];
14744                         array_pop($this->datas);
14745                 }
14746
14747                 array_pop($this->element);
14748                 array_pop($this->namespace);
14749                 array_pop($this->xml_base);
14750                 array_pop($this->xml_base_explicit);
14751                 array_pop($this->xml_lang);
14752         }
14753
14754         function split_ns($string)
14755         {
14756                 static $cache = array();
14757                 if (!isset($cache[$string]))
14758                 {
14759                         if ($pos = strpos($string, $this->separator))
14760                         {
14761                                 static $separator_length;
14762                                 if (!$separator_length)
14763                                 {
14764                                         $separator_length = strlen($this->separator);
14765                                 }
14766                                 $namespace = substr($string, 0, $pos);
14767                                 $local_name = substr($string, $pos + $separator_length);
14768                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14769                                 {
14770                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14771                                 }
14772
14773                                 // Normalize the Media RSS namespaces
14774                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14775                                 {
14776                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14777                                 }
14778                                 $cache[$string] = array($namespace, $local_name);
14779                         }
14780                         else
14781                         {
14782                                 $cache[$string] = array('', $string);
14783                         }
14784                 }
14785                 return $cache[$string];
14786         }
14787 }
14788
14789 /**
14790  * @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
14791  */
14792 class SimplePie_Sanitize
14793 {
14794         // Private vars
14795         var $base;
14796
14797         // Options
14798         var $remove_div = true;
14799         var $image_handler = '';
14800         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14801         var $encode_instead_of_strip = false;
14802         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14803         var $strip_comments = false;
14804         var $output_encoding = 'UTF-8';
14805         var $enable_cache = true;
14806         var $cache_location = './cache';
14807         var $cache_name_function = 'md5';
14808         var $cache_class = 'SimplePie_Cache';
14809         var $file_class = 'SimplePie_File';
14810         var $timeout = 10;
14811         var $useragent = '';
14812         var $force_fsockopen = false;
14813
14814         var $replace_url_attributes = array(
14815                 'a' => 'href',
14816                 'area' => 'href',
14817                 'blockquote' => 'cite',
14818                 'del' => 'cite',
14819                 'form' => 'action',
14820                 'img' => array('longdesc', 'src'),
14821                 'input' => 'src',
14822                 'ins' => 'cite',
14823                 'q' => 'cite'
14824         );
14825
14826         function remove_div($enable = true)
14827         {
14828                 $this->remove_div = (bool) $enable;
14829         }
14830
14831         function set_image_handler($page = false)
14832         {
14833                 if ($page)
14834                 {
14835                         $this->image_handler = (string) $page;
14836                 }
14837                 else
14838                 {
14839                         $this->image_handler = false;
14840                 }
14841         }
14842
14843         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14844         {
14845                 if (isset($enable_cache))
14846                 {
14847                         $this->enable_cache = (bool) $enable_cache;
14848                 }
14849
14850                 if ($cache_location)
14851                 {
14852                         $this->cache_location = (string) $cache_location;
14853                 }
14854
14855                 if ($cache_name_function)
14856                 {
14857                         $this->cache_name_function = (string) $cache_name_function;
14858                 }
14859
14860                 if ($cache_class)
14861                 {
14862                         $this->cache_class = (string) $cache_class;
14863                 }
14864         }
14865
14866         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14867         {
14868                 if ($file_class)
14869                 {
14870                         $this->file_class = (string) $file_class;
14871                 }
14872
14873                 if ($timeout)
14874                 {
14875                         $this->timeout = (string) $timeout;
14876                 }
14877
14878                 if ($useragent)
14879                 {
14880                         $this->useragent = (string) $useragent;
14881                 }
14882
14883                 if ($force_fsockopen)
14884                 {
14885                         $this->force_fsockopen = (string) $force_fsockopen;
14886                 }
14887         }
14888
14889         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14890         {
14891                 if ($tags)
14892                 {
14893                         if (is_array($tags))
14894                         {
14895                                 $this->strip_htmltags = $tags;
14896                         }
14897                         else
14898                         {
14899                                 $this->strip_htmltags = explode(',', $tags);
14900                         }
14901                 }
14902                 else
14903                 {
14904                         $this->strip_htmltags = false;
14905                 }
14906         }
14907
14908         function encode_instead_of_strip($encode = false)
14909         {
14910                 $this->encode_instead_of_strip = (bool) $encode;
14911         }
14912
14913         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14914         {
14915                 if ($attribs)
14916                 {
14917                         if (is_array($attribs))
14918                         {
14919                                 $this->strip_attributes = $attribs;
14920                         }
14921                         else
14922                         {
14923                                 $this->strip_attributes = explode(',', $attribs);
14924                         }
14925                 }
14926                 else
14927                 {
14928                         $this->strip_attributes = false;
14929                 }
14930         }
14931
14932         function strip_comments($strip = false)
14933         {
14934                 $this->strip_comments = (bool) $strip;
14935         }
14936
14937         function set_output_encoding($encoding = 'UTF-8')
14938         {
14939                 $this->output_encoding = (string) $encoding;
14940         }
14941
14942         /**
14943          * Set element/attribute key/value pairs of HTML attributes
14944          * containing URLs that need to be resolved relative to the feed
14945          *
14946          * @access public
14947          * @since 1.0
14948          * @param array $element_attribute Element/attribute key/value pairs
14949          */
14950         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'))
14951         {
14952                 $this->replace_url_attributes = (array) $element_attribute;
14953         }
14954
14955         function sanitize($data, $type, $base = '')
14956         {
14957                 $data = trim($data);
14958                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14959                 {
14960                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14961                         {
14962                                 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))
14963                                 {
14964                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
14965                                 }
14966                                 else
14967                                 {
14968                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14969                                 }
14970                         }
14971
14972                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14973                         {
14974                                 $data = base64_decode($data);
14975                         }
14976
14977                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14978                         {
14979                                 if ($this->remove_div)
14980                                 {
14981                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14982                                         $data = preg_replace('/<\/div>$/', '', $data);
14983                                 }
14984                                 else
14985                                 {
14986                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14987                                 }
14988                         }
14989
14990                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14991                         {
14992                                 // Strip comments
14993                                 if ($this->strip_comments)
14994                                 {
14995                                         $data = SimplePie_Misc::strip_comments($data);
14996                                 }
14997
14998                                 // Strip out HTML tags and attributes that might cause various security problems.
14999                                 // Based on recommendations by Mark Pilgrim at:
15000                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15001                                 if ($this->strip_htmltags)
15002                                 {
15003                                         foreach ($this->strip_htmltags as $tag)
15004                                         {
15005                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15006                                                 while (preg_match($pcre, $data))
15007                                                 {
15008                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15009                                                 }
15010                                         }
15011                                 }
15012
15013                                 if ($this->strip_attributes)
15014                                 {
15015                                         foreach ($this->strip_attributes as $attrib)
15016                                         {
15017                                                 $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);
15018                                         }
15019                                 }
15020
15021                                 // Replace relative URLs
15022                                 $this->base = $base;
15023                                 foreach ($this->replace_url_attributes as $element => $attributes)
15024                                 {
15025                                         $data = $this->replace_urls($data, $element, $attributes);
15026                                 }
15027
15028                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15029                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15030                                 {
15031                                         $images = SimplePie_Misc::get_element('img', $data);
15032                                         foreach ($images as $img)
15033                                         {
15034                                                 if (isset($img['attribs']['src']['data']))
15035                                                 {
15036                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15037                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15038
15039                                                         if ($cache->load())
15040                                                         {
15041                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15042                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15043                                                         }
15044                                                         else
15045                                                         {
15046                                                                 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15047                                                                 $headers = $file->headers;
15048
15049                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15050                                                                 {
15051                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15052                                                                         {
15053                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15054                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15055                                                                         }
15056                                                                         else
15057                                                                         {
15058                                                                                 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);
15059                                                                         }
15060                                                                 }
15061                                                         }
15062                                                 }
15063                                         }
15064                                 }
15065
15066                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15067                                 $data = trim($data);
15068                         }
15069
15070                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15071                         {
15072                                 $data = SimplePie_Misc::absolutize_url($data, $base);
15073                         }
15074
15075                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15076                         {
15077                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15078                         }
15079
15080                         if ($this->output_encoding !== 'UTF-8')
15081                         {
15082                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15083                         }
15084                 }
15085                 return $data;
15086         }
15087
15088         function replace_urls($data, $tag, $attributes)
15089         {
15090                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15091                 {
15092                         $elements = SimplePie_Misc::get_element($tag, $data);
15093                         foreach ($elements as $element)
15094                         {
15095                                 if (is_array($attributes))
15096                                 {
15097                                         foreach ($attributes as $attribute)
15098                                         {
15099                                                 if (isset($element['attribs'][$attribute]['data']))
15100                                                 {
15101                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15102                                                         $new_element = SimplePie_Misc::element_implode($element);
15103                                                         $data = str_replace($element['full'], $new_element, $data);
15104                                                         $element['full'] = $new_element;
15105                                                 }
15106                                         }
15107                                 }
15108                                 elseif (isset($element['attribs'][$attributes]['data']))
15109                                 {
15110                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15111                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15112                                 }
15113                         }
15114                 }
15115                 return $data;
15116         }
15117
15118         function do_strip_htmltags($match)
15119         {
15120                 if ($this->encode_instead_of_strip)
15121                 {
15122                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15123                         {
15124                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15125                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15126                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15127                         }
15128                         else
15129                         {
15130                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15131                         }
15132                 }
15133                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15134                 {
15135                         return $match[4];
15136                 }
15137                 else
15138                 {
15139                         return '';
15140                 }
15141         }
15142 }
15143
15144 ?>