]> git.wh0rd.org Git - tt-rss.git/blob - simplepie/simplepie.inc
fce53d396fce8cc1a524033d0d5c74f428c05ad3
[tt-rss.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-2007, 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.1
37  * @copyright 2004-2007 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.1');
55
56 /**
57  * SimplePie Build
58  */
59 define('SIMPLEPIE_BUILD', 20080102221556);
60
61 /**
62  * SimplePie Website URL
63  */
64 define('SIMPLEPIE_URL', 'http://simplepie.org');
65
66 /**
67  * SimplePie Useragent
68  * @see SimplePie::set_useragent()
69  */
70 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
71
72 /**
73  * SimplePie Linkback
74  */
75 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
76
77 /**
78  * No Autodiscovery
79  * @see SimplePie::set_autodiscovery_level()
80  */
81 define('SIMPLEPIE_LOCATOR_NONE', 0);
82
83 /**
84  * Feed Link Element Autodiscovery
85  * @see SimplePie::set_autodiscovery_level()
86  */
87 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
88
89 /**
90  * Local Feed Extension Autodiscovery
91  * @see SimplePie::set_autodiscovery_level()
92  */
93 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
94
95 /**
96  * Local Feed Body Autodiscovery
97  * @see SimplePie::set_autodiscovery_level()
98  */
99 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
100
101 /**
102  * Remote Feed Extension Autodiscovery
103  * @see SimplePie::set_autodiscovery_level()
104  */
105 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
106
107 /**
108  * Remote Feed Body Autodiscovery
109  * @see SimplePie::set_autodiscovery_level()
110  */
111 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
112
113 /**
114  * All Feed Autodiscovery
115  * @see SimplePie::set_autodiscovery_level()
116  */
117 define('SIMPLEPIE_LOCATOR_ALL', 31);
118
119 /**
120  * No known feed type
121  */
122 define('SIMPLEPIE_TYPE_NONE', 0);
123
124 /**
125  * RSS 0.90
126  */
127 define('SIMPLEPIE_TYPE_RSS_090', 1);
128
129 /**
130  * RSS 0.91 (Netscape)
131  */
132 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
133
134 /**
135  * RSS 0.91 (Userland)
136  */
137 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
138
139 /**
140  * RSS 0.91 (both Netscape and Userland)
141  */
142 define('SIMPLEPIE_TYPE_RSS_091', 6);
143
144 /**
145  * RSS 0.92
146  */
147 define('SIMPLEPIE_TYPE_RSS_092', 8);
148
149 /**
150  * RSS 0.93
151  */
152 define('SIMPLEPIE_TYPE_RSS_093', 16);
153
154 /**
155  * RSS 0.94
156  */
157 define('SIMPLEPIE_TYPE_RSS_094', 32);
158
159 /**
160  * RSS 1.0
161  */
162 define('SIMPLEPIE_TYPE_RSS_10', 64);
163
164 /**
165  * RSS 2.0
166  */
167 define('SIMPLEPIE_TYPE_RSS_20', 128);
168
169 /**
170  * RDF-based RSS
171  */
172 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
173
174 /**
175  * Non-RDF-based RSS (truly intended as syndication format)
176  */
177 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
178
179 /**
180  * All RSS
181  */
182 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
183
184 /**
185  * Atom 0.3
186  */
187 define('SIMPLEPIE_TYPE_ATOM_03', 256);
188
189 /**
190  * Atom 1.0
191  */
192 define('SIMPLEPIE_TYPE_ATOM_10', 512);
193
194 /**
195  * All Atom
196  */
197 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
198
199 /**
200  * All feed types
201  */
202 define('SIMPLEPIE_TYPE_ALL', 1023);
203
204 /**
205  * No construct
206  */
207 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
208
209 /**
210  * Text construct
211  */
212 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
213
214 /**
215  * HTML construct
216  */
217 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
218
219 /**
220  * XHTML construct
221  */
222 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
223
224 /**
225  * base64-encoded construct
226  */
227 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
228
229 /**
230  * IRI construct
231  */
232 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
233
234 /**
235  * A construct that might be HTML
236  */
237 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
238
239 /**
240  * All constructs
241  */
242 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
243
244 /**
245  * PCRE for HTML attributes
246  */
247 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]*');
248
249 /**
250  * PCRE for XML attributes
251  */
252 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
253
254 /**
255  * XML Namespace
256  */
257 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
258
259 /**
260  * Atom 1.0 Namespace
261  */
262 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
263
264 /**
265  * Atom 0.3 Namespace
266  */
267 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
268
269 /**
270  * RDF Namespace
271  */
272 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
273
274 /**
275  * RSS 0.90 Namespace
276  */
277 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
278
279 /**
280  * RSS 1.0 Namespace
281  */
282 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
283
284 /**
285  * RSS 1.0 Content Module Namespace
286  */
287 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
288
289 /**
290  * DC 1.0 Namespace
291  */
292 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
293
294 /**
295  * DC 1.1 Namespace
296  */
297 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
298
299 /**
300  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
301  */
302 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
303
304 /**
305  * GeoRSS Namespace
306  */
307 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
308
309 /**
310  * Media RSS Namespace
311  */
312 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
313
314 /**
315  * iTunes RSS Namespace
316  */
317 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
318
319 /**
320  * XHTML Namespace
321  */
322 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
323
324 /**
325  * IANA Link Relations Registry
326  */
327 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
328
329 /**
330  * Whether we're running on PHP5
331  */
332 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
333
334 /**
335  * No file source
336  */
337 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
338
339 /**
340  * Remote file source
341  */
342 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
343
344 /**
345  * Local file source
346  */
347 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
348
349 /**
350  * fsockopen() file source
351  */
352 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
353
354 /**
355  * cURL file source
356  */
357 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
358
359 /**
360  * file_get_contents() file source
361  */
362 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
363
364 /**
365  * SimplePie
366  *
367  * @package SimplePie
368  * @version "Razzleberry"
369  * @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
370  * @author Ryan Parman
371  * @author Geoffrey Sneddon
372  * @todo Option for type of fetching (cache, not modified header, fetch, etc.)
373  */
374 class SimplePie
375 {
376         /**
377          * @var array Raw data
378          * @access private
379          */
380         var $data = array();
381
382         /**
383          * @var mixed Error string
384          * @access private
385          */
386         var $error;
387
388         /**
389          * @var object Instance of SimplePie_Sanitize (or other class)
390          * @see SimplePie::set_sanitize_class()
391          * @access private
392          */
393         var $sanitize;
394
395         /**
396          * @var string SimplePie Useragent
397          * @see SimplePie::set_useragent()
398          * @access private
399          */
400         var $useragent = SIMPLEPIE_USERAGENT;
401
402         /**
403          * @var string Feed URL
404          * @see SimplePie::set_feed_url()
405          * @access private
406          */
407         var $feed_url;
408
409         /**
410          * @var object Instance of SimplePie_File to use as a feed
411          * @see SimplePie::set_file()
412          * @access private
413          */
414         var $file;
415
416         /**
417          * @var string Raw feed data
418          * @see SimplePie::set_raw_data()
419          * @access private
420          */
421         var $raw_data;
422
423         /**
424          * @var int Timeout for fetching remote files
425          * @see SimplePie::set_timeout()
426          * @access private
427          */
428         var $timeout = 10;
429
430         /**
431          * @var bool Forces fsockopen() to be used for remote files instead
432          * of cURL, even if a new enough version is installed
433          * @see SimplePie::force_fsockopen()
434          * @access private
435          */
436         var $force_fsockopen = false;
437
438         /**
439          * @var bool Force the given data/URL to be treated as a feed no matter what
440          * it appears like
441          * @see SimplePie::force_feed()
442          * @access private
443          */
444         var $force_feed = false;
445
446         /**
447          * @var bool Enable/Disable XML dump
448          * @see SimplePie::enable_xml_dump()
449          * @access private
450          */
451         var $xml_dump = false;
452
453         /**
454          * @var bool Enable/Disable Caching
455          * @see SimplePie::enable_cache()
456          * @access private
457          */
458         var $cache = true;
459
460         /**
461          * @var int Cache duration (in seconds)
462          * @see SimplePie::set_cache_duration()
463          * @access private
464          */
465         var $cache_duration = 3600;
466
467         /**
468          * @var int Auto-discovery cache duration (in seconds)
469          * @see SimplePie::set_autodiscovery_cache_duration()
470          * @access private
471          */
472         var $autodiscovery_cache_duration = 604800; // 7 Days.
473
474         /**
475          * @var string Cache location (relative to executing script)
476          * @see SimplePie::set_cache_location()
477          * @access private
478          */
479         var $cache_location = './cache';
480
481         /**
482          * @var string Function that creates the cache filename
483          * @see SimplePie::set_cache_name_function()
484          * @access private
485          */
486         var $cache_name_function = 'md5';
487
488         /**
489          * @var bool Reorder feed by date descending
490          * @see SimplePie::enable_order_by_date()
491          * @access private
492          */
493         var $order_by_date = true;
494
495         /**
496          * @var mixed Force input encoding to be set to the follow value
497          * (false, or anything type-cast to false, disables this feature)
498          * @see SimplePie::set_input_encoding()
499          * @access private
500          */
501         var $input_encoding = false;
502
503         /**
504          * @var int Feed Autodiscovery Level
505          * @see SimplePie::set_autodiscovery_level()
506          * @access private
507          */
508         var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
509
510         /**
511          * @var string Class used for caching feeds
512          * @see SimplePie::set_cache_class()
513          * @access private
514          */
515         var $cache_class = 'SimplePie_Cache';
516
517         /**
518          * @var string Class used for locating feeds
519          * @see SimplePie::set_locator_class()
520          * @access private
521          */
522         var $locator_class = 'SimplePie_Locator';
523
524         /**
525          * @var string Class used for parsing feeds
526          * @see SimplePie::set_parser_class()
527          * @access private
528          */
529         var $parser_class = 'SimplePie_Parser';
530
531         /**
532          * @var string Class used for fetching feeds
533          * @see SimplePie::set_file_class()
534          * @access private
535          */
536         var $file_class = 'SimplePie_File';
537
538         /**
539          * @var string Class used for items
540          * @see SimplePie::set_item_class()
541          * @access private
542          */
543         var $item_class = 'SimplePie_Item';
544
545         /**
546          * @var string Class used for authors
547          * @see SimplePie::set_author_class()
548          * @access private
549          */
550         var $author_class = 'SimplePie_Author';
551
552         /**
553          * @var string Class used for categories
554          * @see SimplePie::set_category_class()
555          * @access private
556          */
557         var $category_class = 'SimplePie_Category';
558
559         /**
560          * @var string Class used for enclosures
561          * @see SimplePie::set_enclosures_class()
562          * @access private
563          */
564         var $enclosure_class = 'SimplePie_Enclosure';
565
566         /**
567          * @var string Class used for Media RSS <media:text> captions
568          * @see SimplePie::set_caption_class()
569          * @access private
570          */
571         var $caption_class = 'SimplePie_Caption';
572
573         /**
574          * @var string Class used for Media RSS <media:copyright>
575          * @see SimplePie::set_copyright_class()
576          * @access private
577          */
578         var $copyright_class = 'SimplePie_Copyright';
579
580         /**
581          * @var string Class used for Media RSS <media:credit>
582          * @see SimplePie::set_credit_class()
583          * @access private
584          */
585         var $credit_class = 'SimplePie_Credit';
586
587         /**
588          * @var string Class used for Media RSS <media:rating>
589          * @see SimplePie::set_rating_class()
590          * @access private
591          */
592         var $rating_class = 'SimplePie_Rating';
593
594         /**
595          * @var string Class used for Media RSS <media:restriction>
596          * @see SimplePie::set_restriction_class()
597          * @access private
598          */
599         var $restriction_class = 'SimplePie_Restriction';
600
601         /**
602          * @var string Class used for content-type sniffing
603          * @see SimplePie::set_content_type_sniffer_class()
604          * @access private
605          */
606         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
607
608         /**
609          * @var string Class used for item sources.
610          * @see SimplePie::set_source_class()
611          * @access private
612          */
613         var $source_class = 'SimplePie_Source';
614
615         /**
616          * @var mixed Set javascript query string parameter (false, or
617          * anything type-cast to false, disables this feature)
618          * @see SimplePie::set_javascript()
619          * @access private
620          */
621         var $javascript = 'js';
622
623         /**
624          * @var int Maximum number of feeds to check with autodiscovery
625          * @see SimplePie::set_max_checked_feeds()
626          * @access private
627          */
628         var $max_checked_feeds = 10;
629
630         /**
631          * @var string Web-accessible path to the handler_favicon.php file.
632          * @see SimplePie::set_favicon_handler()
633          * @access private
634          */
635         var $favicon_handler = '';
636
637         /**
638          * @var string Web-accessible path to the handler_image.php file.
639          * @see SimplePie::set_image_handler()
640          * @access private
641          */
642         var $image_handler = '';
643
644         /**
645          * @var array Stores the URLs when multiple feeds are being initialized.
646          * @see SimplePie::set_feed_url()
647          * @access private
648          */
649         var $multifeed_url = array();
650
651         /**
652          * @var array Stores SimplePie objects when multiple feeds initialized.
653          * @access private
654          */
655         var $multifeed_objects = array();
656
657         /**
658          * @var array Stores the get_object_vars() array for use with multifeeds.
659          * @see SimplePie::set_feed_url()
660          * @access private
661          */
662         var $config_settings = null;
663
664         /**
665          * @var integer Stores the number of items to return per-feed with multifeeds.
666          * @see SimplePie::set_item_limit()
667          * @access private
668          */
669         var $item_limit = 0;
670
671         /**
672          * @var array Stores the default attributes to be stripped by strip_attributes().
673          * @see SimplePie::strip_attributes()
674          * @access private
675          */
676         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
677
678         /**
679          * @var array Stores the default tags to be stripped by strip_htmltags().
680          * @see SimplePie::strip_htmltags()
681          * @access private
682          */
683         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
684
685         /**
686          * The SimplePie class contains feed level data and options
687          *
688          * There are two ways that you can create a new SimplePie object. The first
689          * is by passing a feed URL as a parameter to the SimplePie constructor
690          * (as well as optionally setting the cache location and cache expiry). This
691          * will initialise the whole feed with all of the default settings, and you
692          * can begin accessing methods and properties immediately.
693          *
694          * The second way is to create the SimplePie object with no parameters
695          * at all. This will enable you to set configuration options. After setting
696          * them, you must initialise the feed using $feed->init(). At that point the
697          * object's methods and properties will be available to you. This format is
698          * what is used throughout this documentation.
699          *
700          * @access public
701          * @since 1.0 Preview Release
702          * @param string $feed_url This is the URL you want to parse.
703          * @param string $cache_location This is where you want the cache to be stored.
704          * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
705          */
706         function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
707         {
708                 // Other objects, instances created here so we can set options on them
709                 $this->sanitize =& new SimplePie_Sanitize;
710
711                 // Set options if they're passed to the constructor
712                 if ($cache_location !== null)
713                 {
714                         $this->set_cache_location($cache_location);
715                 }
716
717                 if ($cache_duration !== null)
718                 {
719                         $this->set_cache_duration($cache_duration);
720                 }
721
722                 // Only init the script if we're passed a feed URL
723                 if ($feed_url !== null)
724                 {
725                         $this->set_feed_url($feed_url);
726                         $this->init();
727                 }
728         }
729
730         /**
731          * Used for converting object to a string
732          */
733         function __toString()
734         {
735                 return md5(serialize($this->data));
736         }
737         
738         /**
739          * Remove items that link back to this before destroying this object
740          */
741         function __destruct()
742         {
743                 if (!empty($this->data['items']))
744                 {
745                         foreach ($this->data['items'] as $item)
746                         {
747                                 $item->__destruct();
748                         }
749                         unset($this->data['items']);
750                 }
751                 if (!empty($this->data['ordered_items']))
752                 {
753                         foreach ($this->data['ordered_items'] as $item)
754                         {
755                                 $item->__destruct();
756                         }
757                         unset($this->data['ordered_items']);
758                 }
759         }
760         
761         /**
762          * Force the given data/URL to be treated as a feed no matter what it
763          * appears like
764          *
765          * @access public
766          * @since 1.1
767          * @param bool $enable Force the given data/URL to be treated as a feed
768          */
769         function force_feed($enable = false)
770         {
771                 $this->force_feed = (bool) $enable;
772         }
773
774         /**
775          * This is the URL of the feed you want to parse.
776          *
777          * This allows you to enter the URL of the feed you want to parse, or the
778          * website you want to try to use auto-discovery on. This takes priority
779          * over any set raw data.
780          *
781          * You can set multiple feeds to mash together by passing an array instead
782          * of a string for the $url. Remember that with each additional feed comes
783          * additional processing and resources.
784          *
785          * @access public
786          * @since 1.0 Preview Release
787          * @param mixed $url This is the URL (or array of URLs) that you want to parse.
788          * @see SimplePie::set_raw_data()
789          */
790         function set_feed_url($url)
791         {
792                 if (is_array($url))
793                 {
794                         $this->multifeed_url = array();
795                         foreach ($url as $value)
796                         {
797                                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
798                         }
799                 }
800                 else
801                 {
802                         $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
803                 }
804         }
805
806         /**
807          * Provides an instance of SimplePie_File to use as a feed
808          *
809          * @access public
810          * @param object &$file Instance of SimplePie_File (or subclass)
811          * @return bool True on success, false on failure
812          */
813         function set_file(&$file)
814         {
815                 if (is_a($file, 'SimplePie_File'))
816                 {
817                         $this->feed_url = $file->url;
818                         $this->file =& $file;
819                         return true;
820                 }
821                 return false;
822         }
823
824         /**
825          * Allows you to use a string of RSS/Atom data instead of a remote feed.
826          *
827          * If you have a feed available as a string in PHP, you can tell SimplePie
828          * to parse that data string instead of a remote feed. Any set feed URL
829          * takes precedence.
830          *
831          * @access public
832          * @since 1.0 Beta 3
833          * @param string $data RSS or Atom data as a string.
834          * @see SimplePie::set_feed_url()
835          */
836         function set_raw_data($data)
837         {
838                 $this->raw_data = trim($data);
839         }
840
841         /**
842          * Allows you to override the default timeout for fetching remote feeds.
843          *
844          * This allows you to change the maximum time the feed's server to respond
845          * and send the feed back.
846          *
847          * @access public
848          * @since 1.0 Beta 3
849          * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
850          */
851         function set_timeout($timeout = 10)
852         {
853                 $this->timeout = (int) $timeout;
854         }
855
856         /**
857          * Forces SimplePie to use fsockopen() instead of the preferred cURL
858          * functions.
859          *
860          * @access public
861          * @since 1.0 Beta 3
862          * @param bool $enable Force fsockopen() to be used
863          */
864         function force_fsockopen($enable = false)
865         {
866                 $this->force_fsockopen = (bool) $enable;
867         }
868
869         /**
870          * Outputs the raw XML content of the feed, after it has gone through
871          * SimplePie's filters.
872          *
873          * Used only for debugging, this function will output the XML content as
874          * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
875          * before trying to parse it. Many parts of the feed are re-written in
876          * memory, and in the end, you have a parsable feed. XML dump shows you the
877          * actual XML that SimplePie tries to parse, which may or may not be very
878          * different from the original feed.
879          *
880          * @access public
881          * @since 1.0 Preview Release
882          * @param bool $enable Enable XML dump
883          */
884         function enable_xml_dump($enable = false)
885         {
886                 $this->xml_dump = (bool) $enable;
887         }
888
889         /**
890          * Enables/disables caching in SimplePie.
891          *
892          * This option allows you to disable caching all-together in SimplePie.
893          * However, disabling the cache can lead to longer load times.
894          *
895          * @access public
896          * @since 1.0 Preview Release
897          * @param bool $enable Enable caching
898          */
899         function enable_cache($enable = true)
900         {
901                 $this->cache = (bool) $enable;
902         }
903
904         /**
905          * Set the length of time (in seconds) that the contents of a feed
906          * will be cached.
907          *
908          * @access public
909          * @param int $seconds The feed content cache duration.
910          */
911         function set_cache_duration($seconds = 3600)
912         {
913                 $this->cache_duration = (int) $seconds;
914         }
915
916         /**
917          * Set the length of time (in seconds) that the autodiscovered feed
918          * URL will be cached.
919          *
920          * @access public
921          * @param int $seconds The autodiscovered feed URL cache duration.
922          */
923         function set_autodiscovery_cache_duration($seconds = 604800)
924         {
925                 $this->autodiscovery_cache_duration = (int) $seconds;
926         }
927
928         /**
929          * Set the file system location where the cached files should be stored.
930          *
931          * @access public
932          * @param string $location The file system location.
933          */
934         function set_cache_location($location = './cache')
935         {
936                 $this->cache_location = (string) $location;
937         }
938
939         /**
940          * Determines whether feed items should be sorted into reverse chronological order.
941          *
942          * @access public
943          * @param bool $enable Sort as reverse chronological order.
944          */
945         function enable_order_by_date($enable = true)
946         {
947                 $this->order_by_date = (bool) $enable;
948         }
949
950         /**
951          * Allows you to override the character encoding reported by the feed.
952          *
953          * @access public
954          * @param string $encoding Character encoding.
955          */
956         function set_input_encoding($encoding = false)
957         {
958                 if ($encoding)
959                 {
960                         $this->input_encoding = (string) $encoding;
961                 }
962                 else
963                 {
964                         $this->input_encoding = false;
965                 }
966         }
967
968         /**
969          * Set how much feed autodiscovery to do
970          *
971          * @access public
972          * @see SIMPLEPIE_LOCATOR_NONE
973          * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
974          * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
975          * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
976          * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
977          * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
978          * @see SIMPLEPIE_LOCATOR_ALL
979          * @param int $level Feed Autodiscovery Level (level can be a
980          * combination of the above constants, see bitwise OR operator)
981          */
982         function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
983         {
984                 $this->autodiscovery = (int) $level;
985         }
986
987         /**
988          * Allows you to change which class SimplePie uses for caching.
989          * Useful when you are overloading or extending SimplePie's default classes.
990          *
991          * @access public
992          * @param string $class Name of custom class.
993          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
994          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
995          */
996         function set_cache_class($class = 'SimplePie_Cache')
997         {
998                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
999                 {
1000                         $this->cache_class = $class;
1001                         return true;
1002                 }
1003                 return false;
1004         }
1005
1006         /**
1007          * Allows you to change which class SimplePie uses for auto-discovery.
1008          * Useful when you are overloading or extending SimplePie's default classes.
1009          *
1010          * @access public
1011          * @param string $class Name of custom class.
1012          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1013          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1014          */
1015         function set_locator_class($class = 'SimplePie_Locator')
1016         {
1017                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1018                 {
1019                         $this->locator_class = $class;
1020                         return true;
1021                 }
1022                 return false;
1023         }
1024
1025         /**
1026          * Allows you to change which class SimplePie uses for XML parsing.
1027          * Useful when you are overloading or extending SimplePie's default classes.
1028          *
1029          * @access public
1030          * @param string $class Name of custom class.
1031          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1032          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1033          */
1034         function set_parser_class($class = 'SimplePie_Parser')
1035         {
1036                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1037                 {
1038                         $this->parser_class = $class;
1039                         return true;
1040                 }
1041                 return false;
1042         }
1043
1044         /**
1045          * Allows you to change which class SimplePie uses for remote file fetching.
1046          * Useful when you are overloading or extending SimplePie's default classes.
1047          *
1048          * @access public
1049          * @param string $class Name of custom class.
1050          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1051          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1052          */
1053         function set_file_class($class = 'SimplePie_File')
1054         {
1055                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1056                 {
1057                         $this->file_class = $class;
1058                         return true;
1059                 }
1060                 return false;
1061         }
1062
1063         /**
1064          * Allows you to change which class SimplePie uses for data sanitization.
1065          * Useful when you are overloading or extending SimplePie's default classes.
1066          *
1067          * @access public
1068          * @param string $class Name of custom class.
1069          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1070          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1071          */
1072         function set_sanitize_class($class = 'SimplePie_Sanitize')
1073         {
1074                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1075                 {
1076                         $this->sanitize =& new $class;
1077                         return true;
1078                 }
1079                 return false;
1080         }
1081
1082         /**
1083          * Allows you to change which class SimplePie uses for handling feed items.
1084          * Useful when you are overloading or extending SimplePie's default classes.
1085          *
1086          * @access public
1087          * @param string $class Name of custom class.
1088          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1089          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1090          */
1091         function set_item_class($class = 'SimplePie_Item')
1092         {
1093                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1094                 {
1095                         $this->item_class = $class;
1096                         return true;
1097                 }
1098                 return false;
1099         }
1100
1101         /**
1102          * Allows you to change which class SimplePie uses for handling author data.
1103          * Useful when you are overloading or extending SimplePie's default classes.
1104          *
1105          * @access public
1106          * @param string $class Name of custom class.
1107          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1108          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1109          */
1110         function set_author_class($class = 'SimplePie_Author')
1111         {
1112                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1113                 {
1114                         $this->author_class = $class;
1115                         return true;
1116                 }
1117                 return false;
1118         }
1119
1120         /**
1121          * Allows you to change which class SimplePie uses for handling category data.
1122          * Useful when you are overloading or extending SimplePie's default classes.
1123          *
1124          * @access public
1125          * @param string $class Name of custom class.
1126          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1127          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1128          */
1129         function set_category_class($class = 'SimplePie_Category')
1130         {
1131                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1132                 {
1133                         $this->category_class = $class;
1134                         return true;
1135                 }
1136                 return false;
1137         }
1138
1139         /**
1140          * Allows you to change which class SimplePie uses for feed enclosures.
1141          * Useful when you are overloading or extending SimplePie's default classes.
1142          *
1143          * @access public
1144          * @param string $class Name of custom class.
1145          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1146          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1147          */
1148         function set_enclosure_class($class = 'SimplePie_Enclosure')
1149         {
1150                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1151                 {
1152                         $this->enclosure_class = $class;
1153                         return true;
1154                 }
1155                 return false;
1156         }
1157
1158         /**
1159          * Allows you to change which class SimplePie uses for <media:text> captions
1160          * Useful when you are overloading or extending SimplePie's default classes.
1161          *
1162          * @access public
1163          * @param string $class Name of custom class.
1164          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1165          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1166          */
1167         function set_caption_class($class = 'SimplePie_Caption')
1168         {
1169                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1170                 {
1171                         $this->caption_class = $class;
1172                         return true;
1173                 }
1174                 return false;
1175         }
1176
1177         /**
1178          * Allows you to change which class SimplePie uses for <media:copyright>
1179          * Useful when you are overloading or extending SimplePie's default classes.
1180          *
1181          * @access public
1182          * @param string $class Name of custom class.
1183          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1184          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1185          */
1186         function set_copyright_class($class = 'SimplePie_Copyright')
1187         {
1188                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1189                 {
1190                         $this->copyright_class = $class;
1191                         return true;
1192                 }
1193                 return false;
1194         }
1195
1196         /**
1197          * Allows you to change which class SimplePie uses for <media:credit>
1198          * Useful when you are overloading or extending SimplePie's default classes.
1199          *
1200          * @access public
1201          * @param string $class Name of custom class.
1202          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1203          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1204          */
1205         function set_credit_class($class = 'SimplePie_Credit')
1206         {
1207                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1208                 {
1209                         $this->credit_class = $class;
1210                         return true;
1211                 }
1212                 return false;
1213         }
1214
1215         /**
1216          * Allows you to change which class SimplePie uses for <media:rating>
1217          * Useful when you are overloading or extending SimplePie's default classes.
1218          *
1219          * @access public
1220          * @param string $class Name of custom class.
1221          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1222          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1223          */
1224         function set_rating_class($class = 'SimplePie_Rating')
1225         {
1226                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1227                 {
1228                         $this->rating_class = $class;
1229                         return true;
1230                 }
1231                 return false;
1232         }
1233
1234         /**
1235          * Allows you to change which class SimplePie uses for <media:restriction>
1236          * Useful when you are overloading or extending SimplePie's default classes.
1237          *
1238          * @access public
1239          * @param string $class Name of custom class.
1240          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1241          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1242          */
1243         function set_restriction_class($class = 'SimplePie_Restriction')
1244         {
1245                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1246                 {
1247                         $this->restriction_class = $class;
1248                         return true;
1249                 }
1250                 return false;
1251         }
1252
1253         /**
1254          * Allows you to change which class SimplePie uses for content-type sniffing.
1255          * Useful when you are overloading or extending SimplePie's default classes.
1256          *
1257          * @access public
1258          * @param string $class Name of custom class.
1259          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1260          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1261          */
1262         function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1263         {
1264                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1265                 {
1266                         $this->content_type_sniffer_class = $class;
1267                         return true;
1268                 }
1269                 return false;
1270         }
1271
1272         /**
1273          * Allows you to change which class SimplePie uses item sources.
1274          * Useful when you are overloading or extending SimplePie's default classes.
1275          *
1276          * @access public
1277          * @param string $class Name of custom class.
1278          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1279          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1280          */
1281         function set_source_class($class = 'SimplePie_Source')
1282         {
1283                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1284                 {
1285                         $this->source_class = $class;
1286                         return true;
1287                 }
1288                 return false;
1289         }
1290
1291         /**
1292          * Allows you to override the default user agent string.
1293          *
1294          * @access public
1295          * @param string $ua New user agent string.
1296          */
1297         function set_useragent($ua = SIMPLEPIE_USERAGENT)
1298         {
1299                 $this->useragent = (string) $ua;
1300         }
1301
1302         /**
1303          * Set callback function to create cache filename with
1304          *
1305          * @access public
1306          * @param mixed $function Callback function
1307          */
1308         function set_cache_name_function($function = 'md5')
1309         {
1310                 if (is_callable($function))
1311                 {
1312                         $this->cache_name_function = $function;
1313                 }
1314         }
1315
1316         /**
1317          * Set javascript query string parameter
1318          *
1319          * @access public
1320          * @param mixed $get Javascript query string parameter
1321          */
1322         function set_javascript($get = 'js')
1323         {
1324                 if ($get)
1325                 {
1326                         $this->javascript = (string) $get;
1327                 }
1328                 else
1329                 {
1330                         $this->javascript = false;
1331                 }
1332         }
1333
1334         /**
1335          * Set options to make SP as fast as possible.  Forgoes a
1336          * substantial amount of data sanitization in favor of speed.
1337          *
1338          * @access public
1339          * @param bool $set Whether to set them or not
1340          */
1341         function set_stupidly_fast($set = false)
1342         {
1343                 if ($set)
1344                 {
1345                         $this->enable_order_by_date(false);
1346                         $this->remove_div(false);
1347                         $this->strip_comments(false);
1348                         $this->strip_htmltags(false);
1349                         $this->strip_attributes(false);
1350                         $this->set_image_handler(false);
1351                 }
1352         }
1353
1354         /**
1355          * Set maximum number of feeds to check with autodiscovery
1356          *
1357          * @access public
1358          * @param int $max Maximum number of feeds to check
1359          */
1360         function set_max_checked_feeds($max = 10)
1361         {
1362                 $this->max_checked_feeds = (int) $max;
1363         }
1364
1365         function remove_div($enable = true)
1366         {
1367                 $this->sanitize->remove_div($enable);
1368         }
1369
1370         function strip_htmltags($tags = '', $encode = null)
1371         {
1372                 if ($tags === '')
1373                 {
1374                         $tags = $this->strip_htmltags;
1375                 }
1376                 $this->sanitize->strip_htmltags($tags);
1377                 if ($encode !== null)
1378                 {
1379                         $this->sanitize->encode_instead_of_strip($tags);
1380                 }
1381         }
1382
1383         function encode_instead_of_strip($enable = true)
1384         {
1385                 $this->sanitize->encode_instead_of_strip($enable);
1386         }
1387
1388         function strip_attributes($attribs = '')
1389         {
1390                 if ($attribs === '')
1391                 {
1392                         $attribs = $this->strip_attributes;
1393                 }
1394                 $this->sanitize->strip_attributes($attribs);
1395         }
1396
1397         function set_output_encoding($encoding = 'UTF-8')
1398         {
1399                 $this->sanitize->set_output_encoding($encoding);
1400         }
1401
1402         function strip_comments($strip = false)
1403         {
1404                 $this->sanitize->strip_comments($strip);
1405         }
1406
1407         /**
1408          * Set element/attribute key/value pairs of HTML attributes
1409          * containing URLs that need to be resolved relative to the feed
1410          *
1411          * @access public
1412          * @since 1.0
1413          * @param array $element_attribute Element/attribute key/value pairs
1414          */
1415         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'))
1416         {
1417                 $this->sanitize->set_url_replacements($element_attribute);
1418         }
1419
1420         /**
1421          * Set the handler to enable the display of cached favicons.
1422          *
1423          * @access public
1424          * @param str $page Web-accessible path to the handler_favicon.php file.
1425          * @param str $qs The query string that the value should be passed to.
1426          */
1427         function set_favicon_handler($page = false, $qs = 'i')
1428         {
1429                 if ($page != false)
1430                 {
1431                         $this->favicon_handler = $page . '?' . $qs . '=';
1432                 }
1433                 else
1434                 {
1435                         $this->favicon_handler = '';
1436                 }
1437         }
1438
1439         /**
1440          * Set the handler to enable the display of cached images.
1441          *
1442          * @access public
1443          * @param str $page Web-accessible path to the handler_image.php file.
1444          * @param str $qs The query string that the value should be passed to.
1445          */
1446         function set_image_handler($page = false, $qs = 'i')
1447         {
1448                 if ($page != false)
1449                 {
1450                         $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1451                 }
1452                 else
1453                 {
1454                         $this->image_handler = '';
1455                 }
1456         }
1457
1458         /**
1459          * Set the limit for items returned per-feed with multifeeds.
1460          *
1461          * @access public
1462          * @param integer $limit The maximum number of items to return.
1463          */
1464         function set_item_limit($limit = 0)
1465         {
1466                 $this->item_limit = (int) $limit;
1467         }
1468
1469         function init()
1470         {
1471                 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1472                 {
1473                         return false;
1474                 }
1475                 if (isset($_GET[$this->javascript]))
1476                 {
1477                         if (function_exists('ob_gzhandler'))
1478                         {
1479                                 ob_start('ob_gzhandler');
1480                         }
1481                         header('Content-type: text/javascript; charset: UTF-8');
1482                         header('Cache-Control: must-revalidate');
1483                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
1484                         ?>
1485 function embed_odeo(link) {
1486         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>');
1487 }
1488
1489 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
1490         if (placeholder != '') {
1491                 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>');
1492         }
1493         else {
1494                 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>');
1495         }
1496 }
1497
1498 function embed_flash(bgcolor, width, height, link, loop, type) {
1499         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>');
1500 }
1501
1502 function embed_flv(width, height, link, placeholder, loop, player) {
1503         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>');
1504 }
1505
1506 function embed_wmedia(width, height, link) {
1507         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
1508 }
1509                         <?php
1510                         exit;
1511                 }
1512
1513                 // Pass whatever was set with config options over to the sanitizer.
1514                 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1515                 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1516
1517                 if ($this->feed_url !== null || $this->raw_data !== null)
1518                 {
1519                         $this->data = array();
1520                         $this->multifeed_objects = array();
1521                         $cache = false;
1522
1523                         if ($this->feed_url !== null)
1524                         {
1525                                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1526                                 // Decide whether to enable caching
1527                                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1528                                 {
1529                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1530                                 }
1531                                 // If it's enabled and we don't want an XML dump, use the cache
1532                                 if ($cache && !$this->xml_dump)
1533                                 {
1534                                         // Load the Cache
1535                                         $this->data = $cache->load();
1536                                         if (!empty($this->data))
1537                                         {
1538                                                 // If the cache is for an outdated build of SimplePie
1539                                                 if (!isset($this->data['build']) || $this->data['build'] != SIMPLEPIE_BUILD)
1540                                                 {
1541                                                         $cache->unlink();
1542                                                         $this->data = array();
1543                                                 }
1544                                                 // If we've hit a collision just rerun it with caching disabled
1545                                                 elseif (isset($this->data['url']) && $this->data['url'] != $this->feed_url)
1546                                                 {
1547                                                         $cache = false;
1548                                                         $this->data = array();
1549                                                 }
1550                                                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1551                                                 elseif (isset($this->data['feed_url']))
1552                                                 {
1553                                                         // If the autodiscovery cache is still valid use it.
1554                                                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1555                                                         {
1556                                                                 // Do not need to do feed autodiscovery yet.
1557                                                                 if ($this->data['feed_url'] == $this->data['url'])
1558                                                                 {
1559                                                                         $cache->unlink();
1560                                                                         $this->data = array();
1561                                                                 }
1562                                                                 else
1563                                                                 {
1564                                                                         $this->set_feed_url($this->data['feed_url']);
1565                                                                         return $this->init();
1566                                                                 }
1567                                                         }
1568                                                 }
1569                                                 // Check if the cache has been updated
1570                                                 elseif ($cache->mtime() + $this->cache_duration < time())
1571                                                 {
1572                                                         // If we have last-modified and/or etag set
1573                                                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1574                                                         {
1575                                                                 $headers = array();
1576                                                                 if (isset($this->data['headers']['last-modified']))
1577                                                                 {
1578                                                                         $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1579                                                                 }
1580                                                                 if (isset($this->data['headers']['etag']))
1581                                                                 {
1582                                                                         $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1583                                                                 }
1584                                                                 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1585                                                                 if ($file->success)
1586                                                                 {
1587                                                                         if ($file->status_code == 304)
1588                                                                         {
1589                                                                                 $cache->touch();
1590                                                                                 return true;
1591                                                                         }
1592                                                                         else
1593                                                                         {
1594                                                                                 $headers = $file->headers;
1595                                                                         }
1596                                                                 }
1597                                                                 else
1598                                                                 {
1599                                                                         unset($file);
1600                                                                 }
1601                                                         }
1602                                                 }
1603                                                 // If the cache is still valid, just return true
1604                                                 else
1605                                                 {
1606                                                         return true;
1607                                                 }
1608                                         }
1609                                         // If the cache is empty, delete it
1610                                         else
1611                                         {
1612                                                 $cache->unlink();
1613                                                 $this->data = array();
1614                                         }
1615                                 }
1616                                 // 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.
1617                                 if (!isset($file))
1618                                 {
1619                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->feed_url)
1620                                         {
1621                                                 $file =& $this->file;
1622                                         }
1623                                         else
1624                                         {
1625                                                 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1626                                         }
1627                                 }
1628                                 // If the file connection has an error, set SimplePie::error to that and quit
1629                                 if (!$file->success)
1630                                 {
1631                                         $this->error = $file->error;
1632                                         if (!empty($this->data))
1633                                         {
1634                                                 return true;
1635                                         }
1636                                         else
1637                                         {
1638                                                 return false;
1639                                         }
1640                                 }
1641
1642                                 if (!$this->force_feed)
1643                                 {
1644                                         // Check if the supplied URL is a feed, if it isn't, look for it.
1645                                         $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1646                                         if (!$locate->is_feed($file))
1647                                         {
1648                                                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1649                                                 unset($file);
1650                                                 if ($file = $locate->find($this->autodiscovery))
1651                                                 {
1652                                                         if ($cache)
1653                                                         {
1654                                                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1655                                                                 if (!$cache->save($this))
1656                                                                 {
1657                                                                         trigger_error("$cache->name is not writeable", E_USER_WARNING);
1658                                                                 }
1659                                                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1660                                                         }
1661                                                         $this->feed_url = $file->url;
1662                                                 }
1663                                                 else
1664                                                 {
1665                                                         $this->error = "A feed could not be found at $this->feed_url";
1666                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1667                                                         return false;
1668                                                 }
1669                                         }
1670                                         $locate = null;
1671                                 }
1672
1673                                 $headers = $file->headers;
1674                                 $data = $file->body;
1675                                 $sniffer = new $this->content_type_sniffer_class($file);
1676                                 $sniffed = $sniffer->get_type();
1677                         }
1678                         else
1679                         {
1680                                 $data = $this->raw_data;
1681                         }
1682                         
1683                         // Set up array of possible encodings
1684                         $encodings = array();
1685
1686                         // First check to see if input has been overridden.
1687                         if ($this->input_encoding !== false)
1688                         {
1689                                 $encodings[] = $this->input_encoding;
1690                         }
1691                         
1692                         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1693                         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1694                         
1695                         // RFC 3023 (only applies to sniffed content)
1696                         if (isset($sniffed))
1697                         {
1698                                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1699                                 {
1700                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1701                                         {
1702                                                 $encodings[] = strtoupper($charset[1]);
1703                                         }
1704                                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1705                                         $encodings[] = 'UTF-8';
1706                                 }
1707                                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1708                                 {
1709                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1710                                         {
1711                                                 $encodings[] = $charset[1];
1712                                         }
1713                                         $encodings[] = 'US-ASCII';
1714                                 }
1715                                 // Text MIME-type default
1716                                 elseif (substr($sniffed, 0, 5) === 'text/')
1717                                 {
1718                                         $encodings[] = 'US-ASCII';
1719                                 }
1720                         }
1721                         
1722                         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1723                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1724                         $encodings[] = 'UTF-8';
1725                         $encodings[] = 'ISO-8859-1';
1726                         
1727                         // There's no point in trying an encoding twice
1728                         $encodings = array_unique($encodings);
1729                         
1730                         // If we want the XML, just output that with the most likely encoding and quit
1731                         if ($this->xml_dump)
1732                         {
1733                                 header('Content-type: text/xml; charset=' . $encodings[0]);
1734                                 echo $data;
1735                                 exit;
1736                         }
1737                         
1738                         // Loop through each possible encoding, till we return something, or run out of possibilities
1739                         foreach ($encodings as $encoding)
1740                         {
1741                                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1742                                 $utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8');
1743
1744                                 // Create new parser
1745                                 $parser =& new $this->parser_class();
1746                                 
1747                                 // If it's parsed fine
1748                                 if ($parser->parse($utf8_data, 'UTF-8'))
1749                                 {
1750                                         $this->data = $parser->get_data();
1751                                         if (isset($this->data['child']))
1752                                         {
1753                                                 if (isset($headers))
1754                                                 {
1755                                                         $this->data['headers'] = $headers;
1756                                                 }
1757                                                 $this->data['build'] = SIMPLEPIE_BUILD;
1758         
1759                                                 // Cache the file if caching is enabled
1760                                                 if ($cache && !$cache->save($this))
1761                                                 {
1762                                                         trigger_error("$cache->name is not writeable", E_USER_WARNING);
1763                                                 }
1764                                                 return true;
1765                                         }
1766                                         else
1767                                         {
1768                                                 $this->error = "A feed could not be found at $this->feed_url";
1769                                                 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1770                                                 return false;
1771                                         }
1772                                 }
1773                         }
1774                         // We have an error, just set SimplePie::error to it and quit
1775                         $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1776                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1777                         return false;
1778                 }
1779                 elseif (!empty($this->multifeed_url))
1780                 {
1781                         $i = 0;
1782                         $success = 0;
1783                         $this->multifeed_objects = array();
1784                         foreach ($this->multifeed_url as $url)
1785                         {
1786                                 if (SIMPLEPIE_PHP5)
1787                                 {
1788                                         // This keyword needs to defy coding standards for PHP4 compatibility
1789                                         $this->multifeed_objects[$i] = clone($this);
1790                                 }
1791                                 else
1792                                 {
1793                                         $this->multifeed_objects[$i] = $this;
1794                                 }
1795                                 $this->multifeed_objects[$i]->set_feed_url($url);
1796                                 $success |= $this->multifeed_objects[$i]->init();
1797                                 $i++;
1798                         }
1799                         return (bool) $success;
1800                 }
1801                 else
1802                 {
1803                         return false;
1804                 }
1805         }
1806
1807         /**
1808          * Return the error message for the occured error
1809          *
1810          * @access public
1811          * @return string Error message
1812          */
1813         function error()
1814         {
1815                 return $this->error;
1816         }
1817
1818         function get_encoding()
1819         {
1820                 return $this->sanitize->output_encoding;
1821         }
1822
1823         function handle_content_type($mime = 'text/html')
1824         {
1825                 if (!headers_sent())
1826                 {
1827                         $header = "Content-type: $mime;";
1828                         if ($this->get_encoding())
1829                         {
1830                                 $header .= ' charset=' . $this->get_encoding();
1831                         }
1832                         else
1833                         {
1834                                 $header .= ' charset=UTF-8';
1835                         }
1836                         header($header);
1837                 }
1838         }
1839
1840         function get_type()
1841         {
1842                 if (!isset($this->data['type']))
1843                 {
1844                         $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1845                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1846                         {
1847                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1848                         }
1849                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1850                         {
1851                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1852                         }
1853                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1854                         {
1855                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1856                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1857                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1858                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1859                                 {
1860                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1861                                 }
1862                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1863                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1864                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1865                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1866                                 {
1867                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1868                                 }
1869                         }
1870                         elseif (isset($this->data['child']['']['rss']))
1871                         {
1872                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1873                                 if (isset($this->data['child']['']['rss'][0]['attribs']['']['version']))
1874                                 {
1875                                         switch (trim($this->data['child']['']['rss'][0]['attribs']['']['version']))
1876                                         {
1877                                                 case '0.91':
1878                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1879                                                         if (isset($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
1880                                                         {
1881                                                                 switch (trim($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
1882                                                                 {
1883                                                                         case '0':
1884                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1885                                                                                 break;
1886
1887                                                                         case '24':
1888                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1889                                                                                 break;
1890                                                                 }
1891                                                         }
1892                                                         break;
1893
1894                                                 case '0.92':
1895                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1896                                                         break;
1897
1898                                                 case '0.93':
1899                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1900                                                         break;
1901
1902                                                 case '0.94':
1903                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1904                                                         break;
1905
1906                                                 case '2.0':
1907                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1908                                                         break;
1909                                         }
1910                                 }
1911                         }
1912                         else
1913                         {
1914                                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1915                         }
1916                 }
1917                 return $this->data['type'];
1918         }
1919
1920         /**
1921          * Returns the URL for the favicon of the feed's website.
1922          *
1923          * @todo Cache atom:icon
1924          * @access public
1925          * @since 1.0
1926          */
1927         function get_favicon()
1928         {
1929                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1930                 {
1931                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1932                 }
1933                 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1934                 {
1935                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1936
1937                         if ($this->cache && $this->favicon_handler)
1938                         {
1939                                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1940                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1941
1942                                 if ($cache->load())
1943                                 {
1944                                         return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1945                                 }
1946                                 else
1947                                 {
1948                                         $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1949
1950                                         if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1951                                         {
1952                                                 $sniffer = new $this->content_type_sniffer_class($file);
1953                                                 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1954                                                 {
1955                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1956                                                         {
1957                                                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1958                                                         }
1959                                                         else
1960                                                         {
1961                                                                 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1962                                                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1963                                                         }
1964                                                 }
1965                                         }
1966                                 }
1967                         }
1968                         else
1969                         {
1970                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1971                         }
1972                 }
1973                 return false;
1974         }
1975
1976         /**
1977          * @todo If we have a perm redirect we should return the new URL
1978          * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1979          * @todo Also, |atom:link|@rel=self
1980          */
1981         function subscribe_url()
1982         {
1983                 if ($this->feed_url !== null)
1984                 {
1985                         return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1986                 }
1987                 else
1988                 {
1989                         return null;
1990                 }
1991         }
1992
1993         function subscribe_feed()
1994         {
1995                 if ($this->feed_url !== null)
1996                 {
1997                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
1998                 }
1999                 else
2000                 {
2001                         return null;
2002                 }
2003         }
2004
2005         function subscribe_outlook()
2006         {
2007                 if ($this->feed_url !== null)
2008                 {
2009                         return 'outlook' . $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2010                 }
2011                 else
2012                 {
2013                         return null;
2014                 }
2015         }
2016
2017         function subscribe_podcast()
2018         {
2019                 if ($this->feed_url !== null)
2020                 {
2021                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2022                 }
2023                 else
2024                 {
2025                         return null;
2026                 }
2027         }
2028
2029         function subscribe_itunes()
2030         {
2031                 if ($this->feed_url !== null)
2032                 {
2033                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2034                 }
2035                 else
2036                 {
2037                         return null;
2038                 }
2039         }
2040
2041         /**
2042          * Creates the subscribe_* methods' return data
2043          *
2044          * @access private
2045          * @param string $feed_url String to prefix to the feed URL
2046          * @param string $site_url String to prefix to the site URL (and
2047          * suffix to the feed URL)
2048          * @return mixed URL if feed exists, false otherwise
2049          */
2050         function subscribe_service($feed_url, $site_url = null)
2051         {
2052                 if ($this->subscribe_url())
2053                 {
2054                         $return = $this->sanitize($feed_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->feed_url);
2055                         if ($site_url !== null && $this->get_link() !== null)
2056                         {
2057                                 $return .= $this->sanitize($site_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_link());
2058                         }
2059                         return $return;
2060                 }
2061                 else
2062                 {
2063                         return null;
2064                 }
2065         }
2066
2067         function subscribe_aol()
2068         {
2069                 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2070         }
2071
2072         function subscribe_bloglines()
2073         {
2074                 return urldecode($this->subscribe_service('http://www.bloglines.com/sub/'));
2075         }
2076
2077         function subscribe_eskobo()
2078         {
2079                 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2080         }
2081
2082         function subscribe_feedfeeds()
2083         {
2084                 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2085         }
2086
2087         function subscribe_feedster()
2088         {
2089                 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2090         }
2091
2092         function subscribe_google()
2093         {
2094                 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2095         }
2096
2097         function subscribe_gritwire()
2098         {
2099                 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2100         }
2101
2102         function subscribe_msn()
2103         {
2104                 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2105         }
2106
2107         function subscribe_netvibes()
2108         {
2109                 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2110         }
2111
2112         function subscribe_newsburst()
2113         {
2114                 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2115         }
2116
2117         function subscribe_newsgator()
2118         {
2119                 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2120         }
2121
2122         function subscribe_odeo()
2123         {
2124                 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2125         }
2126
2127         function subscribe_podnova()
2128         {
2129                 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2130         }
2131
2132         function subscribe_rojo()
2133         {
2134                 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2135         }
2136
2137         function subscribe_yahoo()
2138         {
2139                 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2140         }
2141
2142         function get_feed_tags($namespace, $tag)
2143         {
2144                 $type = $this->get_type();
2145                 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2146                 {
2147                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2148                         {
2149                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2150                         }
2151                 }
2152                 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2153                 {
2154                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2155                         {
2156                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2157                         }
2158                 }
2159                 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2160                 {
2161                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2162                         {
2163                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2164                         }
2165                 }
2166                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2167                 {
2168                         if (isset($this->data['child']['']['rss'][0]['child'][$namespace][$tag]))
2169                         {
2170                                 return $this->data['child']['']['rss'][0]['child'][$namespace][$tag];
2171                         }
2172                 }
2173                 return null;
2174         }
2175
2176         function get_channel_tags($namespace, $tag)
2177         {
2178                 $type = $this->get_type();
2179                 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2180                 {
2181                         if ($return = $this->get_feed_tags($namespace, $tag))
2182                         {
2183                                 return $return;
2184                         }
2185                 }
2186                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2187                 {
2188                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2189                         {
2190                                 if (isset($channel[0]['child'][$namespace][$tag]))
2191                                 {
2192                                         return $channel[0]['child'][$namespace][$tag];
2193                                 }
2194                         }
2195                 }
2196                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2197                 {
2198                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2199                         {
2200                                 if (isset($channel[0]['child'][$namespace][$tag]))
2201                                 {
2202                                         return $channel[0]['child'][$namespace][$tag];
2203                                 }
2204                         }
2205                 }
2206                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2207                 {
2208                         if ($channel = $this->get_feed_tags('', 'channel'))
2209                         {
2210                                 if (isset($channel[0]['child'][$namespace][$tag]))
2211                                 {
2212                                         return $channel[0]['child'][$namespace][$tag];
2213                                 }
2214                         }
2215                 }
2216                 return null;
2217         }
2218
2219         function get_image_tags($namespace, $tag)
2220         {
2221                 $type = $this->get_type();
2222                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2223                 {
2224                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2225                         {
2226                                 if (isset($image[0]['child'][$namespace][$tag]))
2227                                 {
2228                                         return $image[0]['child'][$namespace][$tag];
2229                                 }
2230                         }
2231                 }
2232                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2233                 {
2234                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2235                         {
2236                                 if (isset($image[0]['child'][$namespace][$tag]))
2237                                 {
2238                                         return $image[0]['child'][$namespace][$tag];
2239                                 }
2240                         }
2241                 }
2242                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2243                 {
2244                         if ($image = $this->get_channel_tags('', 'image'))
2245                         {
2246                                 if (isset($image[0]['child'][$namespace][$tag]))
2247                                 {
2248                                         return $image[0]['child'][$namespace][$tag];
2249                                 }
2250                         }
2251                 }
2252                 return null;
2253         }
2254
2255         function get_base($element = array())
2256         {
2257                 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2258                 {
2259                         return $element['xml_base'];
2260                 }
2261                 elseif ($this->get_link() !== null)
2262                 {
2263                         return $this->get_link();
2264                 }
2265                 else
2266                 {
2267                         return $this->subscribe_url();
2268                 }
2269         }
2270
2271         function sanitize($data, $type, $base = '')
2272         {
2273                 return $this->sanitize->sanitize($data, $type, $base);
2274         }
2275
2276         function get_title()
2277         {
2278                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2279                 {
2280                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2281                 }
2282                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2283                 {
2284                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2285                 }
2286                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2287                 {
2288                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2289                 }
2290                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2291                 {
2292                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2293                 }
2294                 elseif ($return = $this->get_channel_tags('', 'title'))
2295                 {
2296                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2297                 }
2298                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2299                 {
2300                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2301                 }
2302                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2303                 {
2304                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2305                 }
2306                 else
2307                 {
2308                         return null;
2309                 }
2310         }
2311
2312         function get_category($key = 0)
2313         {
2314                 $categories = $this->get_categories();
2315                 if (isset($categories[$key]))
2316                 {
2317                         return $categories[$key];
2318                 }
2319                 else
2320                 {
2321                         return null;
2322                 }
2323         }
2324
2325         function get_categories()
2326         {
2327                 $categories = array();
2328
2329                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2330                 {
2331                         $term = null;
2332                         $scheme = null;
2333                         $label = null;
2334                         if (isset($category['attribs']['']['term']))
2335                         {
2336                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2337                         }
2338                         if (isset($category['attribs']['']['scheme']))
2339                         {
2340                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2341                         }
2342                         if (isset($category['attribs']['']['label']))
2343                         {
2344                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2345                         }
2346                         $categories[] =& new $this->category_class($term, $scheme, $label);
2347                 }
2348                 foreach ((array) $this->get_channel_tags('', 'category') as $category)
2349                 {
2350                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2351                 }
2352                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2353                 {
2354                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2355                 }
2356                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2357                 {
2358                         $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2359                 }
2360
2361                 if (!empty($categories))
2362                 {
2363                         return SimplePie_Misc::array_unique($categories);
2364                 }
2365                 else
2366                 {
2367                         return null;
2368                 }
2369         }
2370
2371         function get_author($key = 0)
2372         {
2373                 $authors = $this->get_authors();
2374                 if (isset($authors[$key]))
2375                 {
2376                         return $authors[$key];
2377                 }
2378                 else
2379                 {
2380                         return null;
2381                 }
2382         }
2383
2384         function get_authors()
2385         {
2386                 $authors = array();
2387                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2388                 {
2389                         $name = null;
2390                         $uri = null;
2391                         $email = null;
2392                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2393                         {
2394                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2395                         }
2396                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2397                         {
2398                                 $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]));
2399                         }
2400                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2401                         {
2402                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2403                         }
2404                         if ($name !== null || $email !== null || $uri !== null)
2405                         {
2406                                 $authors[] =& new $this->author_class($name, $uri, $email);
2407                         }
2408                 }
2409                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2410                 {
2411                         $name = null;
2412                         $url = null;
2413                         $email = null;
2414                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2415                         {
2416                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2417                         }
2418                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2419                         {
2420                                 $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]));
2421                         }
2422                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2423                         {
2424                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2425                         }
2426                         if ($name !== null || $email !== null || $url !== null)
2427                         {
2428                                 $authors[] =& new $this->author_class($name, $url, $email);
2429                         }
2430                 }
2431                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2432                 {
2433                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2434                 }
2435                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2436                 {
2437                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2438                 }
2439                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2440                 {
2441                         $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2442                 }
2443
2444                 if (!empty($authors))
2445                 {
2446                         return SimplePie_Misc::array_unique($authors);
2447                 }
2448                 else
2449                 {
2450                         return null;
2451                 }
2452         }
2453
2454         function get_contributor($key = 0)
2455         {
2456                 $contributors = $this->get_contributors();
2457                 if (isset($contributors[$key]))
2458                 {
2459                         return $contributors[$key];
2460                 }
2461                 else
2462                 {
2463                         return null;
2464                 }
2465         }
2466
2467         function get_contributors()
2468         {
2469                 $contributors = array();
2470                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2471                 {
2472                         $name = null;
2473                         $uri = null;
2474                         $email = null;
2475                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2476                         {
2477                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2478                         }
2479                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2480                         {
2481                                 $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]));
2482                         }
2483                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2484                         {
2485                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2486                         }
2487                         if ($name !== null || $email !== null || $uri !== null)
2488                         {
2489                                 $contributors[] =& new $this->author_class($name, $uri, $email);
2490                         }
2491                 }
2492                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2493                 {
2494                         $name = null;
2495                         $url = null;
2496                         $email = null;
2497                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2498                         {
2499                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2500                         }
2501                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2502                         {
2503                                 $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]));
2504                         }
2505                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2506                         {
2507                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2508                         }
2509                         if ($name !== null || $email !== null || $url !== null)
2510                         {
2511                                 $contributors[] =& new $this->author_class($name, $url, $email);
2512                         }
2513                 }
2514
2515                 if (!empty($contributors))
2516                 {
2517                         return SimplePie_Misc::array_unique($contributors);
2518                 }
2519                 else
2520                 {
2521                         return null;
2522                 }
2523         }
2524
2525         function get_link($key = 0, $rel = 'alternate')
2526         {
2527                 $links = $this->get_links($rel);
2528                 if (isset($links[$key]))
2529                 {
2530                         return $links[$key];
2531                 }
2532                 else
2533                 {
2534                         return null;
2535                 }
2536         }
2537
2538         /**
2539          * Added for parity between the parent-level and the item/entry-level.
2540          */
2541         function get_permalink()
2542         {
2543                 return $this->get_link(0);
2544         }
2545
2546         function get_links($rel = 'alternate')
2547         {
2548                 if (!isset($this->data['links']))
2549                 {
2550                         $this->data['links'] = array();
2551                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2552                         {
2553                                 foreach ($links as $link)
2554                                 {
2555                                         if (isset($link['attribs']['']['href']))
2556                                         {
2557                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2558                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2559                                         }
2560                                 }
2561                         }
2562                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2563                         {
2564                                 foreach ($links as $link)
2565                                 {
2566                                         if (isset($link['attribs']['']['href']))
2567                                         {
2568                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2569                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2570
2571                                         }
2572                                 }
2573                         }
2574                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2575                         {
2576                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2577                         }
2578                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2579                         {
2580                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2581                         }
2582                         if ($links = $this->get_channel_tags('', 'link'))
2583                         {
2584                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2585                         }
2586
2587                         $keys = array_keys($this->data['links']);
2588                         foreach ($keys as $key)
2589                         {
2590                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2591                                 {
2592                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2593                                         {
2594                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2595                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2596                                         }
2597                                         else
2598                                         {
2599                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2600                                         }
2601                                 }
2602                                 elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2603                                 {
2604                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2605                                 }
2606                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2607                         }
2608                 }
2609
2610                 if (isset($this->data['links'][$rel]))
2611                 {
2612                         return $this->data['links'][$rel];
2613                 }
2614                 else
2615                 {
2616                         return null;
2617                 }
2618         }
2619
2620         function get_description()
2621         {
2622                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2623                 {
2624                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2625                 }
2626                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2627                 {
2628                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2629                 }
2630                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2631                 {
2632                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2633                 }
2634                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2635                 {
2636                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2637                 }
2638                 elseif ($return = $this->get_channel_tags('', 'description'))
2639                 {
2640                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2641                 }
2642                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2643                 {
2644                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2645                 }
2646                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2647                 {
2648                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2649                 }
2650                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2651                 {
2652                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2653                 }
2654                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2655                 {
2656                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2657                 }
2658                 else
2659                 {
2660                         return null;
2661                 }
2662         }
2663
2664         function get_copyright()
2665         {
2666                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2667                 {
2668                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2669                 }
2670                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2671                 {
2672                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2673                 }
2674                 elseif ($return = $this->get_channel_tags('', 'copyright'))
2675                 {
2676                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2677                 }
2678                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2679                 {
2680                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2681                 }
2682                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2683                 {
2684                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2685                 }
2686                 else
2687                 {
2688                         return null;
2689                 }
2690         }
2691
2692         function get_language()
2693         {
2694                 if ($return = $this->get_channel_tags('', 'language'))
2695                 {
2696                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2697                 }
2698                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2699                 {
2700                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2701                 }
2702                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2703                 {
2704                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2705                 }
2706                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2707                 {
2708                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2709                 }
2710                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2711                 {
2712                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2713                 }
2714                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2715                 {
2716                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2717                 }
2718                 elseif (isset($this->data['headers']['content-language']))
2719                 {
2720                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2721                 }
2722                 else
2723                 {
2724                         return null;
2725                 }
2726         }
2727
2728         function get_latitude()
2729         {
2730                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2731                 {
2732                         return (float) $return[0]['data'];
2733                 }
2734                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2735                 {
2736                         return (float) $match[1];
2737                 }
2738                 else
2739                 {
2740                         return null;
2741                 }
2742         }
2743
2744         function get_longitude()
2745         {
2746                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2747                 {
2748                         return (float) $return[0]['data'];
2749                 }
2750                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2751                 {
2752                         return (float) $return[0]['data'];
2753                 }
2754                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2755                 {
2756                         return (float) $match[2];
2757                 }
2758                 else
2759                 {
2760                         return null;
2761                 }
2762         }
2763
2764         function get_image_title()
2765         {
2766                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2767                 {
2768                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2769                 }
2770                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2771                 {
2772                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2773                 }
2774                 elseif ($return = $this->get_image_tags('', 'title'))
2775                 {
2776                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2777                 }
2778                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2779                 {
2780                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2781                 }
2782                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2783                 {
2784                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2785                 }
2786                 else
2787                 {
2788                         return null;
2789                 }
2790         }
2791
2792         function get_image_url()
2793         {
2794                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2795                 {
2796                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2797                 }
2798                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2799                 {
2800                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2801                 }
2802                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2803                 {
2804                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2805                 }
2806                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2807                 {
2808                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2809                 }
2810                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2811                 {
2812                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2813                 }
2814                 elseif ($return = $this->get_image_tags('', 'url'))
2815                 {
2816                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2817                 }
2818                 else
2819                 {
2820                         return null;
2821                 }
2822         }
2823
2824         function get_image_link()
2825         {
2826                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2827                 {
2828                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2829                 }
2830                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2831                 {
2832                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2833                 }
2834                 elseif ($return = $this->get_image_tags('', 'link'))
2835                 {
2836                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2837                 }
2838                 else
2839                 {
2840                         return null;
2841                 }
2842         }
2843
2844         function get_image_width()
2845         {
2846                 if ($return = $this->get_image_tags('', 'width'))
2847                 {
2848                         return round($return[0]['data']);
2849                 }
2850                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
2851                 {
2852                         return 88.0;
2853                 }
2854                 else
2855                 {
2856                         return null;
2857                 }
2858         }
2859
2860         function get_image_height()
2861         {
2862                 if ($return = $this->get_image_tags('', 'height'))
2863                 {
2864                         return round($return[0]['data']);
2865                 }
2866                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
2867                 {
2868                         return 31.0;
2869                 }
2870                 else
2871                 {
2872                         return null;
2873                 }
2874         }
2875
2876         function get_item_quantity($max = 0)
2877         {
2878                 $qty = count($this->get_items());
2879                 if ($max == 0)
2880                 {
2881                         return $qty;
2882                 }
2883                 else
2884                 {
2885                         return ($qty > $max) ? $max : $qty;
2886                 }
2887         }
2888
2889         function get_item($key = 0)
2890         {
2891                 $items = $this->get_items();
2892                 if (isset($items[$key]))
2893                 {
2894                         return $items[$key];
2895                 }
2896                 else
2897                 {
2898                         return null;
2899                 }
2900         }
2901
2902         function get_items($start = 0, $end = 0)
2903         {
2904                 if (!empty($this->multifeed_objects))
2905                 {
2906                         return SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2907                 }
2908                 elseif (!isset($this->data['items']))
2909                 {
2910                         if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2911                         {
2912                                 $keys = array_keys($items);
2913                                 foreach ($keys as $key)
2914                                 {
2915                                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2916                                 }
2917                         }
2918                         if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2919                         {
2920                                 $keys = array_keys($items);
2921                                 foreach ($keys as $key)
2922                                 {
2923                                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2924                                 }
2925                         }
2926                         if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2927                         {
2928                                 $keys = array_keys($items);
2929                                 foreach ($keys as $key)
2930                                 {
2931                                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2932                                 }
2933                         }
2934                         if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2935                         {
2936                                 $keys = array_keys($items);
2937                                 foreach ($keys as $key)
2938                                 {
2939                                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2940                                 }
2941                         }
2942                         if ($items = $this->get_channel_tags('', 'item'))
2943                         {
2944                                 $keys = array_keys($items);
2945                                 foreach ($keys as $key)
2946                                 {
2947                                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2948                                 }
2949                         }
2950                 }
2951
2952                 if (!empty($this->data['items']))
2953                 {
2954                         // If we want to order it by date, check if all items have a date, and then sort it
2955                         if ($this->order_by_date)
2956                         {
2957                                 if (!isset($this->data['ordered_items']))
2958                                 {
2959                                         $do_sort = true;
2960                                         foreach ($this->data['items'] as $item)
2961                                         {
2962                                                 if (!$item->get_date('U'))
2963                                                 {
2964                                                         $do_sort = false;
2965                                                         break;
2966                                                 }
2967                                         }
2968                                         $item = null;
2969                                         $this->data['ordered_items'] = $this->data['items'];
2970                                         if ($do_sort)
2971                                         {
2972                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
2973                                         }
2974                                 }
2975                                 $items = $this->data['ordered_items'];
2976                         }
2977                         else
2978                         {
2979                                 $items = $this->data['items'];
2980                         }
2981
2982                         // Slice the data as desired
2983                         if ($end == 0)
2984                         {
2985                                 return array_slice($items, $start);
2986                         }
2987                         else
2988                         {
2989                                 return array_slice($items, $start, $end);
2990                         }
2991                 }
2992                 else
2993                 {
2994                         return array();
2995                 }
2996         }
2997
2998         function sort_items($a, $b)
2999         {
3000                 return $a->get_date('U') <= $b->get_date('U');
3001         }
3002
3003         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3004         {
3005                 if (is_array($urls) && sizeof($urls) > 0)
3006                 {
3007                         $items = array();
3008                         foreach ($urls as $arg)
3009                         {
3010                                 if (is_a($arg, 'SimplePie'))
3011                                 {
3012                                         $items = array_merge($items, $arg->get_items(0, $limit));
3013                                 }
3014                                 else
3015                                 {
3016                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3017                                 }
3018                         }
3019
3020                         $do_sort = true;
3021                         foreach ($items as $item)
3022                         {
3023                                 if (!$item->get_date('U'))
3024                                 {
3025                                         $do_sort = false;
3026                                         break;
3027                                 }
3028                         }
3029                         $item = null;
3030                         if ($do_sort)
3031                         {
3032                                 usort($items, array('SimplePie', 'sort_items'));
3033                         }
3034
3035                         if ($end == 0)
3036                         {
3037                                 return array_slice($items, $start);
3038                         }
3039                         else
3040                         {
3041                                 return array_slice($items, $start, $end);
3042                         }
3043                 }
3044                 else
3045                 {
3046                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3047                         return array();
3048                 }
3049         }
3050 }
3051
3052 class SimplePie_Item
3053 {
3054         var $feed;
3055         var $data = array();
3056
3057         function SimplePie_Item($feed, $data)
3058         {
3059                 $this->feed = $feed;
3060                 $this->data = $data;
3061         }
3062
3063         function __toString()
3064         {
3065                 return md5(serialize($this->data));
3066         }
3067         
3068         /**
3069          * Remove items that link back to this before destroying this object
3070          */
3071         function __destruct()
3072         {
3073                 unset($this->feed);
3074         }
3075
3076         function get_item_tags($namespace, $tag)
3077         {
3078                 if (isset($this->data['child'][$namespace][$tag]))
3079                 {
3080                         return $this->data['child'][$namespace][$tag];
3081                 }
3082                 else
3083                 {
3084                         return null;
3085                 }
3086         }
3087
3088         function get_base($element = array())
3089         {
3090                 return $this->feed->get_base($element);
3091         }
3092
3093         function sanitize($data, $type, $base = '')
3094         {
3095                 return $this->feed->sanitize($data, $type, $base);
3096         }
3097
3098         function get_feed()
3099         {
3100                 return $this->feed;
3101         }
3102
3103         function get_id($hash = false)
3104         {
3105                 if (!$hash)
3106                 {
3107                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3108                         {
3109                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3110                         }
3111                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3112                         {
3113                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3114                         }
3115                         elseif ($return = $this->get_item_tags('', 'guid'))
3116                         {
3117                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3118                         }
3119                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3120                         {
3121                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3122                         }
3123                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3124                         {
3125                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3126                         }
3127                         elseif (($return = $this->get_permalink()) !== null)
3128                         {
3129                                 return $return;
3130                         }
3131                         elseif (($return = $this->get_title()) !== null)
3132                         {
3133                                 return $return;
3134                         }
3135                 }
3136                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3137                 {
3138                         return md5($this->get_permalink() . $this->get_title());
3139                 }
3140                 else
3141                 {
3142                         return md5(serialize($this->data));
3143                 }
3144         }
3145
3146         function get_title()
3147         {
3148                 if (!isset($this->data['title']))
3149                 {
3150                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3151                         {
3152                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3153                         }
3154                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3155                         {
3156                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3157                         }
3158                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3159                         {
3160                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3161                         }
3162                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3163                         {
3164                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3165                         }
3166                         elseif ($return = $this->get_item_tags('', 'title'))
3167                         {
3168                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3169                         }
3170                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3171                         {
3172                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3173                         }
3174                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3175                         {
3176                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3177                         }
3178                         else
3179                         {
3180                                 $this->data['title'] = null;
3181                         }
3182                 }
3183                 return $this->data['title'];
3184         }
3185
3186         function get_description($description_only = false)
3187         {
3188                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3189                 {
3190                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3191                 }
3192                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3193                 {
3194                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3195                 }
3196                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3197                 {
3198                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3199                 }
3200                 elseif ($return = $this->get_item_tags('', 'description'))
3201                 {
3202                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3203                 }
3204                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3205                 {
3206                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3207                 }
3208                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3209                 {
3210                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3211                 }
3212                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3213                 {
3214                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3215                 }
3216                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3217                 {
3218                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3219                 }
3220                 elseif (!$description_only)
3221                 {
3222                         return $this->get_content(true);
3223                 }
3224                 else
3225                 {
3226                         return null;
3227                 }
3228         }
3229
3230         function get_content($content_only = false)
3231         {
3232                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3233                 {
3234                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3235                 }
3236                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3237                 {
3238                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3239                 }
3240                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3241                 {
3242                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3243                 }
3244                 elseif (!$content_only)
3245                 {
3246                         return $this->get_description(true);
3247                 }
3248                 else
3249                 {
3250                         return null;
3251                 }
3252         }
3253
3254         function get_category($key = 0)
3255         {
3256                 $categories = $this->get_categories();
3257                 if (isset($categories[$key]))
3258                 {
3259                         return $categories[$key];
3260                 }
3261                 else
3262                 {
3263                         return null;
3264                 }
3265         }
3266
3267         function get_categories()
3268         {
3269                 $categories = array();
3270
3271                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3272                 {
3273                         $term = null;
3274                         $scheme = null;
3275                         $label = null;
3276                         if (isset($category['attribs']['']['term']))
3277                         {
3278                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3279                         }
3280                         if (isset($category['attribs']['']['scheme']))
3281                         {
3282                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3283                         }
3284                         if (isset($category['attribs']['']['label']))
3285                         {
3286                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3287                         }
3288                         $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3289                 }
3290                 foreach ((array) $this->get_item_tags('', 'category') as $category)
3291                 {
3292                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3293                 }
3294                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3295                 {
3296                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3297                 }
3298                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3299                 {
3300                         $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3301                 }
3302
3303                 if (!empty($categories))
3304                 {
3305                         return SimplePie_Misc::array_unique($categories);
3306                 }
3307                 else
3308                 {
3309                         return null;
3310                 }
3311         }
3312
3313         function get_author($key = 0)
3314         {
3315                 $authors = $this->get_authors();
3316                 if (isset($authors[$key]))
3317                 {
3318                         return $authors[$key];
3319                 }
3320                 else
3321                 {
3322                         return null;
3323                 }
3324         }
3325
3326         function get_contributor($key = 0)
3327         {
3328                 $contributors = $this->get_contributors();
3329                 if (isset($contributors[$key]))
3330                 {
3331                         return $contributors[$key];
3332                 }
3333                 else
3334                 {
3335                         return null;
3336                 }
3337         }
3338
3339         function get_contributors()
3340         {
3341                 $contributors = array();
3342                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3343                 {
3344                         $name = null;
3345                         $uri = null;
3346                         $email = null;
3347                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3348                         {
3349                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3350                         }
3351                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3352                         {
3353                                 $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]));
3354                         }
3355                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3356                         {
3357                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3358                         }
3359                         if ($name !== null || $email !== null || $uri !== null)
3360                         {
3361                                 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3362                         }
3363                 }
3364                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3365                 {
3366                         $name = null;
3367                         $url = null;
3368                         $email = null;
3369                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3370                         {
3371                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3372                         }
3373                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3374                         {
3375                                 $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]));
3376                         }
3377                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3378                         {
3379                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3380                         }
3381                         if ($name !== null || $email !== null || $url !== null)
3382                         {
3383                                 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3384                         }
3385                 }
3386
3387                 if (!empty($contributors))
3388                 {
3389                         return SimplePie_Misc::array_unique($contributors);
3390                 }
3391                 else
3392                 {
3393                         return null;
3394                 }
3395         }
3396
3397         /**
3398          * @todo Atom inheritance (item author, source author, feed author)
3399          */
3400         function get_authors()
3401         {
3402                 $authors = array();
3403                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3404                 {
3405                         $name = null;
3406                         $uri = null;
3407                         $email = null;
3408                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3409                         {
3410                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3411                         }
3412                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3413                         {
3414                                 $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]));
3415                         }
3416                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3417                         {
3418                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3419                         }
3420                         if ($name !== null || $email !== null || $uri !== null)
3421                         {
3422                                 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3423                         }
3424                 }
3425                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3426                 {
3427                         $name = null;
3428                         $url = null;
3429                         $email = null;
3430                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3431                         {
3432                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3433                         }
3434                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3435                         {
3436                                 $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]));
3437                         }
3438                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3439                         {
3440                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3441                         }
3442                         if ($name !== null || $email !== null || $url !== null)
3443                         {
3444                                 $authors[] =& new $this->feed->author_class($name, $url, $email);
3445                         }
3446                 }
3447                 if ($author = $this->get_item_tags('', 'author'))
3448                 {
3449                         $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3450                 }
3451                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3452                 {
3453                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3454                 }
3455                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3456                 {
3457                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3458                 }
3459                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3460                 {
3461                         $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3462                 }
3463
3464                 if (!empty($authors))
3465                 {
3466                         return SimplePie_Misc::array_unique($authors);
3467                 }
3468                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3469                 {
3470                         return $authors;
3471                 }
3472                 elseif ($authors = $this->feed->get_authors())
3473                 {
3474                         return $authors;
3475                 }
3476                 else
3477                 {
3478                         return null;
3479                 }
3480         }
3481
3482         function get_copyright()
3483         {
3484                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3485                 {
3486                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3487                 }
3488                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3489                 {
3490                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3491                 }
3492                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3493                 {
3494                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3495                 }
3496                 else
3497                 {
3498                         return null;
3499                 }
3500         }
3501
3502         function get_date($date_format = 'j F Y, g:i a')
3503         {
3504                 if (!isset($this->data['date']))
3505                 {
3506                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3507                         {
3508                                 $this->data['date']['raw'] = $return[0]['data'];
3509                         }
3510                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3511                         {
3512                                 $this->data['date']['raw'] = $return[0]['data'];
3513                         }
3514                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3515                         {
3516                                 $this->data['date']['raw'] = $return[0]['data'];
3517                         }
3518                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3519                         {
3520                                 $this->data['date']['raw'] = $return[0]['data'];
3521                         }
3522                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3523                         {
3524                                 $this->data['date']['raw'] = $return[0]['data'];
3525                         }
3526                         elseif ($return = $this->get_item_tags('', 'pubDate'))
3527                         {
3528                                 $this->data['date']['raw'] = $return[0]['data'];
3529                         }
3530                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3531                         {
3532                                 $this->data['date']['raw'] = $return[0]['data'];
3533                         }
3534                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3535                         {
3536                                 $this->data['date']['raw'] = $return[0]['data'];
3537                         }
3538
3539                         if (!empty($this->data['date']['raw']))
3540                         {
3541                                 $parser = SimplePie_Parse_Date::get();
3542                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3543                         }
3544                         else
3545                         {
3546                                 $this->data['date'] = null;
3547                         }
3548                 }
3549                 if ($this->data['date'])
3550                 {
3551                         $date_format = (string) $date_format;
3552                         switch ($date_format)
3553                         {
3554                                 case '':
3555                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3556
3557                                 case 'U':
3558                                         return $this->data['date']['parsed'];
3559
3560                                 default:
3561                                         return date($date_format, $this->data['date']['parsed']);
3562                         }
3563                 }
3564                 else
3565                 {
3566                         return null;
3567                 }
3568         }
3569
3570         function get_local_date($date_format = '%c')
3571         {
3572                 if (!$date_format)
3573                 {
3574                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3575                 }
3576                 elseif (($date = $this->get_date('U')) !== null)
3577                 {
3578                         return strftime($date_format, $date);
3579                 }
3580                 else
3581                 {
3582                         return null;
3583                 }
3584         }
3585
3586         function get_permalink()
3587         {
3588                 $link = $this->get_link();
3589                 $enclosure = $this->get_enclosure(0);
3590                 if ($link !== null)
3591                 {
3592                         return $link;
3593                 }
3594                 elseif ($enclosure !== null)
3595                 {
3596                         return $enclosure->get_link();
3597                 }
3598                 else
3599                 {
3600                         return null;
3601                 }
3602         }
3603
3604         function get_link($key = 0, $rel = 'alternate')
3605         {
3606                 $links = $this->get_links($rel);
3607                 if ($links[$key] !== null)
3608                 {
3609                         return $links[$key];
3610                 }
3611                 else
3612                 {
3613                         return null;
3614                 }
3615         }
3616
3617         function get_links($rel = 'alternate')
3618         {
3619                 if (!isset($this->data['links']))
3620                 {
3621                         $this->data['links'] = array();
3622                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3623                         {
3624                                 if (isset($link['attribs']['']['href']))
3625                                 {
3626                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3627                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3628
3629                                 }
3630                         }
3631                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3632                         {
3633                                 if (isset($link['attribs']['']['href']))
3634                                 {
3635                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3636                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3637                                 }
3638                         }
3639                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3640                         {
3641                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3642                         }
3643                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3644                         {
3645                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3646                         }
3647                         if ($links = $this->get_item_tags('', 'link'))
3648                         {
3649                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3650                         }
3651                         if ($links = $this->get_item_tags('', 'guid'))
3652                         {
3653                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) == 'true')
3654                                 {
3655                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3656                                 }
3657                         }
3658
3659                         $keys = array_keys($this->data['links']);
3660                         foreach ($keys as $key)
3661                         {
3662                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3663                                 {
3664                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3665                                         {
3666                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3667                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3668                                         }
3669                                         else
3670                                         {
3671                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3672                                         }
3673                                 }
3674                                 elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3675                                 {
3676                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3677                                 }
3678                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3679                         }
3680                 }
3681                 if (isset($this->data['links'][$rel]))
3682                 {
3683                         return $this->data['links'][$rel];
3684                 }
3685                 else
3686                 {
3687                         return null;
3688                 }
3689         }
3690
3691         /**
3692          * @todo Add ability to prefer one type of content over another (in a media group).
3693          */
3694         function get_enclosure($key = 0, $prefer = null)
3695         {
3696                 $enclosures = $this->get_enclosures();
3697                 if (isset($enclosures[$key]))
3698                 {
3699                         return $enclosures[$key];
3700                 }
3701                 else
3702                 {
3703                         return null;
3704                 }
3705         }
3706
3707         /**
3708          * Grabs all available enclosures (podcasts, etc.)
3709          *
3710          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3711          *
3712          * 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.
3713          *
3714          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3715          * @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).
3716          */
3717         function get_enclosures()
3718         {
3719                 if (!isset($this->data['enclosures']))
3720                 {
3721                         $this->data['enclosures'] = array();
3722
3723                         // Elements
3724                         $captions_parent = null;
3725                         $categories_parent = null;
3726                         $copyrights_parent = null;
3727                         $credits_parent = null;
3728                         $description_parent = null;
3729                         $duration_parent = null;
3730                         $hashes_parent = null;
3731                         $keywords_parent = null;
3732                         $player_parent = null;
3733                         $ratings_parent = null;
3734                         $restrictions_parent = null;
3735                         $thumbnails_parent = null;
3736                         $title_parent = null;
3737
3738                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3739                         $parent = $this->get_feed();
3740
3741                         // CAPTIONS
3742                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3743                         {
3744                                 foreach ($captions as $caption)
3745                                 {
3746                                         $caption_type = null;
3747                                         $caption_lang = null;
3748                                         $caption_startTime = null;
3749                                         $caption_endTime = null;
3750                                         $caption_text = null;
3751                                         if (isset($caption['attribs']['']['type']))
3752                                         {
3753                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3754                                         }
3755                                         if (isset($caption['attribs']['']['lang']))
3756                                         {
3757                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3758                                         }
3759                                         if (isset($caption['attribs']['']['start']))
3760                                         {
3761                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3762                                         }
3763                                         if (isset($caption['attribs']['']['end']))
3764                                         {
3765                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3766                                         }
3767                                         if (isset($caption['data']))
3768                                         {
3769                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3770                                         }
3771                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3772                                 }
3773                         }
3774                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3775                         {
3776                                 foreach ($captions as $caption)
3777                                 {
3778                                         $caption_type = null;
3779                                         $caption_lang = null;
3780                                         $caption_startTime = null;
3781                                         $caption_endTime = null;
3782                                         $caption_text = null;
3783                                         if (isset($caption['attribs']['']['type']))
3784                                         {
3785                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3786                                         }
3787                                         if (isset($caption['attribs']['']['lang']))
3788                                         {
3789                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3790                                         }
3791                                         if (isset($caption['attribs']['']['start']))
3792                                         {
3793                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3794                                         }
3795                                         if (isset($caption['attribs']['']['end']))
3796                                         {
3797                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3798                                         }
3799                                         if (isset($caption['data']))
3800                                         {
3801                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3802                                         }
3803                                         $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3804                                 }
3805                         }
3806                         if (is_array($captions_parent))
3807                         {
3808                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3809                         }
3810
3811                         // CATEGORIES
3812                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3813                         {
3814                                 $term = null;
3815                                 $scheme = null;
3816                                 $label = null;
3817                                 if (isset($category['data']))
3818                                 {
3819                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3820                                 }
3821                                 if (isset($category['attribs']['']['scheme']))
3822                                 {
3823                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3824                                 }
3825                                 else
3826                                 {
3827                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3828                                 }
3829                                 if (isset($category['attribs']['']['label']))
3830                                 {
3831                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3832                                 }
3833                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3834                         }
3835                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3836                         {
3837                                 $term = null;
3838                                 $scheme = null;
3839                                 $label = null;
3840                                 if (isset($category['data']))
3841                                 {
3842                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3843                                 }
3844                                 if (isset($category['attribs']['']['scheme']))
3845                                 {
3846                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3847                                 }
3848                                 else
3849                                 {
3850                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3851                                 }
3852                                 if (isset($category['attribs']['']['label']))
3853                                 {
3854                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3855                                 }
3856                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3857                         }
3858                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3859                         {
3860                                 $term = null;
3861                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3862                                 $label = null;
3863                                 if (isset($category['attribs']['']['text']))
3864                                 {
3865                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3866                                 }
3867                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3868
3869                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3870                                 {
3871                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3872                                         {
3873                                                 if (isset($subcategory['attribs']['']['text']))
3874                                                 {
3875                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3876                                                 }
3877                                                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3878                                         }
3879                                 }
3880                         }
3881                         if (is_array($categories_parent))
3882                         {
3883                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3884                         }
3885
3886                         // COPYRIGHT
3887                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3888                         {
3889                                 $copyright_url = null;
3890                                 $copyright_label = null;
3891                                 if (isset($copyright[0]['attribs']['']['url']))
3892                                 {
3893                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3894                                 }
3895                                 if (isset($copyright[0]['data']))
3896                                 {
3897                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3898                                 }
3899                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3900                         }
3901                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3902                         {
3903                                 $copyright_url = null;
3904                                 $copyright_label = null;
3905                                 if (isset($copyright[0]['attribs']['']['url']))
3906                                 {
3907                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3908                                 }
3909                                 if (isset($copyright[0]['data']))
3910                                 {
3911                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3912                                 }
3913                                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3914                         }
3915
3916                         // CREDITS
3917                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3918                         {
3919                                 foreach ($credits as $credit)
3920                                 {
3921                                         $credit_role = null;
3922                                         $credit_scheme = null;
3923                                         $credit_name = null;
3924                                         if (isset($credit['attribs']['']['role']))
3925                                         {
3926                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3927                                         }
3928                                         if (isset($credit['attribs']['']['scheme']))
3929                                         {
3930                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3931                                         }
3932                                         else
3933                                         {
3934                                                 $credit_scheme = 'urn:ebu';
3935                                         }
3936                                         if (isset($credit['data']))
3937                                         {
3938                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3939                                         }
3940                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
3941                                 }
3942                         }
3943                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3944                         {
3945                                 foreach ($credits as $credit)
3946                                 {
3947                                         $credit_role = null;
3948                                         $credit_scheme = null;
3949                                         $credit_name = null;
3950                                         if (isset($credit['attribs']['']['role']))
3951                                         {
3952                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3953                                         }
3954                                         if (isset($credit['attribs']['']['scheme']))
3955                                         {
3956                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3957                                         }
3958                                         else
3959                                         {
3960                                                 $credit_scheme = 'urn:ebu';
3961                                         }
3962                                         if (isset($credit['data']))
3963                                         {
3964                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3965                                         }
3966                                         $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
3967                                 }
3968                         }
3969                         if (is_array($credits_parent))
3970                         {
3971                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
3972                         }
3973
3974                         // DESCRIPTION
3975                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
3976                         {
3977                                 if (isset($description_parent[0]['data']))
3978                                 {
3979                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3980                                 }
3981                         }
3982                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
3983                         {
3984                                 if (isset($description_parent[0]['data']))
3985                                 {
3986                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3987                                 }
3988                         }
3989
3990                         // DURATION
3991                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
3992                         {
3993                                 $seconds = null;
3994                                 $minutes = null;
3995                                 $hours = null;
3996                                 if (isset($duration_parent[0]['data']))
3997                                 {
3998                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3999                                         if (sizeof($temp) > 0)
4000                                         {
4001                                                 (int) $seconds = array_pop($temp);
4002                                         }
4003                                         if (sizeof($temp) > 0)
4004                                         {
4005                                                 (int) $minutes = array_pop($temp);
4006                                                 $seconds += $minutes * 60;
4007                                         }
4008                                         if (sizeof($temp) > 0)
4009                                         {
4010                                                 (int) $hours = array_pop($temp);
4011                                                 $seconds += $hours * 3600;
4012                                         }
4013                                         unset($temp);
4014                                         $duration_parent = $seconds;
4015                                 }
4016                         }
4017
4018                         // HASHES
4019                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4020                         {
4021                                 foreach ($hashes_iterator as $hash)
4022                                 {
4023                                         $value = null;
4024                                         $algo = null;
4025                                         if (isset($hash['data']))
4026                                         {
4027                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4028                                         }
4029                                         if (isset($hash['attribs']['']['algo']))
4030                                         {
4031                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4032                                         }
4033                                         else
4034                                         {
4035                                                 $algo = 'md5';
4036                                         }
4037                                         $hashes_parent[] = $algo.':'.$value;
4038                                 }
4039                         }
4040                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4041                         {
4042                                 foreach ($hashes_iterator as $hash)
4043                                 {
4044                                         $value = null;
4045                                         $algo = null;
4046                                         if (isset($hash['data']))
4047                                         {
4048                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4049                                         }
4050                                         if (isset($hash['attribs']['']['algo']))
4051                                         {
4052                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4053                                         }
4054                                         else
4055                                         {
4056                                                 $algo = 'md5';
4057                                         }
4058                                         $hashes_parent[] = $algo.':'.$value;
4059                                 }
4060                         }
4061                         if (is_array($hashes_parent))
4062                         {
4063                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4064                         }
4065
4066                         // KEYWORDS
4067                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4068                         {
4069                                 if (isset($keywords[0]['data']))
4070                                 {
4071                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4072                                         foreach ($temp as $word)
4073                                         {
4074                                                 $keywords_parent[] = trim($word);
4075                                         }
4076                                 }
4077                                 unset($temp);
4078                         }
4079                         elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4080                         {
4081                                 if (isset($keywords[0]['data']))
4082                                 {
4083                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4084                                         foreach ($temp as $word)
4085                                         {
4086                                                 $keywords_parent[] = trim($word);
4087                                         }
4088                                 }
4089                                 unset($temp);
4090                         }
4091                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4092                         {
4093                                 if (isset($keywords[0]['data']))
4094                                 {
4095                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4096                                         foreach ($temp as $word)
4097                                         {
4098                                                 $keywords_parent[] = trim($word);
4099                                         }
4100                                 }
4101                                 unset($temp);
4102                         }
4103                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4104                         {
4105                                 if (isset($keywords[0]['data']))
4106                                 {
4107                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4108                                         foreach ($temp as $word)
4109                                         {
4110                                                 $keywords_parent[] = trim($word);
4111                                         }
4112                                 }
4113                                 unset($temp);
4114                         }
4115                         if (is_array($keywords_parent))
4116                         {
4117                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4118                         }
4119
4120                         // PLAYER
4121                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4122                         {
4123                                 if (isset($player_parent[0]['attribs']['']['url']))
4124                                 {
4125                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4126                                 }
4127                         }
4128                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4129                         {
4130                                 if (isset($player_parent[0]['attribs']['']['url']))
4131                                 {
4132                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4133                                 }
4134                         }
4135
4136                         // RATINGS
4137                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4138                         {
4139                                 foreach ($ratings as $rating)
4140                                 {
4141                                         $rating_scheme = null;
4142                                         $rating_value = null;
4143                                         if (isset($rating['attribs']['']['scheme']))
4144                                         {
4145                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4146                                         }
4147                                         else
4148                                         {
4149                                                 $rating_scheme = 'urn:simple';
4150                                         }
4151                                         if (isset($rating['data']))
4152                                         {
4153                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4154                                         }
4155                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4156                                 }
4157                         }
4158                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4159                         {
4160                                 foreach ($ratings as $rating)
4161                                 {
4162                                         $rating_scheme = 'urn:itunes';
4163                                         $rating_value = null;
4164                                         if (isset($rating['data']))
4165                                         {
4166                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4167                                         }
4168                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4169                                 }
4170                         }
4171                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4172                         {
4173                                 foreach ($ratings as $rating)
4174                                 {
4175                                         $rating_scheme = null;
4176                                         $rating_value = null;
4177                                         if (isset($rating['attribs']['']['scheme']))
4178                                         {
4179                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4180                                         }
4181                                         else
4182                                         {
4183                                                 $rating_scheme = 'urn:simple';
4184                                         }
4185                                         if (isset($rating['data']))
4186                                         {
4187                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4188                                         }
4189                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4190                                 }
4191                         }
4192                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4193                         {
4194                                 foreach ($ratings as $rating)
4195                                 {
4196                                         $rating_scheme = 'urn:itunes';
4197                                         $rating_value = null;
4198                                         if (isset($rating['data']))
4199                                         {
4200                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4201                                         }
4202                                         $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4203                                 }
4204                         }
4205                         if (is_array($ratings_parent))
4206                         {
4207                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4208                         }
4209
4210                         // RESTRICTIONS
4211                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4212                         {
4213                                 foreach ($restrictions as $restriction)
4214                                 {
4215                                         $restriction_relationship = null;
4216                                         $restriction_type = null;
4217                                         $restriction_value = null;
4218                                         if (isset($restriction['attribs']['']['relationship']))
4219                                         {
4220                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4221                                         }
4222                                         if (isset($restriction['attribs']['']['type']))
4223                                         {
4224                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4225                                         }
4226                                         if (isset($restriction['data']))
4227                                         {
4228                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4229                                         }
4230                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4231                                 }
4232                         }
4233                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4234                         {
4235                                 foreach ($restrictions as $restriction)
4236                                 {
4237                                         $restriction_relationship = 'allow';
4238                                         $restriction_type = null;
4239                                         $restriction_value = 'itunes';
4240                                         if (isset($restriction['data']) && strtolower($restriction['data']) == 'yes')
4241                                         {
4242                                                 $restriction_relationship = 'deny';
4243                                         }
4244                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4245                                 }
4246                         }
4247                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4248                         {
4249                                 foreach ($restrictions as $restriction)
4250                                 {
4251                                         $restriction_relationship = null;
4252                                         $restriction_type = null;
4253                                         $restriction_value = null;
4254                                         if (isset($restriction['attribs']['']['relationship']))
4255                                         {
4256                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4257                                         }
4258                                         if (isset($restriction['attribs']['']['type']))
4259                                         {
4260                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4261                                         }
4262                                         if (isset($restriction['data']))
4263                                         {
4264                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4265                                         }
4266                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4267                                 }
4268                         }
4269                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4270                         {
4271                                 foreach ($restrictions as $restriction)
4272                                 {
4273                                         $restriction_relationship = 'allow';
4274                                         $restriction_type = null;
4275                                         $restriction_value = 'itunes';
4276                                         if (isset($restriction['data']) && strtolower($restriction['data']) == 'yes')
4277                                         {
4278                                                 $restriction_relationship = 'deny';
4279                                         }
4280                                         $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4281                                 }
4282                         }
4283                         if (is_array($restrictions_parent))
4284                         {
4285                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4286                         }
4287
4288                         // THUMBNAILS
4289                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4290                         {
4291                                 foreach ($thumbnails as $thumbnail)
4292                                 {
4293                                         if (isset($thumbnail['attribs']['']['url']))
4294                                         {
4295                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4296                                         }
4297                                 }
4298                         }
4299                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4300                         {
4301                                 foreach ($thumbnails as $thumbnail)
4302                                 {
4303                                         if (isset($thumbnail['attribs']['']['url']))
4304                                         {
4305                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4306                                         }
4307                                 }
4308                         }
4309
4310                         // TITLES
4311                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4312                         {
4313                                 if (isset($title_parent[0]['data']))
4314                                 {
4315                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4316                                 }
4317                         }
4318                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4319                         {
4320                                 if (isset($title_parent[0]['data']))
4321                                 {
4322                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4323                                 }
4324                         }
4325
4326                         // Clear the memory
4327                         unset($parent);
4328
4329                         // If we have media:group tags, loop through them.
4330                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4331                         {
4332                                 // If we have media:content tags, loop through them.
4333                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4334                                 {
4335                                         if (isset($content['attribs']['']['url']))
4336                                         {
4337                                                 // Attributes
4338                                                 $bitrate = null;
4339                                                 $channels = null;
4340                                                 $duration = null;
4341                                                 $expression = null;
4342                                                 $framerate = null;
4343                                                 $height = null;
4344                                                 $javascript = null;
4345                                                 $lang = null;
4346                                                 $length = null;
4347                                                 $medium = null;
4348                                                 $samplingrate = null;
4349                                                 $type = null;
4350                                                 $url = null;
4351                                                 $width = null;
4352
4353                                                 // Elements
4354                                                 $captions = null;
4355                                                 $categories = null;
4356                                                 $copyrights = null;
4357                                                 $credits = null;
4358                                                 $description = null;
4359                                                 $hashes = null;
4360                                                 $keywords = null;
4361                                                 $player = null;
4362                                                 $ratings = null;
4363                                                 $restrictions = null;
4364                                                 $thumbnails = null;
4365                                                 $title = null;
4366
4367                                                 // Start checking the attributes of media:content
4368                                                 if (isset($content['attribs']['']['bitrate']))
4369                                                 {
4370                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4371                                                 }
4372                                                 if (isset($content['attribs']['']['channels']))
4373                                                 {
4374                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4375                                                 }
4376                                                 if (isset($content['attribs']['']['duration']))
4377                                                 {
4378                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4379                                                 }
4380                                                 else
4381                                                 {
4382                                                         $duration = $duration_parent;
4383                                                 }
4384                                                 if (isset($content['attribs']['']['expression']))
4385                                                 {
4386                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4387                                                 }
4388                                                 if (isset($content['attribs']['']['framerate']))
4389                                                 {
4390                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4391                                                 }
4392                                                 if (isset($content['attribs']['']['height']))
4393                                                 {
4394                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4395                                                 }
4396                                                 if (isset($content['attribs']['']['lang']))
4397                                                 {
4398                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4399                                                 }
4400                                                 if (isset($content['attribs']['']['fileSize']))
4401                                                 {
4402                                                         $length = ceil($content['attribs']['']['fileSize']);
4403                                                 }
4404                                                 if (isset($content['attribs']['']['medium']))
4405                                                 {
4406                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4407                                                 }
4408                                                 if (isset($content['attribs']['']['samplingrate']))
4409                                                 {
4410                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4411                                                 }
4412                                                 if (isset($content['attribs']['']['type']))
4413                                                 {
4414                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4415                                                 }
4416                                                 if (isset($content['attribs']['']['width']))
4417                                                 {
4418                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4419                                                 }
4420                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4421
4422                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4423
4424                                                 // CAPTIONS
4425                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4426                                                 {
4427                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4428                                                         {
4429                                                                 $caption_type = null;
4430                                                                 $caption_lang = null;
4431                                                                 $caption_startTime = null;
4432                                                                 $caption_endTime = null;
4433                                                                 $caption_text = null;
4434                                                                 if (isset($caption['attribs']['']['type']))
4435                                                                 {
4436                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4437                                                                 }
4438                                                                 if (isset($caption['attribs']['']['lang']))
4439                                                                 {
4440                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4441                                                                 }
4442                                                                 if (isset($caption['attribs']['']['start']))
4443                                                                 {
4444                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4445                                                                 }
4446                                                                 if (isset($caption['attribs']['']['end']))
4447                                                                 {
4448                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4449                                                                 }
4450                                                                 if (isset($caption['data']))
4451                                                                 {
4452                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4453                                                                 }
4454                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4455                                                         }
4456                                                         if (is_array($captions))
4457                                                         {
4458                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
4459                                                         }
4460                                                 }
4461                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4462                                                 {
4463                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4464                                                         {
4465                                                                 $caption_type = null;
4466                                                                 $caption_lang = null;
4467                                                                 $caption_startTime = null;
4468                                                                 $caption_endTime = null;
4469                                                                 $caption_text = null;
4470                                                                 if (isset($caption['attribs']['']['type']))
4471                                                                 {
4472                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4473                                                                 }
4474                                                                 if (isset($caption['attribs']['']['lang']))
4475                                                                 {
4476                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4477                                                                 }
4478                                                                 if (isset($caption['attribs']['']['start']))
4479                                                                 {
4480                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4481                                                                 }
4482                                                                 if (isset($caption['attribs']['']['end']))
4483                                                                 {
4484                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4485                                                                 }
4486                                                                 if (isset($caption['data']))
4487                                                                 {
4488                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4489                                                                 }
4490                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4491                                                         }
4492                                                         if (is_array($captions))
4493                                                         {
4494                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
4495                                                         }
4496                                                 }
4497                                                 else
4498                                                 {
4499                                                         $captions = $captions_parent;
4500                                                 }
4501
4502                                                 // CATEGORIES
4503                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4504                                                 {
4505                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4506                                                         {
4507                                                                 $term = null;
4508                                                                 $scheme = null;
4509                                                                 $label = null;
4510                                                                 if (isset($category['data']))
4511                                                                 {
4512                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4513                                                                 }
4514                                                                 if (isset($category['attribs']['']['scheme']))
4515                                                                 {
4516                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4517                                                                 }
4518                                                                 else
4519                                                                 {
4520                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4521                                                                 }
4522                                                                 if (isset($category['attribs']['']['label']))
4523                                                                 {
4524                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4525                                                                 }
4526                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4527                                                         }
4528                                                 }
4529                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4530                                                 {
4531                                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4532                                                         {
4533                                                                 $term = null;
4534                                                                 $scheme = null;
4535                                                                 $label = null;
4536                                                                 if (isset($category['data']))
4537                                                                 {
4538                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4539                                                                 }
4540                                                                 if (isset($category['attribs']['']['scheme']))
4541                                                                 {
4542                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4543                                                                 }
4544                                                                 else
4545                                                                 {
4546                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4547                                                                 }
4548                                                                 if (isset($category['attribs']['']['label']))
4549                                                                 {
4550                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4551                                                                 }
4552                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4553                                                         }
4554                                                 }
4555                                                 if (is_array($categories) && is_array($categories_parent))
4556                                                 {
4557                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4558                                                 }
4559                                                 elseif (is_array($categories))
4560                                                 {
4561                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
4562                                                 }
4563                                                 elseif (is_array($categories_parent))
4564                                                 {
4565                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4566                                                 }
4567
4568                                                 // COPYRIGHTS
4569                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4570                                                 {
4571                                                         $copyright_url = null;
4572                                                         $copyright_label = null;
4573                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4574                                                         {
4575                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4576                                                         }
4577                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4578                                                         {
4579                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4580                                                         }
4581                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4582                                                 }
4583                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4584                                                 {
4585                                                         $copyright_url = null;
4586                                                         $copyright_label = null;
4587                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4588                                                         {
4589                                                                 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4590                                                         }
4591                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4592                                                         {
4593                                                                 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4594                                                         }
4595                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4596                                                 }
4597                                                 else
4598                                                 {
4599                                                         $copyrights = $copyrights_parent;
4600                                                 }
4601
4602                                                 // CREDITS
4603                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4604                                                 {
4605                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4606                                                         {
4607                                                                 $credit_role = null;
4608                                                                 $credit_scheme = null;
4609                                                                 $credit_name = null;
4610                                                                 if (isset($credit['attribs']['']['role']))
4611                                                                 {
4612                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4613                                                                 }
4614                                                                 if (isset($credit['attribs']['']['scheme']))
4615                                                                 {
4616                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4617                                                                 }
4618                                                                 else
4619                                                                 {
4620                                                                         $credit_scheme = 'urn:ebu';
4621                                                                 }
4622                                                                 if (isset($credit['data']))
4623                                                                 {
4624                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4625                                                                 }
4626                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4627                                                         }
4628                                                         if (is_array($credits))
4629                                                         {
4630                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
4631                                                         }
4632                                                 }
4633                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4634                                                 {
4635                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4636                                                         {
4637                                                                 $credit_role = null;
4638                                                                 $credit_scheme = null;
4639                                                                 $credit_name = null;
4640                                                                 if (isset($credit['attribs']['']['role']))
4641                                                                 {
4642                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4643                                                                 }
4644                                                                 if (isset($credit['attribs']['']['scheme']))
4645                                                                 {
4646                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4647                                                                 }
4648                                                                 else
4649                                                                 {
4650                                                                         $credit_scheme = 'urn:ebu';
4651                                                                 }
4652                                                                 if (isset($credit['data']))
4653                                                                 {
4654                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4655                                                                 }
4656                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4657                                                         }
4658                                                         if (is_array($credits))
4659                                                         {
4660                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
4661                                                         }
4662                                                 }
4663                                                 else
4664                                                 {
4665                                                         $credits = $credits_parent;
4666                                                 }
4667
4668                                                 // DESCRIPTION
4669                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4670                                                 {
4671                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4672                                                 }
4673                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4674                                                 {
4675                                                         $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4676                                                 }
4677                                                 else
4678                                                 {
4679                                                         $description = $description_parent;
4680                                                 }
4681
4682                                                 // HASHES
4683                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4684                                                 {
4685                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4686                                                         {
4687                                                                 $value = null;
4688                                                                 $algo = null;
4689                                                                 if (isset($hash['data']))
4690                                                                 {
4691                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4692                                                                 }
4693                                                                 if (isset($hash['attribs']['']['algo']))
4694                                                                 {
4695                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4696                                                                 }
4697                                                                 else
4698                                                                 {
4699                                                                         $algo = 'md5';
4700                                                                 }
4701                                                                 $hashes[] = $algo.':'.$value;
4702                                                         }
4703                                                         if (is_array($hashes))
4704                                                         {
4705                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4706                                                         }
4707                                                 }
4708                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4709                                                 {
4710                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4711                                                         {
4712                                                                 $value = null;
4713                                                                 $algo = null;
4714                                                                 if (isset($hash['data']))
4715                                                                 {
4716                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4717                                                                 }
4718                                                                 if (isset($hash['attribs']['']['algo']))
4719                                                                 {
4720                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4721                                                                 }
4722                                                                 else
4723                                                                 {
4724                                                                         $algo = 'md5';
4725                                                                 }
4726                                                                 $hashes[] = $algo.':'.$value;
4727                                                         }
4728                                                         if (is_array($hashes))
4729                                                         {
4730                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4731                                                         }
4732                                                 }
4733                                                 else
4734                                                 {
4735                                                         $hashes = $hashes_parent;
4736                                                 }
4737
4738                                                 // KEYWORDS
4739                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4740                                                 {
4741                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4742                                                         {
4743                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4744                                                                 foreach ($temp as $word)
4745                                                                 {
4746                                                                         $keywords[] = trim($word);
4747                                                                 }
4748                                                                 unset($temp);
4749                                                         }
4750                                                         if (is_array($keywords))
4751                                                         {
4752                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4753                                                         }
4754                                                 }
4755                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4756                                                 {
4757                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4758                                                         {
4759                                                                 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4760                                                                 foreach ($temp as $word)
4761                                                                 {
4762                                                                         $keywords[] = trim($word);
4763                                                                 }
4764                                                                 unset($temp);
4765                                                         }
4766                                                         if (is_array($keywords))
4767                                                         {
4768                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4769                                                         }
4770                                                 }
4771                                                 else
4772                                                 {
4773                                                         $keywords = $keywords_parent;
4774                                                 }
4775
4776                                                 // PLAYER
4777                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4778                                                 {
4779                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4780                                                 }
4781                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4782                                                 {
4783                                                         $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4784                                                 }
4785                                                 else
4786                                                 {
4787                                                         $player = $player_parent;
4788                                                 }
4789
4790                                                 // RATINGS
4791                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4792                                                 {
4793                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4794                                                         {
4795                                                                 $rating_scheme = null;
4796                                                                 $rating_value = null;
4797                                                                 if (isset($rating['attribs']['']['scheme']))
4798                                                                 {
4799                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4800                                                                 }
4801                                                                 else
4802                                                                 {
4803                                                                         $rating_scheme = 'urn:simple';
4804                                                                 }
4805                                                                 if (isset($rating['data']))
4806                                                                 {
4807                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4808                                                                 }
4809                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4810                                                         }
4811                                                         if (is_array($ratings))
4812                                                         {
4813                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4814                                                         }
4815                                                 }
4816                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4817                                                 {
4818                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4819                                                         {
4820                                                                 $rating_scheme = null;
4821                                                                 $rating_value = null;
4822                                                                 if (isset($rating['attribs']['']['scheme']))
4823                                                                 {
4824                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4825                                                                 }
4826                                                                 else
4827                                                                 {
4828                                                                         $rating_scheme = 'urn:simple';
4829                                                                 }
4830                                                                 if (isset($rating['data']))
4831                                                                 {
4832                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4833                                                                 }
4834                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4835                                                         }
4836                                                         if (is_array($ratings))
4837                                                         {
4838                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4839                                                         }
4840                                                 }
4841                                                 else
4842                                                 {
4843                                                         $ratings = $ratings_parent;
4844                                                 }
4845
4846                                                 // RESTRICTIONS
4847                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4848                                                 {
4849                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4850                                                         {
4851                                                                 $restriction_relationship = null;
4852                                                                 $restriction_type = null;
4853                                                                 $restriction_value = null;
4854                                                                 if (isset($restriction['attribs']['']['relationship']))
4855                                                                 {
4856                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4857                                                                 }
4858                                                                 if (isset($restriction['attribs']['']['type']))
4859                                                                 {
4860                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4861                                                                 }
4862                                                                 if (isset($restriction['data']))
4863                                                                 {
4864                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4865                                                                 }
4866                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4867                                                         }
4868                                                         if (is_array($restrictions))
4869                                                         {
4870                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4871                                                         }
4872                                                 }
4873                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4874                                                 {
4875                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4876                                                         {
4877                                                                 $restriction_relationship = null;
4878                                                                 $restriction_type = null;
4879                                                                 $restriction_value = null;
4880                                                                 if (isset($restriction['attribs']['']['relationship']))
4881                                                                 {
4882                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4883                                                                 }
4884                                                                 if (isset($restriction['attribs']['']['type']))
4885                                                                 {
4886                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4887                                                                 }
4888                                                                 if (isset($restriction['data']))
4889                                                                 {
4890                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4891                                                                 }
4892                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4893                                                         }
4894                                                         if (is_array($restrictions))
4895                                                         {
4896                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4897                                                         }
4898                                                 }
4899                                                 else
4900                                                 {
4901                                                         $restrictions = $restrictions_parent;
4902                                                 }
4903
4904                                                 // THUMBNAILS
4905                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4906                                                 {
4907                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4908                                                         {
4909                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4910                                                         }
4911                                                         if (is_array($thumbnails))
4912                                                         {
4913                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4914                                                         }
4915                                                 }
4916                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4917                                                 {
4918                                                         foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4919                                                         {
4920                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4921                                                         }
4922                                                         if (is_array($thumbnails))
4923                                                         {
4924                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4925                                                         }
4926                                                 }
4927                                                 else
4928                                                 {
4929                                                         $thumbnails = $thumbnails_parent;
4930                                                 }
4931
4932                                                 // TITLES
4933                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4934                                                 {
4935                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4936                                                 }
4937                                                 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4938                                                 {
4939                                                         $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4940                                                 }
4941                                                 else
4942                                                 {
4943                                                         $title = $title_parent;
4944                                                 }
4945
4946                                                 $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);
4947                                         }
4948                                 }
4949                         }
4950
4951                         // If we have standalone media:content tags, loop through them.
4952                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4953                         {
4954                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4955                                 {
4956                                         if (isset($content['attribs']['']['url']))
4957                                         {
4958                                                 // Attributes
4959                                                 $bitrate = null;
4960                                                 $channels = null;
4961                                                 $duration = null;
4962                                                 $expression = null;
4963                                                 $framerate = null;
4964                                                 $height = null;
4965                                                 $javascript = null;
4966                                                 $lang = null;
4967                                                 $length = null;
4968                                                 $medium = null;
4969                                                 $samplingrate = null;
4970                                                 $type = null;
4971                                                 $url = null;
4972                                                 $width = null;
4973
4974                                                 // Elements
4975                                                 $captions = null;
4976                                                 $categories = null;
4977                                                 $copyrights = null;
4978                                                 $credits = null;
4979                                                 $description = null;
4980                                                 $hashes = null;
4981                                                 $keywords = null;
4982                                                 $player = null;
4983                                                 $ratings = null;
4984                                                 $restrictions = null;
4985                                                 $thumbnails = null;
4986                                                 $title = null;
4987
4988                                                 // Start checking the attributes of media:content
4989                                                 if (isset($content['attribs']['']['bitrate']))
4990                                                 {
4991                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4992                                                 }
4993                                                 if (isset($content['attribs']['']['channels']))
4994                                                 {
4995                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4996                                                 }
4997                                                 if (isset($content['attribs']['']['duration']))
4998                                                 {
4999                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5000                                                 }
5001                                                 else
5002                                                 {
5003                                                         $duration = $duration_parent;
5004                                                 }
5005                                                 if (isset($content['attribs']['']['expression']))
5006                                                 {
5007                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5008                                                 }
5009                                                 if (isset($content['attribs']['']['framerate']))
5010                                                 {
5011                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5012                                                 }
5013                                                 if (isset($content['attribs']['']['height']))
5014                                                 {
5015                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5016                                                 }
5017                                                 if (isset($content['attribs']['']['lang']))
5018                                                 {
5019                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5020                                                 }
5021                                                 if (isset($content['attribs']['']['fileSize']))
5022                                                 {
5023                                                         $length = ceil($content['attribs']['']['fileSize']);
5024                                                 }
5025                                                 if (isset($content['attribs']['']['medium']))
5026                                                 {
5027                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5028                                                 }
5029                                                 if (isset($content['attribs']['']['samplingrate']))
5030                                                 {
5031                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5032                                                 }
5033                                                 if (isset($content['attribs']['']['type']))
5034                                                 {
5035                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5036                                                 }
5037                                                 if (isset($content['attribs']['']['width']))
5038                                                 {
5039                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5040                                                 }
5041                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5042
5043                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5044
5045                                                 // CAPTIONS
5046                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5047                                                 {
5048                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5049                                                         {
5050                                                                 $caption_type = null;
5051                                                                 $caption_lang = null;
5052                                                                 $caption_startTime = null;
5053                                                                 $caption_endTime = null;
5054                                                                 $caption_text = null;
5055                                                                 if (isset($caption['attribs']['']['type']))
5056                                                                 {
5057                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5058                                                                 }
5059                                                                 if (isset($caption['attribs']['']['lang']))
5060                                                                 {
5061                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5062                                                                 }
5063                                                                 if (isset($caption['attribs']['']['start']))
5064                                                                 {
5065                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5066                                                                 }
5067                                                                 if (isset($caption['attribs']['']['end']))
5068                                                                 {
5069                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5070                                                                 }
5071                                                                 if (isset($caption['data']))
5072                                                                 {
5073                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5074                                                                 }
5075                                                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5076                                                         }
5077                                                         if (is_array($captions))
5078                                                         {
5079                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5080                                                         }
5081                                                 }
5082                                                 else
5083                                                 {
5084                                                         $captions = $captions_parent;
5085                                                 }
5086
5087                                                 // CATEGORIES
5088                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5089                                                 {
5090                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5091                                                         {
5092                                                                 $term = null;
5093                                                                 $scheme = null;
5094                                                                 $label = null;
5095                                                                 if (isset($category['data']))
5096                                                                 {
5097                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5098                                                                 }
5099                                                                 if (isset($category['attribs']['']['scheme']))
5100                                                                 {
5101                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5102                                                                 }
5103                                                                 else
5104                                                                 {
5105                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5106                                                                 }
5107                                                                 if (isset($category['attribs']['']['label']))
5108                                                                 {
5109                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5110                                                                 }
5111                                                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5112                                                         }
5113                                                 }
5114                                                 if (is_array($categories) && is_array($categories_parent))
5115                                                 {
5116                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5117                                                 }
5118                                                 elseif (is_array($categories))
5119                                                 {
5120                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5121                                                 }
5122                                                 elseif (is_array($categories_parent))
5123                                                 {
5124                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5125                                                 }
5126                                                 else
5127                                                 {
5128                                                         $categories = null;
5129                                                 }
5130
5131                                                 // COPYRIGHTS
5132                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5133                                                 {
5134                                                         $copyright_url = null;
5135                                                         $copyright_label = null;
5136                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5137                                                         {
5138                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5139                                                         }
5140                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5141                                                         {
5142                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5143                                                         }
5144                                                         $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5145                                                 }
5146                                                 else
5147                                                 {
5148                                                         $copyrights = $copyrights_parent;
5149                                                 }
5150
5151                                                 // CREDITS
5152                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5153                                                 {
5154                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5155                                                         {
5156                                                                 $credit_role = null;
5157                                                                 $credit_scheme = null;
5158                                                                 $credit_name = null;
5159                                                                 if (isset($credit['attribs']['']['role']))
5160                                                                 {
5161                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5162                                                                 }
5163                                                                 if (isset($credit['attribs']['']['scheme']))
5164                                                                 {
5165                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5166                                                                 }
5167                                                                 else
5168                                                                 {
5169                                                                         $credit_scheme = 'urn:ebu';
5170                                                                 }
5171                                                                 if (isset($credit['data']))
5172                                                                 {
5173                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5174                                                                 }
5175                                                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5176                                                         }
5177                                                         if (is_array($credits))
5178                                                         {
5179                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5180                                                         }
5181                                                 }
5182                                                 else
5183                                                 {
5184                                                         $credits = $credits_parent;
5185                                                 }
5186
5187                                                 // DESCRIPTION
5188                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5189                                                 {
5190                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5191                                                 }
5192                                                 else
5193                                                 {
5194                                                         $description = $description_parent;
5195                                                 }
5196
5197                                                 // HASHES
5198                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5199                                                 {
5200                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5201                                                         {
5202                                                                 $value = null;
5203                                                                 $algo = null;
5204                                                                 if (isset($hash['data']))
5205                                                                 {
5206                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5207                                                                 }
5208                                                                 if (isset($hash['attribs']['']['algo']))
5209                                                                 {
5210                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5211                                                                 }
5212                                                                 else
5213                                                                 {
5214                                                                         $algo = 'md5';
5215                                                                 }
5216                                                                 $hashes[] = $algo.':'.$value;
5217                                                         }
5218                                                         if (is_array($hashes))
5219                                                         {
5220                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5221                                                         }
5222                                                 }
5223                                                 else
5224                                                 {
5225                                                         $hashes = $hashes_parent;
5226                                                 }
5227
5228                                                 // KEYWORDS
5229                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5230                                                 {
5231                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5232                                                         {
5233                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5234                                                                 foreach ($temp as $word)
5235                                                                 {
5236                                                                         $keywords[] = trim($word);
5237                                                                 }
5238                                                                 unset($temp);
5239                                                         }
5240                                                         if (is_array($keywords))
5241                                                         {
5242                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5243                                                         }
5244                                                 }
5245                                                 else
5246                                                 {
5247                                                         $keywords = $keywords_parent;
5248                                                 }
5249
5250                                                 // PLAYER
5251                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5252                                                 {
5253                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5254                                                 }
5255                                                 else
5256                                                 {
5257                                                         $player = $player_parent;
5258                                                 }
5259
5260                                                 // RATINGS
5261                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5262                                                 {
5263                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5264                                                         {
5265                                                                 $rating_scheme = null;
5266                                                                 $rating_value = null;
5267                                                                 if (isset($rating['attribs']['']['scheme']))
5268                                                                 {
5269                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5270                                                                 }
5271                                                                 else
5272                                                                 {
5273                                                                         $rating_scheme = 'urn:simple';
5274                                                                 }
5275                                                                 if (isset($rating['data']))
5276                                                                 {
5277                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5278                                                                 }
5279                                                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5280                                                         }
5281                                                         if (is_array($ratings))
5282                                                         {
5283                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5284                                                         }
5285                                                 }
5286                                                 else
5287                                                 {
5288                                                         $ratings = $ratings_parent;
5289                                                 }
5290
5291                                                 // RESTRICTIONS
5292                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5293                                                 {
5294                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5295                                                         {
5296                                                                 $restriction_relationship = null;
5297                                                                 $restriction_type = null;
5298                                                                 $restriction_value = null;
5299                                                                 if (isset($restriction['attribs']['']['relationship']))
5300                                                                 {
5301                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5302                                                                 }
5303                                                                 if (isset($restriction['attribs']['']['type']))
5304                                                                 {
5305                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5306                                                                 }
5307                                                                 if (isset($restriction['data']))
5308                                                                 {
5309                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5310                                                                 }
5311                                                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5312                                                         }
5313                                                         if (is_array($restrictions))
5314                                                         {
5315                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5316                                                         }
5317                                                 }
5318                                                 else
5319                                                 {
5320                                                         $restrictions = $restrictions_parent;
5321                                                 }
5322
5323                                                 // THUMBNAILS
5324                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5325                                                 {
5326                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5327                                                         {
5328                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5329                                                         }
5330                                                         if (is_array($thumbnails))
5331                                                         {
5332                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5333                                                         }
5334                                                 }
5335                                                 else
5336                                                 {
5337                                                         $thumbnails = $thumbnails_parent;
5338                                                 }
5339
5340                                                 // TITLES
5341                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5342                                                 {
5343                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5344                                                 }
5345                                                 else
5346                                                 {
5347                                                         $title = $title_parent;
5348                                                 }
5349
5350                                                 $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);
5351                                         }
5352                                 }
5353                         }
5354
5355                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5356                         {
5357                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
5358                                 {
5359                                         // Attributes
5360                                         $bitrate = null;
5361                                         $channels = null;
5362                                         $duration = null;
5363                                         $expression = null;
5364                                         $framerate = null;
5365                                         $height = null;
5366                                         $javascript = null;
5367                                         $lang = null;
5368                                         $length = null;
5369                                         $medium = null;
5370                                         $samplingrate = null;
5371                                         $type = null;
5372                                         $url = null;
5373                                         $width = null;
5374
5375                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5376                                         if (isset($link['attribs']['']['type']))
5377                                         {
5378                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5379                                         }
5380                                         if (isset($link['attribs']['']['length']))
5381                                         {
5382                                                 $length = ceil($link['attribs']['']['length']);
5383                                         }
5384
5385                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5386                                         $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);
5387                                 }
5388                         }
5389
5390                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5391                         {
5392                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
5393                                 {
5394                                         // Attributes
5395                                         $bitrate = null;
5396                                         $channels = null;
5397                                         $duration = null;
5398                                         $expression = null;
5399                                         $framerate = null;
5400                                         $height = null;
5401                                         $javascript = null;
5402                                         $lang = null;
5403                                         $length = null;
5404                                         $medium = null;
5405                                         $samplingrate = null;
5406                                         $type = null;
5407                                         $url = null;
5408                                         $width = null;
5409
5410                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5411                                         if (isset($link['attribs']['']['type']))
5412                                         {
5413                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5414                                         }
5415                                         if (isset($link['attribs']['']['length']))
5416                                         {
5417                                                 $length = ceil($link['attribs']['']['length']);
5418                                         }
5419
5420                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5421                                         $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);
5422                                 }
5423                         }
5424
5425                         if ($enclosure = $this->get_item_tags('', 'enclosure'))
5426                         {
5427                                 if (isset($enclosure[0]['attribs']['']['url']))
5428                                 {
5429                                         // Attributes
5430                                         $bitrate = null;
5431                                         $channels = null;
5432                                         $duration = null;
5433                                         $expression = null;
5434                                         $framerate = null;
5435                                         $height = null;
5436                                         $javascript = null;
5437                                         $lang = null;
5438                                         $length = null;
5439                                         $medium = null;
5440                                         $samplingrate = null;
5441                                         $type = null;
5442                                         $url = null;
5443                                         $width = null;
5444
5445                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5446                                         if (isset($enclosure[0]['attribs']['']['type']))
5447                                         {
5448                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5449                                         }
5450                                         if (isset($enclosure[0]['attribs']['']['length']))
5451                                         {
5452                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5453                                         }
5454
5455                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5456                                         $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);
5457                                 }
5458                         }
5459
5460                         if (sizeof($this->data['enclosures']) == 0)
5461                         {
5462                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5463                                 $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);
5464                         }
5465
5466                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5467                 }
5468                 if (!empty($this->data['enclosures']))
5469                 {
5470                         return $this->data['enclosures'];
5471                 }
5472                 else
5473                 {
5474                         return null;
5475                 }
5476         }
5477
5478         function get_latitude()
5479         {
5480                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5481                 {
5482                         return (float) $return[0]['data'];
5483                 }
5484                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5485                 {
5486                         return (float) $match[1];
5487                 }
5488                 else
5489                 {
5490                         return null;
5491                 }
5492         }
5493
5494         function get_longitude()
5495         {
5496                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5497                 {
5498                         return (float) $return[0]['data'];
5499                 }
5500                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5501                 {
5502                         return (float) $return[0]['data'];
5503                 }
5504                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5505                 {
5506                         return (float) $match[2];
5507                 }
5508                 else
5509                 {
5510                         return null;
5511                 }
5512         }
5513         
5514         function get_source()
5515         {
5516                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5517                 {
5518                         return new $this->feed->source_class($this, $return[0]);
5519                 }
5520                 else
5521                 {
5522                         return null;
5523                 }
5524         }
5525
5526         /**
5527          * Creates the add_to_* methods' return data
5528          *
5529          * @access private
5530          * @param string $item_url String to prefix to the item permalink
5531          * @param string $title_url String to prefix to the item title
5532          * (and suffix to the item permalink)
5533          * @return mixed URL if feed exists, false otherwise
5534          */
5535         function add_to_service($item_url, $title_url = null)
5536         {
5537                 if ($this->get_permalink() !== null)
5538                 {
5539                         $return = $this->sanitize($item_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_permalink());
5540                         if ($title_url !== null && $this->get_title() !== null)
5541                         {
5542                                 $return .= $this->sanitize($title_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_title());
5543                         }
5544                         return $return;
5545                 }
5546                 else
5547                 {
5548                         return null;
5549                 }
5550         }
5551
5552         function add_to_blinklist()
5553         {
5554                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5555         }
5556
5557         function add_to_blogmarks()
5558         {
5559                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5560         }
5561
5562         function add_to_delicious()
5563         {
5564                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5565         }
5566
5567         function add_to_digg()
5568         {
5569                 return $this->add_to_service('http://digg.com/submit?phase=2&URL=');
5570         }
5571
5572         function add_to_furl()
5573         {
5574                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5575         }
5576
5577         function add_to_magnolia()
5578         {
5579                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5580         }
5581
5582         function add_to_myweb20()
5583         {
5584                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5585         }
5586
5587         function add_to_newsvine()
5588         {
5589                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5590         }
5591
5592         function add_to_reddit()
5593         {
5594                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5595         }
5596
5597         function add_to_segnalo()
5598         {
5599                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5600         }
5601
5602         function add_to_simpy()
5603         {
5604                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5605         }
5606
5607         function add_to_spurl()
5608         {
5609                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5610         }
5611
5612         function add_to_wists()
5613         {
5614                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5615         }
5616
5617         function search_technorati()
5618         {
5619                 return $this->add_to_service('http://www.technorati.com/search/');
5620         }
5621 }
5622
5623 class SimplePie_Source
5624 {
5625         var $item;
5626         var $data = array();
5627
5628         function SimplePie_Source($item, $data)
5629         {
5630                 $this->item = $item;
5631                 $this->data = $data;
5632         }
5633
5634         function __toString()
5635         {
5636                 return md5(serialize($this->data));
5637         }
5638         
5639         /**
5640          * Remove items that link back to this before destroying this object
5641          */
5642         function __destruct()
5643         {
5644                 unset($this->item);
5645         }
5646
5647         function get_source_tags($namespace, $tag)
5648         {
5649                 if (isset($this->data['child'][$namespace][$tag]))
5650                 {
5651                         return $this->data['child'][$namespace][$tag];
5652                 }
5653                 else
5654                 {
5655                         return null;
5656                 }
5657         }
5658
5659         function get_base($element = array())
5660         {
5661                 return $this->item->get_base($element);
5662         }
5663
5664         function sanitize($data, $type, $base = '')
5665         {
5666                 return $this->item->sanitize($data, $type, $base);
5667         }
5668
5669         function get_item()
5670         {
5671                 return $this->item;
5672         }
5673
5674         function get_title()
5675         {
5676                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5677                 {
5678                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5679                 }
5680                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5681                 {
5682                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5683                 }
5684                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5685                 {
5686                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5687                 }
5688                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5689                 {
5690                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5691                 }
5692                 elseif ($return = $this->get_source_tags('', 'title'))
5693                 {
5694                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5695                 }
5696                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5697                 {
5698                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5699                 }
5700                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5701                 {
5702                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5703                 }
5704                 else
5705                 {
5706                         return null;
5707                 }
5708         }
5709
5710         function get_category($key = 0)
5711         {
5712                 $categories = $this->get_categories();
5713                 if (isset($categories[$key]))
5714                 {
5715                         return $categories[$key];
5716                 }
5717                 else
5718                 {
5719                         return null;
5720                 }
5721         }
5722
5723         function get_categories()
5724         {
5725                 $categories = array();
5726
5727                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5728                 {
5729                         $term = null;
5730                         $scheme = null;
5731                         $label = null;
5732                         if (isset($category['attribs']['']['term']))
5733                         {
5734                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5735                         }
5736                         if (isset($category['attribs']['']['scheme']))
5737                         {
5738                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5739                         }
5740                         if (isset($category['attribs']['']['label']))
5741                         {
5742                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5743                         }
5744                         $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5745                 }
5746                 foreach ((array) $this->get_source_tags('', 'category') as $category)
5747                 {
5748                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5749                 }
5750                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5751                 {
5752                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5753                 }
5754                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5755                 {
5756                         $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5757                 }
5758
5759                 if (!empty($categories))
5760                 {
5761                         return SimplePie_Misc::array_unique($categories);
5762                 }
5763                 else
5764                 {
5765                         return null;
5766                 }
5767         }
5768
5769         function get_author($key = 0)
5770         {
5771                 $authors = $this->get_authors();
5772                 if (isset($authors[$key]))
5773                 {
5774                         return $authors[$key];
5775                 }
5776                 else
5777                 {
5778                         return null;
5779                 }
5780         }
5781
5782         function get_authors()
5783         {
5784                 $authors = array();
5785                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5786                 {
5787                         $name = null;
5788                         $uri = null;
5789                         $email = null;
5790                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5791                         {
5792                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5793                         }
5794                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5795                         {
5796                                 $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]));
5797                         }
5798                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5799                         {
5800                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5801                         }
5802                         if ($name !== null || $email !== null || $uri !== null)
5803                         {
5804                                 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5805                         }
5806                 }
5807                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5808                 {
5809                         $name = null;
5810                         $url = null;
5811                         $email = null;
5812                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5813                         {
5814                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5815                         }
5816                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5817                         {
5818                                 $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]));
5819                         }
5820                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5821                         {
5822                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5823                         }
5824                         if ($name !== null || $email !== null || $url !== null)
5825                         {
5826                                 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5827                         }
5828                 }
5829                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5830                 {
5831                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5832                 }
5833                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5834                 {
5835                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5836                 }
5837                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5838                 {
5839                         $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5840                 }
5841
5842                 if (!empty($authors))
5843                 {
5844                         return SimplePie_Misc::array_unique($authors);
5845                 }
5846                 else
5847                 {
5848                         return null;
5849                 }
5850         }
5851
5852         function get_contributor($key = 0)
5853         {
5854                 $contributors = $this->get_contributors();
5855                 if (isset($contributors[$key]))
5856                 {
5857                         return $contributors[$key];
5858                 }
5859                 else
5860                 {
5861                         return null;
5862                 }
5863         }
5864
5865         function get_contributors()
5866         {
5867                 $contributors = array();
5868                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5869                 {
5870                         $name = null;
5871                         $uri = null;
5872                         $email = null;
5873                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5874                         {
5875                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5876                         }
5877                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5878                         {
5879                                 $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]));
5880                         }
5881                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5882                         {
5883                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5884                         }
5885                         if ($name !== null || $email !== null || $uri !== null)
5886                         {
5887                                 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
5888                         }
5889                 }
5890                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
5891                 {
5892                         $name = null;
5893                         $url = null;
5894                         $email = null;
5895                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5896                         {
5897                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5898                         }
5899                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5900                         {
5901                                 $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]));
5902                         }
5903                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5904                         {
5905                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5906                         }
5907                         if ($name !== null || $email !== null || $url !== null)
5908                         {
5909                                 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
5910                         }
5911                 }
5912
5913                 if (!empty($contributors))
5914                 {
5915                         return SimplePie_Misc::array_unique($contributors);
5916                 }
5917                 else
5918                 {
5919                         return null;
5920                 }
5921         }
5922
5923         function get_link($key = 0, $rel = 'alternate')
5924         {
5925                 $links = $this->get_links($rel);
5926                 if (isset($links[$key]))
5927                 {
5928                         return $links[$key];
5929                 }
5930                 else
5931                 {
5932                         return null;
5933                 }
5934         }
5935
5936         /**
5937          * Added for parity between the parent-level and the item/entry-level.
5938          */
5939         function get_permalink()
5940         {
5941                 return $this->get_link(0);
5942         }
5943
5944         function get_links($rel = 'alternate')
5945         {
5946                 if (!isset($this->data['links']))
5947                 {
5948                         $this->data['links'] = array();
5949                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
5950                         {
5951                                 foreach ($links as $link)
5952                                 {
5953                                         if (isset($link['attribs']['']['href']))
5954                                         {
5955                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
5956                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5957                                         }
5958                                 }
5959                         }
5960                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
5961                         {
5962                                 foreach ($links as $link)
5963                                 {
5964                                         if (isset($link['attribs']['']['href']))
5965                                         {
5966                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
5967                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5968
5969                                         }
5970                                 }
5971                         }
5972                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
5973                         {
5974                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
5975                         }
5976                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
5977                         {
5978                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
5979                         }
5980                         if ($links = $this->get_source_tags('', 'link'))
5981                         {
5982                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
5983                         }
5984
5985                         $keys = array_keys($this->data['links']);
5986                         foreach ($keys as $key)
5987                         {
5988                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
5989                                 {
5990                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
5991                                         {
5992                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
5993                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
5994                                         }
5995                                         else
5996                                         {
5997                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
5998                                         }
5999                                 }
6000                                 elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6001                                 {
6002                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6003                                 }
6004                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6005                         }
6006                 }
6007
6008                 if (isset($this->data['links'][$rel]))
6009                 {
6010                         return $this->data['links'][$rel];
6011                 }
6012                 else
6013                 {
6014                         return null;
6015                 }
6016         }
6017
6018         function get_description()
6019         {
6020                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6021                 {
6022                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6023                 }
6024                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6025                 {
6026                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6027                 }
6028                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6029                 {
6030                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6031                 }
6032                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6033                 {
6034                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6035                 }
6036                 elseif ($return = $this->get_source_tags('', 'description'))
6037                 {
6038                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6039                 }
6040                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6041                 {
6042                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6043                 }
6044                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6045                 {
6046                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6047                 }
6048                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6049                 {
6050                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6051                 }
6052                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6053                 {
6054                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6055                 }
6056                 else
6057                 {
6058                         return null;
6059                 }
6060         }
6061
6062         function get_copyright()
6063         {
6064                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6065                 {
6066                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6067                 }
6068                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6069                 {
6070                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6071                 }
6072                 elseif ($return = $this->get_source_tags('', 'copyright'))
6073                 {
6074                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6075                 }
6076                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6077                 {
6078                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6079                 }
6080                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6081                 {
6082                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6083                 }
6084                 else
6085                 {
6086                         return null;
6087                 }
6088         }
6089
6090         function get_language()
6091         {
6092                 if ($return = $this->get_source_tags('', 'language'))
6093                 {
6094                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6095                 }
6096                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6097                 {
6098                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6099                 }
6100                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6101                 {
6102                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6103                 }
6104                 elseif (isset($this->data['xml_lang']))
6105                 {
6106                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6107                 }
6108                 else
6109                 {
6110                         return null;
6111                 }
6112         }
6113
6114         function get_latitude()
6115         {
6116                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6117                 {
6118                         return (float) $return[0]['data'];
6119                 }
6120                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6121                 {
6122                         return (float) $match[1];
6123                 }
6124                 else
6125                 {
6126                         return null;
6127                 }
6128         }
6129
6130         function get_longitude()
6131         {
6132                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6133                 {
6134                         return (float) $return[0]['data'];
6135                 }
6136                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6137                 {
6138                         return (float) $return[0]['data'];
6139                 }
6140                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6141                 {
6142                         return (float) $match[2];
6143                 }
6144                 else
6145                 {
6146                         return null;
6147                 }
6148         }
6149
6150         function get_image_url()
6151         {
6152                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6153                 {
6154                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6155                 }
6156                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6157                 {
6158                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6159                 }
6160                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6161                 {
6162                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6163                 }
6164                 else
6165                 {
6166                         return null;
6167                 }
6168         }
6169 }
6170
6171 class SimplePie_Author
6172 {
6173         var $name;
6174         var $link;
6175         var $email;
6176
6177         // Constructor, used to input the data
6178         function SimplePie_Author($name = null, $link = null, $email = null)
6179         {
6180                 $this->name = $name;
6181                 $this->link = $link;
6182                 $this->email = $email;
6183         }
6184
6185         function __toString()
6186         {
6187                 // There is no $this->data here
6188                 return md5(serialize($this));
6189         }
6190
6191         function get_name()
6192         {
6193                 if ($this->name !== null)
6194                 {
6195                         return $this->name;
6196                 }
6197                 else
6198                 {
6199                         return null;
6200                 }
6201         }
6202
6203         function get_link()
6204         {
6205                 if ($this->link !== null)
6206                 {
6207                         return $this->link;
6208                 }
6209                 else
6210                 {
6211                         return null;
6212                 }
6213         }
6214
6215         function get_email()
6216         {
6217                 if ($this->email !== null)
6218                 {
6219                         return $this->email;
6220                 }
6221                 else
6222                 {
6223                         return null;
6224                 }
6225         }
6226 }
6227
6228 class SimplePie_Category
6229 {
6230         var $term;
6231         var $scheme;
6232         var $label;
6233
6234         // Constructor, used to input the data
6235         function SimplePie_Category($term = null, $scheme = null, $label = null)
6236         {
6237                 $this->term = $term;
6238                 $this->scheme = $scheme;
6239                 $this->label = $label;
6240         }
6241
6242         function __toString()
6243         {
6244                 // There is no $this->data here
6245                 return md5(serialize($this));
6246         }
6247
6248         function get_term()
6249         {
6250                 if ($this->term !== null)
6251                 {
6252                         return $this->term;
6253                 }
6254                 else
6255                 {
6256                         return null;
6257                 }
6258         }
6259
6260         function get_scheme()
6261         {
6262                 if ($this->scheme !== null)
6263                 {
6264                         return $this->scheme;
6265                 }
6266                 else
6267                 {
6268                         return null;
6269                 }
6270         }
6271
6272         function get_label()
6273         {
6274                 if ($this->label !== null)
6275                 {
6276                         return $this->label;
6277                 }
6278                 else
6279                 {
6280                         return $this->get_term();
6281                 }
6282         }
6283 }
6284
6285 class SimplePie_Enclosure
6286 {
6287         var $bitrate;
6288         var $captions;
6289         var $categories;
6290         var $channels;
6291         var $copyright;
6292         var $credits;
6293         var $description;
6294         var $duration;
6295         var $expression;
6296         var $framerate;
6297         var $handler;
6298         var $hashes;
6299         var $height;
6300         var $javascript;
6301         var $keywords;
6302         var $lang;
6303         var $length;
6304         var $link;
6305         var $medium;
6306         var $player;
6307         var $ratings;
6308         var $restrictions;
6309         var $samplingrate;
6310         var $thumbnails;
6311         var $title;
6312         var $type;
6313         var $width;
6314
6315         // Constructor, used to input the data
6316         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)
6317         {
6318                 $this->bitrate = $bitrate;
6319                 $this->captions = $captions;
6320                 $this->categories = $categories;
6321                 $this->channels = $channels;
6322                 $this->copyright = $copyright;
6323                 $this->credits = $credits;
6324                 $this->description = $description;
6325                 $this->duration = $duration;
6326                 $this->expression = $expression;
6327                 $this->framerate = $framerate;
6328                 $this->hashes = $hashes;
6329                 $this->height = $height;
6330                 $this->javascript = $javascript;
6331                 $this->keywords = $keywords;
6332                 $this->lang = $lang;
6333                 $this->length = $length;
6334                 $this->link = $link;
6335                 $this->medium = $medium;
6336                 $this->player = $player;
6337                 $this->ratings = $ratings;
6338                 $this->restrictions = $restrictions;
6339                 $this->samplingrate = $samplingrate;
6340                 $this->thumbnails = $thumbnails;
6341                 $this->title = $title;
6342                 $this->type = $type;
6343                 $this->width = $width;
6344                 if (class_exists('idna_convert'))
6345                 {
6346                         $idn =& new idna_convert;
6347                         $parsed = SimplePie_Misc::parse_url($link);
6348                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6349                 }
6350                 $this->handler = $this->get_handler(); // Needs to load last
6351         }
6352
6353         function __toString()
6354         {
6355                 // There is no $this->data here
6356                 return md5(serialize($this));
6357         }
6358
6359         function get_bitrate()
6360         {
6361                 if ($this->bitrate !== null)
6362                 {
6363                         return $this->bitrate;
6364                 }
6365                 else
6366                 {
6367                         return null;
6368                 }
6369         }
6370
6371         function get_caption($key = 0)
6372         {
6373                 $captions = $this->get_captions();
6374                 if (isset($captions[$key]))
6375                 {
6376                         return $captions[$key];
6377                 }
6378                 else
6379                 {
6380                         return null;
6381                 }
6382         }
6383
6384         function get_captions()
6385         {
6386                 if ($this->captions !== null)
6387                 {
6388                         return $this->captions;
6389                 }
6390                 else
6391                 {
6392                         return null;
6393                 }
6394         }
6395
6396         function get_category($key = 0)
6397         {
6398                 $categories = $this->get_categories();
6399                 if (isset($categories[$key]))
6400                 {
6401                         return $categories[$key];
6402                 }
6403                 else
6404                 {
6405                         return null;
6406                 }
6407         }
6408
6409         function get_categories()
6410         {
6411                 if ($this->categories !== null)
6412                 {
6413                         return $this->categories;
6414                 }
6415                 else
6416                 {
6417                         return null;
6418                 }
6419         }
6420
6421         function get_channels()
6422         {
6423                 if ($this->channels !== null)
6424                 {
6425                         return $this->channels;
6426                 }
6427                 else
6428                 {
6429                         return null;
6430                 }
6431         }
6432
6433         function get_copyright()
6434         {
6435                 if ($this->copyright !== null)
6436                 {
6437                         return $this->copyright;
6438                 }
6439                 else
6440                 {
6441                         return null;
6442                 }
6443         }
6444
6445         function get_credit($key = 0)
6446         {
6447                 $credits = $this->get_credits();
6448                 if (isset($credits[$key]))
6449                 {
6450                         return $credits[$key];
6451                 }
6452                 else
6453                 {
6454                         return null;
6455                 }
6456         }
6457
6458         function get_credits()
6459         {
6460                 if ($this->credits !== null)
6461                 {
6462                         return $this->credits;
6463                 }
6464                 else
6465                 {
6466                         return null;
6467                 }
6468         }
6469
6470         function get_description()
6471         {
6472                 if ($this->description !== null)
6473                 {
6474                         return $this->description;
6475                 }
6476                 else
6477                 {
6478                         return null;
6479                 }
6480         }
6481
6482         function get_duration($convert = false)
6483         {
6484                 if ($this->duration !== null)
6485                 {
6486                         if ($convert)
6487                         {
6488                                 $time = SimplePie_Misc::time_hms($this->duration);
6489                                 return $time;
6490                         }
6491                         else
6492                         {
6493                                 return $this->duration;
6494                         }
6495                 }
6496                 else
6497                 {
6498                         return null;
6499                 }
6500         }
6501
6502         function get_expression()
6503         {
6504                 if ($this->expression !== null)
6505                 {
6506                         return $this->expression;
6507                 }
6508                 else
6509                 {
6510                         return 'full';
6511                 }
6512         }
6513
6514         function get_extension()
6515         {
6516                 if ($this->link !== null)
6517                 {
6518                         $url = SimplePie_Misc::parse_url($this->link);
6519                         if ($url['path'] !== '')
6520                         {
6521                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6522                         }
6523                 }
6524                 return null;
6525         }
6526
6527         function get_framerate()
6528         {
6529                 if ($this->framerate !== null)
6530                 {
6531                         return $this->framerate;
6532                 }
6533                 else
6534                 {
6535                         return null;
6536                 }
6537         }
6538
6539         function get_handler()
6540         {
6541                 return $this->get_real_type(true);
6542         }
6543
6544         function get_hash($key = 0)
6545         {
6546                 $hashes = $this->get_hashes();
6547                 if (isset($hashes[$key]))
6548                 {
6549                         return $hashes[$key];
6550                 }
6551                 else
6552                 {
6553                         return null;
6554                 }
6555         }
6556
6557         function get_hashes()
6558         {
6559                 if ($this->hashes !== null)
6560                 {
6561                         return $this->hashes;
6562                 }
6563                 else
6564                 {
6565                         return null;
6566                 }
6567         }
6568
6569         function get_height()
6570         {
6571                 if ($this->height !== null)
6572                 {
6573                         return $this->height;
6574                 }
6575                 else
6576                 {
6577                         return null;
6578                 }
6579         }
6580
6581         function get_language()
6582         {
6583                 if ($this->lang !== null)
6584                 {
6585                         return $this->lang;
6586                 }
6587                 else
6588                 {
6589                         return null;
6590                 }
6591         }
6592
6593         function get_keyword($key = 0)
6594         {
6595                 $keywords = $this->get_keywords();
6596                 if (isset($keywords[$key]))
6597                 {
6598                         return $keywords[$key];
6599                 }
6600                 else
6601                 {
6602                         return null;
6603                 }
6604         }
6605
6606         function get_keywords()
6607         {
6608                 if ($this->keywords !== null)
6609                 {
6610                         return $this->keywords;
6611                 }
6612                 else
6613                 {
6614                         return null;
6615                 }
6616         }
6617
6618         function get_length()
6619         {
6620                 if ($this->length !== null)
6621                 {
6622                         return $this->length;
6623                 }
6624                 else
6625                 {
6626                         return null;
6627                 }
6628         }
6629
6630         function get_link()
6631         {
6632                 if ($this->link !== null)
6633                 {
6634                         return urldecode($this->link);
6635                 }
6636                 else
6637                 {
6638                         return null;
6639                 }
6640         }
6641
6642         function get_medium()
6643         {
6644                 if ($this->medium !== null)
6645                 {
6646                         return $this->medium;
6647                 }
6648                 else
6649                 {
6650                         return null;
6651                 }
6652         }
6653
6654         function get_player()
6655         {
6656                 if ($this->player !== null)
6657                 {
6658                         return $this->player;
6659                 }
6660                 else
6661                 {
6662                         return null;
6663                 }
6664         }
6665
6666         function get_rating($key = 0)
6667         {
6668                 $ratings = $this->get_ratings();
6669                 if (isset($ratings[$key]))
6670                 {
6671                         return $ratings[$key];
6672                 }
6673                 else
6674                 {
6675                         return null;
6676                 }
6677         }
6678
6679         function get_ratings()
6680         {
6681                 if ($this->ratings !== null)
6682                 {
6683                         return $this->ratings;
6684                 }
6685                 else
6686                 {
6687                         return null;
6688                 }
6689         }
6690
6691         function get_restriction($key = 0)
6692         {
6693                 $restrictions = $this->get_restrictions();
6694                 if (isset($restrictions[$key]))
6695                 {
6696                         return $restrictions[$key];
6697                 }
6698                 else
6699                 {
6700                         return null;
6701                 }
6702         }
6703
6704         function get_restrictions()
6705         {
6706                 if ($this->restrictions !== null)
6707                 {
6708                         return $this->restrictions;
6709                 }
6710                 else
6711                 {
6712                         return null;
6713                 }
6714         }
6715
6716         function get_sampling_rate()
6717         {
6718                 if ($this->samplingrate !== null)
6719                 {
6720                         return $this->samplingrate;
6721                 }
6722                 else
6723                 {
6724                         return null;
6725                 }
6726         }
6727
6728         function get_size()
6729         {
6730                 $length = $this->get_length();
6731                 if ($length !== null)
6732                 {
6733                         return round($length/1048576, 2);
6734                 }
6735                 else
6736                 {
6737                         return null;
6738                 }
6739         }
6740
6741         function get_thumbnail($key = 0)
6742         {
6743                 $thumbnails = $this->get_thumbnails();
6744                 if (isset($thumbnails[$key]))
6745                 {
6746                         return $thumbnails[$key];
6747                 }
6748                 else
6749                 {
6750                         return null;
6751                 }
6752         }
6753
6754         function get_thumbnails()
6755         {
6756                 if ($this->thumbnails !== null)
6757                 {
6758                         return $this->thumbnails;
6759                 }
6760                 else
6761                 {
6762                         return null;
6763                 }
6764         }
6765
6766         function get_title()
6767         {
6768                 if ($this->title !== null)
6769                 {
6770                         return $this->title;
6771                 }
6772                 else
6773                 {
6774                         return null;
6775                 }
6776         }
6777
6778         function get_type()
6779         {
6780                 if ($this->type !== null)
6781                 {
6782                         return $this->type;
6783                 }
6784                 else
6785                 {
6786                         return null;
6787                 }
6788         }
6789
6790         function get_width()
6791         {
6792                 if ($this->width !== null)
6793                 {
6794                         return $this->width;
6795                 }
6796                 else
6797                 {
6798                         return null;
6799                 }
6800         }
6801
6802         function native_embed($options='')
6803         {
6804                 return $this->embed($options, true);
6805         }
6806
6807         /**
6808          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6809          */
6810         function embed($options = '', $native = false)
6811         {
6812                 // Set up defaults
6813                 $audio = '';
6814                 $video = '';
6815                 $alt = '';
6816                 $altclass = '';
6817                 $loop = 'false';
6818                 $width = 'auto';
6819                 $height = 'auto';
6820                 $bgcolor = '#ffffff';
6821                 $mediaplayer = '';
6822                 $widescreen = false;
6823                 $handler = $this->get_handler();
6824                 $type = $this->get_real_type();
6825
6826                 // Process options and reassign values as necessary
6827                 if (is_array($options))
6828                 {
6829                         extract($options);
6830                 }
6831                 else
6832                 {
6833                         $options = explode(',', $options);
6834                         foreach($options as $option)
6835                         {
6836                                 $opt = explode(':', $option, 2);
6837                                 if (isset($opt[0], $opt[1]))
6838                                 {
6839                                         $opt[0] = trim($opt[0]);
6840                                         $opt[1] = trim($opt[1]);
6841                                         switch ($opt[0])
6842                                         {
6843                                                 case 'audio':
6844                                                         $audio = $opt[1];
6845                                                         break;
6846
6847                                                 case 'video':
6848                                                         $video = $opt[1];
6849                                                         break;
6850
6851                                                 case 'alt':
6852                                                         $alt = $opt[1];
6853                                                         break;
6854
6855                                                 case 'altclass':
6856                                                         $altclass = $opt[1];
6857                                                         break;
6858
6859                                                 case 'loop':
6860                                                         $loop = $opt[1];
6861                                                         break;
6862
6863                                                 case 'width':
6864                                                         $width = $opt[1];
6865                                                         break;
6866
6867                                                 case 'height':
6868                                                         $height = $opt[1];
6869                                                         break;
6870
6871                                                 case 'bgcolor':
6872                                                         $bgcolor = $opt[1];
6873                                                         break;
6874
6875                                                 case 'mediaplayer':
6876                                                         $mediaplayer = $opt[1];
6877                                                         break;
6878
6879                                                 case 'widescreen':
6880                                                         $widescreen = $opt[1];
6881                                                         break;
6882                                         }
6883                                 }
6884                         }
6885                 }
6886
6887                 $mime = explode('/', $type, 2);
6888                 $mime = $mime[0];
6889
6890                 // Process values for 'auto'
6891                 if ($width == 'auto')
6892                 {
6893                         if ($mime == 'video')
6894                         {
6895                                 if ($height == 'auto')
6896                                 {
6897                                         $width = 480;
6898                                 }
6899                                 elseif ($widescreen)
6900                                 {
6901                                         $width = round((intval($height)/9)*16);
6902                                 }
6903                                 else
6904                                 {
6905                                         $width = round((intval($height)/3)*4);
6906                                 }
6907                         }
6908                         else
6909                         {
6910                                 $width = '100%';
6911                         }
6912                 }
6913
6914                 if ($height == 'auto')
6915                 {
6916                         if ($mime == 'audio')
6917                         {
6918                                 $height = 0;
6919                         }
6920                         elseif ($mime == 'video')
6921                         {
6922                                 if ($width == 'auto')
6923                                 {
6924                                         if ($widescreen)
6925                                         {
6926                                                 $height = 270;
6927                                         }
6928                                         else
6929                                         {
6930                                                 $height = 360;
6931                                         }
6932                                 }
6933                                 elseif ($widescreen)
6934                                 {
6935                                         $height = round((intval($width)/16)*9);
6936                                 }
6937                                 else
6938                                 {
6939                                         $height = round((intval($width)/4)*3);
6940                                 }
6941                         }
6942                         else
6943                         {
6944                                 $height = 376;
6945                         }
6946                 }
6947                 elseif ($mime == 'audio')
6948                 {
6949                         $height = 0;
6950                 }
6951
6952                 // Set proper placeholder value
6953                 if ($mime == 'audio')
6954                 {
6955                         $placeholder = $audio;
6956                 }
6957                 elseif ($mime == 'video')
6958                 {
6959                         $placeholder = $video;
6960                 }
6961
6962                 $embed = '';
6963
6964                 // Make sure the JS library is included
6965                 if (!$native)
6966                 {
6967                         static $javascript_outputted = null;
6968                         if (!$javascript_outputted && $this->javascript)
6969                         {
6970                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
6971                                 $javascript_outputted = true;
6972                         }
6973                 }
6974
6975                 // Odeo Feed MP3's
6976                 if ($handler == 'odeo')
6977                 {
6978                         if ($native)
6979                         {
6980                                 $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>';
6981                         }
6982                         else
6983                         {
6984                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
6985                         }
6986                 }
6987
6988                 // Flash
6989                 elseif ($handler == 'flash')
6990                 {
6991                         if ($native)
6992                         {
6993                                 $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>";
6994                         }
6995                         else
6996                         {
6997                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
6998                         }
6999                 }
7000
7001                 // Flash Media Player file types.
7002                 // Preferred handler for MP3 file types.
7003                 elseif ($handler == 'fmedia' || ($handler == 'mp3' && $mediaplayer != ''))
7004                 {
7005                         $height += 20;
7006                         if ($native)
7007                         {
7008                                 $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>";
7009                         }
7010                         else
7011                         {
7012                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7013                         }
7014                 }
7015
7016                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7017                 // Only handle MP3's if the Flash Media Player is not present.
7018                 elseif ($handler == 'quicktime' || ($handler == 'mp3' && $mediaplayer == ''))
7019                 {
7020                         $height += 16;
7021                         if ($native)
7022                         {
7023                                 if ($placeholder != ""){
7024                                         $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>";
7025                                 }
7026                                 else {
7027                                         $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>";
7028                                 }
7029                         }
7030                         else
7031                         {
7032                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7033                         }
7034                 }
7035
7036                 // Windows Media
7037                 elseif ($handler == 'wmedia')
7038                 {
7039                         $height += 45;
7040                         if ($native)
7041                         {
7042                                 $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>";
7043                         }
7044                         else
7045                         {
7046                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7047                         }
7048                 }
7049
7050                 // Everything else
7051                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7052
7053                 return $embed;
7054         }
7055
7056         function get_real_type($find_handler = false)
7057         {
7058                 // If it's Odeo, let's get it out of the way.
7059                 if (substr(strtolower($this->get_link()), 0, 15) == 'http://odeo.com')
7060                 {
7061                         return 'odeo';
7062                 }
7063
7064                 // Mime-types by handler.
7065                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7066                 $types_fmedia = array('video/flv', 'video/x-flv'); // Flash Media Player
7067                 $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
7068                 $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
7069                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7070
7071                 if ($this->get_type() !== null)
7072                 {
7073                         $type = strtolower($this->type);
7074                 }
7075                 else
7076                 {
7077                         $type = null;
7078                 }
7079
7080                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7081                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7082                 {
7083                         switch (strtolower($this->get_extension()))
7084                         {
7085                                 // Audio mime-types
7086                                 case 'aac':
7087                                 case 'adts':
7088                                         $type = 'audio/acc';
7089                                         break;
7090
7091                                 case 'aif':
7092                                 case 'aifc':
7093                                 case 'aiff':
7094                                 case 'cdda':
7095                                         $type = 'audio/aiff';
7096                                         break;
7097
7098                                 case 'bwf':
7099                                         $type = 'audio/wav';
7100                                         break;
7101
7102                                 case 'kar':
7103                                 case 'mid':
7104                                 case 'midi':
7105                                 case 'smf':
7106                                         $type = 'audio/midi';
7107                                         break;
7108
7109                                 case 'm4a':
7110                                         $type = 'audio/x-m4a';
7111                                         break;
7112
7113                                 case 'mp3':
7114                                 case 'swa':
7115                                         $type = 'audio/mp3';
7116                                         break;
7117
7118                                 case 'wav':
7119                                         $type = 'audio/wav';
7120                                         break;
7121
7122                                 case 'wax':
7123                                         $type = 'audio/x-ms-wax';
7124                                         break;
7125
7126                                 case 'wma':
7127                                         $type = 'audio/x-ms-wma';
7128                                         break;
7129
7130                                 // Video mime-types
7131                                 case '3gp':
7132                                 case '3gpp':
7133                                         $type = 'video/3gpp';
7134                                         break;
7135
7136                                 case '3g2':
7137                                 case '3gp2':
7138                                         $type = 'video/3gpp2';
7139                                         break;
7140
7141                                 case 'asf':
7142                                         $type = 'video/x-ms-asf';
7143                                         break;
7144
7145                                 case 'flv':
7146                                         $type = 'video/x-flv';
7147                                         break;
7148
7149                                 case 'm1a':
7150                                 case 'm1s':
7151                                 case 'm1v':
7152                                 case 'm15':
7153                                 case 'm75':
7154                                 case 'mp2':
7155                                 case 'mpa':
7156                                 case 'mpeg':
7157                                 case 'mpg':
7158                                 case 'mpm':
7159                                 case 'mpv':
7160                                         $type = 'video/mpeg';
7161                                         break;
7162
7163                                 case 'm4v':
7164                                         $type = 'video/x-m4v';
7165                                         break;
7166
7167                                 case 'mov':
7168                                 case 'qt':
7169                                         $type = 'video/quicktime';
7170                                         break;
7171
7172                                 case 'mp4':
7173                                 case 'mpg4':
7174                                         $type = 'video/mp4';
7175                                         break;
7176
7177                                 case 'sdv':
7178                                         $type = 'video/sd-video';
7179                                         break;
7180
7181                                 case 'wm':
7182                                         $type = 'video/x-ms-wm';
7183                                         break;
7184
7185                                 case 'wmv':
7186                                         $type = 'video/x-ms-wmv';
7187                                         break;
7188
7189                                 case 'wvx':
7190                                         $type = 'video/x-ms-wvx';
7191                                         break;
7192
7193                                 // Flash mime-types
7194                                 case 'spl':
7195                                         $type = 'application/futuresplash';
7196                                         break;
7197
7198                                 case 'swf':
7199                                         $type = 'application/x-shockwave-flash';
7200                                         break;
7201                         }
7202                 }
7203
7204                 if ($find_handler)
7205                 {
7206                         if (in_array($type, $types_flash))
7207                         {
7208                                 return 'flash';
7209                         }
7210                         elseif (in_array($type, $types_fmedia))
7211                         {
7212                                 return 'fmedia';
7213                         }
7214                         elseif (in_array($type, $types_quicktime))
7215                         {
7216                                 return 'quicktime';
7217                         }
7218                         elseif (in_array($type, $types_wmedia))
7219                         {
7220                                 return 'wmedia';
7221                         }
7222                         elseif (in_array($type, $types_mp3))
7223                         {
7224                                 return 'mp3';
7225                         }
7226                         else
7227                         {
7228                                 return null;
7229                         }
7230                 }
7231                 else
7232                 {
7233                         return $type;
7234                 }
7235         }
7236 }
7237
7238 class SimplePie_Caption
7239 {
7240         var $type;
7241         var $lang;
7242         var $startTime;
7243         var $endTime;
7244         var $text;
7245
7246         // Constructor, used to input the data
7247         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7248         {
7249                 $this->type = $type;
7250                 $this->lang = $lang;
7251                 $this->startTime = $startTime;
7252                 $this->endTime = $endTime;
7253                 $this->text = $text;
7254         }
7255
7256         function __toString()
7257         {
7258                 // There is no $this->data here
7259                 return md5(serialize($this));
7260         }
7261
7262         function get_endtime()
7263         {
7264                 if ($this->endTime !== null)
7265                 {
7266                         return $this->endTime;
7267                 }
7268                 else
7269                 {
7270                         return null;
7271                 }
7272         }
7273
7274         function get_language()
7275         {
7276                 if ($this->lang !== null)
7277                 {
7278                         return $this->lang;
7279                 }
7280                 else
7281                 {
7282                         return null;
7283                 }
7284         }
7285
7286         function get_starttime()
7287         {
7288                 if ($this->startTime !== null)
7289                 {
7290                         return $this->startTime;
7291                 }
7292                 else
7293                 {
7294                         return null;
7295                 }
7296         }
7297
7298         function get_text()
7299         {
7300                 if ($this->text !== null)
7301                 {
7302                         return $this->text;
7303                 }
7304                 else
7305                 {
7306                         return null;
7307                 }
7308         }
7309
7310         function get_type()
7311         {
7312                 if ($this->type !== null)
7313                 {
7314                         return $this->type;
7315                 }
7316                 else
7317                 {
7318                         return null;
7319                 }
7320         }
7321 }
7322
7323 class SimplePie_Credit
7324 {
7325         var $role;
7326         var $scheme;
7327         var $name;
7328
7329         // Constructor, used to input the data
7330         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7331         {
7332                 $this->role = $role;
7333                 $this->scheme = $scheme;
7334                 $this->name = $name;
7335         }
7336
7337         function __toString()
7338         {
7339                 // There is no $this->data here
7340                 return md5(serialize($this));
7341         }
7342
7343         function get_role()
7344         {
7345                 if ($this->role !== null)
7346                 {
7347                         return $this->role;
7348                 }
7349                 else
7350                 {
7351                         return null;
7352                 }
7353         }
7354
7355         function get_scheme()
7356         {
7357                 if ($this->scheme !== null)
7358                 {
7359                         return $this->scheme;
7360                 }
7361                 else
7362                 {
7363                         return null;
7364                 }
7365         }
7366
7367         function get_name()
7368         {
7369                 if ($this->name !== null)
7370                 {
7371                         return $this->name;
7372                 }
7373                 else
7374                 {
7375                         return null;
7376                 }
7377         }
7378 }
7379
7380 class SimplePie_Copyright
7381 {
7382         var $url;
7383         var $label;
7384
7385         // Constructor, used to input the data
7386         function SimplePie_Copyright($url = null, $label = null)
7387         {
7388                 $this->url = $url;
7389                 $this->label = $label;
7390         }
7391
7392         function __toString()
7393         {
7394                 // There is no $this->data here
7395                 return md5(serialize($this));
7396         }
7397
7398         function get_url()
7399         {
7400                 if ($this->url !== null)
7401                 {
7402                         return $this->url;
7403                 }
7404                 else
7405                 {
7406                         return null;
7407                 }
7408         }
7409
7410         function get_attribution()
7411         {
7412                 if ($this->label !== null)
7413                 {
7414                         return $this->label;
7415                 }
7416                 else
7417                 {
7418                         return null;
7419                 }
7420         }
7421 }
7422
7423 class SimplePie_Rating
7424 {
7425         var $scheme;
7426         var $value;
7427
7428         // Constructor, used to input the data
7429         function SimplePie_Rating($scheme = null, $value = null)
7430         {
7431                 $this->scheme = $scheme;
7432                 $this->value = $value;
7433         }
7434
7435         function __toString()
7436         {
7437                 // There is no $this->data here
7438                 return md5(serialize($this));
7439         }
7440
7441         function get_scheme()
7442         {
7443                 if ($this->scheme !== null)
7444                 {
7445                         return $this->scheme;
7446                 }
7447                 else
7448                 {
7449                         return null;
7450                 }
7451         }
7452
7453         function get_value()
7454         {
7455                 if ($this->value !== null)
7456                 {
7457                         return $this->value;
7458                 }
7459                 else
7460                 {
7461                         return null;
7462                 }
7463         }
7464 }
7465
7466 class SimplePie_Restriction
7467 {
7468         var $relationship;
7469         var $type;
7470         var $value;
7471
7472         // Constructor, used to input the data
7473         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7474         {
7475                 $this->relationship = $relationship;
7476                 $this->type = $type;
7477                 $this->value = $value;
7478         }
7479
7480         function __toString()
7481         {
7482                 // There is no $this->data here
7483                 return md5(serialize($this));
7484         }
7485
7486         function get_relationship()
7487         {
7488                 if ($this->relationship !== null)
7489                 {
7490                         return $this->relationship;
7491                 }
7492                 else
7493                 {
7494                         return null;
7495                 }
7496         }
7497
7498         function get_type()
7499         {
7500                 if ($this->type !== null)
7501                 {
7502                         return $this->type;
7503                 }
7504                 else
7505                 {
7506                         return null;
7507                 }
7508         }
7509
7510         function get_value()
7511         {
7512                 if ($this->value !== null)
7513                 {
7514                         return $this->value;
7515                 }
7516                 else
7517                 {
7518                         return null;
7519                 }
7520         }
7521 }
7522
7523 /**
7524  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7525  */
7526 class SimplePie_File
7527 {
7528         var $url;
7529         var $useragent;
7530         var $success = true;
7531         var $headers = array();
7532         var $body;
7533         var $status_code;
7534         var $redirects = 0;
7535         var $error;
7536         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7537
7538         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7539         {
7540                 if (class_exists('idna_convert'))
7541                 {
7542                         $idn =& new idna_convert;
7543                         $parsed = SimplePie_Misc::parse_url($url);
7544                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7545                 }
7546                 $this->url = $url;
7547                 $this->useragent = $useragent;
7548                 if (preg_match('/^http(s)?:\/\//i', $url))
7549                 {
7550                         if ($useragent === null)
7551                         {
7552                                 $useragent = ini_get('user_agent');
7553                                 $this->useragent = $useragent;
7554                         }
7555                         if (!is_array($headers))
7556                         {
7557                                 $headers = array();
7558                         }
7559                         if (!$force_fsockopen && function_exists('curl_exec'))
7560                         {
7561                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7562                                 $fp = curl_init();
7563                                 $headers2 = array();
7564                                 foreach ($headers as $key => $value)
7565                                 {
7566                                         $headers2[] = "$key: $value";
7567                                 }
7568                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7569                                 {
7570                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7571                                 }
7572                                 curl_setopt($fp, CURLOPT_URL, $url);
7573                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7574                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7575                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7576                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7577                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7578                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7579                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7580                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7581                                 {
7582                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7583                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7584                                 }
7585                                 
7586                                 curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false); 
7587                                 curl_setopt($fp, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
7588
7589                                 $this->headers = curl_exec($fp);
7590                                 if (curl_errno($fp) == 23 || curl_errno($fp) == 61)
7591                                 {
7592                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7593                                         $this->headers = curl_exec($fp);
7594                                 }
7595                                 if (curl_errno($fp))
7596                                 {
7597                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7598                                         $this->success = false;
7599                                 }
7600                                 else
7601                                 {
7602                                         $info = curl_getinfo($fp);
7603                                         curl_close($fp);
7604                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7605                                         $this->headers = array_pop($this->headers);
7606                                         $parser =& new SimplePie_HTTP_Parser($this->headers);
7607                                         if ($parser->parse())
7608                                         {
7609                                                 $this->headers = $parser->headers;
7610                                                 $this->body = $parser->body;
7611                                                 $this->status_code = $parser->status_code;
7612                                                 if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303 || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7613                                                 {
7614                                                         $this->redirects++;
7615                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7616                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7617                                                 }
7618                                         }
7619                                 }
7620                         }
7621                         else
7622                         {
7623                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7624                                 $url_parts = parse_url($url);
7625                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) == 'https')
7626                                 {
7627                                         $url_parts['host'] = "ssl://$url_parts[host]";
7628                                         $url_parts['port'] = 443;
7629                                 }
7630                                 if (!isset($url_parts['port']))
7631                                 {
7632                                         $url_parts['port'] = 80;
7633                                 }
7634                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7635                                 if (!$fp)
7636                                 {
7637                                         $this->error = 'fsockopen error: ' . $errstr;
7638                                         $this->success = false;
7639                                 }
7640                                 else
7641                                 {
7642                                         stream_set_timeout($fp, $timeout);
7643                                         if (isset($url_parts['path']))
7644                                         {
7645                                                 if (isset($url_parts['query']))
7646                                                 {
7647                                                         $get = "$url_parts[path]?$url_parts[query]";
7648                                                 }
7649                                                 else
7650                                                 {
7651                                                         $get = $url_parts['path'];
7652                                                 }
7653                                         }
7654                                         else
7655                                         {
7656                                                 $get = '/';
7657                                         }
7658                                         $out = "GET $get HTTP/1.0\r\n";
7659                                         $out .= "Host: $url_parts[host]\r\n";
7660                                         $out .= "User-Agent: $useragent\r\n";
7661                                         if (function_exists('gzinflate'))
7662                                         {
7663                                                 $out .= "Accept-Encoding: gzip,deflate\r\n";
7664                                         }
7665
7666                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7667                                         {
7668                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7669                                         }
7670                                         foreach ($headers as $key => $value)
7671                                         {
7672                                                 $out .= "$key: $value\r\n";
7673                                         }
7674                                         $out .= "Connection: Close\r\n\r\n";
7675                                         fwrite($fp, $out);
7676
7677                                         $info = stream_get_meta_data($fp);
7678
7679                                         $this->headers = '';
7680                                         while (!$info['eof'] && !$info['timed_out'])
7681                                         {
7682                                                 $this->headers .= fread($fp, 1160);
7683                                                 $info = stream_get_meta_data($fp);
7684                                         }
7685                                         if (!$info['timed_out'])
7686                                         {
7687                                                 $parser =& new SimplePie_HTTP_Parser($this->headers);
7688                                                 if ($parser->parse())
7689                                                 {
7690                                                         $this->headers = $parser->headers;
7691                                                         $this->body = $parser->body;
7692                                                         $this->status_code = $parser->status_code;
7693                                                         if (($this->status_code == 300 || $this->status_code == 301 || $this->status_code == 302 || $this->status_code == 303 || $this->status_code == 307 || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7694                                                         {
7695                                                                 $this->redirects++;
7696                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7697                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7698                                                         }
7699                                                         if (isset($this->headers['content-encoding']) && ($this->headers['content-encoding'] == 'gzip' || $this->headers['content-encoding'] == 'deflate'))
7700                                                         {
7701                                                                 if (substr($this->body, 0, 8) == "\x1f\x8b\x08\x00\x00\x00\x00\x00")
7702                                                                 {
7703                                                                         $this->body = substr($this->body, 10);
7704                                                                 }
7705                                                                 $this->body = gzinflate($this->body);
7706                                                         }
7707                                                 }
7708                                         }
7709                                         else
7710                                         {
7711                                                 $this->error = 'fsocket timed out';
7712                                                 $this->success = false;
7713                                         }
7714                                         fclose($fp);
7715                                 }
7716                         }
7717                 }
7718                 else
7719                 {
7720                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7721                         if (!$this->body = file_get_contents($url))
7722                         {
7723                                 $this->error = 'file_get_contents could not read the file';
7724                                 $this->success = false;
7725                         }
7726                 }
7727         }
7728 }
7729
7730 /**
7731  * HTTP Response Parser
7732  *
7733  * @package SimplePie
7734  */
7735 class SimplePie_HTTP_Parser
7736 {
7737         /**
7738          * HTTP Version
7739          *
7740          * @access public
7741          * @var float
7742          */
7743         var $http_version = 0.0;
7744
7745         /**
7746          * Status code
7747          *
7748          * @access public
7749          * @var int
7750          */
7751         var $status_code = 0;
7752
7753         /**
7754          * Reason phrase
7755          *
7756          * @access public
7757          * @var string
7758          */
7759         var $reason = '';
7760
7761         /**
7762          * Key/value pairs of the headers
7763          *
7764          * @access public
7765          * @var array
7766          */
7767         var $headers = array();
7768
7769         /**
7770          * Body of the response
7771          *
7772          * @access public
7773          * @var string
7774          */
7775         var $body = '';
7776
7777         /**
7778          * Current state of the state machine
7779          *
7780          * @access private
7781          * @var string
7782          */
7783         var $state = 'http_version';
7784
7785         /**
7786          * Input data
7787          *
7788          * @access private
7789          * @var string
7790          */
7791         var $data = '';
7792
7793         /**
7794          * Input data length (to avoid calling strlen() everytime this is needed)
7795          *
7796          * @access private
7797          * @var int
7798          */
7799         var $data_length = 0;
7800
7801         /**
7802          * Current position of the pointer
7803          *
7804          * @var int
7805          * @access private
7806          */
7807         var $position = 0;
7808
7809         /**
7810          * Name of the hedaer currently being parsed
7811          *
7812          * @access private
7813          * @var string
7814          */
7815         var $name = '';
7816
7817         /**
7818          * Value of the hedaer currently being parsed
7819          *
7820          * @access private
7821          * @var string
7822          */
7823         var $value = '';
7824
7825         /**
7826          * Create an instance of the class with the input data
7827          *
7828          * @access public
7829          * @param string $data Input data
7830          */
7831         function SimplePie_HTTP_Parser($data)
7832         {
7833                 $this->data = $data;
7834                 $this->data_length = strlen($this->data);
7835         }
7836
7837         /**
7838          * Parse the input data
7839          *
7840          * @access public
7841          * @return bool true on success, false on failure
7842          */
7843         function parse()
7844         {
7845                 while ($this->state && $this->state !== 'emit' && $this->has_data())
7846                 {
7847                         $state = $this->state;
7848                         $this->$state();
7849                 }
7850                 $this->data = '';
7851                 if ($this->state === 'emit')
7852                 {
7853                         return true;
7854                 }
7855                 else
7856                 {
7857                         $this->http_version = '';
7858                         $this->status_code = '';
7859                         $this->reason = '';
7860                         $this->headers = array();
7861                         $this->body = '';
7862                         return false;
7863                 }
7864         }
7865
7866         /**
7867          * Check whether there is data beyond the pointer
7868          *
7869          * @access private
7870          * @return bool true if there is further data, false if not
7871          */
7872         function has_data()
7873         {
7874                 return (bool) ($this->position < $this->data_length);
7875         }
7876
7877         /**
7878          * See if the next character is LWS
7879          *
7880          * @access private
7881          * @return bool true if the next character is LWS, false if not
7882          */
7883         function is_linear_whitespace()
7884         {
7885                 return (bool) ($this->data[$this->position] === "\x09"
7886                         || $this->data[$this->position] === "\x20"
7887                         || ($this->data[$this->position] === "\x0A"
7888                                 && isset($this->data[$this->position + 1])
7889                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
7890         }
7891
7892         /**
7893          * Parse the HTTP version
7894          *
7895          * @access private
7896          */
7897         function http_version()
7898         {
7899                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
7900                 {
7901                         $len = strspn($this->data, '0123456789.', 5);
7902                         $this->http_version = substr($this->data, 5, $len);
7903                         $this->position += 5 + $len;
7904                         if (substr_count($this->http_version, '.') <= 1)
7905                         {
7906                                 $this->http_version = (float) $this->http_version;
7907                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
7908                                 $this->state = 'status';
7909                         }
7910                         else
7911                         {
7912                                 $this->state = false;
7913                         }
7914                 }
7915                 else
7916                 {
7917                         $this->state = false;
7918                 }
7919         }
7920
7921         /**
7922          * Parse the status code
7923          *
7924          * @access private
7925          */
7926         function status()
7927         {
7928                 if ($len = strspn($this->data, '0123456789', $this->position))
7929                 {
7930                         $this->status_code = (int) substr($this->data, $this->position, $len);
7931                         $this->position += $len;
7932                         $this->state = 'reason';
7933                 }
7934                 else
7935                 {
7936                         $this->state = false;
7937                 }
7938         }
7939
7940         /**
7941          * Parse the reason phrase
7942          *
7943          * @access private
7944          */
7945         function reason()
7946         {
7947                 $len = strcspn($this->data, "\x0A", $this->position);
7948                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
7949                 $this->position += $len + 1;
7950                 $this->state = 'new_line';
7951         }
7952
7953         /**
7954          * Deal with a new line, shifting data around as needed
7955          *
7956          * @access private
7957          */
7958         function new_line()
7959         {
7960                 $this->value = trim($this->value, "\x0D\x20");
7961                 if ($this->name !== '' && $this->value !== '')
7962                 {
7963                         $this->name = strtolower($this->name);
7964                         if (isset($this->headers[$this->name]))
7965                         {
7966                                 $this->headers[$this->name] .= ', ' . $this->value;
7967                         }
7968                         else
7969                         {
7970                                 $this->headers[$this->name] = $this->value;
7971                         }
7972                 }
7973                 $this->name = '';
7974                 $this->value = '';
7975                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
7976                 {
7977                         $this->position += 2;
7978                         $this->state = 'body';
7979                 }
7980                 elseif ($this->data[$this->position] === "\x0A")
7981                 {
7982                         $this->position++;
7983                         $this->state = 'body';
7984                 }
7985                 else
7986                 {
7987                         $this->state = 'name';
7988                 }
7989         }
7990
7991         /**
7992          * Parse a header name
7993          *
7994          * @access private
7995          */
7996         function name()
7997         {
7998                 $len = strcspn($this->data, "\x0A:", $this->position);
7999                 if (isset($this->data[$this->position + $len]))
8000                 {
8001                         if ($this->data[$this->position + $len] === "\x0A")
8002                         {
8003                                 $this->position += $len;
8004                                 $this->state = 'new_line';
8005                         }
8006                         else
8007                         {
8008                                 $this->name = substr($this->data, $this->position, $len);
8009                                 $this->position += $len + 1;
8010                                 $this->state = 'value';
8011                         }
8012                 }
8013                 else
8014                 {
8015                         $this->state = false;
8016                 }
8017         }
8018
8019         /**
8020          * Parse LWS, replacing consecutive LWS characters with a single space
8021          *
8022          * @access private
8023          */
8024         function linear_whitespace()
8025         {
8026                 do
8027                 {
8028                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8029                         {
8030                                 $this->position += 2;
8031                         }
8032                         elseif ($this->data[$this->position] === "\x0A")
8033                         {
8034                                 $this->position++;
8035                         }
8036                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8037                 } while ($this->has_data() && $this->is_linear_whitespace());
8038                 $this->value .= "\x20";
8039         }
8040
8041         /**
8042          * See what state to move to while within non-quoted header values
8043          *
8044          * @access private
8045          */
8046         function value()
8047         {
8048                 if ($this->is_linear_whitespace())
8049                 {
8050                         $this->linear_whitespace();
8051                 }
8052                 else
8053                 {
8054                         switch ($this->data[$this->position])
8055                         {
8056                                 case '"':
8057                                         $this->position++;
8058                                         $this->state = 'quote';
8059                                         break;
8060
8061                                 case "\x0A":
8062                                         $this->position++;
8063                                         $this->state = 'new_line';
8064                                         break;
8065
8066                                 default:
8067                                         $this->state = 'value_char';
8068                                         break;
8069                         }
8070                 }
8071         }
8072
8073         /**
8074          * Parse a header value while outside quotes
8075          *
8076          * @access private
8077          */
8078         function value_char()
8079         {
8080                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8081                 $this->value .= substr($this->data, $this->position, $len);
8082                 $this->position += $len;
8083                 $this->state = 'value';
8084         }
8085
8086         /**
8087          * See what state to move to while within quoted header values
8088          *
8089          * @access private
8090          */
8091         function quote()
8092         {
8093                 if ($this->is_linear_whitespace())
8094                 {
8095                         $this->linear_whitespace();
8096                 }
8097                 else
8098                 {
8099                         switch ($this->data[$this->position])
8100                         {
8101                                 case '"':
8102                                         $this->position++;
8103                                         $this->state = 'value';
8104                                         break;
8105
8106                                 case "\x0A":
8107                                         $this->position++;
8108                                         $this->state = 'new_line';
8109                                         break;
8110
8111                                 case '\\':
8112                                         $this->position++;
8113                                         $this->state = 'quote_escaped';
8114                                         break;
8115
8116                                 default:
8117                                         $this->state = 'quote_char';
8118                                         break;
8119                         }
8120                 }
8121         }
8122
8123         /**
8124          * Parse a header value while within quotes
8125          *
8126          * @access private
8127          */
8128         function quote_char()
8129         {
8130                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8131                 $this->value .= substr($this->data, $this->position, $len);
8132                 $this->position += $len;
8133                 $this->state = 'value';
8134         }
8135
8136         /**
8137          * Parse an escaped character within quotes
8138          *
8139          * @access private
8140          */
8141         function quote_escaped()
8142         {
8143                 $this->value .= $this->data[$this->position];
8144                 $this->position++;
8145                 $this->state = 'quote';
8146         }
8147
8148         /**
8149          * Parse the body
8150          *
8151          * @access private
8152          */
8153         function body()
8154         {
8155                 $this->body = substr($this->data, $this->position);
8156                 $this->state = 'emit';
8157         }
8158 }
8159
8160 class SimplePie_Cache
8161 {
8162         /**
8163          * Don't call the constructor. Please.
8164          *
8165          * @access private
8166          */
8167         function SimplePie_Cache()
8168         {
8169                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8170         }
8171
8172         /**
8173          * Create a new SimplePie_Cache object
8174          *
8175          * @static
8176          * @access public
8177          */
8178         function create($location, $filename, $extension)
8179         {
8180                 return new SimplePie_Cache_File($location, $filename, $extension);
8181         }
8182 }
8183
8184 class SimplePie_Cache_File
8185 {
8186         var $location;
8187         var $filename;
8188         var $extension;
8189         var $name;
8190
8191         function SimplePie_Cache_File($location, $filename, $extension)
8192         {
8193                 $this->location = $location;
8194                 $this->filename = rawurlencode($filename);
8195                 $this->extension = rawurlencode($extension);
8196                 $this->name = "$location/$this->filename.$this->extension";
8197         }
8198
8199         function save($data)
8200         {
8201                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8202                 {
8203                         if (is_a($data, 'SimplePie'))
8204                         {
8205                                 $data = $data->data;
8206                         }
8207
8208                         $data = serialize($data);
8209
8210                         if (function_exists('file_put_contents'))
8211                         {
8212                                 return (bool) file_put_contents($this->name, $data);
8213                         }
8214                         else
8215                         {
8216                                 $fp = fopen($this->name, 'wb');
8217                                 if ($fp)
8218                                 {
8219                                         fwrite($fp, $data);
8220                                         fclose($fp);
8221                                         return true;
8222                                 }
8223                         }
8224                 }
8225                 return false;
8226         }
8227
8228         function load()
8229         {
8230                 if (file_exists($this->name) && is_readable($this->name))
8231                 {
8232                         return unserialize(file_get_contents($this->name));
8233                 }
8234                 return false;
8235         }
8236
8237         function mtime()
8238         {
8239                 if (file_exists($this->name))
8240                 {
8241                         return filemtime($this->name);
8242                 }
8243                 return false;
8244         }
8245
8246         function touch()
8247         {
8248                 if (file_exists($this->name))
8249                 {
8250                         return touch($this->name);
8251                 }
8252                 return false;
8253         }
8254
8255         function unlink()
8256         {
8257                 if (file_exists($this->name))
8258                 {
8259                         return unlink($this->name);
8260                 }
8261                 return false;
8262         }
8263 }
8264
8265 class SimplePie_Misc
8266 {
8267         function time_hms($seconds)
8268         {
8269                 $time = '';
8270
8271                 $hours = floor($seconds / 3600);
8272                 $remainder = $seconds % 3600;
8273                 if ($hours > 0)
8274                 {
8275                         $time .= $hours.':';
8276                 }
8277
8278                 $minutes = floor($remainder / 60);
8279                 $seconds = $remainder % 60;
8280                 if ($minutes < 10 && $hours > 0)
8281                 {
8282                         $minutes = '0' . $minutes;
8283                 }
8284                 if ($seconds < 10)
8285                 {
8286                         $seconds = '0' . $seconds;
8287                 }
8288
8289                 $time .= $minutes.':';
8290                 $time .= $seconds;
8291
8292                 return $time;
8293         }
8294
8295         function absolutize_url($relative, $base)
8296         {
8297                 if ($relative !== '')
8298                 {
8299                         $relative = SimplePie_Misc::parse_url($relative);
8300                         if ($relative['scheme'] !== '')
8301                         {
8302                                 $target = $relative;
8303                         }
8304                         elseif ($base !== '')
8305                         {
8306                                 $base = SimplePie_Misc::parse_url($base);
8307                                 $target = SimplePie_Misc::parse_url('');
8308                                 if ($relative['authority'] !== '')
8309                                 {
8310                                         $target = $relative;
8311                                         $target['scheme'] = $base['scheme'];
8312                                 }
8313                                 else
8314                                 {
8315                                         $target['scheme'] = $base['scheme'];
8316                                         $target['authority'] = $base['authority'];
8317                                         if ($relative['path'] !== '')
8318                                         {
8319                                                 if (strpos($relative['path'], '/') === 0)
8320                                                 {
8321                                                         $target['path'] = $relative['path'];
8322                                                 }
8323                                                 elseif ($base['authority'] !== '' && $base['path'] === '')
8324                                                 {
8325                                                         $target['path'] = '/' . $relative['path'];
8326                                                 }
8327                                                 elseif (($last_segment = strrpos($base['path'], '/')) !== false)
8328                                                 {
8329                                                         $target['path'] = substr($base['path'], 0, $last_segment + 1) . $relative['path'];
8330                                                 }
8331                                                 else
8332                                                 {
8333                                                         $target['path'] = $relative['path'];
8334                                                 }
8335                                                 $target['query'] = $relative['query'];
8336                                         }
8337                                         else
8338                                         {
8339                                                 $target['path'] = $base['path'];
8340                                                 if ($relative['query'] !== '')
8341                                                 {
8342                                                         $target['query'] = $relative['query'];
8343                                                 }
8344                                                 elseif ($base['query'] !== '')
8345                                                 {
8346                                                         $target['query'] = $base['query'];
8347                                                 }
8348                                         }
8349                                 }
8350                                 $target['fragment'] = $relative['fragment'];
8351                         }
8352                         else
8353                         {
8354                                 // No base URL, just return the relative URL
8355                                 $target = $relative;
8356                         }
8357                         $return = SimplePie_Misc::compress_parse_url($target['scheme'], $target['authority'], $target['path'], $target['query'], $target['fragment']);
8358                 }
8359                 else
8360                 {
8361                         $return = $base;
8362                 }
8363                 $return = SimplePie_Misc::normalize_url($return);
8364                 return $return;
8365         }
8366
8367         function remove_dot_segments($input)
8368         {
8369                 $output = '';
8370                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input == '.' || $input == '..')
8371                 {
8372                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
8373                         if (strpos($input, '../') === 0)
8374                         {
8375                                 $input = substr($input, 3);
8376                         }
8377                         elseif (strpos($input, './') === 0)
8378                         {
8379                                 $input = substr($input, 2);
8380                         }
8381                         // 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,
8382                         elseif (strpos($input, '/./') === 0)
8383                         {
8384                                 $input = substr_replace($input, '/', 0, 3);
8385                         }
8386                         elseif ($input == '/.')
8387                         {
8388                                 $input = '/';
8389                         }
8390                         // 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,
8391                         elseif (strpos($input, '/../') === 0)
8392                         {
8393                                 $input = substr_replace($input, '/', 0, 4);
8394                                 $output = substr_replace($output, '', strrpos($output, '/'));
8395                         }
8396                         elseif ($input == '/..')
8397                         {
8398                                 $input = '/';
8399                                 $output = substr_replace($output, '', strrpos($output, '/'));
8400                         }
8401                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
8402                         elseif ($input == '.' || $input == '..')
8403                         {
8404                                 $input = '';
8405                         }
8406                         // 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
8407                         elseif (($pos = strpos($input, '/', 1)) !== false)
8408                         {
8409                                 $output .= substr($input, 0, $pos);
8410                                 $input = substr_replace($input, '', 0, $pos);
8411                         }
8412                         else
8413                         {
8414                                 $output .= $input;
8415                                 $input = '';
8416                         }
8417                 }
8418                 return $output . $input;
8419         }
8420
8421         function get_element($realname, $string)
8422         {
8423                 $return = array();
8424                 $name = preg_quote($realname, '/');
8425                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
8426                 {
8427                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
8428                         {
8429                                 $return[$i]['tag'] = $realname;
8430                                 $return[$i]['full'] = $matches[$i][0][0];
8431                                 $return[$i]['offset'] = $matches[$i][0][1];
8432                                 if (strlen($matches[$i][3][0]) <= 2)
8433                                 {
8434                                         $return[$i]['self_closing'] = true;
8435                                 }
8436                                 else
8437                                 {
8438                                         $return[$i]['self_closing'] = false;
8439                                         $return[$i]['content'] = $matches[$i][4][0];
8440                                 }
8441                                 $return[$i]['attribs'] = array();
8442                                 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))
8443                                 {
8444                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
8445                                         {
8446                                                 if (count($attribs[$j]) == 2)
8447                                                 {
8448                                                         $attribs[$j][2] = $attribs[$j][1];
8449                                                 }
8450                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
8451                                         }
8452                                 }
8453                         }
8454                 }
8455                 return $return;
8456         }
8457
8458         function element_implode($element)
8459         {
8460                 $full = "<$element[tag]";
8461                 foreach ($element['attribs'] as $key => $value)
8462                 {
8463                         $key = strtolower($key);
8464                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
8465                 }
8466                 if ($element['self_closing'])
8467                 {
8468                         $full .= ' />';
8469                 }
8470                 else
8471                 {
8472                         $full .= ">$element[content]</$element[tag]>";
8473                 }
8474                 return $full;
8475         }
8476
8477         function error($message, $level, $file, $line)
8478         {
8479                 switch ($level)
8480                 {
8481                         case E_USER_ERROR:
8482                                 $note = 'PHP Error';
8483                                 break;
8484                         case E_USER_WARNING:
8485                                 $note = 'PHP Warning';
8486                                 break;
8487                         case E_USER_NOTICE:
8488                                 $note = 'PHP Notice';
8489                                 break;
8490                         default:
8491                                 $note = 'Unknown Error';
8492                                 break;
8493                 }
8494                 error_log("$note: $message in $file on line $line", 0);
8495                 return $message;
8496         }
8497
8498         /**
8499          * If a file has been cached, retrieve and display it.
8500          *
8501          * This is most useful for caching images (get_favicon(), etc.),
8502          * however it works for all cached files.  This WILL NOT display ANY
8503          * file/image/page/whatever, but rather only display what has already
8504          * been cached by SimplePie.
8505          *
8506          * @access public
8507          * @see SimplePie::get_favicon()
8508          * @param str $identifier_url URL that is used to identify the content.
8509          * This may or may not be the actual URL of the live content.
8510          * @param str $cache_location Location of SimplePie's cache.  Defaults
8511          * to './cache'.
8512          * @param str $cache_extension The file extension that the file was
8513          * cached with.  Defaults to 'spc'.
8514          * @param str $cache_class Name of the cache-handling class being used
8515          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
8516          * as-is unless you've overloaded the class.
8517          * @param str $cache_name_function Obsolete. Exists for backwards
8518          * compatibility reasons only.
8519          */
8520         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
8521         {
8522                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
8523
8524                 if ($file = $cache->load())
8525                 {
8526                         if (isset($file['headers']['content-type']))
8527                         {
8528                                 header('Content-type:' . $file['headers']['content-type']);
8529                         }
8530                         else
8531                         {
8532                                 header('Content-type: application/octet-stream');
8533                         }
8534                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
8535                         echo $file['body'];
8536                         exit;
8537                 }
8538
8539                 die('Cached file for ' . $identifier_url . ' cannot be found.');
8540         }
8541
8542         function fix_protocol($url, $http = 1)
8543         {
8544                 $url = SimplePie_Misc::normalize_url($url);
8545                 $parsed = SimplePie_Misc::parse_url($url);
8546                 if ($parsed['scheme'] !== '' && $parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')
8547                 {
8548                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
8549                 }
8550
8551                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
8552                 {
8553                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
8554                 }
8555
8556                 if ($http == 2 && $parsed['scheme'] !== '')
8557                 {
8558                         return "feed:$url";
8559                 }
8560                 elseif ($http == 3 && strtolower($parsed['scheme']) == 'http')
8561                 {
8562                         return substr_replace($url, 'podcast', 0, 4);
8563                 }
8564                 elseif ($http == 4 && strtolower($parsed['scheme']) == 'http')
8565                 {
8566                         return substr_replace($url, 'itpc', 0, 4);
8567                 }
8568                 else
8569                 {
8570                         return $url;
8571                 }
8572         }
8573
8574         function parse_url($url)
8575         {
8576                 static $cache = array();
8577                 if (isset($cache[$url]))
8578                 {
8579                         return $cache[$url];
8580                 }
8581                 elseif (preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $url, $match))
8582                 {
8583                         for ($i = count($match); $i <= 9; $i++)
8584                         {
8585                                 $match[$i] = '';
8586                         }
8587                         return $cache[$url] = array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
8588                 }
8589                 else
8590                 {
8591                         return $cache[$url] = array('scheme' => '', 'authority' => '', 'path' => '', 'query' => '', 'fragment' => '');
8592                 }
8593         }
8594
8595         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
8596         {
8597                 $return = '';
8598                 if ($scheme !== '')
8599                 {
8600                         $return .= "$scheme:";
8601                 }
8602                 if ($authority !== '')
8603                 {
8604                         $return .= "//$authority";
8605                 }
8606                 if ($path !== '')
8607                 {
8608                         $return .= $path;
8609                 }
8610                 if ($query !== '')
8611                 {
8612                         $return .= "?$query";
8613                 }
8614                 if ($fragment !== '')
8615                 {
8616                         $return .= "#$fragment";
8617                 }
8618                 return $return;
8619         }
8620
8621         function normalize_url($url)
8622         {
8623                 $url = preg_replace_callback('/%([0-9A-Fa-f]{2})/', array('SimplePie_Misc', 'percent_encoding_normalization'), $url);
8624                 $url = SimplePie_Misc::parse_url($url);
8625                 $url['scheme'] = strtolower($url['scheme']);
8626                 if ($url['authority'] !== '')
8627                 {
8628                         $url['authority'] = strtolower($url['authority']);
8629                         $url['path'] = SimplePie_Misc::remove_dot_segments($url['path']);
8630                 }
8631                 return SimplePie_Misc::compress_parse_url($url['scheme'], $url['authority'], $url['path'], $url['query'], $url['fragment']);
8632         }
8633
8634         function percent_encoding_normalization($match)
8635         {
8636                 $integer = hexdec($match[1]);
8637                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer == 0x2D || $integer == 0x2E || $integer == 0x5F || $integer == 0x7E)
8638                 {
8639                         return chr($integer);
8640                 }
8641                 else
8642                 {
8643                         return strtoupper($match[0]);
8644                 }
8645         }
8646
8647         /**
8648          * Remove bad UTF-8 bytes
8649          *
8650          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
8651          * FAQ: Multilingual Forms (modified to include full ASCII range)
8652          *
8653          * @author Geoffrey Sneddon
8654          * @see http://www.w3.org/International/questions/qa-forms-utf-8
8655          * @param string $str String to remove bad UTF-8 bytes from
8656          * @return string UTF-8 string
8657          */
8658         function utf8_bad_replace($str)
8659         {
8660                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
8661                 {
8662                         return $return;
8663                 }
8664                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
8665                 {
8666                         return $return;
8667                 }
8668                 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))
8669                 {
8670                         return implode("\xEF\xBF\xBD", $matches[0]);
8671                 }
8672                 elseif ($str !== '')
8673                 {
8674                         return "\xEF\xBF\xBD";
8675                 }
8676                 else
8677                 {
8678                         return '';
8679                 }
8680         }
8681         
8682         /**
8683          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
8684          *
8685          * @static
8686          * @access public
8687          * @param string $string Windows-1252 encoded string
8688          * @return string UTF-8 encoded string
8689          */
8690         function windows_1252_to_utf8($string)
8691         {
8692                 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");
8693                 
8694                 return strtr($string, $convert_table);
8695         }
8696
8697         function change_encoding($data, $input, $output)
8698         {
8699                 $input = SimplePie_Misc::encoding($input);
8700                 $output = SimplePie_Misc::encoding($output);
8701                 
8702                 // We fail to fail on non US-ASCII bytes
8703                 if ($input === 'US-ASCII')
8704                 {
8705                         static $non_ascii_octects = '';
8706                         if (!$non_ascii_octects)
8707                         {
8708                                 for ($i = 0x80; $i <= 0xFF; $i++)
8709                                 {
8710                                         $non_ascii_octects .= chr($i);
8711                                 }
8712                         }
8713                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
8714                 }
8715
8716                 if (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
8717                 {
8718                         return $return;
8719                 }
8720                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($data, $output, $input)))
8721                 {
8722                         return $return;
8723                 }
8724                 elseif ($input == 'windows-1252' && $output == 'UTF-8')
8725                 {
8726                         return SimplePie_Misc::windows_1252_to_utf8($data);
8727                 }
8728                 elseif ($input == 'UTF-8' && $output == 'windows-1252')
8729                 {
8730                         return utf8_decode($data);
8731                 }
8732                 return $data;
8733         }
8734
8735         function encoding($encoding)
8736         {
8737                 // Character sets are case-insensitive (though we'll return them in the form given in their registration)
8738                 switch (strtoupper($encoding))
8739                 {
8740                         case 'ANSI_X3.110-1983':
8741                         case 'CSA_T500-1983':
8742                         case 'CSISO99NAPLPS':
8743                         case 'ISO-IR-99':
8744                         case 'NAPLPS':
8745                                 return 'ANSI_X3.110-1983';
8746         
8747                         case 'ARABIC7':
8748                         case 'ASMO_449':
8749                         case 'CSISO89ASMO449':
8750                         case 'ISO-IR-89':
8751                         case 'ISO_9036':
8752                                 return 'ASMO_449';
8753         
8754                         case 'ADOBE-STANDARD-ENCODING':
8755                         case 'CSADOBESTANDARDENCODING':
8756                                 return 'Adobe-Standard-Encoding';
8757         
8758                         case 'ADOBE-SYMBOL-ENCODING':
8759                         case 'CSHPPSMATH':
8760                                 return 'Adobe-Symbol-Encoding';
8761         
8762                         case 'AMI-1251':
8763                         case 'AMI1251':
8764                         case 'AMIGA-1251':
8765                         case 'AMIGA1251':
8766                                 return 'Amiga-1251';
8767         
8768                         case 'BOCU-1':
8769                         case 'CSBOCU-1':
8770                                 return 'BOCU-1';
8771         
8772                         case 'BRF':
8773                         case 'CSBRF':
8774                                 return 'BRF';
8775         
8776                         case 'BS_4730':
8777                         case 'CSISO4UNITEDKINGDOM':
8778                         case 'GB':
8779                         case 'ISO-IR-4':
8780                         case 'ISO646-GB':
8781                         case 'UK':
8782                                 return 'BS_4730';
8783         
8784                         case 'BS_VIEWDATA':
8785                         case 'CSISO47BSVIEWDATA':
8786                         case 'ISO-IR-47':
8787                                 return 'BS_viewdata';
8788         
8789                         case 'BIG5':
8790                         case 'CSBIG5':
8791                                 return 'Big5';
8792         
8793                         case 'BIG5-HKSCS':
8794                                 return 'Big5-HKSCS';
8795         
8796                         case 'CESU-8':
8797                         case 'CSCESU-8':
8798                                 return 'CESU-8';
8799         
8800                         case 'CA':
8801                         case 'CSA7-1':
8802                         case 'CSA_Z243.4-1985-1':
8803                         case 'CSISO121CANADIAN1':
8804                         case 'ISO-IR-121':
8805                         case 'ISO646-CA':
8806                                 return 'CSA_Z243.4-1985-1';
8807         
8808                         case 'CSA7-2':
8809                         case 'CSA_Z243.4-1985-2':
8810                         case 'CSISO122CANADIAN2':
8811                         case 'ISO-IR-122':
8812                         case 'ISO646-CA2':
8813                                 return 'CSA_Z243.4-1985-2';
8814         
8815                         case 'CSA_Z243.4-1985-GR':
8816                         case 'CSISO123CSAZ24341985GR':
8817                         case 'ISO-IR-123':
8818                                 return 'CSA_Z243.4-1985-gr';
8819         
8820                         case 'CSISO139CSN369103':
8821                         case 'CSN_369103':
8822                         case 'ISO-IR-139':
8823                                 return 'CSN_369103';
8824         
8825                         case 'CSDECMCS':
8826                         case 'DEC':
8827                         case 'DEC-MCS':
8828                                 return 'DEC-MCS';
8829         
8830                         case 'CSISO21GERMAN':
8831                         case 'DE':
8832                         case 'DIN_66003':
8833                         case 'ISO-IR-21':
8834                         case 'ISO646-DE':
8835                                 return 'DIN_66003';
8836         
8837                         case 'CSISO646DANISH':
8838                         case 'DK':
8839                         case 'DS2089':
8840                         case 'DS_2089':
8841                         case 'ISO646-DK':
8842                                 return 'DS_2089';
8843         
8844                         case 'CSIBMEBCDICATDE':
8845                         case 'EBCDIC-AT-DE':
8846                                 return 'EBCDIC-AT-DE';
8847         
8848                         case 'CSEBCDICATDEA':
8849                         case 'EBCDIC-AT-DE-A':
8850                                 return 'EBCDIC-AT-DE-A';
8851         
8852                         case 'CSEBCDICCAFR':
8853                         case 'EBCDIC-CA-FR':
8854                                 return 'EBCDIC-CA-FR';
8855         
8856                         case 'CSEBCDICDKNO':
8857                         case 'EBCDIC-DK-NO':
8858                                 return 'EBCDIC-DK-NO';
8859         
8860                         case 'CSEBCDICDKNOA':
8861                         case 'EBCDIC-DK-NO-A':
8862                                 return 'EBCDIC-DK-NO-A';
8863         
8864                         case 'CSEBCDICES':
8865                         case 'EBCDIC-ES':
8866                                 return 'EBCDIC-ES';
8867         
8868                         case 'CSEBCDICESA':
8869                         case 'EBCDIC-ES-A':
8870                                 return 'EBCDIC-ES-A';
8871         
8872                         case 'CSEBCDICESS':
8873                         case 'EBCDIC-ES-S':
8874                                 return 'EBCDIC-ES-S';
8875         
8876                         case 'CSEBCDICFISE':
8877                         case 'EBCDIC-FI-SE':
8878                                 return 'EBCDIC-FI-SE';
8879         
8880                         case 'CSEBCDICFISEA':
8881                         case 'EBCDIC-FI-SE-A':
8882                                 return 'EBCDIC-FI-SE-A';
8883         
8884                         case 'CSEBCDICFR':
8885                         case 'EBCDIC-FR':
8886                                 return 'EBCDIC-FR';
8887         
8888                         case 'CSEBCDICIT':
8889                         case 'EBCDIC-IT':
8890                                 return 'EBCDIC-IT';
8891         
8892                         case 'CSEBCDICPT':
8893                         case 'EBCDIC-PT':
8894                                 return 'EBCDIC-PT';
8895         
8896                         case 'CSEBCDICUK':
8897                         case 'EBCDIC-UK':
8898                                 return 'EBCDIC-UK';
8899         
8900                         case 'CSEBCDICUS':
8901                         case 'EBCDIC-US':
8902                                 return 'EBCDIC-US';
8903         
8904                         case 'CSISO111ECMACYRILLIC':
8905                         case 'ECMA-CYRILLIC':
8906                         case 'ISO-IR-111':
8907                         case 'KOI8-E':
8908                                 return 'ECMA-cyrillic';
8909         
8910                         case 'CSISO17SPANISH':
8911                         case 'ES':
8912                         case 'ISO-IR-17':
8913                         case 'ISO646-ES':
8914                                 return 'ES';
8915         
8916                         case 'CSISO85SPANISH2':
8917                         case 'ES2':
8918                         case 'ISO-IR-85':
8919                         case 'ISO646-ES2':
8920                                 return 'ES2';
8921         
8922                         case 'CSEUCPKDFMTJAPANESE':
8923                         case 'EUC-JP':
8924                         case 'EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE':
8925                                 return 'EUC-JP';
8926         
8927                         case 'CSEUCKR':
8928                         case 'EUC-KR':
8929                                 return 'EUC-KR';
8930         
8931                         case 'CSEUCFIXWIDJAPANESE':
8932                         case 'EXTENDED_UNIX_CODE_FIXED_WIDTH_FOR_JAPANESE':
8933                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
8934         
8935                         case 'GB18030':
8936                                 return 'GB18030';
8937         
8938                         case 'CSGB2312':
8939                         case 'GB2312':
8940                                 return 'GB2312';
8941         
8942                         case 'CP936':
8943                         case 'GBK':
8944                         case 'MS936':
8945                         case 'WINDOWS-936':
8946                                 return 'GBK';
8947         
8948                         case 'CN':
8949                         case 'CSISO57GB1988':
8950                         case 'GB_1988-80':
8951                         case 'ISO-IR-57':
8952                         case 'ISO646-CN':
8953                                 return 'GB_1988-80';
8954         
8955                         case 'CHINESE':
8956                         case 'CSISO58GB231280':
8957                         case 'GB_2312-80':
8958                         case 'ISO-IR-58':
8959                                 return 'GB_2312-80';
8960         
8961                         case 'CSISO153GOST1976874':
8962                         case 'GOST_19768-74':
8963                         case 'ISO-IR-153':
8964                         case 'ST_SEV_358-88':
8965                                 return 'GOST_19768-74';
8966         
8967                         case 'CSHPDESKTOP':
8968                         case 'HP-DESKTOP':
8969                                 return 'HP-DeskTop';
8970         
8971                         case 'CSHPLEGAL':
8972                         case 'HP-LEGAL':
8973                                 return 'HP-Legal';
8974         
8975                         case 'CSHPMATH8':
8976                         case 'HP-MATH8':
8977                                 return 'HP-Math8';
8978         
8979                         case 'CSHPPIFONT':
8980                         case 'HP-PI-FONT':
8981                                 return 'HP-Pi-font';
8982         
8983                         case 'HZ-GB-2312':
8984                                 return 'HZ-GB-2312';
8985         
8986                         case 'CSIBMSYMBOLS':
8987                         case 'IBM-SYMBOLS':
8988                                 return 'IBM-Symbols';
8989         
8990                         case 'CSIBMTHAI':
8991                         case 'IBM-THAI':
8992                                 return 'IBM-Thai';
8993         
8994                         case 'CCSID00858':
8995                         case 'CP00858':
8996                         case 'IBM00858':
8997                         case 'PC-MULTILINGUAL-850+EURO':
8998                                 return 'IBM00858';
8999         
9000                         case 'CCSID00924':
9001                         case 'CP00924':
9002                         case 'EBCDIC-LATIN9--EURO':
9003                         case 'IBM00924':
9004                                 return 'IBM00924';
9005         
9006                         case 'CCSID01140':
9007                         case 'CP01140':
9008                         case 'EBCDIC-US-37+EURO':
9009                         case 'IBM01140':
9010                                 return 'IBM01140';
9011         
9012                         case 'CCSID01141':
9013                         case 'CP01141':
9014                         case 'EBCDIC-DE-273+EURO':
9015                         case 'IBM01141':
9016                                 return 'IBM01141';
9017         
9018                         case 'CCSID01142':
9019                         case 'CP01142':
9020                         case 'EBCDIC-DK-277+EURO':
9021                         case 'EBCDIC-NO-277+EURO':
9022                         case 'IBM01142':
9023                                 return 'IBM01142';
9024         
9025                         case 'CCSID01143':
9026                         case 'CP01143':
9027                         case 'EBCDIC-FI-278+EURO':
9028                         case 'EBCDIC-SE-278+EURO':
9029                         case 'IBM01143':
9030                                 return 'IBM01143';
9031         
9032                         case 'CCSID01144':
9033                         case 'CP01144':
9034                         case 'EBCDIC-IT-280+EURO':
9035                         case 'IBM01144':
9036                                 return 'IBM01144';
9037         
9038                         case 'CCSID01145':
9039                         case 'CP01145':
9040                         case 'EBCDIC-ES-284+EURO':
9041                         case 'IBM01145':
9042                                 return 'IBM01145';
9043         
9044                         case 'CCSID01146':
9045                         case 'CP01146':
9046                         case 'EBCDIC-GB-285+EURO':
9047                         case 'IBM01146':
9048                                 return 'IBM01146';
9049         
9050                         case 'CCSID01147':
9051                         case 'CP01147':
9052                         case 'EBCDIC-FR-297+EURO':
9053                         case 'IBM01147':
9054                                 return 'IBM01147';
9055         
9056                         case 'CCSID01148':
9057                         case 'CP01148':
9058                         case 'EBCDIC-INTERNATIONAL-500+EURO':
9059                         case 'IBM01148':
9060                                 return 'IBM01148';
9061         
9062                         case 'CCSID01149':
9063                         case 'CP01149':
9064                         case 'EBCDIC-IS-871+EURO':
9065                         case 'IBM01149':
9066                                 return 'IBM01149';
9067         
9068                         case 'CP037':
9069                         case 'CSIBM037':
9070                         case 'EBCDIC-CP-CA':
9071                         case 'EBCDIC-CP-NL':
9072                         case 'EBCDIC-CP-US':
9073                         case 'EBCDIC-CP-WT':
9074                         case 'IBM037':
9075                                 return 'IBM037';
9076         
9077                         case 'CP038':
9078                         case 'CSIBM038':
9079                         case 'EBCDIC-INT':
9080                         case 'IBM038':
9081                                 return 'IBM038';
9082         
9083                         case 'CP1026':
9084                         case 'CSIBM1026':
9085                         case 'IBM1026':
9086                                 return 'IBM1026';
9087         
9088                         case 'IBM-1047':
9089                         case 'IBM1047':
9090                                 return 'IBM1047';
9091         
9092                         case 'CP273':
9093                         case 'CSIBM273':
9094                         case 'IBM273':
9095                                 return 'IBM273';
9096         
9097                         case 'CP274':
9098                         case 'CSIBM274':
9099                         case 'EBCDIC-BE':
9100                         case 'IBM274':
9101                                 return 'IBM274';
9102         
9103                         case 'CP275':
9104                         case 'CSIBM275':
9105                         case 'EBCDIC-BR':
9106                         case 'IBM275':
9107                                 return 'IBM275';
9108         
9109                         case 'CSIBM277':
9110                         case 'EBCDIC-CP-DK':
9111                         case 'EBCDIC-CP-NO':
9112                         case 'IBM277':
9113                                 return 'IBM277';
9114         
9115                         case 'CP278':
9116                         case 'CSIBM278':
9117                         case 'EBCDIC-CP-FI':
9118                         case 'EBCDIC-CP-SE':
9119                         case 'IBM278':
9120                                 return 'IBM278';
9121         
9122                         case 'CP280':
9123                         case 'CSIBM280':
9124                         case 'EBCDIC-CP-IT':
9125                         case 'IBM280':
9126                                 return 'IBM280';
9127         
9128                         case 'CP281':
9129                         case 'CSIBM281':
9130                         case 'EBCDIC-JP-E':
9131                         case 'IBM281':
9132                                 return 'IBM281';
9133         
9134                         case 'CP284':
9135                         case 'CSIBM284':
9136                         case 'EBCDIC-CP-ES':
9137                         case 'IBM284':
9138                                 return 'IBM284';
9139         
9140                         case 'CP285':
9141                         case 'CSIBM285':
9142                         case 'EBCDIC-CP-GB':
9143                         case 'IBM285':
9144                                 return 'IBM285';
9145         
9146                         case 'CP290':
9147                         case 'CSIBM290':
9148                         case 'EBCDIC-JP-KANA':
9149                         case 'IBM290':
9150                                 return 'IBM290';
9151         
9152                         case 'CP297':
9153                         case 'CSIBM297':
9154                         case 'EBCDIC-CP-FR':
9155                         case 'IBM297':
9156                                 return 'IBM297';
9157         
9158                         case 'CP420':
9159                         case 'CSIBM420':
9160                         case 'EBCDIC-CP-AR1':
9161                         case 'IBM420':
9162                                 return 'IBM420';
9163         
9164                         case 'CP423':
9165                         case 'CSIBM423':
9166                         case 'EBCDIC-CP-GR':
9167                         case 'IBM423':
9168                                 return 'IBM423';
9169         
9170                         case 'CP424':
9171                         case 'CSIBM424':
9172                         case 'EBCDIC-CP-HE':
9173                         case 'IBM424':
9174                                 return 'IBM424';
9175         
9176                         case '437':
9177                         case 'CP437':
9178                         case 'CSPC8CODEPAGE437':
9179                         case 'IBM437':
9180                                 return 'IBM437';
9181         
9182                         case 'CP500':
9183                         case 'CSIBM500':
9184                         case 'EBCDIC-CP-BE':
9185                         case 'EBCDIC-CP-CH':
9186                         case 'IBM500':
9187                                 return 'IBM500';
9188         
9189                         case 'CP775':
9190                         case 'CSPC775BALTIC':
9191                         case 'IBM775':
9192                                 return 'IBM775';
9193         
9194                         case '850':
9195                         case 'CP850':
9196                         case 'CSPC850MULTILINGUAL':
9197                         case 'IBM850':
9198                                 return 'IBM850';
9199         
9200                         case '851':
9201                         case 'CP851':
9202                         case 'CSIBM851':
9203                         case 'IBM851':
9204                                 return 'IBM851';
9205         
9206                         case '852':
9207                         case 'CP852':
9208                         case 'CSPCP852':
9209                         case 'IBM852':
9210                                 return 'IBM852';
9211         
9212                         case '855':
9213                         case 'CP855':
9214                         case 'CSIBM855':
9215                         case 'IBM855':
9216                                 return 'IBM855';
9217         
9218                         case '857':
9219                         case 'CP857':
9220                         case 'CSIBM857':
9221                         case 'IBM857':
9222                                 return 'IBM857';
9223         
9224                         case '860':
9225                         case 'CP860':
9226                         case 'CSIBM860':
9227                         case 'IBM860':
9228                                 return 'IBM860';
9229         
9230                         case '861':
9231                         case 'CP-IS':
9232                         case 'CP861':
9233                         case 'CSIBM861':
9234                         case 'IBM861':
9235                                 return 'IBM861';
9236         
9237                         case '862':
9238                         case 'CP862':
9239                         case 'CSPC862LATINHEBREW':
9240                         case 'IBM862':
9241                                 return 'IBM862';
9242         
9243                         case '863':
9244                         case 'CP863':
9245                         case 'CSIBM863':
9246                         case 'IBM863':
9247                                 return 'IBM863';
9248         
9249                         case 'CP864':
9250                         case 'CSIBM864':
9251                         case 'IBM864':
9252                                 return 'IBM864';
9253         
9254                         case '865':
9255                         case 'CP865':
9256                         case 'CSIBM865':
9257                         case 'IBM865':
9258                                 return 'IBM865';
9259         
9260                         case '866':
9261                         case 'CP866':
9262                         case 'CSIBM866':
9263                         case 'IBM866':
9264                                 return 'IBM866';
9265         
9266                         case 'CP-AR':
9267                         case 'CP868':
9268                         case 'CSIBM868':
9269                         case 'IBM868':
9270                                 return 'IBM868';
9271         
9272                         case '869':
9273                         case 'CP-GR':
9274                         case 'CP869':
9275                         case 'CSIBM869':
9276                         case 'IBM869':
9277                                 return 'IBM869';
9278         
9279                         case 'CP870':
9280                         case 'CSIBM870':
9281                         case 'EBCDIC-CP-ROECE':
9282                         case 'EBCDIC-CP-YU':
9283                         case 'IBM870':
9284                                 return 'IBM870';
9285         
9286                         case 'CP871':
9287                         case 'CSIBM871':
9288                         case 'EBCDIC-CP-IS':
9289                         case 'IBM871':
9290                                 return 'IBM871';
9291         
9292                         case 'CP880':
9293                         case 'CSIBM880':
9294                         case 'EBCDIC-CYRILLIC':
9295                         case 'IBM880':
9296                                 return 'IBM880';
9297         
9298                         case 'CP891':
9299                         case 'CSIBM891':
9300                         case 'IBM891':
9301                                 return 'IBM891';
9302         
9303                         case 'CP903':
9304                         case 'CSIBM903':
9305                         case 'IBM903':
9306                                 return 'IBM903';
9307         
9308                         case '904':
9309                         case 'CP904':
9310                         case 'CSIBBM904':
9311                         case 'IBM904':
9312                                 return 'IBM904';
9313         
9314                         case 'CP905':
9315                         case 'CSIBM905':
9316                         case 'EBCDIC-CP-TR':
9317                         case 'IBM905':
9318                                 return 'IBM905';
9319         
9320                         case 'CP918':
9321                         case 'CSIBM918':
9322                         case 'EBCDIC-CP-AR2':
9323                         case 'IBM918':
9324                                 return 'IBM918';
9325         
9326                         case 'CSISO143IECP271':
9327                         case 'IEC_P27-1':
9328                         case 'ISO-IR-143':
9329                                 return 'IEC_P27-1';
9330         
9331                         case 'CSISO49INIS':
9332                         case 'INIS':
9333                         case 'ISO-IR-49':
9334                                 return 'INIS';
9335         
9336                         case 'CSISO50INIS8':
9337                         case 'INIS-8':
9338                         case 'ISO-IR-50':
9339                                 return 'INIS-8';
9340         
9341                         case 'CSISO51INISCYRILLIC':
9342                         case 'INIS-CYRILLIC':
9343                         case 'ISO-IR-51':
9344                                 return 'INIS-cyrillic';
9345         
9346                         case 'CSINVARIANT':
9347                         case 'INVARIANT':
9348                                 return 'INVARIANT';
9349         
9350                         case 'ISO-10646-J-1':
9351                                 return 'ISO-10646-J-1';
9352         
9353                         case 'CSUNICODE':
9354                         case 'ISO-10646-UCS-2':
9355                                 return 'ISO-10646-UCS-2';
9356         
9357                         case 'CSUCS4':
9358                         case 'ISO-10646-UCS-4':
9359                                 return 'ISO-10646-UCS-4';
9360         
9361                         case 'CSUNICODEASCII':
9362                         case 'ISO-10646-UCS-BASIC':
9363                                 return 'ISO-10646-UCS-Basic';
9364         
9365                         case 'CSISO10646UTF1':
9366                         case 'ISO-10646-UTF-1':
9367                                 return 'ISO-10646-UTF-1';
9368         
9369                         case 'CSUNICODELATIN1':
9370                         case 'ISO-10646':
9371                         case 'ISO-10646-UNICODE-LATIN1':
9372                                 return 'ISO-10646-Unicode-Latin1';
9373         
9374                         case 'CSISO115481':
9375                         case 'ISO-11548-1':
9376                         case 'ISO_11548-1':
9377                         case 'ISO_TR_11548-1':
9378                                 return 'ISO-11548-1';
9379         
9380                         case 'ISO-2022-CN':
9381                                 return 'ISO-2022-CN';
9382         
9383                         case 'ISO-2022-CN-EXT':
9384                                 return 'ISO-2022-CN-EXT';
9385         
9386                         case 'CSISO2022JP':
9387                         case 'ISO-2022-JP':
9388                                 return 'ISO-2022-JP';
9389         
9390                         case 'CSISO2022JP2':
9391                         case 'ISO-2022-JP-2':
9392                                 return 'ISO-2022-JP-2';
9393         
9394                         case 'CSISO2022KR':
9395                         case 'ISO-2022-KR':
9396                                 return 'ISO-2022-KR';
9397         
9398                         case 'CSWINDOWS30LATIN1':
9399                         case 'ISO-8859-1-WINDOWS-3.0-LATIN-1':
9400                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
9401         
9402                         case 'CSWINDOWS31LATIN1':
9403                         case 'ISO-8859-1-WINDOWS-3.1-LATIN-1':
9404                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
9405         
9406                         case 'CSISOLATIN6':
9407                         case 'ISO-8859-10':
9408                         case 'ISO-IR-157':
9409                         case 'ISO_8859-10:1992':
9410                         case 'L6':
9411                         case 'LATIN6':
9412                                 return 'ISO-8859-10';
9413         
9414                         case 'ISO-8859-13':
9415                                 return 'ISO-8859-13';
9416         
9417                         case 'ISO-8859-14':
9418                         case 'ISO-CELTIC':
9419                         case 'ISO-IR-199':
9420                         case 'ISO_8859-14':
9421                         case 'ISO_8859-14:1998':
9422                         case 'L8':
9423                         case 'LATIN8':
9424                                 return 'ISO-8859-14';
9425         
9426                         case 'ISO-8859-15':
9427                         case 'ISO_8859-15':
9428                         case 'LATIN-9':
9429                                 return 'ISO-8859-15';
9430         
9431                         case 'ISO-8859-16':
9432                         case 'ISO-IR-226':
9433                         case 'ISO_8859-16':
9434                         case 'ISO_8859-16:2001':
9435                         case 'L10':
9436                         case 'LATIN10':
9437                                 return 'ISO-8859-16';
9438         
9439                         case 'CSISOLATIN2':
9440                         case 'ISO-8859-2':
9441                         case 'ISO-IR-101':
9442                         case 'ISO_8859-2':
9443                         case 'ISO_8859-2:1987':
9444                         case 'L2':
9445                         case 'LATIN2':
9446                                 return 'ISO-8859-2';
9447         
9448                         case 'CSWINDOWS31LATIN2':
9449                         case 'ISO-8859-2-WINDOWS-LATIN-2':
9450                                 return 'ISO-8859-2-Windows-Latin-2';
9451         
9452                         case 'CSISOLATIN3':
9453                         case 'ISO-8859-3':
9454                         case 'ISO-IR-109':
9455                         case 'ISO_8859-3':
9456                         case 'ISO_8859-3:1988':
9457                         case 'L3':
9458                         case 'LATIN3':
9459                                 return 'ISO-8859-3';
9460         
9461                         case 'CSISOLATIN4':
9462                         case 'ISO-8859-4':
9463                         case 'ISO-IR-110':
9464                         case 'ISO_8859-4':
9465                         case 'ISO_8859-4:1988':
9466                         case 'L4':
9467                         case 'LATIN4':
9468                                 return 'ISO-8859-4';
9469         
9470                         case 'CSISOLATINCYRILLIC':
9471                         case 'CYRILLIC':
9472                         case 'ISO-8859-5':
9473                         case 'ISO-IR-144':
9474                         case 'ISO_8859-5':
9475                         case 'ISO_8859-5:1988':
9476                                 return 'ISO-8859-5';
9477         
9478                         case 'ARABIC':
9479                         case 'ASMO-708':
9480                         case 'CSISOLATINARABIC':
9481                         case 'ECMA-114':
9482                         case 'ISO-8859-6':
9483                         case 'ISO-IR-127':
9484                         case 'ISO_8859-6':
9485                         case 'ISO_8859-6:1987':
9486                                 return 'ISO-8859-6';
9487         
9488                         case 'CSISO88596E':
9489                         case 'ISO-8859-6-E':
9490                         case 'ISO_8859-6-E':
9491                                 return 'ISO-8859-6-E';
9492         
9493                         case 'CSISO88596I':
9494                         case 'ISO-8859-6-I':
9495                         case 'ISO_8859-6-I':
9496                                 return 'ISO-8859-6-I';
9497         
9498                         case 'CSISOLATINGREEK':
9499                         case 'ECMA-118':
9500                         case 'ELOT_928':
9501                         case 'GREEK':
9502                         case 'GREEK8':
9503                         case 'ISO-8859-7':
9504                         case 'ISO-IR-126':
9505                         case 'ISO_8859-7':
9506                         case 'ISO_8859-7:1987':
9507                                 return 'ISO-8859-7';
9508         
9509                         case 'CSISOLATINHEBREW':
9510                         case 'HEBREW':
9511                         case 'ISO-8859-8':
9512                         case 'ISO-IR-138':
9513                         case 'ISO_8859-8':
9514                         case 'ISO_8859-8:1988':
9515                                 return 'ISO-8859-8';
9516         
9517                         case 'CSISO88598E':
9518                         case 'ISO-8859-8-E':
9519                         case 'ISO_8859-8-E':
9520                                 return 'ISO-8859-8-E';
9521         
9522                         case 'CSISO88598I':
9523                         case 'ISO-8859-8-I':
9524                         case 'ISO_8859-8-I':
9525                                 return 'ISO-8859-8-I';
9526         
9527                         case 'CSISOLATIN5':
9528                         case 'ISO-8859-9':
9529                         case 'ISO-IR-148':
9530                         case 'ISO_8859-9':
9531                         case 'ISO_8859-9:1989':
9532                         case 'L5':
9533                         case 'LATIN5':
9534                                 return 'ISO-8859-9';
9535         
9536                         case 'CSWINDOWS31LATIN5':
9537                         case 'ISO-8859-9-WINDOWS-LATIN-5':
9538                                 return 'ISO-8859-9-Windows-Latin-5';
9539         
9540                         case 'CSUNICODEIBM1261':
9541                         case 'ISO-UNICODE-IBM-1261':
9542                                 return 'ISO-Unicode-IBM-1261';
9543         
9544                         case 'CSUNICODEIBM1264':
9545                         case 'ISO-UNICODE-IBM-1264':
9546                                 return 'ISO-Unicode-IBM-1264';
9547         
9548                         case 'CSUNICODEIBM1265':
9549                         case 'ISO-UNICODE-IBM-1265':
9550                                 return 'ISO-Unicode-IBM-1265';
9551         
9552                         case 'CSUNICODEIBM1268':
9553                         case 'ISO-UNICODE-IBM-1268':
9554                                 return 'ISO-Unicode-IBM-1268';
9555         
9556                         case 'CSUNICODEIBM1276':
9557                         case 'ISO-UNICODE-IBM-1276':
9558                                 return 'ISO-Unicode-IBM-1276';
9559         
9560                         case 'CSISO10367BOX':
9561                         case 'ISO-IR-155':
9562                         case 'ISO_10367-BOX':
9563                                 return 'ISO_10367-box';
9564         
9565                         case 'CSISO2033':
9566                         case 'E13B':
9567                         case 'ISO-IR-98':
9568                         case 'ISO_2033-1983':
9569                                 return 'ISO_2033-1983';
9570         
9571                         case 'CSISO5427CYRILLIC':
9572                         case 'ISO-IR-37':
9573                         case 'ISO_5427':
9574                                 return 'ISO_5427';
9575         
9576                         case 'ISO-IR-54':
9577                         case 'ISO5427CYRILLIC1981':
9578                         case 'ISO_5427:1981':
9579                                 return 'ISO_5427:1981';
9580         
9581                         case 'CSISO5428GREEK':
9582                         case 'ISO-IR-55':
9583                         case 'ISO_5428:1980':
9584                                 return 'ISO_5428:1980';
9585         
9586                         case 'CSISO646BASIC1983':
9587                         case 'ISO_646.BASIC:1983':
9588                         case 'REF':
9589                                 return 'ISO_646.basic:1983';
9590         
9591                         case 'CSISO2INTLREFVERSION':
9592                         case 'IRV':
9593                         case 'ISO-IR-2':
9594                         case 'ISO_646.IRV:1983':
9595                                 return 'ISO_646.irv:1983';
9596         
9597                         case 'CSISO6937ADD':
9598                         case 'ISO-IR-152':
9599                         case 'ISO_6937-2-25':
9600                                 return 'ISO_6937-2-25';
9601         
9602                         case 'CSISOTEXTCOMM':
9603                         case 'ISO-IR-142':
9604                         case 'ISO_6937-2-ADD':
9605                                 return 'ISO_6937-2-add';
9606         
9607                         case 'CSISO8859SUPP':
9608                         case 'ISO-IR-154':
9609                         case 'ISO_8859-SUPP':
9610                         case 'LATIN1-2-5':
9611                                 return 'ISO_8859-supp';
9612         
9613                         case 'CSISO15ITALIAN':
9614                         case 'ISO-IR-15':
9615                         case 'ISO646-IT':
9616                         case 'IT':
9617                                 return 'IT';
9618         
9619                         case 'CSISO13JISC6220JP':
9620                         case 'ISO-IR-13':
9621                         case 'JIS_C6220-1969':
9622                         case 'JIS_C6220-1969-JP':
9623                         case 'KATAKANA':
9624                         case 'X0201-7':
9625                                 return 'JIS_C6220-1969-jp';
9626         
9627                         case 'CSISO14JISC6220RO':
9628                         case 'ISO-IR-14':
9629                         case 'ISO646-JP':
9630                         case 'JIS_C6220-1969-RO':
9631                         case 'JP':
9632                                 return 'JIS_C6220-1969-ro';
9633         
9634                         case 'CSISO42JISC62261978':
9635                         case 'ISO-IR-42':
9636                         case 'JIS_C6226-1978':
9637                                 return 'JIS_C6226-1978';
9638         
9639                         case 'CSISO87JISX0208':
9640                         case 'ISO-IR-87':
9641                         case 'JIS_C6226-1983':
9642                         case 'JIS_X0208-1983':
9643                         case 'X0208':
9644                                 return 'JIS_C6226-1983';
9645         
9646                         case 'CSISO91JISC62291984A':
9647                         case 'ISO-IR-91':
9648                         case 'JIS_C6229-1984-A':
9649                         case 'JP-OCR-A':
9650                                 return 'JIS_C6229-1984-a';
9651         
9652                         case 'CSISO92JISC62991984B':
9653                         case 'ISO-IR-92':
9654                         case 'ISO646-JP-OCR-B':
9655                         case 'JIS_C6229-1984-B':
9656                         case 'JP-OCR-B':
9657                                 return 'JIS_C6229-1984-b';
9658         
9659                         case 'CSISO93JIS62291984BADD':
9660                         case 'ISO-IR-93':
9661                         case 'JIS_C6229-1984-B-ADD':
9662                         case 'JP-OCR-B-ADD':
9663                                 return 'JIS_C6229-1984-b-add';
9664         
9665                         case 'CSISO94JIS62291984HAND':
9666                         case 'ISO-IR-94':
9667                         case 'JIS_C6229-1984-HAND':
9668                         case 'JP-OCR-HAND':
9669                                 return 'JIS_C6229-1984-hand';
9670         
9671                         case 'CSISO95JIS62291984HANDADD':
9672                         case 'ISO-IR-95':
9673                         case 'JIS_C6229-1984-HAND-ADD':
9674                         case 'JP-OCR-HAND-ADD':
9675                                 return 'JIS_C6229-1984-hand-add';
9676         
9677                         case 'CSISO96JISC62291984KANA':
9678                         case 'ISO-IR-96':
9679                         case 'JIS_C6229-1984-KANA':
9680                                 return 'JIS_C6229-1984-kana';
9681         
9682                         case 'CSJISENCODING':
9683                         case 'JIS_ENCODING':
9684                                 return 'JIS_Encoding';
9685         
9686                         case 'CSHALFWIDTHKATAKANA':
9687                         case 'JIS_X0201':
9688                         case 'X0201':
9689                                 return 'JIS_X0201';
9690         
9691                         case 'CSISO159JISX02121990':
9692                         case 'ISO-IR-159':
9693                         case 'JIS_X0212-1990':
9694                         case 'X0212':
9695                                 return 'JIS_X0212-1990';
9696         
9697                         case 'CSISO141JUSIB1002':
9698                         case 'ISO-IR-141':
9699                         case 'ISO646-YU':
9700                         case 'JS':
9701                         case 'JUS_I.B1.002':
9702                         case 'YU':
9703                                 return 'JUS_I.B1.002';
9704         
9705                         case 'CSISO147MACEDONIAN':
9706                         case 'ISO-IR-147':
9707                         case 'JUS_I.B1.003-MAC':
9708                         case 'MACEDONIAN':
9709                                 return 'JUS_I.B1.003-mac';
9710         
9711                         case 'CSISO146SERBIAN':
9712                         case 'ISO-IR-146':
9713                         case 'JUS_I.B1.003-SERB':
9714                         case 'SERBIAN':
9715                                 return 'JUS_I.B1.003-serb';
9716         
9717                         case 'KOI7-SWITCHED':
9718                                 return 'KOI7-switched';
9719         
9720                         case 'CSKOI8R':
9721                         case 'KOI8-R':
9722                                 return 'KOI8-R';
9723         
9724                         case 'KOI8-U':
9725                                 return 'KOI8-U';
9726         
9727                         case 'CSKSC5636':
9728                         case 'ISO646-KR':
9729                         case 'KSC5636':
9730                                 return 'KSC5636';
9731         
9732                         case 'CSKSC56011987':
9733                         case 'ISO-IR-149':
9734                         case 'KOREAN':
9735                         case 'KSC_5601':
9736                         case 'KS_C_5601-1987':
9737                         case 'KS_C_5601-1989':
9738                                 return 'KS_C_5601-1987';
9739         
9740                         case 'CSKZ1048':
9741                         case 'KZ-1048':
9742                         case 'RK1048':
9743                         case 'STRK1048-2002':
9744                                 return 'KZ-1048';
9745         
9746                         case 'CSISO27LATINGREEK1':
9747                         case 'ISO-IR-27':
9748                         case 'LATIN-GREEK-1':
9749                                 return 'Latin-greek-1';
9750         
9751                         case 'CSMNEM':
9752                         case 'MNEM':
9753                                 return 'MNEM';
9754         
9755                         case 'CSMNEMONIC':
9756                         case 'MNEMONIC':
9757                                 return 'MNEMONIC';
9758         
9759                         case 'CSISO86HUNGARIAN':
9760                         case 'HU':
9761                         case 'ISO-IR-86':
9762                         case 'ISO646-HU':
9763                         case 'MSZ_7795.3':
9764                                 return 'MSZ_7795.3';
9765         
9766                         case 'CSMICROSOFTPUBLISHING':
9767                         case 'MICROSOFT-PUBLISHING':
9768                                 return 'Microsoft-Publishing';
9769         
9770                         case 'CSNATSDANO':
9771                         case 'ISO-IR-9-1':
9772                         case 'NATS-DANO':
9773                                 return 'NATS-DANO';
9774         
9775                         case 'CSNATSDANOADD':
9776                         case 'ISO-IR-9-2':
9777                         case 'NATS-DANO-ADD':
9778                                 return 'NATS-DANO-ADD';
9779         
9780                         case 'CSNATSSEFI':
9781                         case 'ISO-IR-8-1':
9782                         case 'NATS-SEFI':
9783                                 return 'NATS-SEFI';
9784         
9785                         case 'CSNATSSEFIADD':
9786                         case 'ISO-IR-8-2':
9787                         case 'NATS-SEFI-ADD':
9788                                 return 'NATS-SEFI-ADD';
9789         
9790                         case 'CSISO151CUBA':
9791                         case 'CUBA':
9792                         case 'ISO-IR-151':
9793                         case 'ISO646-CU':
9794                         case 'NC_NC00-10:81':
9795                                 return 'NC_NC00-10:81';
9796         
9797                         case 'CSISO69FRENCH':
9798                         case 'FR':
9799                         case 'ISO-IR-69':
9800                         case 'ISO646-FR':
9801                         case 'NF_Z_62-010':
9802                                 return 'NF_Z_62-010';
9803         
9804                         case 'CSISO25FRENCH':
9805                         case 'ISO-IR-25':
9806                         case 'ISO646-FR1':
9807                         case 'NF_Z_62-010_(1973)':
9808                                 return 'NF_Z_62-010_(1973)';
9809         
9810                         case 'CSISO60DANISHNORWEGIAN':
9811                         case 'CSISO60NORWEGIAN1':
9812                         case 'ISO-IR-60':
9813                         case 'ISO646-NO':
9814                         case 'NO':
9815                         case 'NS_4551-1':
9816                                 return 'NS_4551-1';
9817         
9818                         case 'CSISO61NORWEGIAN2':
9819                         case 'ISO-IR-61':
9820                         case 'ISO646-NO2':
9821                         case 'NO2':
9822                         case 'NS_4551-2':
9823                                 return 'NS_4551-2';
9824         
9825                         case 'OSD_EBCDIC_DF03_IRV':
9826                                 return 'OSD_EBCDIC_DF03_IRV';
9827         
9828                         case 'OSD_EBCDIC_DF04_1':
9829                                 return 'OSD_EBCDIC_DF04_1';
9830         
9831                         case 'OSD_EBCDIC_DF04_15':
9832                                 return 'OSD_EBCDIC_DF04_15';
9833         
9834                         case 'CSPC8DANISHNORWEGIAN':
9835                         case 'PC8-DANISH-NORWEGIAN':
9836                                 return 'PC8-Danish-Norwegian';
9837         
9838                         case 'CSPC8TURKISH':
9839                         case 'PC8-TURKISH':
9840                                 return 'PC8-Turkish';
9841         
9842                         case 'CSISO16PORTUGUESE':
9843                         case 'ISO-IR-16':
9844                         case 'ISO646-PT':
9845                         case 'PT':
9846                                 return 'PT';
9847         
9848                         case 'CSISO84PORTUGUESE2':
9849                         case 'ISO-IR-84':
9850                         case 'ISO646-PT2':
9851                         case 'PT2':
9852                                 return 'PT2';
9853         
9854                         case 'CP154':
9855                         case 'CSPTCP154':
9856                         case 'CYRILLIC-ASIAN':
9857                         case 'PT154':
9858                         case 'PTCP154':
9859                                 return 'PTCP154';
9860         
9861                         case 'SCSU':
9862                                 return 'SCSU';
9863         
9864                         case 'CSISO10SWEDISH':
9865                         case 'FI':
9866                         case 'ISO-IR-10':
9867                         case 'ISO646-FI':
9868                         case 'ISO646-SE':
9869                         case 'SE':
9870                         case 'SEN_850200_B':
9871                                 return 'SEN_850200_B';
9872         
9873                         case 'CSISO11SWEDISHFORNAMES':
9874                         case 'ISO-IR-11':
9875                         case 'ISO646-SE2':
9876                         case 'SE2':
9877                         case 'SEN_850200_C':
9878                                 return 'SEN_850200_C';
9879         
9880                         case 'CSSHIFTJIS':
9881                         case 'MS_KANJI':
9882                         case 'SHIFT_JIS':
9883                                 return 'Shift_JIS';
9884         
9885                         case 'CSISO128T101G2':
9886                         case 'ISO-IR-128':
9887                         case 'T.101-G2':
9888                                 return 'T.101-G2';
9889         
9890                         case 'CSISO102T617BIT':
9891                         case 'ISO-IR-102':
9892                         case 'T.61-7BIT':
9893                                 return 'T.61-7bit';
9894         
9895                         case 'CSISO103T618BIT':
9896                         case 'ISO-IR-103':
9897                         case 'T.61':
9898                         case 'T.61-8BIT':
9899                                 return 'T.61-8bit';
9900         
9901                         case 'CSTSCII':
9902                         case 'TSCII':
9903                                 return 'TSCII';
9904         
9905                         case 'CSUNICODE11':
9906                         case 'UNICODE-1-1':
9907                                 return 'UNICODE-1-1';
9908         
9909                         case 'CSUNICODE11UTF7':
9910                         case 'UNICODE-1-1-UTF-7':
9911                                 return 'UNICODE-1-1-UTF-7';
9912         
9913                         case 'CSUNKNOWN8BIT':
9914                         case 'UNKNOWN-8BIT':
9915                                 return 'UNKNOWN-8BIT';
9916         
9917                         case 'ANSI':
9918                         case 'ANSI_X3.4-1968':
9919                         case 'ANSI_X3.4-1986':
9920                         case 'ASCII':
9921                         case 'CP367':
9922                         case 'CSASCII':
9923                         case 'IBM367':
9924                         case 'ISO-IR-6':
9925                         case 'ISO646-US':
9926                         case 'ISO_646.IRV:1991':
9927                         case 'US':
9928                         case 'US-ASCII':
9929                                 return 'US-ASCII';
9930         
9931                         case 'UTF-16':
9932                                 return 'UTF-16';
9933         
9934                         case 'UTF-16BE':
9935                                 return 'UTF-16BE';
9936         
9937                         case 'UTF-16LE':
9938                                 return 'UTF-16LE';
9939         
9940                         case 'UTF-32':
9941                                 return 'UTF-32';
9942         
9943                         case 'UTF-32BE':
9944                                 return 'UTF-32BE';
9945         
9946                         case 'UTF-32LE':
9947                                 return 'UTF-32LE';
9948         
9949                         case 'UTF-7':
9950                                 return 'UTF-7';
9951         
9952                         case 'UTF-8':
9953                                 return 'UTF-8';
9954         
9955                         case 'CSVIQR':
9956                         case 'VIQR':
9957                                 return 'VIQR';
9958         
9959                         case 'CSVISCII':
9960                         case 'VISCII':
9961                                 return 'VISCII';
9962         
9963                         case 'CSVENTURAINTERNATIONAL':
9964                         case 'VENTURA-INTERNATIONAL':
9965                                 return 'Ventura-International';
9966         
9967                         case 'CSVENTURAMATH':
9968                         case 'VENTURA-MATH':
9969                                 return 'Ventura-Math';
9970         
9971                         case 'CSVENTURAUS':
9972                         case 'VENTURA-US':
9973                                 return 'Ventura-US';
9974         
9975                         case 'CSWINDOWS31J':
9976                         case 'WINDOWS-31J':
9977                                 return 'Windows-31J';
9978         
9979                         case 'CSDKUS':
9980                         case 'DK-US':
9981                                 return 'dk-us';
9982         
9983                         case 'CSISO150':
9984                         case 'CSISO150GREEKCCITT':
9985                         case 'GREEK-CCITT':
9986                         case 'ISO-IR-150':
9987                                 return 'greek-ccitt';
9988         
9989                         case 'CSISO88GREEK7':
9990                         case 'GREEK7':
9991                         case 'ISO-IR-88':
9992                                 return 'greek7';
9993         
9994                         case 'CSISO18GREEK7OLD':
9995                         case 'GREEK7-OLD':
9996                         case 'ISO-IR-18':
9997                                 return 'greek7-old';
9998         
9999                         case 'CSHPROMAN8':
10000                         case 'HP-ROMAN8':
10001                         case 'R8':
10002                         case 'ROMAN8':
10003                                 return 'hp-roman8';
10004         
10005                         case 'CSISO90':
10006                         case 'ISO-IR-90':
10007                                 return 'iso-ir-90';
10008         
10009                         case 'CSISO19LATINGREEK':
10010                         case 'ISO-IR-19':
10011                         case 'LATIN-GREEK':
10012                                 return 'latin-greek';
10013         
10014                         case 'CSISO158LAP':
10015                         case 'ISO-IR-158':
10016                         case 'LAP':
10017                         case 'LATIN-LAP':
10018                                 return 'latin-lap';
10019         
10020                         case 'CSMACINTOSH':
10021                         case 'MAC':
10022                         case 'MACINTOSH':
10023                                 return 'macintosh';
10024         
10025                         case 'CSUSDK':
10026                         case 'US-DK':
10027                                 return 'us-dk';
10028         
10029                         case 'CSISO70VIDEOTEXSUPP1':
10030                         case 'ISO-IR-70':
10031                         case 'VIDEOTEX-SUPPL':
10032                                 return 'videotex-suppl';
10033         
10034                         case 'WINDOWS-1250':
10035                                 return 'windows-1250';
10036         
10037                         case 'WINDOWS-1251':
10038                                 return 'windows-1251';
10039         
10040                         case 'CP819':
10041                         case 'CSISOLATIN1':
10042                         case 'IBM819':
10043                         case 'ISO-8859-1':
10044                         case 'ISO-IR-100':
10045                         case 'ISO_8859-1':
10046                         case 'ISO_8859-1:1987':
10047                         case 'L1':
10048                         case 'LATIN1':
10049                         case 'WINDOWS-1252':
10050                                 return 'windows-1252';
10051         
10052                         case 'WINDOWS-1253':
10053                                 return 'windows-1253';
10054         
10055                         case 'WINDOWS-1254':
10056                                 return 'windows-1254';
10057         
10058                         case 'WINDOWS-1255':
10059                                 return 'windows-1255';
10060         
10061                         case 'WINDOWS-1256':
10062                                 return 'windows-1256';
10063         
10064                         case 'WINDOWS-1257':
10065                                 return 'windows-1257';
10066         
10067                         case 'WINDOWS-1258':
10068                                 return 'windows-1258';
10069         
10070                         default:
10071                                 return $encoding;
10072                 }
10073         }
10074
10075         function get_curl_version()
10076         {
10077                 if (is_array($curl = curl_version()))
10078                 {
10079                         $curl = $curl['version'];
10080                 }
10081                 elseif (substr($curl, 0, 5) == 'curl/')
10082                 {
10083                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10084                 }
10085                 elseif (substr($curl, 0, 8) == 'libcurl/')
10086                 {
10087                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10088                 }
10089                 else
10090                 {
10091                         $curl = 0;
10092                 }
10093                 return $curl;
10094         }
10095
10096         function is_subclass_of($class1, $class2)
10097         {
10098                 if (func_num_args() != 2)
10099                 {
10100                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10101                 }
10102                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10103                 {
10104                         return is_subclass_of($class1, $class2);
10105                 }
10106                 elseif (is_string($class1) && is_string($class2))
10107                 {
10108                         if (class_exists($class1))
10109                         {
10110                                 if (class_exists($class2))
10111                                 {
10112                                         $class2 = strtolower($class2);
10113                                         while ($class1 = strtolower(get_parent_class($class1)))
10114                                         {
10115                                                 if ($class1 == $class2)
10116                                                 {
10117                                                         return true;
10118                                                 }
10119                                         }
10120                                 }
10121                         }
10122                         else
10123                         {
10124                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10125                         }
10126                 }
10127                 return false;
10128         }
10129
10130         /**
10131          * Strip HTML comments
10132          *
10133          * @access public
10134          * @param string $data Data to strip comments from
10135          * @return string Comment stripped string
10136          */
10137         function strip_comments($data)
10138         {
10139                 $output = '';
10140                 while (($start = strpos($data, '<!--')) !== false)
10141                 {
10142                         $output .= substr($data, 0, $start);
10143                         if (($end = strpos($data, '-->', $start)) !== false)
10144                         {
10145                                 $data = substr_replace($data, '', 0, $end + 3);
10146                         }
10147                         else
10148                         {
10149                                 $data = '';
10150                         }
10151                 }
10152                 return $output . $data;
10153         }
10154
10155         function parse_date($dt)
10156         {
10157                 $parser = SimplePie_Parse_Date::get();
10158                 return $parser->parse($dt);
10159         }
10160
10161         /**
10162          * Decode HTML entities
10163          *
10164          * @static
10165          * @access public
10166          * @param string $data Input data
10167          * @return string Output data
10168          */
10169         function entities_decode($data)
10170         {
10171                 $decoder = new SimplePie_Decode_HTML_Entities($data);
10172                 return $decoder->parse();
10173         }
10174
10175         /**
10176          * Remove RFC822 comments
10177          *
10178          * @access public
10179          * @param string $data Data to strip comments from
10180          * @return string Comment stripped string
10181          */
10182         function uncomment_rfc822($string)
10183         {
10184                 $string = (string) $string;
10185                 $position = 0;
10186                 $length = strlen($string);
10187                 $depth = 0;
10188                 
10189                 $output = '';
10190                 
10191                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10192                 {
10193                         $output .= substr($string, $position, $pos - $position);
10194                         $position = $pos + 1;
10195                         if ($string[$pos - 1] !== '\\')
10196                         {
10197                                 $depth++;
10198                                 while ($depth && $position < $length)
10199                                 {
10200                                         $position += strcspn($string, '()', $position);
10201                                         if ($string[$position - 1] === '\\')
10202                                         {
10203                                                 $position++;
10204                                                 continue;
10205                                         }
10206                                         elseif (isset($string[$position]))
10207                                         {
10208                                                 switch ($string[$position])
10209                                                 {
10210                                                         case '(':
10211                                                                 $depth++;
10212                                                                 break;
10213                                                         
10214                                                         case ')':
10215                                                                 $depth--;
10216                                                                 break;
10217                                                 }
10218                                                 $position++;
10219                                         }
10220                                         else
10221                                         {
10222                                                 break;
10223                                         }
10224                                 }
10225                         }
10226                         else
10227                         {
10228                                 $output .= '(';
10229                         }
10230                 }
10231                 $output .= substr($string, $position);
10232                 
10233                 return $output;
10234         }
10235
10236         function parse_mime($mime)
10237         {
10238                 if (($pos = strpos($mime, ';')) === false)
10239                 {
10240                         return trim($mime);
10241                 }
10242                 else
10243                 {
10244                         return trim(substr($mime, 0, $pos));
10245                 }
10246         }
10247
10248         function htmlspecialchars_decode($string, $quote_style)
10249         {
10250                 if (function_exists('htmlspecialchars_decode'))
10251                 {
10252                         return htmlspecialchars_decode($string, $quote_style);
10253                 }
10254                 else
10255                 {
10256                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10257                 }
10258         }
10259
10260         function atom_03_construct_type($attribs)
10261         {
10262                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) == 'base64'))
10263                 {
10264                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10265                 }
10266                 else
10267                 {
10268                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
10269                 }
10270                 if (isset($attribs['']['type']))
10271                 {
10272                         switch (strtolower(trim($attribs['']['type'])))
10273                         {
10274                                 case 'text':
10275                                 case 'text/plain':
10276                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10277
10278                                 case 'html':
10279                                 case 'text/html':
10280                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10281
10282                                 case 'xhtml':
10283                                 case 'application/xhtml+xml':
10284                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10285
10286                                 default:
10287                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10288                         }
10289                 }
10290                 else
10291                 {
10292                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10293                 }
10294         }
10295
10296         function atom_10_construct_type($attribs)
10297         {
10298                 if (isset($attribs['']['type']))
10299                 {
10300                         switch (strtolower(trim($attribs['']['type'])))
10301                         {
10302                                 case 'text':
10303                                         return SIMPLEPIE_CONSTRUCT_TEXT;
10304
10305                                 case 'html':
10306                                         return SIMPLEPIE_CONSTRUCT_HTML;
10307
10308                                 case 'xhtml':
10309                                         return SIMPLEPIE_CONSTRUCT_XHTML;
10310
10311                                 default:
10312                                         return SIMPLEPIE_CONSTRUCT_NONE;
10313                         }
10314                 }
10315                 return SIMPLEPIE_CONSTRUCT_TEXT;
10316         }
10317
10318         function atom_10_content_construct_type($attribs)
10319         {
10320                 if (isset($attribs['']['type']))
10321                 {
10322                         $type = strtolower(trim($attribs['']['type']));
10323                         switch ($type)
10324                         {
10325                                 case 'text':
10326                                         return SIMPLEPIE_CONSTRUCT_TEXT;
10327
10328                                 case 'html':
10329                                         return SIMPLEPIE_CONSTRUCT_HTML;
10330
10331                                 case 'xhtml':
10332                                         return SIMPLEPIE_CONSTRUCT_XHTML;
10333                         }
10334                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) == 'text/')
10335                         {
10336                                 return SIMPLEPIE_CONSTRUCT_NONE;
10337                         }
10338                         else
10339                         {
10340                                 return SIMPLEPIE_CONSTRUCT_BASE64;
10341                         }
10342                 }
10343                 else
10344                 {
10345                         return SIMPLEPIE_CONSTRUCT_TEXT;
10346                 }
10347         }
10348
10349         function is_isegment_nz_nc($string)
10350         {
10351                 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);
10352         }
10353
10354         function space_seperated_tokens($string)
10355         {
10356                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
10357                 $string_length = strlen($string);
10358
10359                 $position = strspn($string, $space_characters);
10360                 $tokens = array();
10361
10362                 while ($position < $string_length)
10363                 {
10364                         $len = strcspn($string, $space_characters, $position);
10365                         $tokens[] = substr($string, $position, $len);
10366                         $position += $len;
10367                         $position += strspn($string, $space_characters, $position);
10368                 }
10369
10370                 return $tokens;
10371         }
10372
10373         function array_unique($array)
10374         {
10375                 if (version_compare(PHP_VERSION, '5.2', '>='))
10376                 {
10377                         return array_unique($array);
10378                 }
10379                 else
10380                 {
10381                         $array = (array) $array;
10382                         $new_array = array();
10383                         $new_array_strings = array();
10384                         foreach ($array as $key => $value)
10385                         {
10386                                 if (is_object($value))
10387                                 {
10388                                         if (method_exists($value, '__toString'))
10389                                         {
10390                                                 $cmp = $value->__toString();
10391                                         }
10392                                         else
10393                                         {
10394                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
10395                                         }
10396                                 }
10397                                 elseif (is_array($value))
10398                                 {
10399                                         $cmp = (string) reset($value);
10400                                 }
10401                                 else
10402                                 {
10403                                         $cmp = (string) $value;
10404                                 }
10405                                 if (!in_array($cmp, $new_array_strings))
10406                                 {
10407                                         $new_array[$key] = $value;
10408                                         $new_array_strings[] = $cmp;
10409                                 }
10410                         }
10411                         return $new_array;
10412                 }
10413         }
10414
10415         /**
10416          * Converts a unicode codepoint to a UTF-8 character
10417          *
10418          * @static
10419          * @access public
10420          * @param int $codepoint Unicode codepoint
10421          * @return string UTF-8 character
10422          */
10423         function codepoint_to_utf8($codepoint)
10424         {
10425                 static $cache = array();
10426                 $codepoint = (int) $codepoint;
10427                 if (isset($cache[$codepoint]))
10428                 {
10429                         return $cache[$codepoint];
10430                 }
10431                 elseif ($codepoint < 0)
10432                 {
10433                         return $cache[$codepoint] = false;
10434                 }
10435                 else if ($codepoint <= 0x7f)
10436                 {
10437                         return $cache[$codepoint] = chr($codepoint);
10438                 }
10439                 else if ($codepoint <= 0x7ff)
10440                 {
10441                         return $cache[$codepoint] = chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
10442                 }
10443                 else if ($codepoint <= 0xffff)
10444                 {
10445                         return $cache[$codepoint] = chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
10446                 }
10447                 else if ($codepoint <= 0x10ffff)
10448                 {
10449                         return $cache[$codepoint] = chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
10450                 }
10451                 else
10452                 {
10453                         // U+FFFD REPLACEMENT CHARACTER
10454                         return $cache[$codepoint] = "\xEF\xBF\xBD";
10455                 }
10456         }
10457
10458         /**
10459          * Re-implementation of PHP 5's stripos()
10460          *
10461          * Returns the numeric position of the first occurrence of needle in the
10462          * haystack string.
10463          *
10464          * @static
10465          * @access string
10466          * @param object $haystack
10467          * @param string $needle Note that the needle may be a string of one or more
10468          *     characters. If needle is not a string, it is converted to an integer
10469          *     and applied as the ordinal value of a character.
10470          * @param int $offset The optional offset parameter allows you to specify which
10471          *     character in haystack to start searching. The position returned is still
10472          *     relative to the beginning of haystack.
10473          * @return bool If needle is not found, stripos() will return boolean false.
10474          */
10475         function stripos($haystack, $needle, $offset = 0)
10476         {
10477                 if (function_exists('stripos'))
10478                 {
10479                         return stripos($haystack, $needle, $offset);
10480                 }
10481                 else
10482                 {
10483                         if (is_string($needle))
10484                         {
10485                                 $needle = strtolower($needle);
10486                         }
10487                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
10488                         {
10489                                 $needle = strtolower(chr($needle));
10490                         }
10491                         else
10492                         {
10493                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
10494                                 return false;
10495                         }
10496         
10497                         return strpos(strtolower($haystack), $needle, $offset);
10498                 }
10499         }
10500
10501         /**
10502          * Similar to parse_str()
10503          *
10504          * Returns an associative array of name/value pairs, where the value is an
10505          * array of values that have used the same name
10506          *
10507          * @static
10508          * @access string
10509          * @param string $str The input string.
10510          * @return array
10511          */
10512         function parse_str($str)
10513         {
10514                 $return = array();
10515                 $str = explode('&', $str);
10516
10517                 foreach ($str as $section)
10518                 {
10519                         if (strpos($section, '=') !== false)
10520                         {
10521                                 list($name, $value) = explode('=', $section, 2);
10522                                 $return[urldecode($name)][] = urldecode($value);
10523                         }
10524                         else
10525                         {
10526                                 $return[urldecode($section)][] = null;
10527                         }
10528                 }
10529
10530                 return $return;
10531         }
10532         
10533         /**
10534          * Detect XML encoding, as per XML 1.0 Appendix F.1
10535          *
10536          * @todo Add support for EBCDIC
10537          * @param string $data XML data
10538          * @return array Possible encodings
10539          */
10540         function xml_encoding($data)
10541         {
10542                 // UTF-32 Big Endian BOM
10543                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
10544                 {
10545                         $encoding[] = 'UTF-32BE';
10546                 }
10547                 // UTF-32 Little Endian BOM
10548                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
10549                 {
10550                         $encoding[] = 'UTF-32LE';
10551                 }
10552                 // UTF-16 Big Endian BOM
10553                 elseif (substr($data, 0, 2) === "\xFE\xFF")
10554                 {
10555                         $encoding[] = 'UTF-16BE';
10556                 }
10557                 // UTF-16 Little Endian BOM
10558                 elseif (substr($data, 0, 2) === "\xFF\xFE")
10559                 {
10560                         $encoding[] = 'UTF-16LE';
10561                 }
10562                 // UTF-8 BOM
10563                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
10564                 {
10565                         $encoding[] = 'UTF-8';
10566                 }
10567                 // UTF-32 Big Endian Without BOM
10568                 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")
10569                 {
10570                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
10571                         {
10572                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
10573                                 if ($parser->parse())
10574                                 {
10575                                         $encoding[] = $parser->encoding;
10576                                 }
10577                         }
10578                         $encoding[] = 'UTF-32BE';
10579                 }
10580                 // UTF-32 Little Endian Without BOM
10581                 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")
10582                 {
10583                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
10584                         {
10585                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
10586                                 if ($parser->parse())
10587                                 {
10588                                         $encoding[] = $parser->encoding;
10589                                 }
10590                         }
10591                         $encoding[] = 'UTF-32LE';
10592                 }
10593                 // UTF-16 Big Endian Without BOM
10594                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
10595                 {
10596                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
10597                         {
10598                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
10599                                 if ($parser->parse())
10600                                 {
10601                                         $encoding[] = $parser->encoding;
10602                                 }
10603                         }
10604                         $encoding[] = 'UTF-16BE';
10605                 }
10606                 // UTF-16 Little Endian Without BOM
10607                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
10608                 {
10609                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
10610                         {
10611                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
10612                                 if ($parser->parse())
10613                                 {
10614                                         $encoding[] = $parser->encoding;
10615                                 }
10616                         }
10617                         $encoding[] = 'UTF-16LE';
10618                 }
10619                 // US-ASCII (or superset)
10620                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
10621                 {
10622                         if ($pos = strpos($data, "\x3F\x3E"))
10623                         {
10624                                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
10625                                 if ($parser->parse())
10626                                 {
10627                                         $encoding[] = $parser->encoding;
10628                                 }
10629                         }
10630                         $encoding[] = 'UTF-8';
10631                 }
10632                 // Fallback to UTF-8
10633                 else
10634                 {
10635                         $encoding[] = 'UTF-8';
10636                 }
10637                 return $encoding;
10638         }
10639 }
10640
10641 /**
10642  * Decode HTML Entities
10643  *
10644  * This implements HTML5 as of revision 967 (2007-06-28)
10645  *
10646  * @package SimplePie
10647  */
10648 class SimplePie_Decode_HTML_Entities
10649 {
10650         /**
10651          * Data to be parsed
10652          *
10653          * @access private
10654          * @var string
10655          */
10656         var $data = '';
10657
10658         /**
10659          * Currently consumed bytes
10660          *
10661          * @access private
10662          * @var string
10663          */
10664         var $consumed = '';
10665
10666         /**
10667          * Position of the current byte being parsed
10668          *
10669          * @access private
10670          * @var int
10671          */
10672         var $position = 0;
10673
10674         /**
10675          * Create an instance of the class with the input data
10676          *
10677          * @access public
10678          * @param string $data Input data
10679          */
10680         function SimplePie_Decode_HTML_Entities($data)
10681         {
10682                 $this->data = $data;
10683         }
10684
10685         /**
10686          * Parse the input data
10687          *
10688          * @access public
10689          * @return string Output data
10690          */
10691         function parse()
10692         {
10693                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
10694                 {
10695                         $this->consume();
10696                         $this->entity();
10697                         $this->consumed = '';
10698                 }
10699                 return $this->data;
10700         }
10701
10702         /**
10703          * Consume the next byte
10704          *
10705          * @access private
10706          * @return mixed The next byte, or false, if there is no more data
10707          */
10708         function consume()
10709         {
10710                 if (isset($this->data[$this->position]))
10711                 {
10712                         $this->consumed .= $this->data[$this->position];
10713                         return $this->data[$this->position++];
10714                 }
10715                 else
10716                 {
10717                         $this->consumed = false;
10718                         return false;
10719                 }
10720         }
10721
10722         /**
10723          * Consume a range of characters
10724          *
10725          * @access private
10726          * @param string $chars Characters to consume
10727          * @return mixed A series of characters that match the range, or false
10728          */
10729         function consume_range($chars)
10730         {
10731                 if ($len = strspn($this->data, $chars, $this->position))
10732                 {
10733                         $data = substr($this->data, $this->position, $len);
10734                         $this->consumed .= $data;
10735                         $this->position += $len;
10736                         return $data;
10737                 }
10738                 else
10739                 {
10740                         $this->consumed = false;
10741                         return false;
10742                 }
10743         }
10744
10745         /**
10746          * Unconsume one byte
10747          *
10748          * @access private
10749          */
10750         function unconsume()
10751         {
10752                 $this->consumed = substr($this->consumed, 0, -1);
10753                 $this->position--;
10754         }
10755
10756         /**
10757          * Decode an entity
10758          *
10759          * @access private
10760          */
10761         function entity()
10762         {
10763                 switch ($this->consume())
10764                 {
10765                         case "\x09":
10766                         case "\x0A":
10767                         case "\x0B":
10768                         case "\x0B":
10769                         case "\x0C":
10770                         case "\x20":
10771                         case "\x3C":
10772                         case "\x26":
10773                         case false:
10774                                 break;
10775
10776                         case "\x23":
10777                                 switch ($this->consume())
10778                                 {
10779                                         case "\x78":
10780                                         case "\x58":
10781                                                 $range = '0123456789ABCDEFabcdef';
10782                                                 $hex = true;
10783                                                 break;
10784
10785                                         default:
10786                                                 $range = '0123456789';
10787                                                 $hex = false;
10788                                                 $this->unconsume();
10789                                                 break;
10790                                 }
10791
10792                                 if ($codepoint = $this->consume_range($range))
10793                                 {
10794                                         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");
10795
10796                                         if ($hex)
10797                                         {
10798                                                 $codepoint = hexdec($codepoint);
10799                                         }
10800                                         else
10801                                         {
10802                                                 $codepoint = intval($codepoint);
10803                                         }
10804
10805                                         if (isset($windows_1252_specials[$codepoint]))
10806                                         {
10807                                                 $replacement = $windows_1252_specials[$codepoint];
10808                                         }
10809                                         else
10810                                         {
10811                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
10812                                         }
10813
10814                                         if ($this->consume() != ';')
10815                                         {
10816                                                 $this->unconsume();
10817                                         }
10818
10819                                         $consumed_length = strlen($this->consumed);
10820                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
10821                                         $this->position += strlen($replacement) - $consumed_length;
10822                                 }
10823                                 break;
10824
10825                         default:
10826                                 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");
10827
10828                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
10829                                 {
10830                                         $consumed = substr($this->consumed, 1);
10831                                         if (isset($entities[$consumed]))
10832                                         {
10833                                                 $match = $consumed;
10834                                         }
10835                                 }
10836
10837                                 if ($match !== null)
10838                                 {
10839                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
10840                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
10841                                 }
10842                                 break;
10843                 }
10844         }
10845 }
10846
10847 /**
10848  * Date Parser
10849  *
10850  * @package SimplePie
10851  */
10852 class SimplePie_Parse_Date
10853 {
10854         /**
10855          * Input data
10856          *
10857          * @access protected
10858          * @var string
10859          */
10860         var $date;
10861
10862         /**
10863          * List of days, calendar day name => ordinal day number in the week
10864          *
10865          * @access protected
10866          * @var array
10867          */
10868         var $day = array(
10869                 // English
10870                 'mon' => 1,
10871                 'monday' => 1,
10872                 'tue' => 2,
10873                 'tuesday' => 2,
10874                 'wed' => 3,
10875                 'wednesday' => 3,
10876                 'thu' => 4,
10877                 'thursday' => 4,
10878                 'fri' => 5,
10879                 'friday' => 5,
10880                 'sat' => 6,
10881                 'saturday' => 6,
10882                 'sun' => 7,
10883                 'sunday' => 7,
10884                 // Dutch
10885                 'maandag' => 1,
10886                 'dinsdag' => 2,
10887                 'woensdag' => 3,
10888                 'donderdag' => 4,
10889                 'vrijdag' => 5,
10890                 'zaterdag' => 6,
10891                 'zondag' => 7,
10892                 // French
10893                 'lundi' => 1,
10894                 'mardi' => 2,
10895                 'mercredi' => 3,
10896                 'jeudi' => 4,
10897                 'vendredi' => 5,
10898                 'samedi' => 6,
10899                 'dimanche' => 7,
10900                 // German
10901                 'montag' => 1,
10902                 'dienstag' => 2,
10903                 'mittwoch' => 3,
10904                 'donnerstag' => 4,
10905                 'freitag' => 5,
10906                 'samstag' => 6,
10907                 'sonnabend' => 6,
10908                 'sonntag' => 7,
10909                 // Italian
10910                 'lunedì' => 1,
10911                 'martedì' => 2,
10912                 'mercoledì' => 3,
10913                 'giovedì' => 4,
10914                 'venerdì' => 5,
10915                 'sabato' => 6,
10916                 'domenica' => 7,
10917                 // Spanish
10918                 'lunes' => 1,
10919                 'martes' => 2,
10920                 'miércoles' => 3,
10921                 'jueves' => 4,
10922                 'viernes' => 5,
10923                 'sábado' => 6,
10924                 'domingo' => 7,
10925                 // Finnish
10926                 'maanantai' => 1,
10927                 'tiistai' => 2,
10928                 'keskiviikko' => 3,
10929                 'torstai' => 4,
10930                 'perjantai' => 5,
10931                 'lauantai' => 6,
10932                 'sunnuntai' => 7,
10933                 // Hungarian
10934                 'hétfő' => 1,
10935                 'kedd' => 2,
10936                 'szerda' => 3,
10937                 'csütörtok' => 4,
10938                 'péntek' => 5,
10939                 'szombat' => 6,
10940                 'vasárnap' => 7,
10941                 // Greek
10942                 'Δευ' => 1,
10943                 'Τρι' => 2,
10944                 'Τετ' => 3,
10945                 'Πεμ' => 4,
10946                 'Παρ' => 5,
10947                 'Σαβ' => 6,
10948                 'Κυρ' => 7,
10949         );
10950
10951         /**
10952          * List of months, calendar month name => calendar month number
10953          *
10954          * @access protected
10955          * @var array
10956          */
10957         var $month = array(
10958                 // English
10959                 'jan' => 1,
10960                 'january' => 1,
10961                 'feb' => 2,
10962                 'february' => 2,
10963                 'mar' => 3,
10964                 'march' => 3,
10965                 'apr' => 4,
10966                 'april' => 4,
10967                 'may' => 5,
10968                 // No long form of May
10969                 'jun' => 6,
10970                 'june' => 6,
10971                 'jul' => 7,
10972                 'july' => 7,
10973                 'aug' => 8,
10974                 'august' => 8,
10975                 'sep' => 9,
10976                 'september' => 8,
10977                 'oct' => 10,
10978                 'october' => 10,
10979                 'nov' => 11,
10980                 'november' => 11,
10981                 'dec' => 12,
10982                 'december' => 12,
10983                 // Dutch
10984                 'januari' => 1,
10985                 'februari' => 2,
10986                 'maart' => 3,
10987                 'april' => 4,
10988                 'mei' => 5,
10989                 'juni' => 6,
10990                 'juli' => 7,
10991                 'augustus' => 8,
10992                 'september' => 9,
10993                 'oktober' => 10,
10994                 'november' => 11,
10995                 'december' => 12,
10996                 // French
10997                 'janvier' => 1,
10998                 'février' => 2,
10999                 'mars' => 3,
11000                 'avril' => 4,
11001                 'mai' => 5,
11002                 'juin' => 6,
11003                 'juillet' => 7,
11004                 'août' => 8,
11005                 'septembre' => 9,
11006                 'octobre' => 10,
11007                 'novembre' => 11,
11008                 'décembre' => 12,
11009                 // German
11010                 'januar' => 1,
11011                 'februar' => 2,
11012                 'märz' => 3,
11013                 'april' => 4,
11014                 'mai' => 5,
11015                 'juni' => 6,
11016                 'juli' => 7,
11017                 'august' => 8,
11018                 'september' => 9,
11019                 'oktober' => 10,
11020                 'november' => 11,
11021                 'dezember' => 12,
11022                 // Italian
11023                 'gennaio' => 1,
11024                 'febbraio' => 2,
11025                 'marzo' => 3,
11026                 'aprile' => 4,
11027                 'maggio' => 5,
11028                 'giugno' => 6,
11029                 'luglio' => 7,
11030                 'agosto' => 8,
11031                 'settembre' => 9,
11032                 'ottobre' => 10,
11033                 'novembre' => 11,
11034                 'dicembre' => 12,
11035                 // Spanish
11036                 'enero' => 1,
11037                 'febrero' => 2,
11038                 'marzo' => 3,
11039                 'abril' => 4,
11040                 'mayo' => 5,
11041                 'junio' => 6,
11042                 'julio' => 7,
11043                 'agosto' => 8,
11044                 'septiembre' => 9,
11045                 'setiembre' => 9,
11046                 'octubre' => 10,
11047                 'noviembre' => 11,
11048                 'diciembre' => 12,
11049                 // Finnish
11050                 'tammikuu' => 1,
11051                 'helmikuu' => 2,
11052                 'maaliskuu' => 3,
11053                 'huhtikuu' => 4,
11054                 'toukokuu' => 5,
11055                 'kesäkuu' => 6,
11056                 'heinäkuu' => 7,
11057                 'elokuu' => 8,
11058                 'suuskuu' => 9,
11059                 'lokakuu' => 10,
11060                 'marras' => 11,
11061                 'joulukuu' => 12,
11062                 // Hungarian
11063                 'január' => 1,
11064                 'február' => 2,
11065                 'március' => 3,
11066                 'április' => 4,
11067                 'május' => 5,
11068                 'június' => 6,
11069                 'július' => 7,
11070                 'augusztus' => 8,
11071                 'szeptember' => 9,
11072                 'október' => 10,
11073                 'november' => 11,
11074                 'december' => 12,
11075                 // Greek
11076                 'Ιαν' => 1,
11077                 'Φεβ' => 2,
11078                 'Μάώ' => 3,
11079                 'Μαώ' => 3,
11080                 'Απρ' => 4,
11081                 'Μάι' => 5,
11082                 'Μαϊ' => 5,
11083                 'Μαι' => 5,
11084                 'Ιούν' => 6,
11085                 'Ιον' => 6,
11086                 'Ιούλ' => 7,
11087                 'Ιολ' => 7,
11088                 'Αύγ' => 8,
11089                 'Αυγ' => 8,
11090                 'Σεπ' => 9,
11091                 'Οκτ' => 10,
11092                 'Νοέ' => 11,
11093                 'Δεκ' => 12,
11094         );
11095
11096         /**
11097          * List of timezones, abbreviation => offset from UTC
11098          *
11099          * @access protected
11100          * @var array
11101          */
11102         var $timezone = array(
11103                 'ACDT' => 37800,
11104                 'ACIT' => 28800,
11105                 'ACST' => 34200,
11106                 'ACT' => -18000,
11107                 'ACWDT' => 35100,
11108                 'ACWST' => 31500,
11109                 'AEDT' => 39600,
11110                 'AEST' => 36000,
11111                 'AFT' => 16200,
11112                 'AKDT' => -28800,
11113                 'AKST' => -32400,
11114                 'AMDT' => 18000,
11115                 'AMT' => -14400,
11116                 'ANAST' => 46800,
11117                 'ANAT' => 43200,
11118                 'ART' => -10800,
11119                 'AZOST' => -3600,
11120                 'AZST' => 18000,
11121                 'AZT' => 14400,
11122                 'BIOT' => 21600,
11123                 'BIT' => -43200,
11124                 'BOT' => -14400,
11125                 'BRST' => -7200,
11126                 'BRT' => -10800,
11127                 'BST' => 3600,
11128                 'BTT' => 21600,
11129                 'CAST' => 18000,
11130                 'CAT' => 7200,
11131                 'CCT' => 23400,
11132                 'CDT' => -18000,
11133                 'CEDT' => 7200,
11134                 'CET' => 3600,
11135                 'CGST' => -7200,
11136                 'CGT' => -10800,
11137                 'CHADT' => 49500,
11138                 'CHAST' => 45900,
11139                 'CIST' => -28800,
11140                 'CKT' => -36000,
11141                 'CLDT' => -10800,
11142                 'CLST' => -14400,
11143                 'COT' => -18000,
11144                 'CST' => -21600,
11145                 'CVT' => -3600,
11146                 'CXT' => 25200,
11147                 'DAVT' => 25200,
11148                 'DTAT' => 36000,
11149                 'EADT' => -18000,
11150                 'EAST' => -21600,
11151                 'EAT' => 10800,
11152                 'ECT' => -18000,
11153                 'EDT' => -14400,
11154                 'EEST' => 10800,
11155                 'EET' => 7200,
11156                 'EGT' => -3600,
11157                 'EKST' => 21600,
11158                 'EST' => -18000,
11159                 'FJT' => 43200,
11160                 'FKDT' => -10800,
11161                 'FKST' => -14400,
11162                 'FNT' => -7200,
11163                 'GALT' => -21600,
11164                 'GEDT' => 14400,
11165                 'GEST' => 10800,
11166                 'GFT' => -10800,
11167                 'GILT' => 43200,
11168                 'GIT' => -32400,
11169                 'GST' => 14400,
11170                 'GST' => -7200,
11171                 'GYT' => -14400,
11172                 'HAA' => -10800,
11173                 'HAC' => -18000,
11174                 'HADT' => -32400,
11175                 'HAE' => -14400,
11176                 'HAP' => -25200,
11177                 'HAR' => -21600,
11178                 'HAST' => -36000,
11179                 'HAT' => -9000,
11180                 'HAY' => -28800,
11181                 'HKST' => 28800,
11182                 'HMT' => 18000,
11183                 'HNA' => -14400,
11184                 'HNC' => -21600,
11185                 'HNE' => -18000,
11186                 'HNP' => -28800,
11187                 'HNR' => -25200,
11188                 'HNT' => -12600,
11189                 'HNY' => -32400,
11190                 'IRDT' => 16200,
11191                 'IRKST' => 32400,
11192                 'IRKT' => 28800,
11193                 'IRST' => 12600,
11194                 'JFDT' => -10800,
11195                 'JFST' => -14400,
11196                 'JST' => 32400,
11197                 'KGST' => 21600,
11198                 'KGT' => 18000,
11199                 'KOST' => 39600,
11200                 'KOVST' => 28800,
11201                 'KOVT' => 25200,
11202                 'KRAST' => 28800,
11203                 'KRAT' => 25200,
11204                 'KST' => 32400,
11205                 'LHDT' => 39600,
11206                 'LHST' => 37800,
11207                 'LINT' => 50400,
11208                 'LKT' => 21600,
11209                 'MAGST' => 43200,
11210                 'MAGT' => 39600,
11211                 'MAWT' => 21600,
11212                 'MDT' => -21600,
11213                 'MESZ' => 7200,
11214                 'MEZ' => 3600,
11215                 'MHT' => 43200,
11216                 'MIT' => -34200,
11217                 'MNST' => 32400,
11218                 'MSDT' => 14400,
11219                 'MSST' => 10800,
11220                 'MST' => -25200,
11221                 'MUT' => 14400,
11222                 'MVT' => 18000,
11223                 'MYT' => 28800,
11224                 'NCT' => 39600,
11225                 'NDT' => -9000,
11226                 'NFT' => 41400,
11227                 'NMIT' => 36000,
11228                 'NOVST' => 25200,
11229                 'NOVT' => 21600,
11230                 'NPT' => 20700,
11231                 'NRT' => 43200,
11232                 'NST' => -12600,
11233                 'NUT' => -39600,
11234                 'NZDT' => 46800,
11235                 'NZST' => 43200,
11236                 'OMSST' => 25200,
11237                 'OMST' => 21600,
11238                 'PDT' => -25200,
11239                 'PET' => -18000,
11240                 'PETST' => 46800,
11241                 'PETT' => 43200,
11242                 'PGT' => 36000,
11243                 'PHOT' => 46800,
11244                 'PHT' => 28800,
11245                 'PKT' => 18000,
11246                 'PMDT' => -7200,
11247                 'PMST' => -10800,
11248                 'PONT' => 39600,
11249                 'PST' => -28800,
11250                 'PWT' => 32400,
11251                 'PYST' => -10800,
11252                 'PYT' => -14400,
11253                 'RET' => 14400,
11254                 'ROTT' => -10800,
11255                 'SAMST' => 18000,
11256                 'SAMT' => 14400,
11257                 'SAST' => 7200,
11258                 'SBT' => 39600,
11259                 'SCDT' => 46800,
11260                 'SCST' => 43200,
11261                 'SCT' => 14400,
11262                 'SEST' => 3600,
11263                 'SGT' => 28800,
11264                 'SIT' => 28800,
11265                 'SRT' => -10800,
11266                 'SST' => -39600,
11267                 'SYST' => 10800,
11268                 'SYT' => 7200,
11269                 'TFT' => 18000,
11270                 'THAT' => -36000,
11271                 'TJT' => 18000,
11272                 'TKT' => -36000,
11273                 'TMT' => 18000,
11274                 'TOT' => 46800,
11275                 'TPT' => 32400,
11276                 'TRUT' => 36000,
11277                 'TVT' => 43200,
11278                 'TWT' => 28800,
11279                 'UYST' => -7200,
11280                 'UYT' => -10800,
11281                 'UZT' => 18000,
11282                 'VET' => -14400,
11283                 'VLAST' => 39600,
11284                 'VLAT' => 36000,
11285                 'VOST' => 21600,
11286                 'VUT' => 39600,
11287                 'WAST' => 7200,
11288                 'WAT' => 3600,
11289                 'WDT' => 32400,
11290                 'WEST' => 3600,
11291                 'WFT' => 43200,
11292                 'WIB' => 25200,
11293                 'WIT' => 32400,
11294                 'WITA' => 28800,
11295                 'WKST' => 18000,
11296                 'WST' => 28800,
11297                 'YAKST' => 36000,
11298                 'YAKT' => 32400,
11299                 'YAPT' => 36000,
11300                 'YEKST' => 21600,
11301                 'YEKT' => 18000,
11302         );
11303
11304         /**
11305          * Cached PCRE for SimplePie_Parse_Date::$day
11306          *
11307          * @access protected
11308          * @var string
11309          */
11310         var $day_pcre;
11311
11312         /**
11313          * Cached PCRE for SimplePie_Parse_Date::$month
11314          *
11315          * @access protected
11316          * @var string
11317          */
11318         var $month_pcre;
11319
11320         /**
11321          * Array of user-added callback methods
11322          *
11323          * @access private
11324          * @var array
11325          */
11326         var $built_in = array();
11327
11328         /**
11329          * Array of user-added callback methods
11330          *
11331          * @access private
11332          * @var array
11333          */
11334         var $user = array();
11335
11336         /**
11337          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
11338          * self::month_pcre, and self::built_in
11339          *
11340          * @access private
11341          */
11342         function SimplePie_Parse_Date()
11343         {
11344                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
11345                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
11346                 
11347                 static $cache;
11348                 if (!isset($cache[get_class($this)]))
11349                 {
11350                         if (extension_loaded('Reflection'))
11351                         {
11352                                 $class = new ReflectionClass(get_class($this));
11353                                 $methods = $class->getMethods();
11354                                 $all_methods = array();
11355                                 foreach ($methods as $method)
11356                                 {
11357                                         $all_methods[] = $method->getName();
11358                                 }
11359                         }
11360                         else
11361                         {
11362                                 $all_methods = get_class_methods($this);
11363                         }
11364                 
11365                         foreach ($all_methods as $method)
11366                         {
11367                                 if (strtolower(substr($method, 0, 5)) === 'date_')
11368                                 {
11369                                         $cache[get_class($this)][] = $method;
11370                                 }
11371                         }
11372                 }
11373                 
11374                 foreach ($cache[get_class($this)] as $method)
11375                 {
11376                         $this->built_in[] = $method;
11377                 }
11378         }
11379         
11380         /**
11381          * Get the object
11382          *
11383          * @access public
11384          */
11385         function get()
11386         {
11387                 static $object;
11388                 if (!$object)
11389                 {
11390                         $object = new SimplePie_Parse_Date;
11391                 }
11392                 return $object;
11393         }
11394
11395         /**
11396          * Parse a date
11397          *
11398          * @final
11399          * @access public
11400          * @param string $date Date to parse
11401          * @return int Timestamp corresponding to date string, or false on failure
11402          */
11403         function parse($date)
11404         {
11405                 foreach ($this->user as $method)
11406                 {
11407                         if (($returned = call_user_func($method, $date)) !== false)
11408                         {
11409                                 return $returned;
11410                         }
11411                 }
11412                 
11413                 foreach ($this->built_in as $method)
11414                 {
11415                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
11416                         {
11417                                 return $returned;
11418                         }
11419                 }
11420
11421                 return false;
11422         }
11423
11424         /**
11425          * Add a callback method to parse a date
11426          *
11427          * @final
11428          * @access public
11429          * @param callback $callback
11430          */
11431         function add_callback($callback)
11432         {
11433                 if (is_callable($callback))
11434                 {
11435                         $this->user[] = $callback;
11436                 }
11437                 else
11438                 {
11439                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
11440                 }
11441         }
11442
11443         /**
11444          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
11445          * well as allowing any of upper or lower case "T", horizontal tabs, or
11446          * spaces to be used as the time seperator (including more than one))
11447          *
11448          * @access protected
11449          * @return int Timestamp
11450          */
11451         function date_w3cdtf($date)
11452         {
11453                 static $pcre;
11454                 if (!$pcre)
11455                 {
11456                         $year = '([0-9]{4})';
11457                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
11458                         $decimal = '([0-9]*)';
11459                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
11460                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
11461                 }
11462                 if (preg_match($pcre, $date, $match))
11463                 {
11464                         /*
11465                         Capturing subpatterns:
11466                         1: Year
11467                         2: Month
11468                         3: Day
11469                         4: Hour
11470                         5: Minute
11471                         6: Second
11472                         7: Decimal fraction of a second
11473                         8: Zulu
11474                         9: Timezone ±
11475                         10: Timezone hours
11476                         11: Timezone minutes
11477                         */
11478
11479                         // Fill in empty matches
11480                         for ($i = count($match); $i <= 3; $i++)
11481                         {
11482                                 $match[$i] = '1';
11483                         }
11484
11485                         for ($i = count($match); $i <= 7; $i++)
11486                         {
11487                                 $match[$i] = '0';
11488                         }
11489
11490                         // Numeric timezone
11491                         if (isset($match[9]) && $match[9] !== '')
11492                         {
11493                                 $timezone = $match[10] * 3600;
11494                                 $timezone += $match[11] * 60;
11495                                 if ($match[9] === '-')
11496                                 {
11497                                         $timezone = 0 - $timezone;
11498                                 }
11499                         }
11500                         else
11501                         {
11502                                 $timezone = 0;
11503                         }
11504
11505                         // Convert the number of seconds to an integer, taking decimals into account
11506                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
11507
11508                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
11509                 }
11510                 else
11511                 {
11512                         return false;
11513                 }
11514         }
11515
11516         /**
11517          * Remove RFC822 comments
11518          *
11519          * @access protected
11520          * @param string $data Data to strip comments from
11521          * @return string Comment stripped string
11522          */
11523         function remove_rfc2822_comments($string)
11524         {
11525                 $string = (string) $string;
11526                 $position = 0;
11527                 $length = strlen($string);
11528                 $depth = 0;
11529
11530                 $output = '';
11531
11532                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11533                 {
11534                         $output .= substr($string, $position, $pos - $position);
11535                         $position = $pos + 1;
11536                         if ($string[$pos - 1] !== '\\')
11537                         {
11538                                 $depth++;
11539                                 while ($depth && $position < $length)
11540                                 {
11541                                         $position += strcspn($string, '()', $position);
11542                                         if ($string[$position - 1] === '\\')
11543                                         {
11544                                                 $position++;
11545                                                 continue;
11546                                         }
11547                                         elseif (isset($string[$position]))
11548                                         {
11549                                                 switch ($string[$position])
11550                                                 {
11551                                                         case '(':
11552                                                                 $depth++;
11553                                                                 break;
11554
11555                                                         case ')':
11556                                                                 $depth--;
11557                                                                 break;
11558                                                 }
11559                                                 $position++;
11560                                         }
11561                                         else
11562                                         {
11563                                                 break;
11564                                         }
11565                                 }
11566                         }
11567                         else
11568                         {
11569                                 $output .= '(';
11570                         }
11571                 }
11572                 $output .= substr($string, $position);
11573
11574                 return $output;
11575         }
11576
11577         /**
11578          * Parse RFC2822's date format
11579          *
11580          * @access protected
11581          * @return int Timestamp
11582          */
11583         function date_rfc2822($date)
11584         {
11585                 static $pcre;
11586                 if (!$pcre)
11587                 {
11588                         $wsp = '[\x09\x20]';
11589                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
11590                         $optional_fws = $fws . '?';
11591                         $day_name = $this->day_pcre;
11592                         $month = $this->month_pcre;
11593                         $day = '([0-9]{1,2})';
11594                         $hour = $minute = $second = '([0-9]{2})';
11595                         $year = '([0-9]{2,4})';
11596                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
11597                         $character_zone = '([A-Z]{1,5})';
11598                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
11599                         $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';
11600                 }
11601                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
11602                 {
11603                         /*
11604                         Capturing subpatterns:
11605                         1: Day name
11606                         2: Day
11607                         3: Month
11608                         4: Year
11609                         5: Hour
11610                         6: Minute
11611                         7: Second
11612                         8: Timezone ±
11613                         9: Timezone hours
11614                         10: Timezone minutes
11615                         11: Alphabetic timezone
11616                         */
11617
11618                         // Find the month number
11619                         $month = $this->month[strtolower($match[3])];
11620
11621                         // Numeric timezone
11622                         if ($match[8] !== '')
11623                         {
11624                                 $timezone = $match[9] * 3600;
11625                                 $timezone += $match[10] * 60;
11626                                 if ($match[8] === '-')
11627                                 {
11628                                         $timezone = 0 - $timezone;
11629                                 }
11630                         }
11631                         // Character timezone
11632                         elseif (isset($this->timezone[strtoupper($match[11])]))
11633                         {
11634                                 $timezone = $this->timezone[strtoupper($match[11])];
11635                         }
11636                         // Assume everything else to be -0000
11637                         else
11638                         {
11639                                 $timezone = 0;
11640                         }
11641
11642                         // Deal with 2/3 digit years
11643                         if ($match[4] < 50)
11644                         {
11645                                 $match[4] += 2000;
11646                         }
11647                         elseif ($match[4] < 1000)
11648                         {
11649                                 $match[4] += 1900;
11650                         }
11651                         
11652                         // Second is optional, if it is empty set it to zero
11653                         if ($match[7] !== '')
11654                         {
11655                                 $second = $match[7];
11656                         }
11657                         else
11658                         {
11659                                 $second = 0;
11660                         }
11661
11662                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
11663                 }
11664                 else
11665                 {
11666                         return false;
11667                 }
11668         }
11669
11670         /**
11671          * Parse RFC850's date format
11672          *
11673          * @access protected
11674          * @return int Timestamp
11675          */
11676         function date_rfc850($date)
11677         {
11678                 static $pcre;
11679                 if (!$pcre)
11680                 {
11681                         $space = '[\x09\x20]+';
11682                         $day_name = $this->day_pcre;
11683                         $month = $this->month_pcre;
11684                         $day = '([0-9]{1,2})';
11685                         $year = $hour = $minute = $second = '([0-9]{2})';
11686                         $zone = '([A-Z]{1,5})';
11687                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
11688                 }
11689                 if (preg_match($pcre, $date, $match))
11690                 {
11691                         /*
11692                         Capturing subpatterns:
11693                         1: Day name
11694                         2: Day
11695                         3: Month
11696                         4: Year
11697                         5: Hour
11698                         6: Minute
11699                         7: Second
11700                         8: Timezone
11701                         */
11702
11703                         // Month
11704                         $month = $this->month[strtolower($match[3])];
11705
11706                         // Character timezone
11707                         if (isset($this->timezone[strtoupper($match[8])]))
11708                         {
11709                                 $timezone = $this->timezone[strtoupper($match[8])];
11710                         }
11711                         // Assume everything else to be -0000
11712                         else
11713                         {
11714                                 $timezone = 0;
11715                         }
11716
11717                         // Deal with 2 digit year
11718                         if ($match[4] < 50)
11719                         {
11720                                 $match[4] += 2000;
11721                         }
11722                         else
11723                         {
11724                                 $match[4] += 1900;
11725                         }
11726
11727                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
11728                 }
11729                 else
11730                 {
11731                         return false;
11732                 }
11733         }
11734
11735         /**
11736          * Parse C99's asctime()'s date format
11737          *
11738          * @access protected
11739          * @return int Timestamp
11740          */
11741         function date_asctime($date)
11742         {
11743                 static $pcre;
11744                 if (!$pcre)
11745                 {
11746                         $space = '[\x09\x20]+';
11747                         $wday_name = $this->day_pcre;
11748                         $mon_name = $this->month_pcre;
11749                         $day = '([0-9]{1,2})';
11750                         $hour = $sec = $min = '([0-9]{2})';
11751                         $year = '([0-9]{4})';
11752                         $terminator = '\x0A?\x00?';
11753                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
11754                 }
11755                 if (preg_match($pcre, $date, $match))
11756                 {
11757                         /*
11758                         Capturing subpatterns:
11759                         1: Day name
11760                         2: Month
11761                         3: Day
11762                         4: Hour
11763                         5: Minute
11764                         6: Second
11765                         7: Year
11766                         */
11767
11768                         $month = $this->month[strtolower($match[2])];
11769                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
11770                 }
11771                 else
11772                 {
11773                         return false;
11774                 }
11775         }
11776
11777         /**
11778          * Parse dates using strtotime()
11779          *
11780          * @access protected
11781          * @return int Timestamp
11782          */
11783         function date_strtotime($date)
11784         {
11785                 $strtotime = strtotime($date);
11786                 if ($strtotime === -1 || $strtotime === false)
11787                 {
11788                         return false;
11789                 }
11790                 else
11791                 {
11792                         return $strtotime;
11793                 }
11794         }
11795 }
11796
11797 /**
11798  * Content-type sniffing
11799  *
11800  * @package SimplePie
11801  */
11802 class SimplePie_Content_Type_Sniffer
11803 {
11804         /**
11805          * File object
11806          *
11807          * @var SimplePie_File
11808          * @access private
11809          */
11810         var $file;
11811         
11812         /**
11813          * Create an instance of the class with the input file
11814          *
11815          * @access public
11816          * @param SimplePie_Content_Type_Sniffer $file Input file
11817          */
11818         function SimplePie_Content_Type_Sniffer($file)
11819         {
11820                 $this->file = $file;
11821         }
11822         
11823         /**
11824          * Get the Content-Type of the specified file
11825          *
11826          * @access public
11827          * @return string Actual Content-Type
11828          */
11829         function get_type()
11830         {
11831                 if (isset($this->file->headers['content-type']))
11832                 {
11833                         if (!isset($this->file->headers['content-encoding'])
11834                                 && ($this->file->headers['content-type'] === 'text/plain'
11835                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
11836                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
11837                         {
11838                                 return $this->text_or_binary();
11839                         }
11840                         
11841                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
11842                         { 
11843                                 $official = substr($this->file->headers['content-type'], 0, $pos);
11844                         }
11845                         else
11846                         {
11847                                 $official = $this->file->headers['content-type'];
11848                         }
11849                         $official = strtolower($official);
11850                         
11851                         if ($official === 'unknown/unknown'
11852                                 || $official === 'application/unknown')
11853                         {
11854                                 return $this->unknown();
11855                         }
11856                         elseif (substr($official, -4) === '+xml'
11857                                 || $official === 'text/xml'
11858                                 || $official === 'application/xml')
11859                         {
11860                                 return $official;
11861                         }
11862                         elseif (substr($official, 0, 6) === 'image/')
11863                         {
11864                                 if ($return = $this->image())
11865                                 {
11866                                         return $return;
11867                                 }
11868                                 else
11869                                 {
11870                                         return $official;
11871                                 }
11872                         }
11873                         elseif ($official === 'text/html')
11874                         {
11875                                 return $this->feed_or_html();
11876                         }
11877                         else
11878                         {
11879                                 return $official;
11880                         }
11881                 }
11882                 else
11883                 {
11884                         return $this->unknown();
11885                 }
11886         }
11887         
11888         /**
11889          * Sniff text or binary
11890          *
11891          * @access private
11892          * @return string Actual Content-Type
11893          */
11894         function text_or_binary()
11895         {
11896                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
11897                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
11898                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
11899                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
11900                 {
11901                         return 'text/plain';
11902                 }
11903                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
11904                 {
11905                         return 'application/octect-stream';
11906                 }
11907                 else
11908                 {
11909                         return 'text/plain';
11910                 }
11911         }
11912         
11913         /**
11914          * Sniff unknown
11915          *
11916          * @access private
11917          * @return string Actual Content-Type
11918          */
11919         function unknown()
11920         {
11921                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
11922                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
11923                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
11924                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
11925                 {
11926                         return 'text/html';
11927                 }
11928                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
11929                 {
11930                         return 'application/pdf';
11931                 }
11932                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
11933                 {
11934                         return 'application/postscript';
11935                 }
11936                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
11937                         || substr($this->file->body, 0, 6) === 'GIF89a')
11938                 {
11939                         return 'image/gif';
11940                 }
11941                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
11942                 {
11943                         return 'image/png';
11944                 }
11945                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
11946                 {
11947                         return 'image/jpeg';
11948                 }
11949                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
11950                 {
11951                         return 'image/bmp';
11952                 }
11953                 else
11954                 {
11955                         return $this->text_or_binary();
11956                 }
11957         }
11958         
11959         /**
11960          * Sniff images
11961          *
11962          * @access private
11963          * @return string Actual Content-Type
11964          */
11965         function image()
11966         {
11967                 if (substr($this->file->body, 0, 6) === 'GIF87a'
11968                         || substr($this->file->body, 0, 6) === 'GIF89a')
11969                 {
11970                         return 'image/gif';
11971                 }
11972                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
11973                 {
11974                         return 'image/png';
11975                 }
11976                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
11977                 {
11978                         return 'image/jpeg';
11979                 }
11980                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
11981                 {
11982                         return 'image/bmp';
11983                 }
11984                 else
11985                 {
11986                         return false;
11987                 }
11988         }
11989         
11990         /**
11991          * Sniff HTML
11992          *
11993          * @access private
11994          * @return string Actual Content-Type
11995          */
11996         function feed_or_html()
11997         {
11998                 $len = strlen($this->file->body);
11999                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
12000                 
12001                 while ($pos < $len)
12002                 {
12003                         switch ($this->file->body[$pos])
12004                         {
12005                                 case "\x09":
12006                                 case "\x0A":
12007                                 case "\x0D":
12008                                 case "\x20":
12009                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
12010                                         continue 2;
12011                                 
12012                                 case '<':
12013                                         $pos++;
12014                                         break;
12015                                 
12016                                 default:
12017                                         return 'text/html';
12018                         }
12019                         
12020                         if (substr($this->file->body, $pos, 3) === '!--')
12021                         {
12022                                 $pos += 3;
12023                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
12024                                 {
12025                                         $pos += 3;
12026                                 }
12027                                 else
12028                                 {
12029                                         return 'text/html';
12030                                 }
12031                         }
12032                         elseif (substr($this->file->body, $pos, 1) === '!')
12033                         {
12034                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
12035                                 {
12036                                         $pos++;
12037                                 }
12038                                 else
12039                                 {
12040                                         return 'text/html';
12041                                 }
12042                         }
12043                         elseif (substr($this->file->body, $pos, 1) === '?')
12044                         {
12045                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
12046                                 {
12047                                         $pos += 2;
12048                                 }
12049                                 else
12050                                 {
12051                                         return 'text/html';
12052                                 }
12053                         }
12054                         elseif (substr($this->file->body, $pos, 3) === 'rss'
12055                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
12056                         {
12057                                 return 'application/rss+xml';
12058                         }
12059                         elseif (substr($this->file->body, $pos, 4) === 'feed')
12060                         {
12061                                 return 'application/atom+xml';
12062                         }
12063                         else
12064                         {
12065                                 return 'text/html';
12066                         }
12067                 }
12068                 
12069                 return 'text/html';
12070         }
12071 }
12072
12073 /**
12074  * Parses the XML Declaration
12075  *
12076  * @package SimplePie
12077  */
12078 class SimplePie_XML_Declaration_Parser
12079 {
12080         /**
12081          * XML Version
12082          *
12083          * @access public
12084          * @var string
12085          */
12086         var $version = '1.0';
12087         
12088         /**
12089          * Encoding
12090          *
12091          * @access public
12092          * @var string
12093          */
12094         var $encoding = 'UTF-8';
12095         
12096         /**
12097          * Standalone
12098          *
12099          * @access public
12100          * @var bool
12101          */
12102         var $standalone = false;
12103
12104         /**
12105          * Current state of the state machine
12106          *
12107          * @access private
12108          * @var string
12109          */
12110         var $state = 'before_version_name';
12111         
12112         /**
12113          * Input data
12114          *
12115          * @access private
12116          * @var string
12117          */
12118         var $data = '';
12119
12120         /**
12121          * Input data length (to avoid calling strlen() everytime this is needed)
12122          *
12123          * @access private
12124          * @var int
12125          */
12126         var $data_length = 0;
12127
12128         /**
12129          * Current position of the pointer
12130          *
12131          * @var int
12132          * @access private
12133          */
12134         var $position = 0;
12135         
12136         /**
12137          * Create an instance of the class with the input data
12138          *
12139          * @access public
12140          * @param string $data Input data
12141          */
12142         function SimplePie_XML_Declaration_Parser($data)
12143         {
12144                 $this->data = $data;
12145                 $this->data_length = strlen($this->data);
12146         }
12147
12148         /**
12149          * Parse the input data
12150          *
12151          * @access public
12152          * @return bool true on success, false on failure
12153          */
12154         function parse()
12155         {
12156                 while ($this->state && $this->state !== 'emit' && $this->has_data())
12157                 {
12158                         $state = $this->state;
12159                         $this->$state();
12160                 }
12161                 $this->data = '';
12162                 if ($this->state === 'emit')
12163                 {
12164                         return true;
12165                 }
12166                 else
12167                 {
12168                         $this->version = '';
12169                         $this->encoding = '';
12170                         $this->standalone = '';
12171                         return false;
12172                 }
12173         }
12174
12175         /**
12176          * Check whether there is data beyond the pointer
12177          *
12178          * @access private
12179          * @return bool true if there is further data, false if not
12180          */
12181         function has_data()
12182         {
12183                 return (bool) ($this->position < $this->data_length);
12184         }
12185         
12186         /**
12187          * Advance past any whitespace
12188          *
12189          * @return int Number of whitespace characters passed
12190          */
12191         function skip_whitespace()
12192         {
12193                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
12194                 $this->position += $whitespace;
12195                 return $whitespace;
12196         }
12197         
12198         /**
12199          * Read value
12200          */
12201         function get_value()
12202         {
12203                 $quote = substr($this->data, $this->position, 1);
12204                 if ($quote === '"' || $quote === "'")
12205                 {
12206                         $this->position++;
12207                         $len = strcspn($this->data, $quote, $this->position);
12208                         if ($this->has_data())
12209                         {
12210                                 $value = substr($this->data, $this->position, $len);
12211                                 $this->position += $len + 1;
12212                                 return $value;
12213                         }
12214                 }
12215                 return false;
12216         }
12217         
12218         function before_version_name()
12219         {
12220                 if ($this->skip_whitespace())
12221                 {
12222                         $this->state = 'version_name';
12223                 }
12224                 else
12225                 {
12226                         $this->state = false;
12227                 }
12228         }
12229         
12230         function version_name()
12231         {
12232                 if (substr($this->data, $this->position, 7) === 'version')
12233                 {
12234                         $this->position += 7;
12235                         $this->skip_whitespace();
12236                         $this->state = 'version_equals';
12237                 }
12238                 else
12239                 {
12240                         $this->state = false;
12241                 }
12242         }
12243         
12244         function version_equals()
12245         {
12246                 if (substr($this->data, $this->position, 1) === '=')
12247                 {
12248                         $this->position++;
12249                         $this->skip_whitespace();
12250                         $this->state = 'version_value';
12251                 }
12252                 else
12253                 {
12254                         $this->state = false;
12255                 }
12256         }
12257         
12258         function version_value()
12259         {
12260                 if ($this->version = $this->get_value())
12261                 {
12262                         $this->skip_whitespace();
12263                         if ($this->has_data())
12264                         {
12265                                 $this->state = 'encoding_name';
12266                         }
12267                         else
12268                         {
12269                                 $this->state = 'emit';
12270                         }
12271                 }
12272                 else
12273                 {
12274                         $this->state = 'standalone_name';
12275                 }
12276         }
12277         
12278         function encoding_name()
12279         {
12280                 if (substr($this->data, $this->position, 8) === 'encoding')
12281                 {
12282                         $this->position += 8;
12283                         $this->skip_whitespace();
12284                         $this->state = 'encoding_equals';
12285                 }
12286                 else
12287                 {
12288                         $this->state = false;
12289                 }
12290         }
12291         
12292         function encoding_equals()
12293         {
12294                 if (substr($this->data, $this->position, 1) === '=')
12295                 {
12296                         $this->position++;
12297                         $this->skip_whitespace();
12298                         $this->state = 'encoding_value';
12299                 }
12300                 else
12301                 {
12302                         $this->state = false;
12303                 }
12304         }
12305         
12306         function encoding_value()
12307         {
12308                 if ($this->encoding = $this->get_value())
12309                 {
12310                         $this->skip_whitespace();
12311                         if ($this->has_data())
12312                         {
12313                                 $this->state = 'standalone_name';
12314                         }
12315                         else
12316                         {
12317                                 $this->state = 'emit';
12318                         }
12319                 }
12320                 else
12321                 {
12322                         $this->state = false;
12323                 }
12324         }
12325         
12326         function standalone_name()
12327         {
12328                 if (substr($this->data, $this->position, 10) === 'standalone')
12329                 {
12330                         $this->position += 10;
12331                         $this->skip_whitespace();
12332                         $this->state = 'standalone_equals';
12333                 }
12334                 else
12335                 {
12336                         $this->state = false;
12337                 }
12338         }
12339         
12340         function standalone_equals()
12341         {
12342                 if (substr($this->data, $this->position, 1) === '=')
12343                 {
12344                         $this->position++;
12345                         $this->skip_whitespace();
12346                         $this->state = 'standalone_value';
12347                 }
12348                 else
12349                 {
12350                         $this->state = false;
12351                 }
12352         }
12353         
12354         function standalone_value()
12355         {
12356                 if ($standalone = $this->get_value())
12357                 {
12358                         switch ($standalone)
12359                         {
12360                                 case 'yes':
12361                                         $this->standalone = true;
12362                                         break;
12363                                 
12364                                 case 'no':
12365                                         $this->standalone = false;
12366                                         break;
12367                                 
12368                                 default:
12369                                         $this->state = false;
12370                                         return;
12371                         }
12372                         
12373                         $this->skip_whitespace();
12374                         if ($this->has_data())
12375                         {
12376                                 $this->state = false;
12377                         }
12378                         else
12379                         {
12380                                 $this->state = 'emit';
12381                         }
12382                 }
12383                 else
12384                 {
12385                         $this->state = false;
12386                 }
12387         }
12388 }
12389
12390 class SimplePie_Locator
12391 {
12392         var $useragent;
12393         var $timeout;
12394         var $file;
12395         var $local = array();
12396         var $elsewhere = array();
12397         var $file_class = 'SimplePie_File';
12398         var $cached_entities = array();
12399         var $http_base;
12400         var $base;
12401         var $base_location = 0;
12402         var $checked_feeds = 0;
12403         var $max_checked_feeds = 10;
12404         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
12405
12406         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
12407         {
12408                 $this->file =& $file;
12409                 $this->file_class = $file_class;
12410                 $this->useragent = $useragent;
12411                 $this->timeout = $timeout;
12412                 $this->max_checked_feeds = $max_checked_feeds;
12413                 $this->content_type_sniffer_class;
12414         }
12415
12416         function find($type = SIMPLEPIE_LOCATOR_ALL)
12417         {
12418                 if ($this->is_feed($this->file))
12419                 {
12420                         return $this->file;
12421                 }
12422                 
12423                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
12424                 {
12425                         $sniffer = new $this->content_type_sniffer_class($this->file);
12426                         if ($sniffer->get_type() !== 'text/html')
12427                         {
12428                                 return null;
12429                         }
12430                 }
12431
12432                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
12433                 {
12434                         $this->get_base();
12435                 }
12436
12437                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
12438                 {
12439                         return $working;
12440                 }
12441
12442                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
12443                 {
12444                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
12445                         {
12446                                 return $working;
12447                         }
12448
12449                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
12450                         {
12451                                 return $working;
12452                         }
12453
12454                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
12455                         {
12456                                 return $working;
12457                         }
12458
12459                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
12460                         {
12461                                 return $working;
12462                         }
12463                 }
12464                 return null;
12465         }
12466
12467         function is_feed(&$file)
12468         {
12469                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
12470                 {
12471                         $sniffer = new $this->content_type_sniffer_class($file);
12472                         $sniffed = $sniffer->get_type();
12473                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'application/atom+xml', 'text/xml', 'application/xml', 'text/plain')))
12474                         {
12475                                 return true;
12476                         }
12477                         else
12478                         {
12479                                 return false;
12480                         }
12481                 }
12482                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
12483                 {
12484                         return true;
12485                 }
12486                 else
12487                 {
12488                         return false;
12489                 }
12490         }
12491
12492         function get_base()
12493         {
12494                 $this->http_base = $this->file->url;
12495                 $this->base = $this->http_base;
12496                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
12497                 foreach ($elements as $element)
12498                 {
12499                         if ($element['attribs']['href']['data'] !== '')
12500                         {
12501                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
12502                                 $this->base_location = $element['offset'];
12503                                 break;
12504                         }
12505                 }
12506         }
12507
12508         function autodiscovery()
12509         {
12510                 $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));
12511                 $done = array();
12512                 foreach ($links as $link)
12513                 {
12514                         if ($this->checked_feeds == $this->max_checked_feeds)
12515                         {
12516                                 break;
12517                         }
12518                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
12519                         {
12520                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
12521
12522                                 if ($this->base_location < $link['offset'])
12523                                 {
12524                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
12525                                 }
12526                                 else
12527                                 {
12528                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
12529                                 }
12530
12531                                 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'))))
12532                                 {
12533                                         $this->checked_feeds++;
12534                                         $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
12535                                         if ($this->is_feed($feed))
12536                                         {
12537                                                 return $feed;
12538                                         }
12539                                 }
12540                                 $done[] = $href;
12541                         }
12542                 }
12543                 return null;
12544         }
12545
12546         function get_links()
12547         {
12548                 $links = SimplePie_Misc::get_element('a', $this->file->body);
12549                 foreach ($links as $link)
12550                 {
12551                         if (isset($link['attribs']['href']['data']))
12552                         {
12553                                 $href = trim($link['attribs']['href']['data']);
12554                                 $parsed = SimplePie_Misc::parse_url($href);
12555                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
12556                                 {
12557                                         if ($this->base_location < $link['offset'])
12558                                         {
12559                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
12560                                         }
12561                                         else
12562                                         {
12563                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
12564                                         }
12565
12566                                         $current = SimplePie_Misc::parse_url($this->file->url);
12567
12568                                         if ($parsed['authority'] === '' || $parsed['authority'] == $current['authority'])
12569                                         {
12570                                                 $this->local[] = $href;
12571                                         }
12572                                         else
12573                                         {
12574                                                 $this->elsewhere[] = $href;
12575                                         }
12576                                 }
12577                         }
12578                 }
12579                 $this->local = array_unique($this->local);
12580                 $this->elsewhere = array_unique($this->elsewhere);
12581                 if (!empty($this->local) || !empty($this->elsewhere))
12582                 {
12583                         return true;
12584                 }
12585                 return null;
12586         }
12587
12588         function extension(&$array)
12589         {
12590                 foreach ($array as $key => $value)
12591                 {
12592                         if ($this->checked_feeds == $this->max_checked_feeds)
12593                         {
12594                                 break;
12595                         }
12596                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
12597                         {
12598                                 $this->checked_feeds++;
12599                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
12600                                 if ($this->is_feed($feed))
12601                                 {
12602                                         return $feed;
12603                                 }
12604                                 else
12605                                 {
12606                                         unset($array[$key]);
12607                                 }
12608                         }
12609                 }
12610                 return null;
12611         }
12612
12613         function body(&$array)
12614         {
12615                 foreach ($array as $key => $value)
12616                 {
12617                         if ($this->checked_feeds == $this->max_checked_feeds)
12618                         {
12619                                 break;
12620                         }
12621                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
12622                         {
12623                                 $this->checked_feeds++;
12624                                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
12625                                 if ($this->is_feed($feed))
12626                                 {
12627                                         return $feed;
12628                                 }
12629                                 else
12630                                 {
12631                                         unset($array[$key]);
12632                                 }
12633                         }
12634                 }
12635                 return null;
12636         }
12637 }
12638
12639 class SimplePie_Parser
12640 {
12641         var $error_code;
12642         var $error_string;
12643         var $current_line;
12644         var $current_column;
12645         var $current_byte;
12646         var $separator = ' ';
12647         var $feed = false;
12648         var $namespace = array('');
12649         var $element = array('');
12650         var $xml_base = array('');
12651         var $xml_base_explicit = array(false);
12652         var $xml_lang = array('');
12653         var $data = array();
12654         var $datas = array(array());
12655         var $current_xhtml_construct = -1;
12656         var $encoding;
12657
12658         function parse(&$data, $encoding)
12659         {
12660                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
12661                 if (strtoupper($encoding) == 'US-ASCII')
12662                 {
12663                         $this->encoding = 'UTF-8';
12664                 }
12665                 else
12666                 {
12667                         $this->encoding = $encoding;
12668                 }
12669
12670                 // Strip BOM:
12671                 // UTF-32 Big Endian BOM
12672                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
12673                 {
12674                         $data = substr($data, 4);
12675                 }
12676                 // UTF-32 Little Endian BOM
12677                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
12678                 {
12679                         $data = substr($data, 4);
12680                 }
12681                 // UTF-16 Big Endian BOM
12682                 elseif (substr($data, 0, 2) === "\xFE\xFF")
12683                 {
12684                         $data = substr($data, 2);
12685                 }
12686                 // UTF-16 Little Endian BOM
12687                 elseif (substr($data, 0, 2) === "\xFF\xFE")
12688                 {
12689                         $data = substr($data, 2);
12690                 }
12691                 // UTF-8 BOM
12692                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
12693                 {
12694                         $data = substr($data, 3);
12695                 }
12696                 
12697                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
12698                 {
12699                         $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
12700                         if ($declaration->parse())
12701                         {
12702                                 $data = substr($data, $pos + 2);
12703                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
12704                         }
12705                         else
12706                         {
12707                                 $this->error_string = 'SimplePie bug! Please report this!';
12708                                 return false;
12709                         }
12710                 }
12711                 
12712                 $return = true;
12713
12714                 // Create the parser
12715                 $xml = xml_parser_create_ns($this->encoding, $this->separator);
12716                 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
12717                 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
12718                 xml_set_object($xml, $this);
12719                 xml_set_character_data_handler($xml, 'cdata');
12720                 xml_set_element_handler($xml, 'tag_open', 'tag_close');
12721
12722                 // Parse!
12723                 if (!xml_parse($xml, $data, true))
12724                 {
12725                         $this->error_code = xml_get_error_code($xml);
12726                         $this->error_string = xml_error_string($this->error_code);
12727                         $return = false;
12728                 }
12729                 $this->current_line = xml_get_current_line_number($xml);
12730                 $this->current_column = xml_get_current_column_number($xml);
12731                 $this->current_byte = xml_get_current_byte_index($xml);
12732                 xml_parser_free($xml);
12733                 return $return;
12734         }
12735
12736         function get_error_code()
12737         {
12738                 return $this->error_code;
12739         }
12740
12741         function get_error_string()
12742         {
12743                 return $this->error_string;
12744         }
12745
12746         function get_current_line()
12747         {
12748                 return $this->current_line;
12749         }
12750
12751         function get_current_column()
12752         {
12753                 return $this->current_column;
12754         }
12755
12756         function get_current_byte()
12757         {
12758                 return $this->current_byte;
12759         }
12760
12761         function get_data()
12762         {
12763                 return $this->data;
12764         }
12765
12766         function tag_open($parser, $tag, $attributes)
12767         {
12768                 if ($this->feed === 0)
12769                 {
12770                         return;
12771                 }
12772                 elseif ($this->feed == false)
12773                 {
12774                         if (in_array($tag, array(
12775                                 SIMPLEPIE_NAMESPACE_ATOM_10 . $this->separator . 'feed',
12776                                 SIMPLEPIE_NAMESPACE_ATOM_03 . $this->separator . 'feed',
12777                                 'rss',
12778                                 SIMPLEPIE_NAMESPACE_RDF . $this->separator . 'RDF'
12779                         )))
12780                         {
12781                                         $this->feed = 1;
12782                         }
12783                 }
12784                 else
12785                 {
12786                         $this->feed++;
12787                 }
12788
12789                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
12790
12791                 $attribs = array();
12792                 foreach ($attributes as $name => $value)
12793                 {
12794                         list($attrib_namespace, $attribute) = $this->split_ns($name);
12795                         $attribs[$attrib_namespace][$attribute] = $value;
12796                 }
12797
12798                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
12799                 {
12800                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
12801                         $this->xml_base_explicit[] = true;
12802                 }
12803                 else
12804                 {
12805                         $this->xml_base[] = end($this->xml_base);
12806                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
12807                 }
12808
12809                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
12810                 {
12811                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
12812                 }
12813                 else
12814                 {
12815                         $this->xml_lang[] = end($this->xml_lang);
12816                 }
12817
12818                 if ($this->current_xhtml_construct >= 0)
12819                 {
12820                         $this->current_xhtml_construct++;
12821                         if (end($this->namespace) == SIMPLEPIE_NAMESPACE_XHTML)
12822                         {
12823                                 $this->data['data'] .= '<' . end($this->element);
12824                                 if (isset($attribs['']))
12825                                 {
12826                                         foreach ($attribs[''] as $name => $value)
12827                                         {
12828                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
12829                                         }
12830                                 }
12831                                 $this->data['data'] .= '>';
12832                         }
12833                 }
12834                 else
12835                 {
12836                         $this->datas[] =& $this->data;
12837                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
12838                         $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));
12839                         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')
12840                         || (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'))
12841                         {
12842                                 $this->current_xhtml_construct = 0;
12843                         }
12844                 }
12845         }
12846
12847         function cdata($parser, $cdata)
12848         {
12849                 if ($this->current_xhtml_construct >= 0)
12850                 {
12851                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
12852                 }
12853                 elseif ($this->feed > 1)
12854                 {
12855                         $this->data['data'] .= $cdata;
12856                 }
12857         }
12858
12859         function tag_close($parser, $tag)
12860         {
12861                 if (!$this->feed)
12862                 {
12863                         return;
12864                 }
12865
12866                 if ($this->current_xhtml_construct >= 0)
12867                 {
12868                         $this->current_xhtml_construct--;
12869                         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')))
12870                         {
12871                                 $this->data['data'] .= '</' . end($this->element) . '>';
12872                         }
12873                 }
12874                 if ($this->current_xhtml_construct == -1)
12875                 {
12876                         $this->data =& $this->datas[$this->feed];
12877                         array_pop($this->datas);
12878                 }
12879
12880                 array_pop($this->element);
12881                 array_pop($this->namespace);
12882                 array_pop($this->xml_base);
12883                 array_pop($this->xml_base_explicit);
12884                 array_pop($this->xml_lang);
12885                 $this->feed--;
12886         }
12887
12888         function split_ns($string)
12889         {
12890                 static $cache = array();
12891                 if (!isset($cache[$string]))
12892                 {
12893                         if ($pos = strpos($string, $this->separator))
12894                         {
12895                                 static $separator_length;
12896                                 if (!$separator_length)
12897                                 {
12898                                         $separator_length = strlen($this->separator);
12899                                 }
12900                                 $namespace = substr($string, 0, $pos);
12901                                 $local_name = substr($string, $pos + $separator_length);
12902                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
12903                                 {
12904                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
12905                                 }
12906                                 $cache[$string] = array($namespace, $local_name);
12907                         }
12908                         else
12909                         {
12910                                 $cache[$string] = array('', $string);
12911                         }
12912                 }
12913                 return $cache[$string];
12914         }
12915 }
12916
12917 /**
12918  * @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 shortern a string while preserving HTML tags
12919  */
12920 class SimplePie_Sanitize
12921 {
12922         // Private vars
12923         var $base;
12924
12925         // Options
12926         var $remove_div = true;
12927         var $image_handler = '';
12928         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
12929         var $encode_instead_of_strip = false;
12930         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
12931         var $strip_comments = false;
12932         var $output_encoding = 'UTF-8';
12933         var $enable_cache = true;
12934         var $cache_location = './cache';
12935         var $cache_name_function = 'md5';
12936         var $cache_class = 'SimplePie_Cache';
12937         var $file_class = 'SimplePie_File';
12938         var $timeout = 10;
12939         var $useragent = '';
12940         var $force_fsockopen = false;
12941
12942         var $replace_url_attributes = array(
12943                 'a' => 'href',
12944                 'area' => 'href',
12945                 'blockquote' => 'cite',
12946                 'del' => 'cite',
12947                 'form' => 'action',
12948                 'img' => array('longdesc', 'src'),
12949                 'input' => 'src',
12950                 'ins' => 'cite',
12951                 'q' => 'cite'
12952         );
12953
12954         function remove_div($enable = true)
12955         {
12956                 $this->remove_div = (bool) $enable;
12957         }
12958
12959         function set_image_handler($page = false)
12960         {
12961                 if ($page)
12962                 {
12963                         $this->image_handler = (string) $page;
12964                 }
12965                 else
12966                 {
12967                         $this->image_handler = false;
12968                 }
12969         }
12970
12971         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
12972         {
12973                 if (isset($enable_cache))
12974                 {
12975                         $this->enable_cache = (bool) $enable_cache;
12976                 }
12977
12978                 if ($cache_location)
12979                 {
12980                         $this->cache_location = (string) $cache_location;
12981                 }
12982
12983                 if ($cache_name_function)
12984                 {
12985                         $this->cache_name_function = (string) $cache_name_function;
12986                 }
12987
12988                 if ($cache_class)
12989                 {
12990                         $this->cache_class = (string) $cache_class;
12991                 }
12992         }
12993
12994         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
12995         {
12996                 if ($file_class)
12997                 {
12998                         $this->file_class = (string) $file_class;
12999                 }
13000
13001                 if ($timeout)
13002                 {
13003                         $this->timeout = (string) $timeout;
13004                 }
13005
13006                 if ($useragent)
13007                 {
13008                         $this->useragent = (string) $useragent;
13009                 }
13010
13011                 if ($force_fsockopen)
13012                 {
13013                         $this->force_fsockopen = (string) $force_fsockopen;
13014                 }
13015         }
13016
13017         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
13018         {
13019                 if ($tags)
13020                 {
13021                         if (is_array($tags))
13022                         {
13023                                 $this->strip_htmltags = $tags;
13024                         }
13025                         else
13026                         {
13027                                 $this->strip_htmltags = explode(',', $tags);
13028                         }
13029                 }
13030                 else
13031                 {
13032                         $this->strip_htmltags = false;
13033                 }
13034         }
13035
13036         function encode_instead_of_strip($encode = false)
13037         {
13038                 $this->encode_instead_of_strip = (bool) $encode;
13039         }
13040
13041         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
13042         {
13043                 if ($attribs)
13044                 {
13045                         if (is_array($attribs))
13046                         {
13047                                 $this->strip_attributes = $attribs;
13048                         }
13049                         else
13050                         {
13051                                 $this->strip_attributes = explode(',', $attribs);
13052                         }
13053                 }
13054                 else
13055                 {
13056                         $this->strip_attributes = false;
13057                 }
13058         }
13059
13060         function strip_comments($strip = false)
13061         {
13062                 $this->strip_comments = (bool) $strip;
13063         }
13064
13065         function set_output_encoding($encoding = 'UTF-8')
13066         {
13067                 $this->output_encoding = (string) $encoding;
13068         }
13069
13070         /**
13071          * Set element/attribute key/value pairs of HTML attributes
13072          * containing URLs that need to be resolved relative to the feed
13073          *
13074          * @access public
13075          * @since 1.0
13076          * @param array $element_attribute Element/attribute key/value pairs
13077          */
13078         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'))
13079         {
13080                 $this->replace_url_attributes = (array) $element_attribute;
13081         }
13082
13083         function sanitize($data, $type, $base = '')
13084         {
13085                 $data = trim($data);
13086                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
13087                 {
13088                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
13089                         {
13090                                 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))
13091                                 {
13092                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
13093                                 }
13094                                 else
13095                                 {
13096                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
13097                                 }
13098                         }
13099
13100                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
13101                         {
13102                                 $data = base64_decode($data);
13103                         }
13104
13105                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
13106                         {
13107                                 if ($this->remove_div)
13108                                 {
13109                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
13110                                         $data = preg_replace('/<\/div>$/', '', $data);
13111                                 }
13112                                 else
13113                                 {
13114                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
13115                                 }
13116                         }
13117
13118                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
13119                         {
13120                                 // Strip comments
13121                                 if ($this->strip_comments)
13122                                 {
13123                                         $data = SimplePie_Misc::strip_comments($data);
13124                                 }
13125
13126                                 // Strip out HTML tags and attributes that might cause various security problems.
13127                                 // Based on recommendations by Mark Pilgrim at:
13128                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
13129                                 if ($this->strip_htmltags)
13130                                 {
13131                                         foreach ($this->strip_htmltags as $tag)
13132                                         {
13133                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
13134                                                 while (preg_match($pcre, $data))
13135                                                 {
13136                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
13137                                                 }
13138                                         }
13139                                 }
13140
13141                                 if ($this->strip_attributes)
13142                                 {
13143                                         foreach ($this->strip_attributes as $attrib)
13144                                         {
13145                                                 $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);
13146                                         }
13147                                 }
13148
13149                                 // Replace relative URLs
13150                                 $this->base = $base;
13151                                 foreach ($this->replace_url_attributes as $element => $attributes)
13152                                 {
13153                                         $data = $this->replace_urls($data, $element, $attributes);
13154                                 }
13155
13156                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
13157                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
13158                                 {
13159                                         $images = SimplePie_Misc::get_element('img', $data);
13160                                         foreach ($images as $img)
13161                                         {
13162                                                 if (isset($img['attribs']['src']['data']))
13163                                                 {
13164                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
13165                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
13166
13167                                                         if ($cache->load())
13168                                                         {
13169                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
13170                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
13171                                                         }
13172                                                         else
13173                                                         {
13174                                                                 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
13175                                                                 $headers = $file->headers;
13176
13177                                                                 if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)))
13178                                                                 {
13179                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
13180                                                                         {
13181                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
13182                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
13183                                                                         }
13184                                                                         else
13185                                                                         {
13186                                                                                 trigger_error("$cache->name is not writeable", E_USER_WARNING);
13187                                                                         }
13188                                                                 }
13189                                                         }
13190                                                 }
13191                                         }
13192                                 }
13193
13194                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
13195                                 $data = trim($data);
13196                         }
13197
13198                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
13199                         {
13200                                 $data = SimplePie_Misc::absolutize_url($data, $base);
13201                         }
13202
13203                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
13204                         {
13205                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
13206                         }
13207
13208                         if ($this->output_encoding != 'UTF-8')
13209                         {
13210                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
13211                         }
13212                 }
13213                 return $data;
13214         }
13215
13216         function replace_urls($data, $tag, $attributes)
13217         {
13218                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
13219                 {
13220                         $elements = SimplePie_Misc::get_element($tag, $data);
13221                         foreach ($elements as $element)
13222                         {
13223                                 if (is_array($attributes))
13224                                 {
13225                                         foreach ($attributes as $attribute)
13226                                         {
13227                                                 if (isset($element['attribs'][$attribute]['data']))
13228                                                 {
13229                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
13230                                                         $new_element = SimplePie_Misc::element_implode($element);
13231                                                         $data = str_replace($element['full'], $new_element, $data);
13232                                                         $element['full'] = $new_element;
13233                                                 }
13234                                         }
13235                                 }
13236                                 elseif (isset($element['attribs'][$attributes]['data']))
13237                                 {
13238                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
13239                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
13240                                 }
13241                         }
13242                 }
13243                 return $data;
13244         }
13245
13246         function do_strip_htmltags($match)
13247         {
13248                 if ($this->encode_instead_of_strip)
13249                 {
13250                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
13251                         {
13252                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
13253                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
13254                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
13255                         }
13256                         else
13257                         {
13258                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
13259                         }
13260                 }
13261                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
13262                 {
13263                         return $match[4];
13264                 }
13265                 else
13266                 {
13267                         return '';
13268                 }
13269         }
13270 }
13271
13272 ?>