1<?php
2if ( !class_exists( 'SimplePie' ) ) :
3/**
4 * SimplePie
5 *
6 * A PHP-Based RSS and Atom Feed Framework.
7 * Takes the hard work out of managing a complete RSS/Atom solution.
8 *
9 * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without modification, are
13 * permitted provided that the following conditions are met:
14 *
15 * 	* Redistributions of source code must retain the above copyright notice, this list of
16 * 	  conditions and the following disclaimer.
17 *
18 * 	* Redistributions in binary form must reproduce the above copyright notice, this list
19 * 	  of conditions and the following disclaimer in the documentation and/or other materials
20 * 	  provided with the distribution.
21 *
22 * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
23 * 	  to endorse or promote products derived from this software without specific prior
24 * 	  written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
29 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 * @package SimplePie
37 * @version 1.2
38 * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
39 * @author Ryan Parman
40 * @author Geoffrey Sneddon
41 * @link http://simplepie.org/ SimplePie
42 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
43 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
44 * @todo phpDoc comments
45 */
46
47/**
48 * SimplePie Name
49 */
50define('SIMPLEPIE_NAME', 'SimplePie');
51
52/**
53 * SimplePie Version
54 */
55define('SIMPLEPIE_VERSION', '1.2');
56
57/**
58 * SimplePie Build
59 */
60define('SIMPLEPIE_BUILD', '20090627192103');
61
62/**
63 * SimplePie Website URL
64 */
65define('SIMPLEPIE_URL', 'http://simplepie.org');
66
67/**
68 * SimplePie Useragent
69 * @see SimplePie::set_useragent()
70 */
71define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
72
73/**
74 * SimplePie Linkback
75 */
76define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
77
78/**
79 * No Autodiscovery
80 * @see SimplePie::set_autodiscovery_level()
81 */
82define('SIMPLEPIE_LOCATOR_NONE', 0);
83
84/**
85 * Feed Link Element Autodiscovery
86 * @see SimplePie::set_autodiscovery_level()
87 */
88define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
89
90/**
91 * Local Feed Extension Autodiscovery
92 * @see SimplePie::set_autodiscovery_level()
93 */
94define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
95
96/**
97 * Local Feed Body Autodiscovery
98 * @see SimplePie::set_autodiscovery_level()
99 */
100define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
101
102/**
103 * Remote Feed Extension Autodiscovery
104 * @see SimplePie::set_autodiscovery_level()
105 */
106define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
107
108/**
109 * Remote Feed Body Autodiscovery
110 * @see SimplePie::set_autodiscovery_level()
111 */
112define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
113
114/**
115 * All Feed Autodiscovery
116 * @see SimplePie::set_autodiscovery_level()
117 */
118define('SIMPLEPIE_LOCATOR_ALL', 31);
119
120/**
121 * No known feed type
122 */
123define('SIMPLEPIE_TYPE_NONE', 0);
124
125/**
126 * RSS 0.90
127 */
128define('SIMPLEPIE_TYPE_RSS_090', 1);
129
130/**
131 * RSS 0.91 (Netscape)
132 */
133define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
134
135/**
136 * RSS 0.91 (Userland)
137 */
138define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
139
140/**
141 * RSS 0.91 (both Netscape and Userland)
142 */
143define('SIMPLEPIE_TYPE_RSS_091', 6);
144
145/**
146 * RSS 0.92
147 */
148define('SIMPLEPIE_TYPE_RSS_092', 8);
149
150/**
151 * RSS 0.93
152 */
153define('SIMPLEPIE_TYPE_RSS_093', 16);
154
155/**
156 * RSS 0.94
157 */
158define('SIMPLEPIE_TYPE_RSS_094', 32);
159
160/**
161 * RSS 1.0
162 */
163define('SIMPLEPIE_TYPE_RSS_10', 64);
164
165/**
166 * RSS 2.0
167 */
168define('SIMPLEPIE_TYPE_RSS_20', 128);
169
170/**
171 * RDF-based RSS
172 */
173define('SIMPLEPIE_TYPE_RSS_RDF', 65);
174
175/**
176 * Non-RDF-based RSS (truly intended as syndication format)
177 */
178define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
179
180/**
181 * All RSS
182 */
183define('SIMPLEPIE_TYPE_RSS_ALL', 255);
184
185/**
186 * Atom 0.3
187 */
188define('SIMPLEPIE_TYPE_ATOM_03', 256);
189
190/**
191 * Atom 1.0
192 */
193define('SIMPLEPIE_TYPE_ATOM_10', 512);
194
195/**
196 * All Atom
197 */
198define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
199
200/**
201 * All feed types
202 */
203define('SIMPLEPIE_TYPE_ALL', 1023);
204
205/**
206 * No construct
207 */
208define('SIMPLEPIE_CONSTRUCT_NONE', 0);
209
210/**
211 * Text construct
212 */
213define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
214
215/**
216 * HTML construct
217 */
218define('SIMPLEPIE_CONSTRUCT_HTML', 2);
219
220/**
221 * XHTML construct
222 */
223define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
224
225/**
226 * base64-encoded construct
227 */
228define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
229
230/**
231 * IRI construct
232 */
233define('SIMPLEPIE_CONSTRUCT_IRI', 16);
234
235/**
236 * A construct that might be HTML
237 */
238define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
239
240/**
241 * All constructs
242 */
243define('SIMPLEPIE_CONSTRUCT_ALL', 63);
244
245/**
246 * Don't change case
247 */
248define('SIMPLEPIE_SAME_CASE', 1);
249
250/**
251 * Change to lowercase
252 */
253define('SIMPLEPIE_LOWERCASE', 2);
254
255/**
256 * Change to uppercase
257 */
258define('SIMPLEPIE_UPPERCASE', 4);
259
260/**
261 * PCRE for HTML attributes
262 */
263define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
264
265/**
266 * PCRE for XML attributes
267 */
268define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
269
270/**
271 * XML Namespace
272 */
273define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
274
275/**
276 * Atom 1.0 Namespace
277 */
278define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
279
280/**
281 * Atom 0.3 Namespace
282 */
283define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
284
285/**
286 * RDF Namespace
287 */
288define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
289
290/**
291 * RSS 0.90 Namespace
292 */
293define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
294
295/**
296 * RSS 1.0 Namespace
297 */
298define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
299
300/**
301 * RSS 1.0 Content Module Namespace
302 */
303define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
304
305/**
306 * RSS 2.0 Namespace
307 * (Stupid, I know, but I'm certain it will confuse people less with support.)
308 */
309define('SIMPLEPIE_NAMESPACE_RSS_20', '');
310
311/**
312 * DC 1.0 Namespace
313 */
314define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
315
316/**
317 * DC 1.1 Namespace
318 */
319define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
320
321/**
322 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
323 */
324define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
325
326/**
327 * GeoRSS Namespace
328 */
329define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
330
331/**
332 * Media RSS Namespace
333 */
334define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
335
336/**
337 * Wrong Media RSS Namespace
338 */
339define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
340
341/**
342 * iTunes RSS Namespace
343 */
344define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
345
346/**
347 * XHTML Namespace
348 */
349define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
350
351/**
352 * IANA Link Relations Registry
353 */
354define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
355
356/**
357 * Whether we're running on PHP5
358 */
359define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
360
361/**
362 * No file source
363 */
364define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
365
366/**
367 * Remote file source
368 */
369define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
370
371/**
372 * Local file source
373 */
374define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
375
376/**
377 * fsockopen() file source
378 */
379define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
380
381/**
382 * cURL file source
383 */
384define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
385
386/**
387 * file_get_contents() file source
388 */
389define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
390
391/**
392 * SimplePie
393 *
394 * @package SimplePie
395 */
396class SimplePie
397{
398	/**
399	 * @var array Raw data
400	 * @access private
401	 */
402	var $data = array();
403
404	/**
405	 * @var mixed Error string
406	 * @access private
407	 */
408	var $error;
409
410	/**
411	 * @var object Instance of SimplePie_Sanitize (or other class)
412	 * @see SimplePie::set_sanitize_class()
413	 * @access private
414	 */
415	var $sanitize;
416
417	/**
418	 * @var string SimplePie Useragent
419	 * @see SimplePie::set_useragent()
420	 * @access private
421	 */
422	var $useragent = SIMPLEPIE_USERAGENT;
423
424	/**
425	 * @var string Feed URL
426	 * @see SimplePie::set_feed_url()
427	 * @access private
428	 */
429	var $feed_url;
430
431	/**
432	 * @var object Instance of SimplePie_File to use as a feed
433	 * @see SimplePie::set_file()
434	 * @access private
435	 */
436	var $file;
437
438	/**
439	 * @var string Raw feed data
440	 * @see SimplePie::set_raw_data()
441	 * @access private
442	 */
443	var $raw_data;
444
445	/**
446	 * @var int Timeout for fetching remote files
447	 * @see SimplePie::set_timeout()
448	 * @access private
449	 */
450	var $timeout = 10;
451
452	/**
453	 * @var bool Forces fsockopen() to be used for remote files instead
454	 * of cURL, even if a new enough version is installed
455	 * @see SimplePie::force_fsockopen()
456	 * @access private
457	 */
458	var $force_fsockopen = false;
459
460	/**
461	 * @var bool Force the given data/URL to be treated as a feed no matter what
462	 * it appears like
463	 * @see SimplePie::force_feed()
464	 * @access private
465	 */
466	var $force_feed = false;
467
468	/**
469	 * @var bool Enable/Disable XML dump
470	 * @see SimplePie::enable_xml_dump()
471	 * @access private
472	 */
473	var $xml_dump = false;
474
475	/**
476	 * @var bool Enable/Disable Caching
477	 * @see SimplePie::enable_cache()
478	 * @access private
479	 */
480	var $cache = true;
481
482	/**
483	 * @var int Cache duration (in seconds)
484	 * @see SimplePie::set_cache_duration()
485	 * @access private
486	 */
487	var $cache_duration = 3600;
488
489	/**
490	 * @var int Auto-discovery cache duration (in seconds)
491	 * @see SimplePie::set_autodiscovery_cache_duration()
492	 * @access private
493	 */
494	var $autodiscovery_cache_duration = 604800; // 7 Days.
495
496	/**
497	 * @var string Cache location (relative to executing script)
498	 * @see SimplePie::set_cache_location()
499	 * @access private
500	 */
501	var $cache_location = './cache';
502
503	/**
504	 * @var string Function that creates the cache filename
505	 * @see SimplePie::set_cache_name_function()
506	 * @access private
507	 */
508	var $cache_name_function = 'md5';
509
510	/**
511	 * @var bool Reorder feed by date descending
512	 * @see SimplePie::enable_order_by_date()
513	 * @access private
514	 */
515	var $order_by_date = true;
516
517	/**
518	 * @var mixed Force input encoding to be set to the follow value
519	 * (false, or anything type-cast to false, disables this feature)
520	 * @see SimplePie::set_input_encoding()
521	 * @access private
522	 */
523	var $input_encoding = false;
524
525	/**
526	 * @var int Feed Autodiscovery Level
527	 * @see SimplePie::set_autodiscovery_level()
528	 * @access private
529	 */
530	var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
531
532	/**
533	 * @var string Class used for caching feeds
534	 * @see SimplePie::set_cache_class()
535	 * @access private
536	 */
537	var $cache_class = 'SimplePie_Cache';
538
539	/**
540	 * @var string Class used for locating feeds
541	 * @see SimplePie::set_locator_class()
542	 * @access private
543	 */
544	var $locator_class = 'SimplePie_Locator';
545
546	/**
547	 * @var string Class used for parsing feeds
548	 * @see SimplePie::set_parser_class()
549	 * @access private
550	 */
551	var $parser_class = 'SimplePie_Parser';
552
553	/**
554	 * @var string Class used for fetching feeds
555	 * @see SimplePie::set_file_class()
556	 * @access private
557	 */
558	var $file_class = 'SimplePie_File';
559
560	/**
561	 * @var string Class used for items
562	 * @see SimplePie::set_item_class()
563	 * @access private
564	 */
565	var $item_class = 'SimplePie_Item';
566
567	/**
568	 * @var string Class used for authors
569	 * @see SimplePie::set_author_class()
570	 * @access private
571	 */
572	var $author_class = 'SimplePie_Author';
573
574	/**
575	 * @var string Class used for categories
576	 * @see SimplePie::set_category_class()
577	 * @access private
578	 */
579	var $category_class = 'SimplePie_Category';
580
581	/**
582	 * @var string Class used for enclosures
583	 * @see SimplePie::set_enclosures_class()
584	 * @access private
585	 */
586	var $enclosure_class = 'SimplePie_Enclosure';
587
588	/**
589	 * @var string Class used for Media RSS <media:text> captions
590	 * @see SimplePie::set_caption_class()
591	 * @access private
592	 */
593	var $caption_class = 'SimplePie_Caption';
594
595	/**
596	 * @var string Class used for Media RSS <media:copyright>
597	 * @see SimplePie::set_copyright_class()
598	 * @access private
599	 */
600	var $copyright_class = 'SimplePie_Copyright';
601
602	/**
603	 * @var string Class used for Media RSS <media:credit>
604	 * @see SimplePie::set_credit_class()
605	 * @access private
606	 */
607	var $credit_class = 'SimplePie_Credit';
608
609	/**
610	 * @var string Class used for Media RSS <media:rating>
611	 * @see SimplePie::set_rating_class()
612	 * @access private
613	 */
614	var $rating_class = 'SimplePie_Rating';
615
616	/**
617	 * @var string Class used for Media RSS <media:restriction>
618	 * @see SimplePie::set_restriction_class()
619	 * @access private
620	 */
621	var $restriction_class = 'SimplePie_Restriction';
622
623	/**
624	 * @var string Class used for content-type sniffing
625	 * @see SimplePie::set_content_type_sniffer_class()
626	 * @access private
627	 */
628	var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
629
630	/**
631	 * @var string Class used for item sources.
632	 * @see SimplePie::set_source_class()
633	 * @access private
634	 */
635	var $source_class = 'SimplePie_Source';
636
637	/**
638	 * @var mixed Set javascript query string parameter (false, or
639	 * anything type-cast to false, disables this feature)
640	 * @see SimplePie::set_javascript()
641	 * @access private
642	 */
643	var $javascript = 'js';
644
645	/**
646	 * @var int Maximum number of feeds to check with autodiscovery
647	 * @see SimplePie::set_max_checked_feeds()
648	 * @access private
649	 */
650	var $max_checked_feeds = 10;
651
652	/**
653	 * @var array All the feeds found during the autodiscovery process
654	 * @see SimplePie::get_all_discovered_feeds()
655	 * @access private
656	 */
657	var $all_discovered_feeds = array();
658
659	/**
660	 * @var string Web-accessible path to the handler_favicon.php file.
661	 * @see SimplePie::set_favicon_handler()
662	 * @access private
663	 */
664	var $favicon_handler = '';
665
666	/**
667	 * @var string Web-accessible path to the handler_image.php file.
668	 * @see SimplePie::set_image_handler()
669	 * @access private
670	 */
671	var $image_handler = '';
672
673	/**
674	 * @var array Stores the URLs when multiple feeds are being initialized.
675	 * @see SimplePie::set_feed_url()
676	 * @access private
677	 */
678	var $multifeed_url = array();
679
680	/**
681	 * @var array Stores SimplePie objects when multiple feeds initialized.
682	 * @access private
683	 */
684	var $multifeed_objects = array();
685
686	/**
687	 * @var array Stores the get_object_vars() array for use with multifeeds.
688	 * @see SimplePie::set_feed_url()
689	 * @access private
690	 */
691	var $config_settings = null;
692
693	/**
694	 * @var integer Stores the number of items to return per-feed with multifeeds.
695	 * @see SimplePie::set_item_limit()
696	 * @access private
697	 */
698	var $item_limit = 0;
699
700	/**
701	 * @var array Stores the default attributes to be stripped by strip_attributes().
702	 * @see SimplePie::strip_attributes()
703	 * @access private
704	 */
705	var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
706
707	/**
708	 * @var array Stores the default tags to be stripped by strip_htmltags().
709	 * @see SimplePie::strip_htmltags()
710	 * @access private
711	 */
712	var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
713
714	/**
715	 * The SimplePie class contains feed level data and options
716	 *
717	 * There are two ways that you can create a new SimplePie object. The first
718	 * is by passing a feed URL as a parameter to the SimplePie constructor
719	 * (as well as optionally setting the cache location and cache expiry). This
720	 * will initialise the whole feed with all of the default settings, and you
721	 * can begin accessing methods and properties immediately.
722	 *
723	 * The second way is to create the SimplePie object with no parameters
724	 * at all. This will enable you to set configuration options. After setting
725	 * them, you must initialise the feed using $feed->init(). At that point the
726	 * object's methods and properties will be available to you. This format is
727	 * what is used throughout this documentation.
728	 *
729	 * @access public
730	 * @since 1.0 Preview Release
731	 * @param string $feed_url This is the URL you want to parse.
732	 * @param string $cache_location This is where you want the cache to be stored.
733	 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
734	 */
735	function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
736	{
737		// Other objects, instances created here so we can set options on them
738		$this->sanitize =& new SimplePie_Sanitize;
739
740		// Set options if they're passed to the constructor
741		if ($cache_location !== null)
742		{
743			$this->set_cache_location($cache_location);
744		}
745
746		if ($cache_duration !== null)
747		{
748			$this->set_cache_duration($cache_duration);
749		}
750
751		// Only init the script if we're passed a feed URL
752		if ($feed_url !== null)
753		{
754			$this->set_feed_url($feed_url);
755			$this->init();
756		}
757	}
758
759	/**
760	 * Used for converting object to a string
761	 */
762	function __toString()
763	{
764		return md5(serialize($this->data));
765	}
766
767	/**
768	 * Remove items that link back to this before destroying this object
769	 */
770	function __destruct()
771	{
772		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
773		{
774			if (!empty($this->data['items']))
775			{
776				foreach ($this->data['items'] as $item)
777				{
778					$item->__destruct();
779				}
780				unset($item, $this->data['items']);
781			}
782			if (!empty($this->data['ordered_items']))
783			{
784				foreach ($this->data['ordered_items'] as $item)
785				{
786					$item->__destruct();
787				}
788				unset($item, $this->data['ordered_items']);
789			}
790		}
791	}
792
793	/**
794	 * Force the given data/URL to be treated as a feed no matter what it
795	 * appears like
796	 *
797	 * @access public
798	 * @since 1.1
799	 * @param bool $enable Force the given data/URL to be treated as a feed
800	 */
801	function force_feed($enable = false)
802	{
803		$this->force_feed = (bool) $enable;
804	}
805
806	/**
807	 * This is the URL of the feed you want to parse.
808	 *
809	 * This allows you to enter the URL of the feed you want to parse, or the
810	 * website you want to try to use auto-discovery on. This takes priority
811	 * over any set raw data.
812	 *
813	 * You can set multiple feeds to mash together by passing an array instead
814	 * of a string for the $url. Remember that with each additional feed comes
815	 * additional processing and resources.
816	 *
817	 * @access public
818	 * @since 1.0 Preview Release
819	 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
820	 * @see SimplePie::set_raw_data()
821	 */
822	function set_feed_url($url)
823	{
824		if (is_array($url))
825		{
826			$this->multifeed_url = array();
827			foreach ($url as $value)
828			{
829				$this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
830			}
831		}
832		else
833		{
834			$this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
835		}
836	}
837
838	/**
839	 * Provides an instance of SimplePie_File to use as a feed
840	 *
841	 * @access public
842	 * @param object &$file Instance of SimplePie_File (or subclass)
843	 * @return bool True on success, false on failure
844	 */
845	function set_file(&$file)
846	{
847		if (is_a($file, 'SimplePie_File'))
848		{
849			$this->feed_url = $file->url;
850			$this->file =& $file;
851			return true;
852		}
853		return false;
854	}
855
856	/**
857	 * Allows you to use a string of RSS/Atom data instead of a remote feed.
858	 *
859	 * If you have a feed available as a string in PHP, you can tell SimplePie
860	 * to parse that data string instead of a remote feed. Any set feed URL
861	 * takes precedence.
862	 *
863	 * @access public
864	 * @since 1.0 Beta 3
865	 * @param string $data RSS or Atom data as a string.
866	 * @see SimplePie::set_feed_url()
867	 */
868	function set_raw_data($data)
869	{
870		$this->raw_data = $data;
871	}
872
873	/**
874	 * Allows you to override the default timeout for fetching remote feeds.
875	 *
876	 * This allows you to change the maximum time the feed's server to respond
877	 * and send the feed back.
878	 *
879	 * @access public
880	 * @since 1.0 Beta 3
881	 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
882	 */
883	function set_timeout($timeout = 10)
884	{
885		$this->timeout = (int) $timeout;
886	}
887
888	/**
889	 * Forces SimplePie to use fsockopen() instead of the preferred cURL
890	 * functions.
891	 *
892	 * @access public
893	 * @since 1.0 Beta 3
894	 * @param bool $enable Force fsockopen() to be used
895	 */
896	function force_fsockopen($enable = false)
897	{
898		$this->force_fsockopen = (bool) $enable;
899	}
900
901	/**
902	 * Outputs the raw XML content of the feed, after it has gone through
903	 * SimplePie's filters.
904	 *
905	 * Used only for debugging, this function will output the XML content as
906	 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
907	 * before trying to parse it. Many parts of the feed are re-written in
908	 * memory, and in the end, you have a parsable feed. XML dump shows you the
909	 * actual XML that SimplePie tries to parse, which may or may not be very
910	 * different from the original feed.
911	 *
912	 * @access public
913	 * @since 1.0 Preview Release
914	 * @param bool $enable Enable XML dump
915	 */
916	function enable_xml_dump($enable = false)
917	{
918		$this->xml_dump = (bool) $enable;
919	}
920
921	/**
922	 * Enables/disables caching in SimplePie.
923	 *
924	 * This option allows you to disable caching all-together in SimplePie.
925	 * However, disabling the cache can lead to longer load times.
926	 *
927	 * @access public
928	 * @since 1.0 Preview Release
929	 * @param bool $enable Enable caching
930	 */
931	function enable_cache($enable = true)
932	{
933		$this->cache = (bool) $enable;
934	}
935
936	/**
937	 * Set the length of time (in seconds) that the contents of a feed
938	 * will be cached.
939	 *
940	 * @access public
941	 * @param int $seconds The feed content cache duration.
942	 */
943	function set_cache_duration($seconds = 3600)
944	{
945		$this->cache_duration = (int) $seconds;
946	}
947
948	/**
949	 * Set the length of time (in seconds) that the autodiscovered feed
950	 * URL will be cached.
951	 *
952	 * @access public
953	 * @param int $seconds The autodiscovered feed URL cache duration.
954	 */
955	function set_autodiscovery_cache_duration($seconds = 604800)
956	{
957		$this->autodiscovery_cache_duration = (int) $seconds;
958	}
959
960	/**
961	 * Set the file system location where the cached files should be stored.
962	 *
963	 * @access public
964	 * @param string $location The file system location.
965	 */
966	function set_cache_location($location = './cache')
967	{
968		$this->cache_location = (string) $location;
969	}
970
971	/**
972	 * Determines whether feed items should be sorted into reverse chronological order.
973	 *
974	 * @access public
975	 * @param bool $enable Sort as reverse chronological order.
976	 */
977	function enable_order_by_date($enable = true)
978	{
979		$this->order_by_date = (bool) $enable;
980	}
981
982	/**
983	 * Allows you to override the character encoding reported by the feed.
984	 *
985	 * @access public
986	 * @param string $encoding Character encoding.
987	 */
988	function set_input_encoding($encoding = false)
989	{
990		if ($encoding)
991		{
992			$this->input_encoding = (string) $encoding;
993		}
994		else
995		{
996			$this->input_encoding = false;
997		}
998	}
999
1000	/**
1001	 * Set how much feed autodiscovery to do
1002	 *
1003	 * @access public
1004	 * @see SIMPLEPIE_LOCATOR_NONE
1005	 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1006	 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1007	 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1008	 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1009	 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1010	 * @see SIMPLEPIE_LOCATOR_ALL
1011	 * @param int $level Feed Autodiscovery Level (level can be a
1012	 * combination of the above constants, see bitwise OR operator)
1013	 */
1014	function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1015	{
1016		$this->autodiscovery = (int) $level;
1017	}
1018
1019	/**
1020	 * Allows you to change which class SimplePie uses for caching.
1021	 * Useful when you are overloading or extending SimplePie's default classes.
1022	 *
1023	 * @access public
1024	 * @param string $class Name of custom class.
1025	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1026	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1027	 */
1028	function set_cache_class($class = 'SimplePie_Cache')
1029	{
1030		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1031		{
1032			$this->cache_class = $class;
1033			return true;
1034		}
1035		return false;
1036	}
1037
1038	/**
1039	 * Allows you to change which class SimplePie uses for auto-discovery.
1040	 * Useful when you are overloading or extending SimplePie's default classes.
1041	 *
1042	 * @access public
1043	 * @param string $class Name of custom class.
1044	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1045	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1046	 */
1047	function set_locator_class($class = 'SimplePie_Locator')
1048	{
1049		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1050		{
1051			$this->locator_class = $class;
1052			return true;
1053		}
1054		return false;
1055	}
1056
1057	/**
1058	 * Allows you to change which class SimplePie uses for XML parsing.
1059	 * Useful when you are overloading or extending SimplePie's default classes.
1060	 *
1061	 * @access public
1062	 * @param string $class Name of custom class.
1063	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1064	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1065	 */
1066	function set_parser_class($class = 'SimplePie_Parser')
1067	{
1068		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1069		{
1070			$this->parser_class = $class;
1071			return true;
1072		}
1073		return false;
1074	}
1075
1076	/**
1077	 * Allows you to change which class SimplePie uses for remote file fetching.
1078	 * Useful when you are overloading or extending SimplePie's default classes.
1079	 *
1080	 * @access public
1081	 * @param string $class Name of custom class.
1082	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1083	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1084	 */
1085	function set_file_class($class = 'SimplePie_File')
1086	{
1087		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1088		{
1089			$this->file_class = $class;
1090			return true;
1091		}
1092		return false;
1093	}
1094
1095	/**
1096	 * Allows you to change which class SimplePie uses for data sanitization.
1097	 * Useful when you are overloading or extending SimplePie's default classes.
1098	 *
1099	 * @access public
1100	 * @param string $class Name of custom class.
1101	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1102	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1103	 */
1104	function set_sanitize_class($class = 'SimplePie_Sanitize')
1105	{
1106		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1107		{
1108			$this->sanitize =& new $class;
1109			return true;
1110		}
1111		return false;
1112	}
1113
1114	/**
1115	 * Allows you to change which class SimplePie uses for handling feed items.
1116	 * Useful when you are overloading or extending SimplePie's default classes.
1117	 *
1118	 * @access public
1119	 * @param string $class Name of custom class.
1120	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1121	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1122	 */
1123	function set_item_class($class = 'SimplePie_Item')
1124	{
1125		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1126		{
1127			$this->item_class = $class;
1128			return true;
1129		}
1130		return false;
1131	}
1132
1133	/**
1134	 * Allows you to change which class SimplePie uses for handling author data.
1135	 * Useful when you are overloading or extending SimplePie's default classes.
1136	 *
1137	 * @access public
1138	 * @param string $class Name of custom class.
1139	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1140	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1141	 */
1142	function set_author_class($class = 'SimplePie_Author')
1143	{
1144		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1145		{
1146			$this->author_class = $class;
1147			return true;
1148		}
1149		return false;
1150	}
1151
1152	/**
1153	 * Allows you to change which class SimplePie uses for handling category data.
1154	 * Useful when you are overloading or extending SimplePie's default classes.
1155	 *
1156	 * @access public
1157	 * @param string $class Name of custom class.
1158	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1159	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1160	 */
1161	function set_category_class($class = 'SimplePie_Category')
1162	{
1163		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1164		{
1165			$this->category_class = $class;
1166			return true;
1167		}
1168		return false;
1169	}
1170
1171	/**
1172	 * Allows you to change which class SimplePie uses for feed enclosures.
1173	 * Useful when you are overloading or extending SimplePie's default classes.
1174	 *
1175	 * @access public
1176	 * @param string $class Name of custom class.
1177	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1178	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1179	 */
1180	function set_enclosure_class($class = 'SimplePie_Enclosure')
1181	{
1182		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1183		{
1184			$this->enclosure_class = $class;
1185			return true;
1186		}
1187		return false;
1188	}
1189
1190	/**
1191	 * Allows you to change which class SimplePie uses for <media:text> captions
1192	 * Useful when you are overloading or extending SimplePie's default classes.
1193	 *
1194	 * @access public
1195	 * @param string $class Name of custom class.
1196	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1197	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1198	 */
1199	function set_caption_class($class = 'SimplePie_Caption')
1200	{
1201		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1202		{
1203			$this->caption_class = $class;
1204			return true;
1205		}
1206		return false;
1207	}
1208
1209	/**
1210	 * Allows you to change which class SimplePie uses for <media:copyright>
1211	 * Useful when you are overloading or extending SimplePie's default classes.
1212	 *
1213	 * @access public
1214	 * @param string $class Name of custom class.
1215	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1216	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1217	 */
1218	function set_copyright_class($class = 'SimplePie_Copyright')
1219	{
1220		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1221		{
1222			$this->copyright_class = $class;
1223			return true;
1224		}
1225		return false;
1226	}
1227
1228	/**
1229	 * Allows you to change which class SimplePie uses for <media:credit>
1230	 * Useful when you are overloading or extending SimplePie's default classes.
1231	 *
1232	 * @access public
1233	 * @param string $class Name of custom class.
1234	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1235	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1236	 */
1237	function set_credit_class($class = 'SimplePie_Credit')
1238	{
1239		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1240		{
1241			$this->credit_class = $class;
1242			return true;
1243		}
1244		return false;
1245	}
1246
1247	/**
1248	 * Allows you to change which class SimplePie uses for <media:rating>
1249	 * Useful when you are overloading or extending SimplePie's default classes.
1250	 *
1251	 * @access public
1252	 * @param string $class Name of custom class.
1253	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1254	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1255	 */
1256	function set_rating_class($class = 'SimplePie_Rating')
1257	{
1258		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1259		{
1260			$this->rating_class = $class;
1261			return true;
1262		}
1263		return false;
1264	}
1265
1266	/**
1267	 * Allows you to change which class SimplePie uses for <media:restriction>
1268	 * Useful when you are overloading or extending SimplePie's default classes.
1269	 *
1270	 * @access public
1271	 * @param string $class Name of custom class.
1272	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1273	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1274	 */
1275	function set_restriction_class($class = 'SimplePie_Restriction')
1276	{
1277		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1278		{
1279			$this->restriction_class = $class;
1280			return true;
1281		}
1282		return false;
1283	}
1284
1285	/**
1286	 * Allows you to change which class SimplePie uses for content-type sniffing.
1287	 * Useful when you are overloading or extending SimplePie's default classes.
1288	 *
1289	 * @access public
1290	 * @param string $class Name of custom class.
1291	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1292	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1293	 */
1294	function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1295	{
1296		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1297		{
1298			$this->content_type_sniffer_class = $class;
1299			return true;
1300		}
1301		return false;
1302	}
1303
1304	/**
1305	 * Allows you to change which class SimplePie uses item sources.
1306	 * Useful when you are overloading or extending SimplePie's default classes.
1307	 *
1308	 * @access public
1309	 * @param string $class Name of custom class.
1310	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1311	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1312	 */
1313	function set_source_class($class = 'SimplePie_Source')
1314	{
1315		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1316		{
1317			$this->source_class = $class;
1318			return true;
1319		}
1320		return false;
1321	}
1322
1323	/**
1324	 * Allows you to override the default user agent string.
1325	 *
1326	 * @access public
1327	 * @param string $ua New user agent string.
1328	 */
1329	function set_useragent($ua = SIMPLEPIE_USERAGENT)
1330	{
1331		$this->useragent = (string) $ua;
1332	}
1333
1334	/**
1335	 * Set callback function to create cache filename with
1336	 *
1337	 * @access public
1338	 * @param mixed $function Callback function
1339	 */
1340	function set_cache_name_function($function = 'md5')
1341	{
1342		if (is_callable($function))
1343		{
1344			$this->cache_name_function = $function;
1345		}
1346	}
1347
1348	/**
1349	 * Set javascript query string parameter
1350	 *
1351	 * @access public
1352	 * @param mixed $get Javascript query string parameter
1353	 */
1354	function set_javascript($get = 'js')
1355	{
1356		if ($get)
1357		{
1358			$this->javascript = (string) $get;
1359		}
1360		else
1361		{
1362			$this->javascript = false;
1363		}
1364	}
1365
1366	/**
1367	 * Set options to make SP as fast as possible.  Forgoes a
1368	 * substantial amount of data sanitization in favor of speed.
1369	 *
1370	 * @access public
1371	 * @param bool $set Whether to set them or not
1372	 */
1373	function set_stupidly_fast($set = false)
1374	{
1375		if ($set)
1376		{
1377			$this->enable_order_by_date(false);
1378			$this->remove_div(false);
1379			$this->strip_comments(false);
1380			$this->strip_htmltags(false);
1381			$this->strip_attributes(false);
1382			$this->set_image_handler(false);
1383		}
1384	}
1385
1386	/**
1387	 * Set maximum number of feeds to check with autodiscovery
1388	 *
1389	 * @access public
1390	 * @param int $max Maximum number of feeds to check
1391	 */
1392	function set_max_checked_feeds($max = 10)
1393	{
1394		$this->max_checked_feeds = (int) $max;
1395	}
1396
1397	function remove_div($enable = true)
1398	{
1399		$this->sanitize->remove_div($enable);
1400	}
1401
1402	function strip_htmltags($tags = '', $encode = null)
1403	{
1404		if ($tags === '')
1405		{
1406			$tags = $this->strip_htmltags;
1407		}
1408		$this->sanitize->strip_htmltags($tags);
1409		if ($encode !== null)
1410		{
1411			$this->sanitize->encode_instead_of_strip($tags);
1412		}
1413	}
1414
1415	function encode_instead_of_strip($enable = true)
1416	{
1417		$this->sanitize->encode_instead_of_strip($enable);
1418	}
1419
1420	function strip_attributes($attribs = '')
1421	{
1422		if ($attribs === '')
1423		{
1424			$attribs = $this->strip_attributes;
1425		}
1426		$this->sanitize->strip_attributes($attribs);
1427	}
1428
1429	function set_output_encoding($encoding = 'UTF-8')
1430	{
1431		$this->sanitize->set_output_encoding($encoding);
1432	}
1433
1434	function strip_comments($strip = false)
1435	{
1436		$this->sanitize->strip_comments($strip);
1437	}
1438
1439	/**
1440	 * Set element/attribute key/value pairs of HTML attributes
1441	 * containing URLs that need to be resolved relative to the feed
1442	 *
1443	 * @access public
1444	 * @since 1.0
1445	 * @param array $element_attribute Element/attribute key/value pairs
1446	 */
1447	function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1448	{
1449		$this->sanitize->set_url_replacements($element_attribute);
1450	}
1451
1452	/**
1453	 * Set the handler to enable the display of cached favicons.
1454	 *
1455	 * @access public
1456	 * @param str $page Web-accessible path to the handler_favicon.php file.
1457	 * @param str $qs The query string that the value should be passed to.
1458	 */
1459	function set_favicon_handler($page = false, $qs = 'i')
1460	{
1461		if ($page !== false)
1462		{
1463			$this->favicon_handler = $page . '?' . $qs . '=';
1464		}
1465		else
1466		{
1467			$this->favicon_handler = '';
1468		}
1469	}
1470
1471	/**
1472	 * Set the handler to enable the display of cached images.
1473	 *
1474	 * @access public
1475	 * @param str $page Web-accessible path to the handler_image.php file.
1476	 * @param str $qs The query string that the value should be passed to.
1477	 */
1478	function set_image_handler($page = false, $qs = 'i')
1479	{
1480		if ($page !== false)
1481		{
1482			$this->sanitize->set_image_handler($page . '?' . $qs . '=');
1483		}
1484		else
1485		{
1486			$this->image_handler = '';
1487		}
1488	}
1489
1490	/**
1491	 * Set the limit for items returned per-feed with multifeeds.
1492	 *
1493	 * @access public
1494	 * @param integer $limit The maximum number of items to return.
1495	 */
1496	function set_item_limit($limit = 0)
1497	{
1498		$this->item_limit = (int) $limit;
1499	}
1500
1501	function init()
1502	{
1503		// Check absolute bare minimum requirements.
1504		if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1505		{
1506			return false;
1507		}
1508		// Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1509		elseif (!extension_loaded('xmlreader'))
1510		{
1511			static $xml_is_sane = null;
1512			if ($xml_is_sane === null)
1513			{
1514				$parser_check = xml_parser_create();
1515				xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1516				xml_parser_free($parser_check);
1517				$xml_is_sane = isset($values[0]['value']);
1518			}
1519			if (!$xml_is_sane)
1520			{
1521				return false;
1522			}
1523		}
1524
1525		if (isset($_GET[$this->javascript]))
1526		{
1527			SimplePie_Misc::output_javascript();
1528			exit;
1529		}
1530
1531		// Pass whatever was set with config options over to the sanitizer.
1532		$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1533		$this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1534
1535		if ($this->feed_url !== null || $this->raw_data !== null)
1536		{
1537			$this->data = array();
1538			$this->multifeed_objects = array();
1539			$cache = false;
1540
1541			if ($this->feed_url !== null)
1542			{
1543				$parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1544				// Decide whether to enable caching
1545				if ($this->cache && $parsed_feed_url['scheme'] !== '')
1546				{
1547					$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1548				}
1549				// If it's enabled and we don't want an XML dump, use the cache
1550				if ($cache && !$this->xml_dump)
1551				{
1552					// Load the Cache
1553					$this->data = $cache->load();
1554					if (!empty($this->data))
1555					{
1556						// If the cache is for an outdated build of SimplePie
1557						if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1558						{
1559							$cache->unlink();
1560							$this->data = array();
1561						}
1562						// If we've hit a collision just rerun it with caching disabled
1563						elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1564						{
1565							$cache = false;
1566							$this->data = array();
1567						}
1568						// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1569						elseif (isset($this->data['feed_url']))
1570						{
1571							// If the autodiscovery cache is still valid use it.
1572							if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1573							{
1574								// Do not need to do feed autodiscovery yet.
1575								if ($this->data['feed_url'] === $this->data['url'])
1576								{
1577									$cache->unlink();
1578									$this->data = array();
1579								}
1580								else
1581								{
1582									$this->set_feed_url($this->data['feed_url']);
1583									return $this->init();
1584								}
1585							}
1586						}
1587						// Check if the cache has been updated
1588						elseif ($cache->mtime() + $this->cache_duration < time())
1589						{
1590							// If we have last-modified and/or etag set
1591							if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1592							{
1593								$headers = array();
1594								if (isset($this->data['headers']['last-modified']))
1595								{
1596									$headers['if-modified-since'] = $this->data['headers']['last-modified'];
1597								}
1598								if (isset($this->data['headers']['etag']))
1599								{
1600									$headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1601								}
1602								$file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1603								if ($file->success)
1604								{
1605									if ($file->status_code === 304)
1606									{
1607										$cache->touch();
1608										return true;
1609									}
1610									else
1611									{
1612										$headers = $file->headers;
1613									}
1614								}
1615								else
1616								{
1617									unset($file);
1618								}
1619							}
1620						}
1621						// If the cache is still valid, just return true
1622						else
1623						{
1624							return true;
1625						}
1626					}
1627					// If the cache is empty, delete it
1628					else
1629					{
1630						$cache->unlink();
1631						$this->data = array();
1632					}
1633				}
1634				// If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
1635				if (!isset($file))
1636				{
1637					if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1638					{
1639						$file =& $this->file;
1640					}
1641					else
1642					{
1643						$file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1644					}
1645				}
1646				// If the file connection has an error, set SimplePie::error to that and quit
1647				if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1648				{
1649					$this->error = $file->error;
1650					if (!empty($this->data))
1651					{
1652						return true;
1653					}
1654					else
1655					{
1656						return false;
1657					}
1658				}
1659
1660				if (!$this->force_feed)
1661				{
1662					// Check if the supplied URL is a feed, if it isn't, look for it.
1663					$locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1664					if (!$locate->is_feed($file))
1665					{
1666						// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1667						unset($file);
1668						if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1669						{
1670							if ($cache)
1671							{
1672								$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673								if (!$cache->save($this))
1674								{
1675									trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
1676								}
1677								$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1678							}
1679							$this->feed_url = $file->url;
1680						}
1681						else
1682						{
1683							$this->error = "A feed could not be found at $this->feed_url";
1684							SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1685							return false;
1686						}
1687					}
1688					$locate = null;
1689				}
1690
1691				$headers = $file->headers;
1692				$data = $file->body;
1693				$sniffer =& new $this->content_type_sniffer_class($file);
1694				$sniffed = $sniffer->get_type();
1695			}
1696			else
1697			{
1698				$data = $this->raw_data;
1699			}
1700
1701			// Set up array of possible encodings
1702			$encodings = array();
1703
1704			// First check to see if input has been overridden.
1705			if ($this->input_encoding !== false)
1706			{
1707				$encodings[] = $this->input_encoding;
1708			}
1709
1710			$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1711			$text_types = array('text/xml', 'text/xml-external-parsed-entity');
1712
1713			// RFC 3023 (only applies to sniffed content)
1714			if (isset($sniffed))
1715			{
1716				if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1717				{
1718					if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1719					{
1720						$encodings[] = strtoupper($charset[1]);
1721					}
1722					$encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723					$encodings[] = 'UTF-8';
1724				}
1725				elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1726				{
1727					if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1728					{
1729						$encodings[] = $charset[1];
1730					}
1731					$encodings[] = 'US-ASCII';
1732				}
1733				// Text MIME-type default
1734				elseif (substr($sniffed, 0, 5) === 'text/')
1735				{
1736					$encodings[] = 'US-ASCII';
1737				}
1738			}
1739
1740			// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1741			$encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1742			$encodings[] = 'UTF-8';
1743			$encodings[] = 'ISO-8859-1';
1744
1745			// There's no point in trying an encoding twice
1746			$encodings = array_unique($encodings);
1747
1748			// If we want the XML, just output that with the most likely encoding and quit
1749			if ($this->xml_dump)
1750			{
1751				header('Content-type: text/xml; charset=' . $encodings[0]);
1752				echo $data;
1753				exit;
1754			}
1755
1756			// Loop through each possible encoding, till we return something, or run out of possibilities
1757			foreach ($encodings as $encoding)
1758			{
1759				// Change the encoding to UTF-8 (as we always use UTF-8 internally)
1760				if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1761				{
1762					// Create new parser
1763					$parser =& new $this->parser_class();
1764
1765					// If it's parsed fine
1766					if ($parser->parse($utf8_data, 'UTF-8'))
1767					{
1768						$this->data = $parser->get_data();
1769						if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1770						{
1771							if (isset($headers))
1772							{
1773								$this->data['headers'] = $headers;
1774							}
1775							$this->data['build'] = SIMPLEPIE_BUILD;
1776
1777							// Cache the file if caching is enabled
1778							if ($cache && !$cache->save($this))
1779							{
1780								trigger_error("$cache->name is not writeable", E_USER_WARNING);
1781							}
1782							return true;
1783						}
1784						else
1785						{
1786							$this->error = "A feed could not be found at $this->feed_url";
1787							SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1788							return false;
1789						}
1790					}
1791				}
1792			}
1793			if(isset($parser))
1794			{
1795				// We have an error, just set SimplePie_Misc::error to it and quit
1796				$this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1797			}
1798			else
1799			{
1800				$this->error = 'The data could not be converted to UTF-8';
1801			}
1802			SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1803			return false;
1804		}
1805		elseif (!empty($this->multifeed_url))
1806		{
1807			$i = 0;
1808			$success = 0;
1809			$this->multifeed_objects = array();
1810			foreach ($this->multifeed_url as $url)
1811			{
1812				if (SIMPLEPIE_PHP5)
1813				{
1814					// This keyword needs to defy coding standards for PHP4 compatibility
1815					$this->multifeed_objects[$i] = clone($this);
1816				}
1817				else
1818				{
1819					$this->multifeed_objects[$i] = $this;
1820				}
1821				$this->multifeed_objects[$i]->set_feed_url($url);
1822				$success |= $this->multifeed_objects[$i]->init();
1823				$i++;
1824			}
1825			return (bool) $success;
1826		}
1827		else
1828		{
1829			return false;
1830		}
1831	}
1832
1833	/**
1834	 * Return the error message for the occured error
1835	 *
1836	 * @access public
1837	 * @return string Error message
1838	 */
1839	function error()
1840	{
1841		return $this->error;
1842	}
1843
1844	function get_encoding()
1845	{
1846		return $this->sanitize->output_encoding;
1847	}
1848
1849	function handle_content_type($mime = 'text/html')
1850	{
1851		if (!headers_sent())
1852		{
1853			$header = "Content-type: $mime;";
1854			if ($this->get_encoding())
1855			{
1856				$header .= ' charset=' . $this->get_encoding();
1857			}
1858			else
1859			{
1860				$header .= ' charset=UTF-8';
1861			}
1862			header($header);
1863		}
1864	}
1865
1866	function get_type()
1867	{
1868		if (!isset($this->data['type']))
1869		{
1870			$this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1872			{
1873				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1874			}
1875			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1876			{
1877				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1878			}
1879			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1880			{
1881				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1882				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1883				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1884				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1885				{
1886					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1887				}
1888				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1889				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1890				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1891				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1892				{
1893					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1894				}
1895			}
1896			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1897			{
1898				$this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1900				{
1901					switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1902					{
1903						case '0.91':
1904							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1905							if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1906							{
1907								switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1908								{
1909									case '0':
1910										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1911										break;
1912
1913									case '24':
1914										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1915										break;
1916								}
1917							}
1918							break;
1919
1920						case '0.92':
1921							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1922							break;
1923
1924						case '0.93':
1925							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1926							break;
1927
1928						case '0.94':
1929							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1930							break;
1931
1932						case '2.0':
1933							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1934							break;
1935					}
1936				}
1937			}
1938			else
1939			{
1940				$this->data['type'] = SIMPLEPIE_TYPE_NONE;
1941			}
1942		}
1943		return $this->data['type'];
1944	}
1945
1946	/**
1947	 * Returns the URL for the favicon of the feed's website.
1948	 *
1949	 * @todo Cache atom:icon
1950	 * @access public
1951	 * @since 1.0
1952	 */
1953	function get_favicon()
1954	{
1955		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1956		{
1957			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1958		}
1959		elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1960		{
1961			$favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1962
1963			if ($this->cache && $this->favicon_handler)
1964			{
1965				$favicon_filename = call_user_func($this->cache_name_function, $favicon);
1966				$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1967
1968				if ($cache->load())
1969				{
1970					return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1971				}
1972				else
1973				{
1974					$file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1975
1976					if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1977					{
1978						$sniffer =& new $this->content_type_sniffer_class($file);
1979						if (substr($sniffer->get_type(), 0, 6) === 'image/')
1980						{
1981							if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1982							{
1983								return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1984							}
1985							else
1986							{
1987								trigger_error("$cache->name is not writeable", E_USER_WARNING);
1988								return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1989							}
1990						}
1991						// not an image
1992						else
1993						{
1994							return false;
1995						}
1996					}
1997				}
1998			}
1999			else
2000			{
2001				return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2002			}
2003		}
2004		return false;
2005	}
2006
2007	/**
2008	 * @todo If we have a perm redirect we should return the new URL
2009	 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2010	 * @todo Also, |atom:link|@rel=self
2011	 */
2012	function subscribe_url()
2013	{
2014		if ($this->feed_url !== null)
2015		{
2016			return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2017		}
2018		else
2019		{
2020			return null;
2021		}
2022	}
2023
2024	function subscribe_feed()
2025	{
2026		if ($this->feed_url !== null)
2027		{
2028			return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2029		}
2030		else
2031		{
2032			return null;
2033		}
2034	}
2035
2036	function subscribe_outlook()
2037	{
2038		if ($this->feed_url !== null)
2039		{
2040			return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2041		}
2042		else
2043		{
2044			return null;
2045		}
2046	}
2047
2048	function subscribe_podcast()
2049	{
2050		if ($this->feed_url !== null)
2051		{
2052			return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2053		}
2054		else
2055		{
2056			return null;
2057		}
2058	}
2059
2060	function subscribe_itunes()
2061	{
2062		if ($this->feed_url !== null)
2063		{
2064			return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2065		}
2066		else
2067		{
2068			return null;
2069		}
2070	}
2071
2072	/**
2073	 * Creates the subscribe_* methods' return data
2074	 *
2075	 * @access private
2076	 * @param string $feed_url String to prefix to the feed URL
2077	 * @param string $site_url String to prefix to the site URL (and
2078	 * suffix to the feed URL)
2079	 * @return mixed URL if feed exists, false otherwise
2080	 */
2081	function subscribe_service($feed_url, $site_url = null)
2082	{
2083		if ($this->subscribe_url())
2084		{
2085			$return = $feed_url . rawurlencode($this->feed_url);
2086			if ($site_url !== null && $this->get_link() !== null)
2087			{
2088				$return .= $site_url . rawurlencode($this->get_link());
2089			}
2090			return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2091		}
2092		else
2093		{
2094			return null;
2095		}
2096	}
2097
2098	function subscribe_aol()
2099	{
2100		return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2101	}
2102
2103	function subscribe_bloglines()
2104	{
2105		return $this->subscribe_service('http://www.bloglines.com/sub/');
2106	}
2107
2108	function subscribe_eskobo()
2109	{
2110		return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2111	}
2112
2113	function subscribe_feedfeeds()
2114	{
2115		return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2116	}
2117
2118	function subscribe_feedster()
2119	{
2120		return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2121	}
2122
2123	function subscribe_google()
2124	{
2125		return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2126	}
2127
2128	function subscribe_gritwire()
2129	{
2130		return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2131	}
2132
2133	function subscribe_msn()
2134	{
2135		return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2136	}
2137
2138	function subscribe_netvibes()
2139	{
2140		return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2141	}
2142
2143	function subscribe_newsburst()
2144	{
2145		return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2146	}
2147
2148	function subscribe_newsgator()
2149	{
2150		return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2151	}
2152
2153	function subscribe_odeo()
2154	{
2155		return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2156	}
2157
2158	function subscribe_podnova()
2159	{
2160		return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2161	}
2162
2163	function subscribe_rojo()
2164	{
2165		return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2166	}
2167
2168	function subscribe_yahoo()
2169	{
2170		return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2171	}
2172
2173	function get_feed_tags($namespace, $tag)
2174	{
2175		$type = $this->get_type();
2176		if ($type & SIMPLEPIE_TYPE_ATOM_10)
2177		{
2178			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2179			{
2180				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2181			}
2182		}
2183		if ($type & SIMPLEPIE_TYPE_ATOM_03)
2184		{
2185			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2186			{
2187				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2188			}
2189		}
2190		if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2191		{
2192			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2193			{
2194				return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2195			}
2196		}
2197		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2198		{
2199			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2200			{
2201				return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2202			}
2203		}
2204		return null;
2205	}
2206
2207	function get_channel_tags($namespace, $tag)
2208	{
2209		$type = $this->get_type();
2210		if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2211		{
2212			if ($return = $this->get_feed_tags($namespace, $tag))
2213			{
2214				return $return;
2215			}
2216		}
2217		if ($type & SIMPLEPIE_TYPE_RSS_10)
2218		{
2219			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2220			{
2221				if (isset($channel[0]['child'][$namespace][$tag]))
2222				{
2223					return $channel[0]['child'][$namespace][$tag];
2224				}
2225			}
2226		}
2227		if ($type & SIMPLEPIE_TYPE_RSS_090)
2228		{
2229			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2230			{
2231				if (isset($channel[0]['child'][$namespace][$tag]))
2232				{
2233					return $channel[0]['child'][$namespace][$tag];
2234				}
2235			}
2236		}
2237		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2238		{
2239			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2240			{
2241				if (isset($channel[0]['child'][$namespace][$tag]))
2242				{
2243					return $channel[0]['child'][$namespace][$tag];
2244				}
2245			}
2246		}
2247		return null;
2248	}
2249
2250	function get_image_tags($namespace, $tag)
2251	{
2252		$type = $this->get_type();
2253		if ($type & SIMPLEPIE_TYPE_RSS_10)
2254		{
2255			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2256			{
2257				if (isset($image[0]['child'][$namespace][$tag]))
2258				{
2259					return $image[0]['child'][$namespace][$tag];
2260				}
2261			}
2262		}
2263		if ($type & SIMPLEPIE_TYPE_RSS_090)
2264		{
2265			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2266			{
2267				if (isset($image[0]['child'][$namespace][$tag]))
2268				{
2269					return $image[0]['child'][$namespace][$tag];
2270				}
2271			}
2272		}
2273		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2274		{
2275			if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2276			{
2277				if (isset($image[0]['child'][$namespace][$tag]))
2278				{
2279					return $image[0]['child'][$namespace][$tag];
2280				}
2281			}
2282		}
2283		return null;
2284	}
2285
2286	function get_base($element = array())
2287	{
2288		if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2289		{
2290			return $element['xml_base'];
2291		}
2292		elseif ($this->get_link() !== null)
2293		{
2294			return $this->get_link();
2295		}
2296		else
2297		{
2298			return $this->subscribe_url();
2299		}
2300	}
2301
2302	function sanitize($data, $type, $base = '')
2303	{
2304		return $this->sanitize->sanitize($data, $type, $base);
2305	}
2306
2307	function get_title()
2308	{
2309		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2310		{
2311			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2312		}
2313		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2314		{
2315			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2316		}
2317		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2318		{
2319			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2320		}
2321		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2322		{
2323			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2324		}
2325		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2326		{
2327			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2328		}
2329		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2330		{
2331			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2332		}
2333		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2334		{
2335			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2336		}
2337		else
2338		{
2339			return null;
2340		}
2341	}
2342
2343	function get_category($key = 0)
2344	{
2345		$categories = $this->get_categories();
2346		if (isset($categories[$key]))
2347		{
2348			return $categories[$key];
2349		}
2350		else
2351		{
2352			return null;
2353		}
2354	}
2355
2356	function get_categories()
2357	{
2358		$categories = array();
2359
2360		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2361		{
2362			$term = null;
2363			$scheme = null;
2364			$label = null;
2365			if (isset($category['attribs']['']['term']))
2366			{
2367				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2368			}
2369			if (isset($category['attribs']['']['scheme']))
2370			{
2371				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2372			}
2373			if (isset($category['attribs']['']['label']))
2374			{
2375				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2376			}
2377			$categories[] =& new $this->category_class($term, $scheme, $label);
2378		}
2379		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2380		{
2381			// This is really the label, but keep this as the term also for BC.
2382			// Label will also work on retrieving because that falls back to term.
2383			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384			if (isset($category['attribs']['']['domain']))
2385			{
2386				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2387			}
2388			else
2389			{
2390				$scheme = null;
2391			}
2392			$categories[] =& new $this->category_class($term, $scheme, null);
2393		}
2394		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2395		{
2396			$categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2397		}
2398		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2399		{
2400			$categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2401		}
2402
2403		if (!empty($categories))
2404		{
2405			return SimplePie_Misc::array_unique($categories);
2406		}
2407		else
2408		{
2409			return null;
2410		}
2411	}
2412
2413	function get_author($key = 0)
2414	{
2415		$authors = $this->get_authors();
2416		if (isset($authors[$key]))
2417		{
2418			return $authors[$key];
2419		}
2420		else
2421		{
2422			return null;
2423		}
2424	}
2425
2426	function get_authors()
2427	{
2428		$authors = array();
2429		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2430		{
2431			$name = null;
2432			$uri = null;
2433			$email = null;
2434			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2435			{
2436				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2437			}
2438			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2439			{
2440				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2441			}
2442			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2443			{
2444				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2445			}
2446			if ($name !== null || $email !== null || $uri !== null)
2447			{
2448				$authors[] =& new $this->author_class($name, $uri, $email);
2449			}
2450		}
2451		if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2452		{
2453			$name = null;
2454			$url = null;
2455			$email = null;
2456			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2457			{
2458				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2459			}
2460			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2461			{
2462				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2463			}
2464			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2465			{
2466				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2467			}
2468			if ($name !== null || $email !== null || $url !== null)
2469			{
2470				$authors[] =& new $this->author_class($name, $url, $email);
2471			}
2472		}
2473		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2474		{
2475			$authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2476		}
2477		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2478		{
2479			$authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2480		}
2481		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2482		{
2483			$authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2484		}
2485
2486		if (!empty($authors))
2487		{
2488			return SimplePie_Misc::array_unique($authors);
2489		}
2490		else
2491		{
2492			return null;
2493		}
2494	}
2495
2496	function get_contributor($key = 0)
2497	{
2498		$contributors = $this->get_contributors();
2499		if (isset($contributors[$key]))
2500		{
2501			return $contributors[$key];
2502		}
2503		else
2504		{
2505			return null;
2506		}
2507	}
2508
2509	function get_contributors()
2510	{
2511		$contributors = array();
2512		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2513		{
2514			$name = null;
2515			$uri = null;
2516			$email = null;
2517			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2518			{
2519				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2520			}
2521			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2522			{
2523				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2524			}
2525			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2526			{
2527				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2528			}
2529			if ($name !== null || $email !== null || $uri !== null)
2530			{
2531				$contributors[] =& new $this->author_class($name, $uri, $email);
2532			}
2533		}
2534		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2535		{
2536			$name = null;
2537			$url = null;
2538			$email = null;
2539			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2540			{
2541				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2542			}
2543			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2544			{
2545				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2546			}
2547			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2548			{
2549				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2550			}
2551			if ($name !== null || $email !== null || $url !== null)
2552			{
2553				$contributors[] =& new $this->author_class($name, $url, $email);
2554			}
2555		}
2556
2557		if (!empty($contributors))
2558		{
2559			return SimplePie_Misc::array_unique($contributors);
2560		}
2561		else
2562		{
2563			return null;
2564		}
2565	}
2566
2567	function get_link($key = 0, $rel = 'alternate')
2568	{
2569		$links = $this->get_links($rel);
2570		if (isset($links[$key]))
2571		{
2572			return $links[$key];
2573		}
2574		else
2575		{
2576			return null;
2577		}
2578	}
2579
2580	/**
2581	 * Added for parity between the parent-level and the item/entry-level.
2582	 */
2583	function get_permalink()
2584	{
2585		return $this->get_link(0);
2586	}
2587
2588	function get_links($rel = 'alternate')
2589	{
2590		if (!isset($this->data['links']))
2591		{
2592			$this->data['links'] = array();
2593			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2594			{
2595				foreach ($links as $link)
2596				{
2597					if (isset($link['attribs']['']['href']))
2598					{
2599						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2600						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2601					}
2602				}
2603			}
2604			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2605			{
2606				foreach ($links as $link)
2607				{
2608					if (isset($link['attribs']['']['href']))
2609					{
2610						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2611						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2612
2613					}
2614				}
2615			}
2616			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2617			{
2618				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2619			}
2620			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2621			{
2622				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2623			}
2624			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2625			{
2626				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2627			}
2628
2629			$keys = array_keys($this->data['links']);
2630			foreach ($keys as $key)
2631			{
2632				if (SimplePie_Misc::is_isegment_nz_nc($key))
2633				{
2634					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2635					{
2636						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2637						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2638					}
2639					else
2640					{
2641						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2642					}
2643				}
2644				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2645				{
2646					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2647				}
2648				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
2649			}
2650		}
2651
2652		if (isset($this->data['links'][$rel]))
2653		{
2654			return $this->data['links'][$rel];
2655		}
2656		else
2657		{
2658			return null;
2659		}
2660	}
2661
2662	function get_all_discovered_feeds()
2663	{
2664		return $this->all_discovered_feeds;
2665	}
2666
2667	function get_description()
2668	{
2669		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2670		{
2671			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2672		}
2673		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2674		{
2675			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2676		}
2677		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2678		{
2679			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2680		}
2681		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2682		{
2683			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2684		}
2685		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2686		{
2687			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2688		}
2689		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2690		{
2691			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2692		}
2693		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2694		{
2695			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2696		}
2697		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2698		{
2699			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2700		}
2701		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2702		{
2703			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2704		}
2705		else
2706		{
2707			return null;
2708		}
2709	}
2710
2711	function get_copyright()
2712	{
2713		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2714		{
2715			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2716		}
2717		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2718		{
2719			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2720		}
2721		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2722		{
2723			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2724		}
2725		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2726		{
2727			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2728		}
2729		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2730		{
2731			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2732		}
2733		else
2734		{
2735			return null;
2736		}
2737	}
2738
2739	function get_language()
2740	{
2741		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2742		{
2743			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2744		}
2745		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2746		{
2747			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2748		}
2749		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2750		{
2751			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2752		}
2753		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2754		{
2755			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2756		}
2757		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2758		{
2759			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2760		}
2761		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2762		{
2763			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2764		}
2765		elseif (isset($this->data['headers']['content-language']))
2766		{
2767			return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2768		}
2769		else
2770		{
2771			return null;
2772		}
2773	}
2774
2775	function get_latitude()
2776	{
2777		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2778		{
2779			return (float) $return[0]['data'];
2780		}
2781		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2782		{
2783			return (float) $match[1];
2784		}
2785		else
2786		{
2787			return null;
2788		}
2789	}
2790
2791	function get_longitude()
2792	{
2793		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2794		{
2795			return (float) $return[0]['data'];
2796		}
2797		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2798		{
2799			return (float) $return[0]['data'];
2800		}
2801		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2802		{
2803			return (float) $match[2];
2804		}
2805		else
2806		{
2807			return null;
2808		}
2809	}
2810
2811	function get_image_title()
2812	{
2813		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2814		{
2815			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2816		}
2817		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2818		{
2819			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2820		}
2821		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2822		{
2823			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2824		}
2825		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2826		{
2827			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2828		}
2829		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2830		{
2831			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2832		}
2833		else
2834		{
2835			return null;
2836		}
2837	}
2838
2839	function get_image_url()
2840	{
2841		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2842		{
2843			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2844		}
2845		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2846		{
2847			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2848		}
2849		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2850		{
2851			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2852		}
2853		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2854		{
2855			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2856		}
2857		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2858		{
2859			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2860		}
2861		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2862		{
2863			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2864		}
2865		else
2866		{
2867			return null;
2868		}
2869	}
2870
2871	function get_image_link()
2872	{
2873		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2874		{
2875			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2876		}
2877		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2878		{
2879			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2880		}
2881		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2882		{
2883			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2884		}
2885		else
2886		{
2887			return null;
2888		}
2889	}
2890
2891	function get_image_width()
2892	{
2893		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2894		{
2895			return round($return[0]['data']);
2896		}
2897		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2898		{
2899			return 88.0;
2900		}
2901		else
2902		{
2903			return null;
2904		}
2905	}
2906
2907	function get_image_height()
2908	{
2909		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2910		{
2911			return round($return[0]['data']);
2912		}
2913		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2914		{
2915			return 31.0;
2916		}
2917		else
2918		{
2919			return null;
2920		}
2921	}
2922
2923	function get_item_quantity($max = 0)
2924	{
2925		$max = (int) $max;
2926		$qty = count($this->get_items());
2927		if ($max === 0)
2928		{
2929			return $qty;
2930		}
2931		else
2932		{
2933			return ($qty > $max) ? $max : $qty;
2934		}
2935	}
2936
2937	function get_item($key = 0)
2938	{
2939		$items = $this->get_items();
2940		if (isset($items[$key]))
2941		{
2942			return $items[$key];
2943		}
2944		else
2945		{
2946			return null;
2947		}
2948	}
2949
2950	function get_items($start = 0, $end = 0)
2951	{
2952		if (!isset($this->data['items']))
2953		{
2954			if (!empty($this->multifeed_objects))
2955			{
2956				$this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2957			}
2958			else
2959			{
2960				$this->data['items'] = array();
2961				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2962				{
2963					$keys = array_keys($items);
2964					foreach ($keys as $key)
2965					{
2966						$this->data['items'][] =& new $this->item_class($this, $items[$key]);
2967					}
2968				}
2969				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2970				{
2971					$keys = array_keys($items);
2972					foreach ($keys as $key)
2973					{
2974						$this->data['items'][] =& new $this->item_class($this, $items[$key]);
2975					}
2976				}
2977				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2978				{
2979					$keys = array_keys($items);
2980					foreach ($keys as $key)
2981					{
2982						$this->data['items'][] =& new $this->item_class($this, $items[$key]);
2983					}
2984				}
2985				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2986				{
2987					$keys = array_keys($items);
2988					foreach ($keys as $key)
2989					{
2990						$this->data['items'][] =& new $this->item_class($this, $items[$key]);
2991					}
2992				}
2993				if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2994				{
2995					$keys = array_keys($items);
2996					foreach ($keys as $key)
2997					{
2998						$this->data['items'][] =& new $this->item_class($this, $items[$key]);
2999					}
3000				}
3001			}
3002		}
3003
3004		if (!empty($this->data['items']))
3005		{
3006			// If we want to order it by date, check if all items have a date, and then sort it
3007			if ($this->order_by_date && empty($this->multifeed_objects))
3008			{
3009				if (!isset($this->data['ordered_items']))
3010				{
3011					$do_sort = true;
3012					foreach ($this->data['items'] as $item)
3013					{
3014						if (!$item->get_date('U'))
3015						{
3016							$do_sort = false;
3017							break;
3018						}
3019					}
3020					$item = null;
3021					$this->data['ordered_items'] = $this->data['items'];
3022					if ($do_sort)
3023					{
3024						usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3025					}
3026				}
3027				$items = $this->data['ordered_items'];
3028			}
3029			else
3030			{
3031				$items = $this->data['items'];
3032			}
3033
3034			// Slice the data as desired
3035			if ($end === 0)
3036			{
3037				return array_slice($items, $start);
3038			}
3039			else
3040			{
3041				return array_slice($items, $start, $end);
3042			}
3043		}
3044		else
3045		{
3046			return array();
3047		}
3048	}
3049
3050	/**
3051	 * @static
3052	 */
3053	function sort_items($a, $b)
3054	{
3055		return $a->get_date('U') <= $b->get_date('U');
3056	}
3057
3058	/**
3059	 * @static
3060	 */
3061	function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3062	{
3063		if (is_array($urls) && sizeof($urls) > 0)
3064		{
3065			$items = array();
3066			foreach ($urls as $arg)
3067			{
3068				if (is_a($arg, 'SimplePie'))
3069				{
3070					$items = array_merge($items, $arg->get_items(0, $limit));
3071				}
3072				else
3073				{
3074					trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3075				}
3076			}
3077
3078			$do_sort = true;
3079			foreach ($items as $item)
3080			{
3081				if (!$item->get_date('U'))
3082				{
3083					$do_sort = false;
3084					break;
3085				}
3086			}
3087			$item = null;
3088			if ($do_sort)
3089			{
3090				usort($items, array('SimplePie', 'sort_items'));
3091			}
3092
3093			if ($end === 0)
3094			{
3095				return array_slice($items, $start);
3096			}
3097			else
3098			{
3099				return array_slice($items, $start, $end);
3100			}
3101		}
3102		else
3103		{
3104			trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3105			return array();
3106		}
3107	}
3108}
3109
3110class SimplePie_Item
3111{
3112	var $feed;
3113	var $data = array();
3114
3115	function SimplePie_Item($feed, $data)
3116	{
3117		$this->feed = $feed;
3118		$this->data = $data;
3119	}
3120
3121	function __toString()
3122	{
3123		return md5(serialize($this->data));
3124	}
3125
3126	/**
3127	 * Remove items that link back to this before destroying this object
3128	 */
3129	function __destruct()
3130	{
3131		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3132		{
3133			unset($this->feed);
3134		}
3135	}
3136
3137	function get_item_tags($namespace, $tag)
3138	{
3139		if (isset($this->data['child'][$namespace][$tag]))
3140		{
3141			return $this->data['child'][$namespace][$tag];
3142		}
3143		else
3144		{
3145			return null;
3146		}
3147	}
3148
3149	function get_base($element = array())
3150	{
3151		return $this->feed->get_base($element);
3152	}
3153
3154	function sanitize($data, $type, $base = '')
3155	{
3156		return $this->feed->sanitize($data, $type, $base);
3157	}
3158
3159	function get_feed()
3160	{
3161		return $this->feed;
3162	}
3163
3164	function get_id($hash = false)
3165	{
3166		if (!$hash)
3167		{
3168			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3169			{
3170				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3171			}
3172			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3173			{
3174				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3175			}
3176			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3177			{
3178				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3179			}
3180			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3181			{
3182				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3183			}
3184			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3185			{
3186				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3187			}
3188			elseif (($return = $this->get_permalink()) !== null)
3189			{
3190				return $return;
3191			}
3192			elseif (($return = $this->get_title()) !== null)
3193			{
3194				return $return;
3195			}
3196		}
3197		if ($this->get_permalink() !== null || $this->get_title() !== null)
3198		{
3199			return md5($this->get_permalink() . $this->get_title());
3200		}
3201		else
3202		{
3203			return md5(serialize($this->data));
3204		}
3205	}
3206
3207	function get_title()
3208	{
3209		if (!isset($this->data['title']))
3210		{
3211			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3212			{
3213				$this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3214			}
3215			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3216			{
3217				$this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3218			}
3219			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3220			{
3221				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3222			}
3223			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3224			{
3225				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3226			}
3227			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3228			{
3229				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3230			}
3231			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3232			{
3233				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3234			}
3235			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3236			{
3237				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3238			}
3239			else
3240			{
3241				$this->data['title'] = null;
3242			}
3243		}
3244		return $this->data['title'];
3245	}
3246
3247	function get_description($description_only = false)
3248	{
3249		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3250		{
3251			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3252		}
3253		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3254		{
3255			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3256		}
3257		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3258		{
3259			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3260		}
3261		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3262		{
3263			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3264		}
3265		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3266		{
3267			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3268		}
3269		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3270		{
3271			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3272		}
3273		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3274		{
3275			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3276		}
3277		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3278		{
3279			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3280		}
3281		elseif (!$description_only)
3282		{
3283			return $this->get_content(true);
3284		}
3285		else
3286		{
3287			return null;
3288		}
3289	}
3290
3291	function get_content($content_only = false)
3292	{
3293		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3294		{
3295			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3296		}
3297		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3298		{
3299			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3300		}
3301		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3302		{
3303			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3304		}
3305		elseif (!$content_only)
3306		{
3307			return $this->get_description(true);
3308		}
3309		else
3310		{
3311			return null;
3312		}
3313	}
3314
3315	function get_category($key = 0)
3316	{
3317		$categories = $this->get_categories();
3318		if (isset($categories[$key]))
3319		{
3320			return $categories[$key];
3321		}
3322		else
3323		{
3324			return null;
3325		}
3326	}
3327
3328	function get_categories()
3329	{
3330		$categories = array();
3331
3332		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3333		{
3334			$term = null;
3335			$scheme = null;
3336			$label = null;
3337			if (isset($category['attribs']['']['term']))
3338			{
3339				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3340			}
3341			if (isset($category['attribs']['']['scheme']))
3342			{
3343				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3344			}
3345			if (isset($category['attribs']['']['label']))
3346			{
3347				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3348			}
3349			$categories[] =& new $this->feed->category_class($term, $scheme, $label);
3350		}
3351		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3352		{
3353			// This is really the label, but keep this as the term also for BC.
3354			// Label will also work on retrieving because that falls back to term.
3355			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3356			if (isset($category['attribs']['']['domain']))
3357			{
3358				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3359			}
3360			else
3361			{
3362				$scheme = null;
3363			}
3364			$categories[] =& new $this->feed->category_class($term, $scheme, null);
3365		}
3366		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3367		{
3368			$categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3369		}
3370		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3371		{
3372			$categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3373		}
3374
3375		if (!empty($categories))
3376		{
3377			return SimplePie_Misc::array_unique($categories);
3378		}
3379		else
3380		{
3381			return null;
3382		}
3383	}
3384
3385	function get_author($key = 0)
3386	{
3387		$authors = $this->get_authors();
3388		if (isset($authors[$key]))
3389		{
3390			return $authors[$key];
3391		}
3392		else
3393		{
3394			return null;
3395		}
3396	}
3397
3398	function get_contributor($key = 0)
3399	{
3400		$contributors = $this->get_contributors();
3401		if (isset($contributors[$key]))
3402		{
3403			return $contributors[$key];
3404		}
3405		else
3406		{
3407			return null;
3408		}
3409	}
3410
3411	function get_contributors()
3412	{
3413		$contributors = array();
3414		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3415		{
3416			$name = null;
3417			$uri = null;
3418			$email = null;
3419			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3420			{
3421				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3422			}
3423			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3424			{
3425				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3426			}
3427			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3428			{
3429				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3430			}
3431			if ($name !== null || $email !== null || $uri !== null)
3432			{
3433				$contributors[] =& new $this->feed->author_class($name, $uri, $email);
3434			}
3435		}
3436		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3437		{
3438			$name = null;
3439			$url = null;
3440			$email = null;
3441			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3442			{
3443				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3444			}
3445			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3446			{
3447				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3448			}
3449			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3450			{
3451				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3452			}
3453			if ($name !== null || $email !== null || $url !== null)
3454			{
3455				$contributors[] =& new $this->feed->author_class($name, $url, $email);
3456			}
3457		}
3458
3459		if (!empty($contributors))
3460		{
3461			return SimplePie_Misc::array_unique($contributors);
3462		}
3463		else
3464		{
3465			return null;
3466		}
3467	}
3468
3469	function get_authors()
3470	{
3471		$authors = array();
3472		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3473		{
3474			$name = null;
3475			$uri = null;
3476			$email = null;
3477			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3478			{
3479				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3480			}
3481			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3482			{
3483				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
3484			}
3485			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3486			{
3487				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3488			}
3489			if ($name !== null || $email !== null || $uri !== null)
3490			{
3491				$authors[] =& new $this->feed->author_class($name, $uri, $email);
3492			}
3493		}
3494		if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3495		{
3496			$name = null;
3497			$url = null;
3498			$email = null;
3499			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3500			{
3501				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3502			}
3503			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3504			{
3505				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
3506			}
3507			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3508			{
3509				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3510			}
3511			if ($name !== null || $email !== null || $url !== null)
3512			{
3513				$authors[] =& new $this->feed->author_class($name, $url, $email);
3514			}
3515		}
3516		if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3517		{
3518			$authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3519		}
3520		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3521		{
3522			$authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3523		}
3524		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3525		{
3526			$authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3527		}
3528		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3529		{
3530			$authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3531		}
3532
3533		if (!empty($authors))
3534		{
3535			return SimplePie_Misc::array_unique($authors);
3536		}
3537		elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3538		{
3539			return $authors;
3540		}
3541		elseif ($authors = $this->feed->get_authors())
3542		{
3543			return $authors;
3544		}
3545		else
3546		{
3547			return null;
3548		}
3549	}
3550
3551	function get_copyright()
3552	{
3553		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3554		{
3555			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3556		}
3557		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3558		{
3559			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3560		}
3561		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3562		{
3563			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3564		}
3565		else
3566		{
3567			return null;
3568		}
3569	}
3570
3571	function get_date($date_format = 'j F Y, g:i a')
3572	{
3573		if (!isset($this->data['date']))
3574		{
3575			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3576			{
3577				$this->data['date']['raw'] = $return[0]['data'];
3578			}
3579			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3580			{
3581				$this->data['date']['raw'] = $return[0]['data'];
3582			}
3583			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3584			{
3585				$this->data['date']['raw'] = $return[0]['data'];
3586			}
3587			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3588			{
3589				$this->data['date']['raw'] = $return[0]['data'];
3590			}
3591			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3592			{
3593				$this->data['date']['raw'] = $return[0]['data'];
3594			}
3595			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3596			{
3597				$this->data['date']['raw'] = $return[0]['data'];
3598			}
3599			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3600			{
3601				$this->data['date']['raw'] = $return[0]['data'];
3602			}
3603			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3604			{
3605				$this->data['date']['raw'] = $return[0]['data'];
3606			}
3607
3608			if (!empty($this->data['date']['raw']))
3609			{
3610				$parser = SimplePie_Parse_Date::get();
3611				$this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3612			}
3613			else
3614			{
3615				$this->data['date'] = null;
3616			}
3617		}
3618		if ($this->data['date'])
3619		{
3620			$date_format = (string) $date_format;
3621			switch ($date_format)
3622			{
3623				case '':
3624					return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3625
3626				case 'U':
3627					return $this->data['date']['parsed'];
3628
3629				default:
3630					return date($date_format, $this->data['date']['parsed']);
3631			}
3632		}
3633		else
3634		{
3635			return null;
3636		}
3637	}
3638
3639	function get_local_date($date_format = '%c')
3640	{
3641		if (!$date_format)
3642		{
3643			return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3644		}
3645		elseif (($date = $this->get_date('U')) !== null)
3646		{
3647			return strftime($date_format, $date);
3648		}
3649		else
3650		{
3651			return null;
3652		}
3653	}
3654
3655	function get_permalink()
3656	{
3657		$link = $this->get_link();
3658		$enclosure = $this->get_enclosure(0);
3659		if ($link !== null)
3660		{
3661			return $link;
3662		}
3663		elseif ($enclosure !== null)
3664		{
3665			return $enclosure->get_link();
3666		}
3667		else
3668		{
3669			return null;
3670		}
3671	}
3672
3673	function get_link($key = 0, $rel = 'alternate')
3674	{
3675		$links = $this->get_links($rel);
3676		if ($links[$key] !== null)
3677		{
3678			return $links[$key];
3679		}
3680		else
3681		{
3682			return null;
3683		}
3684	}
3685
3686	function get_links($rel = 'alternate')
3687	{
3688		if (!isset($this->data['links']))
3689		{
3690			$this->data['links'] = array();
3691			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3692			{
3693				if (isset($link['attribs']['']['href']))
3694				{
3695					$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3696					$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3697
3698				}
3699			}
3700			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3701			{
3702				if (isset($link['attribs']['']['href']))
3703				{
3704					$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3705					$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3706				}
3707			}
3708			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3709			{
3710				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3711			}
3712			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3713			{
3714				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3715			}
3716			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3717			{
3718				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3719			}
3720			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3721			{
3722				if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3723				{
3724					$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3725				}
3726			}
3727
3728			$keys = array_keys($this->data['links']);
3729			foreach ($keys as $key)
3730			{
3731				if (SimplePie_Misc::is_isegment_nz_nc($key))
3732				{
3733					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3734					{
3735						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3736						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3737					}
3738					else
3739					{
3740						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3741					}
3742				}
3743				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3744				{
3745					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3746				}
3747				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
3748			}
3749		}
3750		if (isset($this->data['links'][$rel]))
3751		{
3752			return $this->data['links'][$rel];
3753		}
3754		else
3755		{
3756			return null;
3757		}
3758	}
3759
3760	/**
3761	 * @todo Add ability to prefer one type of content over another (in a media group).
3762	 */
3763	function get_enclosure($key = 0, $prefer = null)
3764	{
3765		$enclosures = $this->get_enclosures();
3766		if (isset($enclosures[$key]))
3767		{
3768			return $enclosures[$key];
3769		}
3770		else
3771		{
3772			return null;
3773		}
3774	}
3775
3776	/**
3777	 * Grabs all available enclosures (podcasts, etc.)
3778	 *
3779	 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3780	 *
3781	 * At this point, we're pretty much assuming that all enclosures for an item are the same content.  Anything else is too complicated to properly support.
3782	 *
3783	 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3784	 * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
3785	 */
3786	function get_enclosures()
3787	{
3788		if (!isset($this->data['enclosures']))
3789		{
3790			$this->data['enclosures'] = array();
3791
3792			// Elements
3793			$captions_parent = null;
3794			$categories_parent = null;
3795			$copyrights_parent = null;
3796			$credits_parent = null;
3797			$description_parent = null;
3798			$duration_parent = null;
3799			$hashes_parent = null;
3800			$keywords_parent = null;
3801			$player_parent = null;
3802			$ratings_parent = null;
3803			$restrictions_parent = null;
3804			$thumbnails_parent = null;
3805			$title_parent = null;
3806
3807			// Let's do the channel and item-level ones first, and just re-use them if we need to.
3808			$parent = $this->get_feed();
3809
3810			// CAPTIONS
3811			if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3812			{
3813				foreach ($captions as $caption)
3814				{
3815					$caption_type = null;
3816					$caption_lang = null;
3817					$caption_startTime = null;
3818					$caption_endTime = null;
3819					$caption_text = null;
3820					if (isset($caption['attribs']['']['type']))
3821					{
3822						$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3823					}
3824					if (isset($caption['attribs']['']['lang']))
3825					{
3826						$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3827					}
3828					if (isset($caption['attribs']['']['start']))
3829					{
3830						$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3831					}
3832					if (isset($caption['attribs']['']['end']))
3833					{
3834						$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3835					}
3836					if (isset($caption['data']))
3837					{
3838						$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3839					}
3840					$captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3841				}
3842			}
3843			elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3844			{
3845				foreach ($captions as $caption)
3846				{
3847					$caption_type = null;
3848					$caption_lang = null;
3849					$caption_startTime = null;
3850					$caption_endTime = null;
3851					$caption_text = null;
3852					if (isset($caption['attribs']['']['type']))
3853					{
3854						$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3855					}
3856					if (isset($caption['attribs']['']['lang']))
3857					{
3858						$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3859					}
3860					if (isset($caption['attribs']['']['start']))
3861					{
3862						$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3863					}
3864					if (isset($caption['attribs']['']['end']))
3865					{
3866						$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3867					}
3868					if (isset($caption['data']))
3869					{
3870						$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3871					}
3872					$captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3873				}
3874			}
3875			if (is_array($captions_parent))
3876			{
3877				$captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3878			}
3879
3880			// CATEGORIES
3881			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3882			{
3883				$term = null;
3884				$scheme = null;
3885				$label = null;
3886				if (isset($category['data']))
3887				{
3888					$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3889				}
3890				if (isset($category['attribs']['']['scheme']))
3891				{
3892					$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3893				}
3894				else
3895				{
3896					$scheme = 'http://search.yahoo.com/mrss/category_schema';
3897				}
3898				if (isset($category['attribs']['']['label']))
3899				{
3900					$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3901				}
3902				$categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3903			}
3904			foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3905			{
3906				$term = null;
3907				$scheme = null;
3908				$label = null;
3909				if (isset($category['data']))
3910				{
3911					$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3912				}
3913				if (isset($category['attribs']['']['scheme']))
3914				{
3915					$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3916				}
3917				else
3918				{
3919					$scheme = 'http://search.yahoo.com/mrss/category_schema';
3920				}
3921				if (isset($category['attribs']['']['label']))
3922				{
3923					$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3924				}
3925				$categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3926			}
3927			foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3928			{
3929				$term = null;
3930				$scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3931				$label = null;
3932				if (isset($category['attribs']['']['text']))
3933				{
3934					$label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3935				}
3936				$categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3937
3938				if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3939				{
3940					foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3941					{
3942						if (isset($subcategory['attribs']['']['text']))
3943						{
3944							$label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3945						}
3946						$categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3947					}
3948				}
3949			}
3950			if (is_array($categories_parent))
3951			{
3952				$categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3953			}
3954
3955			// COPYRIGHT
3956			if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3957			{
3958				$copyright_url = null;
3959				$copyright_label = null;
3960				if (isset($copyright[0]['attribs']['']['url']))
3961				{
3962					$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3963				}
3964				if (isset($copyright[0]['data']))
3965				{
3966					$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3967				}
3968				$copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3969			}
3970			elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3971			{
3972				$copyright_url = null;
3973				$copyright_label = null;
3974				if (isset($copyright[0]['attribs']['']['url']))
3975				{
3976					$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3977				}
3978				if (isset($copyright[0]['data']))
3979				{
3980					$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3981				}
3982				$copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3983			}
3984
3985			// CREDITS
3986			if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3987			{
3988				foreach ($credits as $credit)
3989				{
3990					$credit_role = null;
3991					$credit_scheme = null;
3992					$credit_name = null;
3993					if (isset($credit['attribs']['']['role']))
3994					{
3995						$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3996					}
3997					if (isset($credit['attribs']['']['scheme']))
3998					{
3999						$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4000					}
4001					else
4002					{
4003						$credit_scheme = 'urn:ebu';
4004					}
4005					if (isset($credit['data']))
4006					{
4007						$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4008					}
4009					$credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4010				}
4011			}
4012			elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4013			{
4014				foreach ($credits as $credit)
4015				{
4016					$credit_role = null;
4017					$credit_scheme = null;
4018					$credit_name = null;
4019					if (isset($credit['attribs']['']['role']))
4020					{
4021						$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4022					}
4023					if (isset($credit['attribs']['']['scheme']))
4024					{
4025						$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4026					}
4027					else
4028					{
4029						$credit_scheme = 'urn:ebu';
4030					}
4031					if (isset($credit['data']))
4032					{
4033						$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4034					}
4035					$credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4036				}
4037			}
4038			if (is_array($credits_parent))
4039			{
4040				$credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4041			}
4042
4043			// DESCRIPTION
4044			if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4045			{
4046				if (isset($description_parent[0]['data']))
4047				{
4048					$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4049				}
4050			}
4051			elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4052			{
4053				if (isset($description_parent[0]['data']))
4054				{
4055					$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4056				}
4057			}
4058
4059			// DURATION
4060			if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4061			{
4062				$seconds = null;
4063				$minutes = null;
4064				$hours = null;
4065				if (isset($duration_parent[0]['data']))
4066				{
4067					$temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4068					if (sizeof($temp) > 0)
4069					{
4070						$seconds = (int) array_pop($temp);
4071					}
4072					if (sizeof($temp) > 0)
4073					{
4074						$minutes = (int) array_pop($temp);
4075						$seconds += $minutes * 60;
4076					}
4077					if (sizeof($temp) > 0)
4078					{
4079						$hours = (int) array_pop($temp);
4080						$seconds += $hours * 3600;
4081					}
4082					unset($temp);
4083					$duration_parent = $seconds;
4084				}
4085			}
4086
4087			// HASHES
4088			if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4089			{
4090				foreach ($hashes_iterator as $hash)
4091				{
4092					$value = null;
4093					$algo = null;
4094					if (isset($hash['data']))
4095					{
4096						$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4097					}
4098					if (isset($hash['attribs']['']['algo']))
4099					{
4100						$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4101					}
4102					else
4103					{
4104						$algo = 'md5';
4105					}
4106					$hashes_parent[] = $algo.':'.$value;
4107				}
4108			}
4109			elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4110			{
4111				foreach ($hashes_iterator as $hash)
4112				{
4113					$value = null;
4114					$algo = null;
4115					if (isset($hash['data']))
4116					{
4117						$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4118					}
4119					if (isset($hash['attribs']['']['algo']))
4120					{
4121						$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4122					}
4123					else
4124					{
4125						$algo = 'md5';
4126					}
4127					$hashes_parent[] = $algo.':'.$value;
4128				}
4129			}
4130			if (is_array($hashes_parent))
4131			{
4132				$hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4133			}
4134
4135			// KEYWORDS
4136			if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4137			{
4138				if (isset($keywords[0]['data']))
4139				{
4140					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4141					foreach ($temp as $word)
4142					{
4143						$keywords_parent[] = trim($word);
4144					}
4145				}
4146				unset($temp);
4147			}
4148			elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4149			{
4150				if (isset($keywords[0]['data']))
4151				{
4152					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4153					foreach ($temp as $word)
4154					{
4155						$keywords_parent[] = trim($word);
4156					}
4157				}
4158				unset($temp);
4159			}
4160			elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4161			{
4162				if (isset($keywords[0]['data']))
4163				{
4164					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4165					foreach ($temp as $word)
4166					{
4167						$keywords_parent[] = trim($word);
4168					}
4169				}
4170				unset($temp);
4171			}
4172			elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4173			{
4174				if (isset($keywords[0]['data']))
4175				{
4176					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4177					foreach ($temp as $word)
4178					{
4179						$keywords_parent[] = trim($word);
4180					}
4181				}
4182				unset($temp);
4183			}
4184			if (is_array($keywords_parent))
4185			{
4186				$keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4187			}
4188
4189			// PLAYER
4190			if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4191			{
4192				if (isset($player_parent[0]['attribs']['']['url']))
4193				{
4194					$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4195				}
4196			}
4197			elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4198			{
4199				if (isset($player_parent[0]['attribs']['']['url']))
4200				{
4201					$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4202				}
4203			}
4204
4205			// RATINGS
4206			if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4207			{
4208				foreach ($ratings as $rating)
4209				{
4210					$rating_scheme = null;
4211					$rating_value = null;
4212					if (isset($rating['attribs']['']['scheme']))
4213					{
4214						$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4215					}
4216					else
4217					{
4218						$rating_scheme = 'urn:simple';
4219					}
4220					if (isset($rating['data']))
4221					{
4222						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4223					}
4224					$ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4225				}
4226			}
4227			elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4228			{
4229				foreach ($ratings as $rating)
4230				{
4231					$rating_scheme = 'urn:itunes';
4232					$rating_value = null;
4233					if (isset($rating['data']))
4234					{
4235						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4236					}
4237					$ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4238				}
4239			}
4240			elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4241			{
4242				foreach ($ratings as $rating)
4243				{
4244					$rating_scheme = null;
4245					$rating_value = null;
4246					if (isset($rating['attribs']['']['scheme']))
4247					{
4248						$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4249					}
4250					else
4251					{
4252						$rating_scheme = 'urn:simple';
4253					}
4254					if (isset($rating['data']))
4255					{
4256						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4257					}
4258					$ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4259				}
4260			}
4261			elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4262			{
4263				foreach ($ratings as $rating)
4264				{
4265					$rating_scheme = 'urn:itunes';
4266					$rating_value = null;
4267					if (isset($rating['data']))
4268					{
4269						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4270					}
4271					$ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4272				}
4273			}
4274			if (is_array($ratings_parent))
4275			{
4276				$ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4277			}
4278
4279			// RESTRICTIONS
4280			if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4281			{
4282				foreach ($restrictions as $restriction)
4283				{
4284					$restriction_relationship = null;
4285					$restriction_type = null;
4286					$restriction_value = null;
4287					if (isset($restriction['attribs']['']['relationship']))
4288					{
4289						$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4290					}
4291					if (isset($restriction['attribs']['']['type']))
4292					{
4293						$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4294					}
4295					if (isset($restriction['data']))
4296					{
4297						$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4298					}
4299					$restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4300				}
4301			}
4302			elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4303			{
4304				foreach ($restrictions as $restriction)
4305				{
4306					$restriction_relationship = 'allow';
4307					$restriction_type = null;
4308					$restriction_value = 'itunes';
4309					if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4310					{
4311						$restriction_relationship = 'deny';
4312					}
4313					$restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4314				}
4315			}
4316			elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4317			{
4318				foreach ($restrictions as $restriction)
4319				{
4320					$restriction_relationship = null;
4321					$restriction_type = null;
4322					$restriction_value = null;
4323					if (isset($restriction['attribs']['']['relationship']))
4324					{
4325						$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4326					}
4327					if (isset($restriction['attribs']['']['type']))
4328					{
4329						$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4330					}
4331					if (isset($restriction['data']))
4332					{
4333						$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4334					}
4335					$restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4336				}
4337			}
4338			elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4339			{
4340				foreach ($restrictions as $restriction)
4341				{
4342					$restriction_relationship = 'allow';
4343					$restriction_type = null;
4344					$restriction_value = 'itunes';
4345					if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4346					{
4347						$restriction_relationship = 'deny';
4348					}
4349					$restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4350				}
4351			}
4352			if (is_array($restrictions_parent))
4353			{
4354				$restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4355			}
4356
4357			// THUMBNAILS
4358			if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4359			{
4360				foreach ($thumbnails as $thumbnail)
4361				{
4362					if (isset($thumbnail['attribs']['']['url']))
4363					{
4364						$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4365					}
4366				}
4367			}
4368			elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4369			{
4370				foreach ($thumbnails as $thumbnail)
4371				{
4372					if (isset($thumbnail['attribs']['']['url']))
4373					{
4374						$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4375					}
4376				}
4377			}
4378
4379			// TITLES
4380			if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4381			{
4382				if (isset($title_parent[0]['data']))
4383				{
4384					$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4385				}
4386			}
4387			elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4388			{
4389				if (isset($title_parent[0]['data']))
4390				{
4391					$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4392				}
4393			}
4394
4395			// Clear the memory
4396			unset($parent);
4397
4398			// Attributes
4399			$bitrate = null;
4400			$channels = null;
4401			$duration = null;
4402			$expression = null;
4403			$framerate = null;
4404			$height = null;
4405			$javascript = null;
4406			$lang = null;
4407			$length = null;
4408			$medium = null;
4409			$samplingrate = null;
4410			$type = null;
4411			$url = null;
4412			$width = null;
4413
4414			// Elements
4415			$captions = null;
4416			$categories = null;
4417			$copyrights = null;
4418			$credits = null;
4419			$description = null;
4420			$hashes = null;
4421			$keywords = null;
4422			$player = null;
4423			$ratings = null;
4424			$restrictions = null;
4425			$thumbnails = null;
4426			$title = null;
4427
4428			// If we have media:group tags, loop through them.
4429			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4430			{
4431				// If we have media:content tags, loop through them.
4432				foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4433				{
4434					if (isset($content['attribs']['']['url']))
4435					{
4436						// Attributes
4437						$bitrate = null;
4438						$channels = null;
4439						$duration = null;
4440						$expression = null;
4441						$framerate = null;
4442						$height = null;
4443						$javascript = null;
4444						$lang = null;
4445						$length = null;
4446						$medium = null;
4447						$samplingrate = null;
4448						$type = null;
4449						$url = null;
4450						$width = null;
4451
4452						// Elements
4453						$captions = null;
4454						$categories = null;
4455						$copyrights = null;
4456						$credits = null;
4457						$description = null;
4458						$hashes = null;
4459						$keywords = null;
4460						$player = null;
4461						$ratings = null;
4462						$restrictions = null;
4463						$thumbnails = null;
4464						$title = null;
4465
4466						// Start checking the attributes of media:content
4467						if (isset($content['attribs']['']['bitrate']))
4468						{
4469							$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4470						}
4471						if (isset($content['attribs']['']['channels']))
4472						{
4473							$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4474						}
4475						if (isset($content['attribs']['']['duration']))
4476						{
4477							$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4478						}
4479						else
4480						{
4481							$duration = $duration_parent;
4482						}
4483						if (isset($content['attribs']['']['expression']))
4484						{
4485							$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4486						}
4487						if (isset($content['attribs']['']['framerate']))
4488						{
4489							$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4490						}
4491						if (isset($content['attribs']['']['height']))
4492						{
4493							$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4494						}
4495						if (isset($content['attribs']['']['lang']))
4496						{
4497							$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4498						}
4499						if (isset($content['attribs']['']['fileSize']))
4500						{
4501							$length = ceil($content['attribs']['']['fileSize']);
4502						}
4503						if (isset($content['attribs']['']['medium']))
4504						{
4505							$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4506						}
4507						if (isset($content['attribs']['']['samplingrate']))
4508						{
4509							$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4510						}
4511						if (isset($content['attribs']['']['type']))
4512						{
4513							$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4514						}
4515						if (isset($content['attribs']['']['width']))
4516						{
4517							$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4518						}
4519						$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4520
4521						// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4522
4523						// CAPTIONS
4524						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4525						{
4526							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4527							{
4528								$caption_type = null;
4529								$caption_lang = null;
4530								$caption_startTime = null;
4531								$caption_endTime = null;
4532								$caption_text = null;
4533								if (isset($caption['attribs']['']['type']))
4534								{
4535									$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4536								}
4537								if (isset($caption['attribs']['']['lang']))
4538								{
4539									$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4540								}
4541								if (isset($caption['attribs']['']['start']))
4542								{
4543									$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4544								}
4545								if (isset($caption['attribs']['']['end']))
4546								{
4547									$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4548								}
4549								if (isset($caption['data']))
4550								{
4551									$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4552								}
4553								$captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4554							}
4555							if (is_array($captions))
4556							{
4557								$captions = array_values(SimplePie_Misc::array_unique($captions));
4558							}
4559						}
4560						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4561						{
4562							foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4563							{
4564								$caption_type = null;
4565								$caption_lang = null;
4566								$caption_startTime = null;
4567								$caption_endTime = null;
4568								$caption_text = null;
4569								if (isset($caption['attribs']['']['type']))
4570								{
4571									$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4572								}
4573								if (isset($caption['attribs']['']['lang']))
4574								{
4575									$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4576								}
4577								if (isset($caption['attribs']['']['start']))
4578								{
4579									$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4580								}
4581								if (isset($caption['attribs']['']['end']))
4582								{
4583									$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4584								}
4585								if (isset($caption['data']))
4586								{
4587									$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4588								}
4589								$captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4590							}
4591							if (is_array($captions))
4592							{
4593								$captions = array_values(SimplePie_Misc::array_unique($captions));
4594							}
4595						}
4596						else
4597						{
4598							$captions = $captions_parent;
4599						}
4600
4601						// CATEGORIES
4602						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4603						{
4604							foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4605							{
4606								$term = null;
4607								$scheme = null;
4608								$label = null;
4609								if (isset($category['data']))
4610								{
4611									$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4612								}
4613								if (isset($category['attribs']['']['scheme']))
4614								{
4615									$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4616								}
4617								else
4618								{
4619									$scheme = 'http://search.yahoo.com/mrss/category_schema';
4620								}
4621								if (isset($category['attribs']['']['label']))
4622								{
4623									$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4624								}
4625								$categories[] =& new $this->feed->category_class($term, $scheme, $label);
4626							}
4627						}
4628						if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4629						{
4630							foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4631							{
4632								$term = null;
4633								$scheme = null;
4634								$label = null;
4635								if (isset($category['data']))
4636								{
4637									$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4638								}
4639								if (isset($category['attribs']['']['scheme']))
4640								{
4641									$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4642								}
4643								else
4644								{
4645									$scheme = 'http://search.yahoo.com/mrss/category_schema';
4646								}
4647								if (isset($category['attribs']['']['label']))
4648								{
4649									$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4650								}
4651								$categories[] =& new $this->feed->category_class($term, $scheme, $label);
4652							}
4653						}
4654						if (is_array($categories) && is_array($categories_parent))
4655						{
4656							$categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4657						}
4658						elseif (is_array($categories))
4659						{
4660							$categories = array_values(SimplePie_Misc::array_unique($categories));
4661						}
4662						elseif (is_array($categories_parent))
4663						{
4664							$categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4665						}
4666
4667						// COPYRIGHTS
4668						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4669						{
4670							$copyright_url = null;
4671							$copyright_label = null;
4672							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4673							{
4674								$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4675							}
4676							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4677							{
4678								$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4679							}
4680							$copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4681						}
4682						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4683						{
4684							$copyright_url = null;
4685							$copyright_label = null;
4686							if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4687							{
4688								$copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4689							}
4690							if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4691							{
4692								$copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4693							}
4694							$copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4695						}
4696						else
4697						{
4698							$copyrights = $copyrights_parent;
4699						}
4700
4701						// CREDITS
4702						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4703						{
4704							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4705							{
4706								$credit_role = null;
4707								$credit_scheme = null;
4708								$credit_name = null;
4709								if (isset($credit['attribs']['']['role']))
4710								{
4711									$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4712								}
4713								if (isset($credit['attribs']['']['scheme']))
4714								{
4715									$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4716								}
4717								else
4718								{
4719									$credit_scheme = 'urn:ebu';
4720								}
4721								if (isset($credit['data']))
4722								{
4723									$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4724								}
4725								$credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4726							}
4727							if (is_array($credits))
4728							{
4729								$credits = array_values(SimplePie_Misc::array_unique($credits));
4730							}
4731						}
4732						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4733						{
4734							foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4735							{
4736								$credit_role = null;
4737								$credit_scheme = null;
4738								$credit_name = null;
4739								if (isset($credit['attribs']['']['role']))
4740								{
4741									$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4742								}
4743								if (isset($credit['attribs']['']['scheme']))
4744								{
4745									$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4746								}
4747								else
4748								{
4749									$credit_scheme = 'urn:ebu';
4750								}
4751								if (isset($credit['data']))
4752								{
4753									$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4754								}
4755								$credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4756							}
4757							if (is_array($credits))
4758							{
4759								$credits = array_values(SimplePie_Misc::array_unique($credits));
4760							}
4761						}
4762						else
4763						{
4764							$credits = $credits_parent;
4765						}
4766
4767						// DESCRIPTION
4768						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4769						{
4770							$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4771						}
4772						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4773						{
4774							$description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4775						}
4776						else
4777						{
4778							$description = $description_parent;
4779						}
4780
4781						// HASHES
4782						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4783						{
4784							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4785							{
4786								$value = null;
4787								$algo = null;
4788								if (isset($hash['data']))
4789								{
4790									$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4791								}
4792								if (isset($hash['attribs']['']['algo']))
4793								{
4794									$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4795								}
4796								else
4797								{
4798									$algo = 'md5';
4799								}
4800								$hashes[] = $algo.':'.$value;
4801							}
4802							if (is_array($hashes))
4803							{
4804								$hashes = array_values(SimplePie_Misc::array_unique($hashes));
4805							}
4806						}
4807						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4808						{
4809							foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4810							{
4811								$value = null;
4812								$algo = null;
4813								if (isset($hash['data']))
4814								{
4815									$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4816								}
4817								if (isset($hash['attribs']['']['algo']))
4818								{
4819									$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4820								}
4821								else
4822								{
4823									$algo = 'md5';
4824								}
4825								$hashes[] = $algo.':'.$value;
4826							}
4827							if (is_array($hashes))
4828							{
4829								$hashes = array_values(SimplePie_Misc::array_unique($hashes));
4830							}
4831						}
4832						else
4833						{
4834							$hashes = $hashes_parent;
4835						}
4836
4837						// KEYWORDS
4838						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4839						{
4840							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4841							{
4842								$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4843								foreach ($temp as $word)
4844								{
4845									$keywords[] = trim($word);
4846								}
4847								unset($temp);
4848							}
4849							if (is_array($keywords))
4850							{
4851								$keywords = array_values(SimplePie_Misc::array_unique($keywords));
4852							}
4853						}
4854						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4855						{
4856							if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4857							{
4858								$temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4859								foreach ($temp as $word)
4860								{
4861									$keywords[] = trim($word);
4862								}
4863								unset($temp);
4864							}
4865							if (is_array($keywords))
4866							{
4867								$keywords = array_values(SimplePie_Misc::array_unique($keywords));
4868							}
4869						}
4870						else
4871						{
4872							$keywords = $keywords_parent;
4873						}
4874
4875						// PLAYER
4876						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4877						{
4878							$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4879						}
4880						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4881						{
4882							$player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4883						}
4884						else
4885						{
4886							$player = $player_parent;
4887						}
4888
4889						// RATINGS
4890						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4891						{
4892							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4893							{
4894								$rating_scheme = null;
4895								$rating_value = null;
4896								if (isset($rating['attribs']['']['scheme']))
4897								{
4898									$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4899								}
4900								else
4901								{
4902									$rating_scheme = 'urn:simple';
4903								}
4904								if (isset($rating['data']))
4905								{
4906									$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4907								}
4908								$ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4909							}
4910							if (is_array($ratings))
4911							{
4912								$ratings = array_values(SimplePie_Misc::array_unique($ratings));
4913							}
4914						}
4915						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4916						{
4917							foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4918							{
4919								$rating_scheme = null;
4920								$rating_value = null;
4921								if (isset($rating['attribs']['']['scheme']))
4922								{
4923									$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4924								}
4925								else
4926								{
4927									$rating_scheme = 'urn:simple';
4928								}
4929								if (isset($rating['data']))
4930								{
4931									$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4932								}
4933								$ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4934							}
4935							if (is_array($ratings))
4936							{
4937								$ratings = array_values(SimplePie_Misc::array_unique($ratings));
4938							}
4939						}
4940						else
4941						{
4942							$ratings = $ratings_parent;
4943						}
4944
4945						// RESTRICTIONS
4946						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4947						{
4948							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4949							{
4950								$restriction_relationship = null;
4951								$restriction_type = null;
4952								$restriction_value = null;
4953								if (isset($restriction['attribs']['']['relationship']))
4954								{
4955									$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4956								}
4957								if (isset($restriction['attribs']['']['type']))
4958								{
4959									$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4960								}
4961								if (isset($restriction['data']))
4962								{
4963									$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4964								}
4965								$restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4966							}
4967							if (is_array($restrictions))
4968							{
4969								$restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4970							}
4971						}
4972						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4973						{
4974							foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4975							{
4976								$restriction_relationship = null;
4977								$restriction_type = null;
4978								$restriction_value = null;
4979								if (isset($restriction['attribs']['']['relationship']))
4980								{
4981									$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4982								}
4983								if (isset($restriction['attribs']['']['type']))
4984								{
4985									$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4986								}
4987								if (isset($restriction['data']))
4988								{
4989									$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4990								}
4991								$restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4992							}
4993							if (is_array($restrictions))
4994							{
4995								$restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4996							}
4997						}
4998						else
4999						{
5000							$restrictions = $restrictions_parent;
5001						}
5002
5003						// THUMBNAILS
5004						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5005						{
5006							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5007							{
5008								$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5009							}
5010							if (is_array($thumbnails))
5011							{
5012								$thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5013							}
5014						}
5015						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5016						{
5017							foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5018							{
5019								$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5020							}
5021							if (is_array($thumbnails))
5022							{
5023								$thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5024							}
5025						}
5026						else
5027						{
5028							$thumbnails = $thumbnails_parent;
5029						}
5030
5031						// TITLES
5032						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5033						{
5034							$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5035						}
5036						elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5037						{
5038							$title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5039						}
5040						else
5041						{
5042							$title = $title_parent;
5043						}
5044
5045						$this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5046					}
5047				}
5048			}
5049
5050			// If we have standalone media:content tags, loop through them.
5051			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5052			{
5053				foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5054				{
5055					if (isset($content['attribs']['']['url']))
5056					{
5057						// Attributes
5058						$bitrate = null;
5059						$channels = null;
5060						$duration = null;
5061						$expression = null;
5062						$framerate = null;
5063						$height = null;
5064						$javascript = null;
5065						$lang = null;
5066						$length = null;
5067						$medium = null;
5068						$samplingrate = null;
5069						$type = null;
5070						$url = null;
5071						$width = null;
5072
5073						// Elements
5074						$captions = null;
5075						$categories = null;
5076						$copyrights = null;
5077						$credits = null;
5078						$description = null;
5079						$hashes = null;
5080						$keywords = null;
5081						$player = null;
5082						$ratings = null;
5083						$restrictions = null;
5084						$thumbnails = null;
5085						$title = null;
5086
5087						// Start checking the attributes of media:content
5088						if (isset($content['attribs']['']['bitrate']))
5089						{
5090							$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5091						}
5092						if (isset($content['attribs']['']['channels']))
5093						{
5094							$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5095						}
5096						if (isset($content['attribs']['']['duration']))
5097						{
5098							$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5099						}
5100						else
5101						{
5102							$duration = $duration_parent;
5103						}
5104						if (isset($content['attribs']['']['expression']))
5105						{
5106							$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5107						}
5108						if (isset($content['attribs']['']['framerate']))
5109						{
5110							$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5111						}
5112						if (isset($content['attribs']['']['height']))
5113						{
5114							$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5115						}
5116						if (isset($content['attribs']['']['lang']))
5117						{
5118							$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5119						}
5120						if (isset($content['attribs']['']['fileSize']))
5121						{
5122							$length = ceil($content['attribs']['']['fileSize']);
5123						}
5124						if (isset($content['attribs']['']['medium']))
5125						{
5126							$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5127						}
5128						if (isset($content['attribs']['']['samplingrate']))
5129						{
5130							$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5131						}
5132						if (isset($content['attribs']['']['type']))
5133						{
5134							$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5135						}
5136						if (isset($content['attribs']['']['width']))
5137						{
5138							$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5139						}
5140						$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5141
5142						// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5143
5144						// CAPTIONS
5145						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5146						{
5147							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5148							{
5149								$caption_type = null;
5150								$caption_lang = null;
5151								$caption_startTime = null;
5152								$caption_endTime = null;
5153								$caption_text = null;
5154								if (isset($caption['attribs']['']['type']))
5155								{
5156									$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5157								}
5158								if (isset($caption['attribs']['']['lang']))
5159								{
5160									$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5161								}
5162								if (isset($caption['attribs']['']['start']))
5163								{
5164									$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5165								}
5166								if (isset($caption['attribs']['']['end']))
5167								{
5168									$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5169								}
5170								if (isset($caption['data']))
5171								{
5172									$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5173								}
5174								$captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5175							}
5176							if (is_array($captions))
5177							{
5178								$captions = array_values(SimplePie_Misc::array_unique($captions));
5179							}
5180						}
5181						else
5182						{
5183							$captions = $captions_parent;
5184						}
5185
5186						// CATEGORIES
5187						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5188						{
5189							foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5190							{
5191								$term = null;
5192								$scheme = null;
5193								$label = null;
5194								if (isset($category['data']))
5195								{
5196									$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5197								}
5198								if (isset($category['attribs']['']['scheme']))
5199								{
5200									$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5201								}
5202								else
5203								{
5204									$scheme = 'http://search.yahoo.com/mrss/category_schema';
5205								}
5206								if (isset($category['attribs']['']['label']))
5207								{
5208									$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5209								}
5210								$categories[] =& new $this->feed->category_class($term, $scheme, $label);
5211							}
5212						}
5213						if (is_array($categories) && is_array($categories_parent))
5214						{
5215							$categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5216						}
5217						elseif (is_array($categories))
5218						{
5219							$categories = array_values(SimplePie_Misc::array_unique($categories));
5220						}
5221						elseif (is_array($categories_parent))
5222						{
5223							$categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5224						}
5225						else
5226						{
5227							$categories = null;
5228						}
5229
5230						// COPYRIGHTS
5231						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5232						{
5233							$copyright_url = null;
5234							$copyright_label = null;
5235							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5236							{
5237								$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5238							}
5239							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5240							{
5241								$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5242							}
5243							$copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5244						}
5245						else
5246						{
5247							$copyrights = $copyrights_parent;
5248						}
5249
5250						// CREDITS
5251						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5252						{
5253							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5254							{
5255								$credit_role = null;
5256								$credit_scheme = null;
5257								$credit_name = null;
5258								if (isset($credit['attribs']['']['role']))
5259								{
5260									$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5261								}
5262								if (isset($credit['attribs']['']['scheme']))
5263								{
5264									$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5265								}
5266								else
5267								{
5268									$credit_scheme = 'urn:ebu';
5269								}
5270								if (isset($credit['data']))
5271								{
5272									$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5273								}
5274								$credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5275							}
5276							if (is_array($credits))
5277							{
5278								$credits = array_values(SimplePie_Misc::array_unique($credits));
5279							}
5280						}
5281						else
5282						{
5283							$credits = $credits_parent;
5284						}
5285
5286						// DESCRIPTION
5287						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5288						{
5289							$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5290						}
5291						else
5292						{
5293							$description = $description_parent;
5294						}
5295
5296						// HASHES
5297						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5298						{
5299							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5300							{
5301								$value = null;
5302								$algo = null;
5303								if (isset($hash['data']))
5304								{
5305									$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5306								}
5307								if (isset($hash['attribs']['']['algo']))
5308								{
5309									$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5310								}
5311								else
5312								{
5313									$algo = 'md5';
5314								}
5315								$hashes[] = $algo.':'.$value;
5316							}
5317							if (is_array($hashes))
5318							{
5319								$hashes = array_values(SimplePie_Misc::array_unique($hashes));
5320							}
5321						}
5322						else
5323						{
5324							$hashes = $hashes_parent;
5325						}
5326
5327						// KEYWORDS
5328						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5329						{
5330							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5331							{
5332								$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5333								foreach ($temp as $word)
5334								{
5335									$keywords[] = trim($word);
5336								}
5337								unset($temp);
5338							}
5339							if (is_array($keywords))
5340							{
5341								$keywords = array_values(SimplePie_Misc::array_unique($keywords));
5342							}
5343						}
5344						else
5345						{
5346							$keywords = $keywords_parent;
5347						}
5348
5349						// PLAYER
5350						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5351						{
5352							$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5353						}
5354						else
5355						{
5356							$player = $player_parent;
5357						}
5358
5359						// RATINGS
5360						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5361						{
5362							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5363							{
5364								$rating_scheme = null;
5365								$rating_value = null;
5366								if (isset($rating['attribs']['']['scheme']))
5367								{
5368									$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5369								}
5370								else
5371								{
5372									$rating_scheme = 'urn:simple';
5373								}
5374								if (isset($rating['data']))
5375								{
5376									$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5377								}
5378								$ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5379							}
5380							if (is_array($ratings))
5381							{
5382								$ratings = array_values(SimplePie_Misc::array_unique($ratings));
5383							}
5384						}
5385						else
5386						{
5387							$ratings = $ratings_parent;
5388						}
5389
5390						// RESTRICTIONS
5391						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5392						{
5393							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5394							{
5395								$restriction_relationship = null;
5396								$restriction_type = null;
5397								$restriction_value = null;
5398								if (isset($restriction['attribs']['']['relationship']))
5399								{
5400									$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5401								}
5402								if (isset($restriction['attribs']['']['type']))
5403								{
5404									$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5405								}
5406								if (isset($restriction['data']))
5407								{
5408									$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5409								}
5410								$restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5411							}
5412							if (is_array($restrictions))
5413							{
5414								$restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5415							}
5416						}
5417						else
5418						{
5419							$restrictions = $restrictions_parent;
5420						}
5421
5422						// THUMBNAILS
5423						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5424						{
5425							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5426							{
5427								$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5428							}
5429							if (is_array($thumbnails))
5430							{
5431								$thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5432							}
5433						}
5434						else
5435						{
5436							$thumbnails = $thumbnails_parent;
5437						}
5438
5439						// TITLES
5440						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5441						{
5442							$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5443						}
5444						else
5445						{
5446							$title = $title_parent;
5447						}
5448
5449						$this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5450					}
5451				}
5452			}
5453
5454			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5455			{
5456				if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5457				{
5458					// Attributes
5459					$bitrate = null;
5460					$channels = null;
5461					$duration = null;
5462					$expression = null;
5463					$framerate = null;
5464					$height = null;
5465					$javascript = null;
5466					$lang = null;
5467					$length = null;
5468					$medium = null;
5469					$samplingrate = null;
5470					$type = null;
5471					$url = null;
5472					$width = null;
5473
5474					$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5475					if (isset($link['attribs']['']['type']))
5476					{
5477						$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5478					}
5479					if (isset($link['attribs']['']['length']))
5480					{
5481						$length = ceil($link['attribs']['']['length']);
5482					}
5483
5484					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5485					$this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5486				}
5487			}
5488
5489			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5490			{
5491				if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5492				{
5493					// Attributes
5494					$bitrate = null;
5495					$channels = null;
5496					$duration = null;
5497					$expression = null;
5498					$framerate = null;
5499					$height = null;
5500					$javascript = null;
5501					$lang = null;
5502					$length = null;
5503					$medium = null;
5504					$samplingrate = null;
5505					$type = null;
5506					$url = null;
5507					$width = null;
5508
5509					$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5510					if (isset($link['attribs']['']['type']))
5511					{
5512						$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5513					}
5514					if (isset($link['attribs']['']['length']))
5515					{
5516						$length = ceil($link['attribs']['']['length']);
5517					}
5518
5519					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5520					$this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5521				}
5522			}
5523
5524			if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5525			{
5526				if (isset($enclosure[0]['attribs']['']['url']))
5527				{
5528					// Attributes
5529					$bitrate = null;
5530					$channels = null;
5531					$duration = null;
5532					$expression = null;
5533					$framerate = null;
5534					$height = null;
5535					$javascript = null;
5536					$lang = null;
5537					$length = null;
5538					$medium = null;
5539					$samplingrate = null;
5540					$type = null;
5541					$url = null;
5542					$width = null;
5543
5544					$url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5545					if (isset($enclosure[0]['attribs']['']['type']))
5546					{
5547						$type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5548					}
5549					if (isset($enclosure[0]['attribs']['']['length']))
5550					{
5551						$length = ceil($enclosure[0]['attribs']['']['length']);
5552					}
5553
5554					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5555					$this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5556				}
5557			}
5558
5559			if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
5560			{
5561				// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5562				$this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5563			}
5564
5565			$this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5566		}
5567		if (!empty($this->data['enclosures']))
5568		{
5569			return $this->data['enclosures'];
5570		}
5571		else
5572		{
5573			return null;
5574		}
5575	}
5576
5577	function get_latitude()
5578	{
5579		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5580		{
5581			return (float) $return[0]['data'];
5582		}
5583		elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5584		{
5585			return (float) $match[1];
5586		}
5587		else
5588		{
5589			return null;
5590		}
5591	}
5592
5593	function get_longitude()
5594	{
5595		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5596		{
5597			return (float) $return[0]['data'];
5598		}
5599		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5600		{
5601			return (float) $return[0]['data'];
5602		}
5603		elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5604		{
5605			return (float) $match[2];
5606		}
5607		else
5608		{
5609			return null;
5610		}
5611	}
5612
5613	function get_source()
5614	{
5615		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5616		{
5617			return new $this->feed->source_class($this, $return[0]);
5618		}
5619		else
5620		{
5621			return null;
5622		}
5623	}
5624
5625	/**
5626	 * Creates the add_to_* methods' return data
5627	 *
5628	 * @access private
5629	 * @param string $item_url String to prefix to the item permalink
5630	 * @param string $title_url String to prefix to the item title
5631	 * (and suffix to the item permalink)
5632	 * @return mixed URL if feed exists, false otherwise
5633	 */
5634	function add_to_service($item_url, $title_url = null, $summary_url = null)
5635	{
5636		if ($this->get_permalink() !== null)
5637		{
5638			$return = $item_url . rawurlencode($this->get_permalink());
5639			if ($title_url !== null && $this->get_title() !== null)
5640			{
5641				$return .= $title_url . rawurlencode($this->get_title());
5642			}
5643			if ($summary_url !== null && $this->get_description() !== null)
5644			{
5645				$return .= $summary_url . rawurlencode($this->get_description());
5646			}
5647			return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5648		}
5649		else
5650		{
5651			return null;
5652		}
5653	}
5654
5655	function add_to_blinklist()
5656	{
5657		return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5658	}
5659
5660	function add_to_blogmarks()
5661	{
5662		return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5663	}
5664
5665	function add_to_delicious()
5666	{
5667		return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5668	}
5669
5670	function add_to_digg()
5671	{
5672		return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5673	}
5674
5675	function add_to_furl()
5676	{
5677		return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5678	}
5679
5680	function add_to_magnolia()
5681	{
5682		return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5683	}
5684
5685	function add_to_myweb20()
5686	{
5687		return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5688	}
5689
5690	function add_to_newsvine()
5691	{
5692		return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5693	}
5694
5695	function add_to_reddit()
5696	{
5697		return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5698	}
5699
5700	function add_to_segnalo()
5701	{
5702		return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5703	}
5704
5705	function add_to_simpy()
5706	{
5707		return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5708	}
5709
5710	function add_to_spurl()
5711	{
5712		return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5713	}
5714
5715	function add_to_wists()
5716	{
5717		return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5718	}
5719
5720	function search_technorati()
5721	{
5722		return $this->add_to_service('http://www.technorati.com/search/');
5723	}
5724}
5725
5726class SimplePie_Source
5727{
5728	var $item;
5729	var $data = array();
5730
5731	function SimplePie_Source($item, $data)
5732	{
5733		$this->item = $item;
5734		$this->data = $data;
5735	}
5736
5737	function __toString()
5738	{
5739		return md5(serialize($this->data));
5740	}
5741
5742	function get_source_tags($namespace, $tag)
5743	{
5744		if (isset($this->data['child'][$namespace][$tag]))
5745		{
5746			return $this->data['child'][$namespace][$tag];
5747		}
5748		else
5749		{
5750			return null;
5751		}
5752	}
5753
5754	function get_base($element = array())
5755	{
5756		return $this->item->get_base($element);
5757	}
5758
5759	function sanitize($data, $type, $base = '')
5760	{
5761		return $this->item->sanitize($data, $type, $base);
5762	}
5763
5764	function get_item()
5765	{
5766		return $this->item;
5767	}
5768
5769	function get_title()
5770	{
5771		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5772		{
5773			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5774		}
5775		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5776		{
5777			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5778		}
5779		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5780		{
5781			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5782		}
5783		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5784		{
5785			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5786		}
5787		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5788		{
5789			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5790		}
5791		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5792		{
5793			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5794		}
5795		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5796		{
5797			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5798		}
5799		else
5800		{
5801			return null;
5802		}
5803	}
5804
5805	function get_category($key = 0)
5806	{
5807		$categories = $this->get_categories();
5808		if (isset($categories[$key]))
5809		{
5810			return $categories[$key];
5811		}
5812		else
5813		{
5814			return null;
5815		}
5816	}
5817
5818	function get_categories()
5819	{
5820		$categories = array();
5821
5822		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5823		{
5824			$term = null;
5825			$scheme = null;
5826			$label = null;
5827			if (isset($category['attribs']['']['term']))
5828			{
5829				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5830			}
5831			if (isset($category['attribs']['']['scheme']))
5832			{
5833				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5834			}
5835			if (isset($category['attribs']['']['label']))
5836			{
5837				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5838			}
5839			$categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5840		}
5841		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5842		{
5843			// This is really the label, but keep this as the term also for BC.
5844			// Label will also work on retrieving because that falls back to term.
5845			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5846			if (isset($category['attribs']['']['domain']))
5847			{
5848				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5849			}
5850			else
5851			{
5852				$scheme = null;
5853			}
5854			$categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5855		}
5856		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5857		{
5858			$categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5859		}
5860		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5861		{
5862			$categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5863		}
5864
5865		if (!empty($categories))
5866		{
5867			return SimplePie_Misc::array_unique($categories);
5868		}
5869		else
5870		{
5871			return null;
5872		}
5873	}
5874
5875	function get_author($key = 0)
5876	{
5877		$authors = $this->get_authors();
5878		if (isset($authors[$key]))
5879		{
5880			return $authors[$key];
5881		}
5882		else
5883		{
5884			return null;
5885		}
5886	}
5887
5888	function get_authors()
5889	{
5890		$authors = array();
5891		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5892		{
5893			$name = null;
5894			$uri = null;
5895			$email = null;
5896			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5897			{
5898				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5899			}
5900			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5901			{
5902				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
5903			}
5904			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5905			{
5906				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5907			}
5908			if ($name !== null || $email !== null || $uri !== null)
5909			{
5910				$authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5911			}
5912		}
5913		if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5914		{
5915			$name = null;
5916			$url = null;
5917			$email = null;
5918			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5919			{
5920				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5921			}
5922			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5923			{
5924				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
5925			}
5926			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5927			{
5928				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5929			}
5930			if ($name !== null || $email !== null || $url !== null)
5931			{
5932				$authors[] =& new $this->item->feed->author_class($name, $url, $email);
5933			}
5934		}
5935		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5936		{
5937			$authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5938		}
5939		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5940		{
5941			$authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5942		}
5943		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5944		{
5945			$authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5946		}
5947
5948		if (!empty($authors))
5949		{
5950			return SimplePie_Misc::array_unique($authors);
5951		}
5952		else
5953		{
5954			return null;
5955		}
5956	}
5957
5958	function get_contributor($key = 0)
5959	{
5960		$contributors = $this->get_contributors();
5961		if (isset($contributors[$key]))
5962		{
5963			return $contributors[$key];
5964		}
5965		else
5966		{
5967			return null;
5968		}
5969	}
5970
5971	function get_contributors()
5972	{
5973		$contributors = array();
5974		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5975		{
5976			$name = null;
5977			$uri = null;
5978			$email = null;
5979			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5980			{
5981				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5982			}
5983			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5984			{
5985				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
5986			}
5987			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5988			{
5989				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5990			}
5991			if ($name !== null || $email !== null || $uri !== null)
5992			{
5993				$contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
5994			}
5995		}
5996		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
5997		{
5998			$name = null;
5999			$url = null;
6000			$email = null;
6001			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6002			{
6003				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6004			}
6005			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6006			{
6007				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
6008			}
6009			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6010			{
6011				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6012			}
6013			if ($name !== null || $email !== null || $url !== null)
6014			{
6015				$contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6016			}
6017		}
6018
6019		if (!empty($contributors))
6020		{
6021			return SimplePie_Misc::array_unique($contributors);
6022		}
6023		else
6024		{
6025			return null;
6026		}
6027	}
6028
6029	function get_link($key = 0, $rel = 'alternate')
6030	{
6031		$links = $this->get_links($rel);
6032		if (isset($links[$key]))
6033		{
6034			return $links[$key];
6035		}
6036		else
6037		{
6038			return null;
6039		}
6040	}
6041
6042	/**
6043	 * Added for parity between the parent-level and the item/entry-level.
6044	 */
6045	function get_permalink()
6046	{
6047		return $this->get_link(0);
6048	}
6049
6050	function get_links($rel = 'alternate')
6051	{
6052		if (!isset($this->data['links']))
6053		{
6054			$this->data['links'] = array();
6055			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6056			{
6057				foreach ($links as $link)
6058				{
6059					if (isset($link['attribs']['']['href']))
6060					{
6061						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6062						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6063					}
6064				}
6065			}
6066			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6067			{
6068				foreach ($links as $link)
6069				{
6070					if (isset($link['attribs']['']['href']))
6071					{
6072						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6073						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6074
6075					}
6076				}
6077			}
6078			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6079			{
6080				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6081			}
6082			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6083			{
6084				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6085			}
6086			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6087			{
6088				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6089			}
6090
6091			$keys = array_keys($this->data['links']);
6092			foreach ($keys as $key)
6093			{
6094				if (SimplePie_Misc::is_isegment_nz_nc($key))
6095				{
6096					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6097					{
6098						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6099						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6100					}
6101					else
6102					{
6103						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6104					}
6105				}
6106				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6107				{
6108					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6109				}
6110				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
6111			}
6112		}
6113
6114		if (isset($this->data['links'][$rel]))
6115		{
6116			return $this->data['links'][$rel];
6117		}
6118		else
6119		{
6120			return null;
6121		}
6122	}
6123
6124	function get_description()
6125	{
6126		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6127		{
6128			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6129		}
6130		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6131		{
6132			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6133		}
6134		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6135		{
6136			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6137		}
6138		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6139		{
6140			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6141		}
6142		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6143		{
6144			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6145		}
6146		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6147		{
6148			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6149		}
6150		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6151		{
6152			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6153		}
6154		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6155		{
6156			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6157		}
6158		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6159		{
6160			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6161		}
6162		else
6163		{
6164			return null;
6165		}
6166	}
6167
6168	function get_copyright()
6169	{
6170		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6171		{
6172			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6173		}
6174		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6175		{
6176			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6177		}
6178		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6179		{
6180			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6181		}
6182		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6183		{
6184			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6185		}
6186		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6187		{
6188			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6189		}
6190		else
6191		{
6192			return null;
6193		}
6194	}
6195
6196	function get_language()
6197	{
6198		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6199		{
6200			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6201		}
6202		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6203		{
6204			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6205		}
6206		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6207		{
6208			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6209		}
6210		elseif (isset($this->data['xml_lang']))
6211		{
6212			return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6213		}
6214		else
6215		{
6216			return null;
6217		}
6218	}
6219
6220	function get_latitude()
6221	{
6222		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6223		{
6224			return (float) $return[0]['data'];
6225		}
6226		elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6227		{
6228			return (float) $match[1];
6229		}
6230		else
6231		{
6232			return null;
6233		}
6234	}
6235
6236	function get_longitude()
6237	{
6238		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6239		{
6240			return (float) $return[0]['data'];
6241		}
6242		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6243		{
6244			return (float) $return[0]['data'];
6245		}
6246		elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6247		{
6248			return (float) $match[2];
6249		}
6250		else
6251		{
6252			return null;
6253		}
6254	}
6255
6256	function get_image_url()
6257	{
6258		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6259		{
6260			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6261		}
6262		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6263		{
6264			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6265		}
6266		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6267		{
6268			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6269		}
6270		else
6271		{
6272			return null;
6273		}
6274	}
6275}
6276
6277class SimplePie_Author
6278{
6279	var $name;
6280	var $link;
6281	var $email;
6282
6283	// Constructor, used to input the data
6284	function SimplePie_Author($name = null, $link = null, $email = null)
6285	{
6286		$this->name = $name;
6287		$this->link = $link;
6288		$this->email = $email;
6289	}
6290
6291	function __toString()
6292	{
6293		// There is no $this->data here
6294		return md5(serialize($this));
6295	}
6296
6297	function get_name()
6298	{
6299		if ($this->name !== null)
6300		{
6301			return $this->name;
6302		}
6303		else
6304		{
6305			return null;
6306		}
6307	}
6308
6309	function get_link()
6310	{
6311		if ($this->link !== null)
6312		{
6313			return $this->link;
6314		}
6315		else
6316		{
6317			return null;
6318		}
6319	}
6320
6321	function get_email()
6322	{
6323		if ($this->email !== null)
6324		{
6325			return $this->email;
6326		}
6327		else
6328		{
6329			return null;
6330		}
6331	}
6332}
6333
6334class SimplePie_Category
6335{
6336	var $term;
6337	var $scheme;
6338	var $label;
6339
6340	// Constructor, used to input the data
6341	function SimplePie_Category($term = null, $scheme = null, $label = null)
6342	{
6343		$this->term = $term;
6344		$this->scheme = $scheme;
6345		$this->label = $label;
6346	}
6347
6348	function __toString()
6349	{
6350		// There is no $this->data here
6351		return md5(serialize($this));
6352	}
6353
6354	function get_term()
6355	{
6356		if ($this->term !== null)
6357		{
6358			return $this->term;
6359		}
6360		else
6361		{
6362			return null;
6363		}
6364	}
6365
6366	function get_scheme()
6367	{
6368		if ($this->scheme !== null)
6369		{
6370			return $this->scheme;
6371		}
6372		else
6373		{
6374			return null;
6375		}
6376	}
6377
6378	function get_label()
6379	{
6380		if ($this->label !== null)
6381		{
6382			return $this->label;
6383		}
6384		else
6385		{
6386			return $this->get_term();
6387		}
6388	}
6389}
6390
6391class SimplePie_Enclosure
6392{
6393	var $bitrate;
6394	var $captions;
6395	var $categories;
6396	var $channels;
6397	var $copyright;
6398	var $credits;
6399	var $description;
6400	var $duration;
6401	var $expression;
6402	var $framerate;
6403	var $handler;
6404	var $hashes;
6405	var $height;
6406	var $javascript;
6407	var $keywords;
6408	var $lang;
6409	var $length;
6410	var $link;
6411	var $medium;
6412	var $player;
6413	var $ratings;
6414	var $restrictions;
6415	var $samplingrate;
6416	var $thumbnails;
6417	var $title;
6418	var $type;
6419	var $width;
6420
6421	// Constructor, used to input the data
6422	function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
6423	{
6424		$this->bitrate = $bitrate;
6425		$this->captions = $captions;
6426		$this->categories = $categories;
6427		$this->channels = $channels;
6428		$this->copyright = $copyright;
6429		$this->credits = $credits;
6430		$this->description = $description;
6431		$this->duration = $duration;
6432		$this->expression = $expression;
6433		$this->framerate = $framerate;
6434		$this->hashes = $hashes;
6435		$this->height = $height;
6436		$this->javascript = $javascript;
6437		$this->keywords = $keywords;
6438		$this->lang = $lang;
6439		$this->length = $length;
6440		$this->link = $link;
6441		$this->medium = $medium;
6442		$this->player = $player;
6443		$this->ratings = $ratings;
6444		$this->restrictions = $restrictions;
6445		$this->samplingrate = $samplingrate;
6446		$this->thumbnails = $thumbnails;
6447		$this->title = $title;
6448		$this->type = $type;
6449		$this->width = $width;
6450		if (class_exists('idna_convert'))
6451		{
6452			$idn =& new idna_convert;
6453			$parsed = SimplePie_Misc::parse_url($link);
6454			$this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6455		}
6456		$this->handler = $this->get_handler(); // Needs to load last
6457	}
6458
6459	function __toString()
6460	{
6461		// There is no $this->data here
6462		return md5(serialize($this));
6463	}
6464
6465	function get_bitrate()
6466	{
6467		if ($this->bitrate !== null)
6468		{
6469			return $this->bitrate;
6470		}
6471		else
6472		{
6473			return null;
6474		}
6475	}
6476
6477	function get_caption($key = 0)
6478	{
6479		$captions = $this->get_captions();
6480		if (isset($captions[$key]))
6481		{
6482			return $captions[$key];
6483		}
6484		else
6485		{
6486			return null;
6487		}
6488	}
6489
6490	function get_captions()
6491	{
6492		if ($this->captions !== null)
6493		{
6494			return $this->captions;
6495		}
6496		else
6497		{
6498			return null;
6499		}
6500	}
6501
6502	function get_category($key = 0)
6503	{
6504		$categories = $this->get_categories();
6505		if (isset($categories[$key]))
6506		{
6507			return $categories[$key];
6508		}
6509		else
6510		{
6511			return null;
6512		}
6513	}
6514
6515	function get_categories()
6516	{
6517		if ($this->categories !== null)
6518		{
6519			return $this->categories;
6520		}
6521		else
6522		{
6523			return null;
6524		}
6525	}
6526
6527	function get_channels()
6528	{
6529		if ($this->channels !== null)
6530		{
6531			return $this->channels;
6532		}
6533		else
6534		{
6535			return null;
6536		}
6537	}
6538
6539	function get_copyright()
6540	{
6541		if ($this->copyright !== null)
6542		{
6543			return $this->copyright;
6544		}
6545		else
6546		{
6547			return null;
6548		}
6549	}
6550
6551	function get_credit($key = 0)
6552	{
6553		$credits = $this->get_credits();
6554		if (isset($credits[$key]))
6555		{
6556			return $credits[$key];
6557		}
6558		else
6559		{
6560			return null;
6561		}
6562	}
6563
6564	function get_credits()
6565	{
6566		if ($this->credits !== null)
6567		{
6568			return $this->credits;
6569		}
6570		else
6571		{
6572			return null;
6573		}
6574	}
6575
6576	function get_description()
6577	{
6578		if ($this->description !== null)
6579		{
6580			return $this->description;
6581		}
6582		else
6583		{
6584			return null;
6585		}
6586	}
6587
6588	function get_duration($convert = false)
6589	{
6590		if ($this->duration !== null)
6591		{
6592			if ($convert)
6593			{
6594				$time = SimplePie_Misc::time_hms($this->duration);
6595				return $time;
6596			}
6597			else
6598			{
6599				return $this->duration;
6600			}
6601		}
6602		else
6603		{
6604			return null;
6605		}
6606	}
6607
6608	function get_expression()
6609	{
6610		if ($this->expression !== null)
6611		{
6612			return $this->expression;
6613		}
6614		else
6615		{
6616			return 'full';
6617		}
6618	}
6619
6620	function get_extension()
6621	{
6622		if ($this->link !== null)
6623		{
6624			$url = SimplePie_Misc::parse_url($this->link);
6625			if ($url['path'] !== '')
6626			{
6627				return pathinfo($url['path'], PATHINFO_EXTENSION);
6628			}
6629		}
6630		return null;
6631	}
6632
6633	function get_framerate()
6634	{
6635		if ($this->framerate !== null)
6636		{
6637			return $this->framerate;
6638		}
6639		else
6640		{
6641			return null;
6642		}
6643	}
6644
6645	function get_handler()
6646	{
6647		return $this->get_real_type(true);
6648	}
6649
6650	function get_hash($key = 0)
6651	{
6652		$hashes = $this->get_hashes();
6653		if (isset($hashes[$key]))
6654		{
6655			return $hashes[$key];
6656		}
6657		else
6658		{
6659			return null;
6660		}
6661	}
6662
6663	function get_hashes()
6664	{
6665		if ($this->hashes !== null)
6666		{
6667			return $this->hashes;
6668		}
6669		else
6670		{
6671			return null;
6672		}
6673	}
6674
6675	function get_height()
6676	{
6677		if ($this->height !== null)
6678		{
6679			return $this->height;
6680		}
6681		else
6682		{
6683			return null;
6684		}
6685	}
6686
6687	function get_language()
6688	{
6689		if ($this->lang !== null)
6690		{
6691			return $this->lang;
6692		}
6693		else
6694		{
6695			return null;
6696		}
6697	}
6698
6699	function get_keyword($key = 0)
6700	{
6701		$keywords = $this->get_keywords();
6702		if (isset($keywords[$key]))
6703		{
6704			return $keywords[$key];
6705		}
6706		else
6707		{
6708			return null;
6709		}
6710	}
6711
6712	function get_keywords()
6713	{
6714		if ($this->keywords !== null)
6715		{
6716			return $this->keywords;
6717		}
6718		else
6719		{
6720			return null;
6721		}
6722	}
6723
6724	function get_length()
6725	{
6726		if ($this->length !== null)
6727		{
6728			return $this->length;
6729		}
6730		else
6731		{
6732			return null;
6733		}
6734	}
6735
6736	function get_link()
6737	{
6738		if ($this->link !== null)
6739		{
6740			return urldecode($this->link);
6741		}
6742		else
6743		{
6744			return null;
6745		}
6746	}
6747
6748	function get_medium()
6749	{
6750		if ($this->medium !== null)
6751		{
6752			return $this->medium;
6753		}
6754		else
6755		{
6756			return null;
6757		}
6758	}
6759
6760	function get_player()
6761	{
6762		if ($this->player !== null)
6763		{
6764			return $this->player;
6765		}
6766		else
6767		{
6768			return null;
6769		}
6770	}
6771
6772	function get_rating($key = 0)
6773	{
6774		$ratings = $this->get_ratings();
6775		if (isset($ratings[$key]))
6776		{
6777			return $ratings[$key];
6778		}
6779		else
6780		{
6781			return null;
6782		}
6783	}
6784
6785	function get_ratings()
6786	{
6787		if ($this->ratings !== null)
6788		{
6789			return $this->ratings;
6790		}
6791		else
6792		{
6793			return null;
6794		}
6795	}
6796
6797	function get_restriction($key = 0)
6798	{
6799		$restrictions = $this->get_restrictions();
6800		if (isset($restrictions[$key]))
6801		{
6802			return $restrictions[$key];
6803		}
6804		else
6805		{
6806			return null;
6807		}
6808	}
6809
6810	function get_restrictions()
6811	{
6812		if ($this->restrictions !== null)
6813		{
6814			return $this->restrictions;
6815		}
6816		else
6817		{
6818			return null;
6819		}
6820	}
6821
6822	function get_sampling_rate()
6823	{
6824		if ($this->samplingrate !== null)
6825		{
6826			return $this->samplingrate;
6827		}
6828		else
6829		{
6830			return null;
6831		}
6832	}
6833
6834	function get_size()
6835	{
6836		$length = $this->get_length();
6837		if ($length !== null)
6838		{
6839			return round($length/1048576, 2);
6840		}
6841		else
6842		{
6843			return null;
6844		}
6845	}
6846
6847	function get_thumbnail($key = 0)
6848	{
6849		$thumbnails = $this->get_thumbnails();
6850		if (isset($thumbnails[$key]))
6851		{
6852			return $thumbnails[$key];
6853		}
6854		else
6855		{
6856			return null;
6857		}
6858	}
6859
6860	function get_thumbnails()
6861	{
6862		if ($this->thumbnails !== null)
6863		{
6864			return $this->thumbnails;
6865		}
6866		else
6867		{
6868			return null;
6869		}
6870	}
6871
6872	function get_title()
6873	{
6874		if ($this->title !== null)
6875		{
6876			return $this->title;
6877		}
6878		else
6879		{
6880			return null;
6881		}
6882	}
6883
6884	function get_type()
6885	{
6886		if ($this->type !== null)
6887		{
6888			return $this->type;
6889		}
6890		else
6891		{
6892			return null;
6893		}
6894	}
6895
6896	function get_width()
6897	{
6898		if ($this->width !== null)
6899		{
6900			return $this->width;
6901		}
6902		else
6903		{
6904			return null;
6905		}
6906	}
6907
6908	function native_embed($options='')
6909	{
6910		return $this->embed($options, true);
6911	}
6912
6913	/**
6914	 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6915	 */
6916	function embed($options = '', $native = false)
6917	{
6918		// Set up defaults
6919		$audio = '';
6920		$video = '';
6921		$alt = '';
6922		$altclass = '';
6923		$loop = 'false';
6924		$width = 'auto';
6925		$height = 'auto';
6926		$bgcolor = '#ffffff';
6927		$mediaplayer = '';
6928		$widescreen = false;
6929		$handler = $this->get_handler();
6930		$type = $this->get_real_type();
6931
6932		// Process options and reassign values as necessary
6933		if (is_array($options))
6934		{
6935			extract($options);
6936		}
6937		else
6938		{
6939			$options = explode(',', $options);
6940			foreach($options as $option)
6941			{
6942				$opt = explode(':', $option, 2);
6943				if (isset($opt[0], $opt[1]))
6944				{
6945					$opt[0] = trim($opt[0]);
6946					$opt[1] = trim($opt[1]);
6947					switch ($opt[0])
6948					{
6949						case 'audio':
6950							$audio = $opt[1];
6951							break;
6952
6953						case 'video':
6954							$video = $opt[1];
6955							break;
6956
6957						case 'alt':
6958							$alt = $opt[1];
6959							break;
6960
6961						case 'altclass':
6962							$altclass = $opt[1];
6963							break;
6964
6965						case 'loop':
6966							$loop = $opt[1];
6967							break;
6968
6969						case 'width':
6970							$width = $opt[1];
6971							break;
6972
6973						case 'height':
6974							$height = $opt[1];
6975							break;
6976
6977						case 'bgcolor':
6978							$bgcolor = $opt[1];
6979							break;
6980
6981						case 'mediaplayer':
6982							$mediaplayer = $opt[1];
6983							break;
6984
6985						case 'widescreen':
6986							$widescreen = $opt[1];
6987							break;
6988					}
6989				}
6990			}
6991		}
6992
6993		$mime = explode('/', $type, 2);
6994		$mime = $mime[0];
6995
6996		// Process values for 'auto'
6997		if ($width === 'auto')
6998		{
6999			if ($mime === 'video')
7000			{
7001				if ($height === 'auto')
7002				{
7003					$width = 480;
7004				}
7005				elseif ($widescreen)
7006				{
7007					$width = round((intval($height)/9)*16);
7008				}
7009				else
7010				{
7011					$width = round((intval($height)/3)*4);
7012				}
7013			}
7014			else
7015			{
7016				$width = '100%';
7017			}
7018		}
7019
7020		if ($height === 'auto')
7021		{
7022			if ($mime === 'audio')
7023			{
7024				$height = 0;
7025			}
7026			elseif ($mime === 'video')
7027			{
7028				if ($width === 'auto')
7029				{
7030					if ($widescreen)
7031					{
7032						$height = 270;
7033					}
7034					else
7035					{
7036						$height = 360;
7037					}
7038				}
7039				elseif ($widescreen)
7040				{
7041					$height = round((intval($width)/16)*9);
7042				}
7043				else
7044				{
7045					$height = round((intval($width)/4)*3);
7046				}
7047			}
7048			else
7049			{
7050				$height = 376;
7051			}
7052		}
7053		elseif ($mime === 'audio')
7054		{
7055			$height = 0;
7056		}
7057
7058		// Set proper placeholder value
7059		if ($mime === 'audio')
7060		{
7061			$placeholder = $audio;
7062		}
7063		elseif ($mime === 'video')
7064		{
7065			$placeholder = $video;
7066		}
7067
7068		$embed = '';
7069
7070		// Make sure the JS library is included
7071		if (!$native)
7072		{
7073			static $javascript_outputted = null;
7074			if (!$javascript_outputted && $this->javascript)
7075			{
7076				$embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7077				$javascript_outputted = true;
7078			}
7079		}
7080
7081		// Odeo Feed MP3's
7082		if ($handler === 'odeo')
7083		{
7084			if ($native)
7085			{
7086				$embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
7087			}
7088			else
7089			{
7090				$embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7091			}
7092		}
7093
7094		// Flash
7095		elseif ($handler === 'flash')
7096		{
7097			if ($native)
7098			{
7099				$embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
7100			}
7101			else
7102			{
7103				$embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7104			}
7105		}
7106
7107		// Flash Media Player file types.
7108		// Preferred handler for MP3 file types.
7109		elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7110		{
7111			$height += 20;
7112			if ($native)
7113			{
7114				$embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
7115			}
7116			else
7117			{
7118				$embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7119			}
7120		}
7121
7122		// QuickTime 7 file types.  Need to test with QuickTime 6.
7123		// Only handle MP3's if the Flash Media Player is not present.
7124		elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7125		{
7126			$height += 16;
7127			if ($native)
7128			{
7129				if ($placeholder !== '')
7130				{
7131					$embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7132				}
7133				else
7134				{
7135					$embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7136				}
7137			}
7138			else
7139			{
7140				$embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7141			}
7142		}
7143
7144		// Windows Media
7145		elseif ($handler === 'wmedia')
7146		{
7147			$height += 45;
7148			if ($native)
7149			{
7150				$embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
7151			}
7152			else
7153			{
7154				$embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7155			}
7156		}
7157
7158		// Everything else
7159		else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7160
7161		return $embed;
7162	}
7163
7164	function get_real_type($find_handler = false)
7165	{
7166		// If it's Odeo, let's get it out of the way.
7167		if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7168		{
7169			return 'odeo';
7170		}
7171
7172		// Mime-types by handler.
7173		$types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7174		$types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7175		$types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
7176		$types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
7177		$types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7178
7179		if ($this->get_type() !== null)
7180		{
7181			$type = strtolower($this->type);
7182		}
7183		else
7184		{
7185			$type = null;
7186		}
7187
7188		// If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7189		if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7190		{
7191			switch (strtolower($this->get_extension()))
7192			{
7193				// Audio mime-types
7194				case 'aac':
7195				case 'adts':
7196					$type = 'audio/acc';
7197					break;
7198
7199				case 'aif':
7200				case 'aifc':
7201				case 'aiff':
7202				case 'cdda':
7203					$type = 'audio/aiff';
7204					break;
7205
7206				case 'bwf':
7207					$type = 'audio/wav';
7208					break;
7209
7210				case 'kar':
7211				case 'mid':
7212				case 'midi':
7213				case 'smf':
7214					$type = 'audio/midi';
7215					break;
7216
7217				case 'm4a':
7218					$type = 'audio/x-m4a';
7219					break;
7220
7221				case 'mp3':
7222				case 'swa':
7223					$type = 'audio/mp3';
7224					break;
7225
7226				case 'wav':
7227					$type = 'audio/wav';
7228					break;
7229
7230				case 'wax':
7231					$type = 'audio/x-ms-wax';
7232					break;
7233
7234				case 'wma':
7235					$type = 'audio/x-ms-wma';
7236					break;
7237
7238				// Video mime-types
7239				case '3gp':
7240				case '3gpp':
7241					$type = 'video/3gpp';
7242					break;
7243
7244				case '3g2':
7245				case '3gp2':
7246					$type = 'video/3gpp2';
7247					break;
7248
7249				case 'asf':
7250					$type = 'video/x-ms-asf';
7251					break;
7252
7253				case 'flv':
7254					$type = 'video/x-flv';
7255					break;
7256
7257				case 'm1a':
7258				case 'm1s':
7259				case 'm1v':
7260				case 'm15':
7261				case 'm75':
7262				case 'mp2':
7263				case 'mpa':
7264				case 'mpeg':
7265				case 'mpg':
7266				case 'mpm':
7267				case 'mpv':
7268					$type = 'video/mpeg';
7269					break;
7270
7271				case 'm4v':
7272					$type = 'video/x-m4v';
7273					break;
7274
7275				case 'mov':
7276				case 'qt':
7277					$type = 'video/quicktime';
7278					break;
7279
7280				case 'mp4':
7281				case 'mpg4':
7282					$type = 'video/mp4';
7283					break;
7284
7285				case 'sdv':
7286					$type = 'video/sd-video';
7287					break;
7288
7289				case 'wm':
7290					$type = 'video/x-ms-wm';
7291					break;
7292
7293				case 'wmv':
7294					$type = 'video/x-ms-wmv';
7295					break;
7296
7297				case 'wvx':
7298					$type = 'video/x-ms-wvx';
7299					break;
7300
7301				// Flash mime-types
7302				case 'spl':
7303					$type = 'application/futuresplash';
7304					break;
7305
7306				case 'swf':
7307					$type = 'application/x-shockwave-flash';
7308					break;
7309			}
7310		}
7311
7312		if ($find_handler)
7313		{
7314			if (in_array($type, $types_flash))
7315			{
7316				return 'flash';
7317			}
7318			elseif (in_array($type, $types_fmedia))
7319			{
7320				return 'fmedia';
7321			}
7322			elseif (in_array($type, $types_quicktime))
7323			{
7324				return 'quicktime';
7325			}
7326			elseif (in_array($type, $types_wmedia))
7327			{
7328				return 'wmedia';
7329			}
7330			elseif (in_array($type, $types_mp3))
7331			{
7332				return 'mp3';
7333			}
7334			else
7335			{
7336				return null;
7337			}
7338		}
7339		else
7340		{
7341			return $type;
7342		}
7343	}
7344}
7345
7346class SimplePie_Caption
7347{
7348	var $type;
7349	var $lang;
7350	var $startTime;
7351	var $endTime;
7352	var $text;
7353
7354	// Constructor, used to input the data
7355	function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7356	{
7357		$this->type = $type;
7358		$this->lang = $lang;
7359		$this->startTime = $startTime;
7360		$this->endTime = $endTime;
7361		$this->text = $text;
7362	}
7363
7364	function __toString()
7365	{
7366		// There is no $this->data here
7367		return md5(serialize($this));
7368	}
7369
7370	function get_endtime()
7371	{
7372		if ($this->endTime !== null)
7373		{
7374			return $this->endTime;
7375		}
7376		else
7377		{
7378			return null;
7379		}
7380	}
7381
7382	function get_language()
7383	{
7384		if ($this->lang !== null)
7385		{
7386			return $this->lang;
7387		}
7388		else
7389		{
7390			return null;
7391		}
7392	}
7393
7394	function get_starttime()
7395	{
7396		if ($this->startTime !== null)
7397		{
7398			return $this->startTime;
7399		}
7400		else
7401		{
7402			return null;
7403		}
7404	}
7405
7406	function get_text()
7407	{
7408		if ($this->text !== null)
7409		{
7410			return $this->text;
7411		}
7412		else
7413		{
7414			return null;
7415		}
7416	}
7417
7418	function get_type()
7419	{
7420		if ($this->type !== null)
7421		{
7422			return $this->type;
7423		}
7424		else
7425		{
7426			return null;
7427		}
7428	}
7429}
7430
7431class SimplePie_Credit
7432{
7433	var $role;
7434	var $scheme;
7435	var $name;
7436
7437	// Constructor, used to input the data
7438	function SimplePie_Credit($role = null, $scheme = null, $name = null)
7439	{
7440		$this->role = $role;
7441		$this->scheme = $scheme;
7442		$this->name = $name;
7443	}
7444
7445	function __toString()
7446	{
7447		// There is no $this->data here
7448		return md5(serialize($this));
7449	}
7450
7451	function get_role()
7452	{
7453		if ($this->role !== null)
7454		{
7455			return $this->role;
7456		}
7457		else
7458		{
7459			return null;
7460		}
7461	}
7462
7463	function get_scheme()
7464	{
7465		if ($this->scheme !== null)
7466		{
7467			return $this->scheme;
7468		}
7469		else
7470		{
7471			return null;
7472		}
7473	}
7474
7475	function get_name()
7476	{
7477		if ($this->name !== null)
7478		{
7479			return $this->name;
7480		}
7481		else
7482		{
7483			return null;
7484		}
7485	}
7486}
7487
7488class SimplePie_Copyright
7489{
7490	var $url;
7491	var $label;
7492
7493	// Constructor, used to input the data
7494	function SimplePie_Copyright($url = null, $label = null)
7495	{
7496		$this->url = $url;
7497		$this->label = $label;
7498	}
7499
7500	function __toString()
7501	{
7502		// There is no $this->data here
7503		return md5(serialize($this));
7504	}
7505
7506	function get_url()
7507	{
7508		if ($this->url !== null)
7509		{
7510			return $this->url;
7511		}
7512		else
7513		{
7514			return null;
7515		}
7516	}
7517
7518	function get_attribution()
7519	{
7520		if ($this->label !== null)
7521		{
7522			return $this->label;
7523		}
7524		else
7525		{
7526			return null;
7527		}
7528	}
7529}
7530
7531class SimplePie_Rating
7532{
7533	var $scheme;
7534	var $value;
7535
7536	// Constructor, used to input the data
7537	function SimplePie_Rating($scheme = null, $value = null)
7538	{
7539		$this->scheme = $scheme;
7540		$this->value = $value;
7541	}
7542
7543	function __toString()
7544	{
7545		// There is no $this->data here
7546		return md5(serialize($this));
7547	}
7548
7549	function get_scheme()
7550	{
7551		if ($this->scheme !== null)
7552		{
7553			return $this->scheme;
7554		}
7555		else
7556		{
7557			return null;
7558		}
7559	}
7560
7561	function get_value()
7562	{
7563		if ($this->value !== null)
7564		{
7565			return $this->value;
7566		}
7567		else
7568		{
7569			return null;
7570		}
7571	}
7572}
7573
7574class SimplePie_Restriction
7575{
7576	var $relationship;
7577	var $type;
7578	var $value;
7579
7580	// Constructor, used to input the data
7581	function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7582	{
7583		$this->relationship = $relationship;
7584		$this->type = $type;
7585		$this->value = $value;
7586	}
7587
7588	function __toString()
7589	{
7590		// There is no $this->data here
7591		return md5(serialize($this));
7592	}
7593
7594	function get_relationship()
7595	{
7596		if ($this->relationship !== null)
7597		{
7598			return $this->relationship;
7599		}
7600		else
7601		{
7602			return null;
7603		}
7604	}
7605
7606	function get_type()
7607	{
7608		if ($this->type !== null)
7609		{
7610			return $this->type;
7611		}
7612		else
7613		{
7614			return null;
7615		}
7616	}
7617
7618	function get_value()
7619	{
7620		if ($this->value !== null)
7621		{
7622			return $this->value;
7623		}
7624		else
7625		{
7626			return null;
7627		}
7628	}
7629}
7630
7631/**
7632 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7633 */
7634class SimplePie_File
7635{
7636	var $url;
7637	var $useragent;
7638	var $success = true;
7639	var $headers = array();
7640	var $body;
7641	var $status_code;
7642	var $redirects = 0;
7643	var $error;
7644	var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7645
7646	function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7647	{
7648		if (class_exists('idna_convert'))
7649		{
7650			$idn =& new idna_convert;
7651			$parsed = SimplePie_Misc::parse_url($url);
7652			$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7653		}
7654		$this->url = $url;
7655		$this->useragent = $useragent;
7656		if (preg_match('/^http(s)?:\/\//i', $url))
7657		{
7658			if ($useragent === null)
7659			{
7660				$useragent = ini_get('user_agent');
7661				$this->useragent = $useragent;
7662			}
7663			if (!is_array($headers))
7664			{
7665				$headers = array();
7666			}
7667			if (!$force_fsockopen && function_exists('curl_exec'))
7668			{
7669				$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7670				$fp = curl_init();
7671				$headers2 = array();
7672				foreach ($headers as $key => $value)
7673				{
7674					$headers2[] = "$key: $value";
7675				}
7676				if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7677				{
7678					curl_setopt($fp, CURLOPT_ENCODING, '');
7679				}
7680				curl_setopt($fp, CURLOPT_URL, $url);
7681				curl_setopt($fp, CURLOPT_HEADER, 1);
7682				curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7683				curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7684				curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7685				curl_setopt($fp, CURLOPT_REFERER, $url);
7686				curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7687				curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7688				if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7689				{
7690					curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7691					curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7692				}
7693
7694				$this->headers = curl_exec($fp);
7695				if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7696				{
7697					curl_setopt($fp, CURLOPT_ENCODING, 'none');
7698					$this->headers = curl_exec($fp);
7699				}
7700				if (curl_errno($fp))
7701				{
7702					$this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7703					$this->success = false;
7704				}
7705				else
7706				{
7707					$info = curl_getinfo($fp);
7708					curl_close($fp);
7709					$this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7710					$this->headers = array_pop($this->headers);
7711					$parser =& new SimplePie_HTTP_Parser($this->headers);
7712					if ($parser->parse())
7713					{
7714						$this->headers = $parser->headers;
7715						$this->body = $parser->body;
7716						$this->status_code = $parser->status_code;
7717						if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7718						{
7719							$this->redirects++;
7720							$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7721							return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7722						}
7723					}
7724				}
7725			}
7726			else
7727			{
7728				$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7729				$url_parts = parse_url($url);
7730				if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7731				{
7732					$url_parts['host'] = "ssl://$url_parts[host]";
7733					$url_parts['port'] = 443;
7734				}
7735				if (!isset($url_parts['port']))
7736				{
7737					$url_parts['port'] = 80;
7738				}
7739				$fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7740				if (!$fp)
7741				{
7742					$this->error = 'fsockopen error: ' . $errstr;
7743					$this->success = false;
7744				}
7745				else
7746				{
7747					stream_set_timeout($fp, $timeout);
7748					if (isset($url_parts['path']))
7749					{
7750						if (isset($url_parts['query']))
7751						{
7752							$get = "$url_parts[path]?$url_parts[query]";
7753						}
7754						else
7755						{
7756							$get = $url_parts['path'];
7757						}
7758					}
7759					else
7760					{
7761						$get = '/';
7762					}
7763					$out = "GET $get HTTP/1.0\r\n";
7764					$out .= "Host: $url_parts[host]\r\n";
7765					$out .= "User-Agent: $useragent\r\n";
7766					if (extension_loaded('zlib'))
7767					{
7768						$out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7769					}
7770
7771					if (isset($url_parts['user']) && isset($url_parts['pass']))
7772					{
7773						$out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7774					}
7775					foreach ($headers as $key => $value)
7776					{
7777						$out .= "$key: $value\r\n";
7778					}
7779					$out .= "Connection: Close\r\n\r\n";
7780					fwrite($fp, $out);
7781
7782					$info = stream_get_meta_data($fp);
7783
7784					$this->headers = '';
7785					while (!$info['eof'] && !$info['timed_out'])
7786					{
7787						$this->headers .= fread($fp, 1160);
7788						$info = stream_get_meta_data($fp);
7789					}
7790					if (!$info['timed_out'])
7791					{
7792						$parser =& new SimplePie_HTTP_Parser($this->headers);
7793						if ($parser->parse())
7794						{
7795							$this->headers = $parser->headers;
7796							$this->body = $parser->body;
7797							$this->status_code = $parser->status_code;
7798							if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7799							{
7800								$this->redirects++;
7801								$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7802								return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7803							}
7804							if (isset($this->headers['content-encoding']))
7805							{
7806								// Hey, we act dumb elsewhere, so let's do that here too
7807								switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7808								{
7809									case 'gzip':
7810									case 'x-gzip':
7811										$decoder =& new SimplePie_gzdecode($this->body);
7812										if (!$decoder->parse())
7813										{
7814											$this->error = 'Unable to decode HTTP "gzip" stream';
7815											$this->success = false;
7816										}
7817										else
7818										{
7819											$this->body = $decoder->data;
7820										}
7821										break;
7822
7823									case 'deflate':
7824										if (($body = gzuncompress($this->body)) === false)
7825										{
7826											if (($body = gzinflate($this->body)) === false)
7827											{
7828												$this->error = 'Unable to decode HTTP "deflate" stream';
7829												$this->success = false;
7830											}
7831										}
7832										$this->body = $body;
7833										break;
7834
7835									default:
7836										$this->error = 'Unknown content coding';
7837										$this->success = false;
7838								}
7839							}
7840						}
7841					}
7842					else
7843					{
7844						$this->error = 'fsocket timed out';
7845						$this->success = false;
7846					}
7847					fclose($fp);
7848				}
7849			}
7850		}
7851		else
7852		{
7853			$this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7854			if (!$this->body = file_get_contents($url))
7855			{
7856				$this->error = 'file_get_contents could not read the file';
7857				$this->success = false;
7858			}
7859		}
7860	}
7861}
7862
7863/**
7864 * HTTP Response Parser
7865 *
7866 * @package SimplePie
7867 */
7868class SimplePie_HTTP_Parser
7869{
7870	/**
7871	 * HTTP Version
7872	 *
7873	 * @access public
7874	 * @var float
7875	 */
7876	var $http_version = 0.0;
7877
7878	/**
7879	 * Status code
7880	 *
7881	 * @access public
7882	 * @var int
7883	 */
7884	var $status_code = 0;
7885
7886	/**
7887	 * Reason phrase
7888	 *
7889	 * @access public
7890	 * @var string
7891	 */
7892	var $reason = '';
7893
7894	/**
7895	 * Key/value pairs of the headers
7896	 *
7897	 * @access public
7898	 * @var array
7899	 */
7900	var $headers = array();
7901
7902	/**
7903	 * Body of the response
7904	 *
7905	 * @access public
7906	 * @var string
7907	 */
7908	var $body = '';
7909
7910	/**
7911	 * Current state of the state machine
7912	 *
7913	 * @access private
7914	 * @var string
7915	 */
7916	var $state = 'http_version';
7917
7918	/**
7919	 * Input data
7920	 *
7921	 * @access private
7922	 * @var string
7923	 */
7924	var $data = '';
7925
7926	/**
7927	 * Input data length (to avoid calling strlen() everytime this is needed)
7928	 *
7929	 * @access private
7930	 * @var int
7931	 */
7932	var $data_length = 0;
7933
7934	/**
7935	 * Current position of the pointer
7936	 *
7937	 * @var int
7938	 * @access private
7939	 */
7940	var $position = 0;
7941
7942	/**
7943	 * Name of the hedaer currently being parsed
7944	 *
7945	 * @access private
7946	 * @var string
7947	 */
7948	var $name = '';
7949
7950	/**
7951	 * Value of the hedaer currently being parsed
7952	 *
7953	 * @access private
7954	 * @var string
7955	 */
7956	var $value = '';
7957
7958	/**
7959	 * Create an instance of the class with the input data
7960	 *
7961	 * @access public
7962	 * @param string $data Input data
7963	 */
7964	function SimplePie_HTTP_Parser($data)
7965	{
7966		$this->data = $data;
7967		$this->data_length = strlen($this->data);
7968	}
7969
7970	/**
7971	 * Parse the input data
7972	 *
7973	 * @access public
7974	 * @return bool true on success, false on failure
7975	 */
7976	function parse()
7977	{
7978		while ($this->state && $this->state !== 'emit' && $this->has_data())
7979		{
7980			$state = $this->state;
7981			$this->$state();
7982		}
7983		$this->data = '';
7984		if ($this->state === 'emit' || $this->state === 'body')
7985		{
7986			return true;
7987		}
7988		else
7989		{
7990			$this->http_version = '';
7991			$this->status_code = '';
7992			$this->reason = '';
7993			$this->headers = array();
7994			$this->body = '';
7995			return false;
7996		}
7997	}
7998
7999	/**
8000	 * Check whether there is data beyond the pointer
8001	 *
8002	 * @access private
8003	 * @return bool true if there is further data, false if not
8004	 */
8005	function has_data()
8006	{
8007		return (bool) ($this->position < $this->data_length);
8008	}
8009
8010	/**
8011	 * See if the next character is LWS
8012	 *
8013	 * @access private
8014	 * @return bool true if the next character is LWS, false if not
8015	 */
8016	function is_linear_whitespace()
8017	{
8018		return (bool) ($this->data[$this->position] === "\x09"
8019			|| $this->data[$this->position] === "\x20"
8020			|| ($this->data[$this->position] === "\x0A"
8021				&& isset($this->data[$this->position + 1])
8022				&& ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8023	}
8024
8025	/**
8026	 * Parse the HTTP version
8027	 *
8028	 * @access private
8029	 */
8030	function http_version()
8031	{
8032		if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8033		{
8034			$len = strspn($this->data, '0123456789.', 5);
8035			$this->http_version = substr($this->data, 5, $len);
8036			$this->position += 5 + $len;
8037			if (substr_count($this->http_version, '.') <= 1)
8038			{
8039				$this->http_version = (float) $this->http_version;
8040				$this->position += strspn($this->data, "\x09\x20", $this->position);
8041				$this->state = 'status';
8042			}
8043			else
8044			{
8045				$this->state = false;
8046			}
8047		}
8048		else
8049		{
8050			$this->state = false;
8051		}
8052	}
8053
8054	/**
8055	 * Parse the status code
8056	 *
8057	 * @access private
8058	 */
8059	function status()
8060	{
8061		if ($len = strspn($this->data, '0123456789', $this->position))
8062		{
8063			$this->status_code = (int) substr($this->data, $this->position, $len);
8064			$this->position += $len;
8065			$this->state = 'reason';
8066		}
8067		else
8068		{
8069			$this->state = false;
8070		}
8071	}
8072
8073	/**
8074	 * Parse the reason phrase
8075	 *
8076	 * @access private
8077	 */
8078	function reason()
8079	{
8080		$len = strcspn($this->data, "\x0A", $this->position);
8081		$this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8082		$this->position += $len + 1;
8083		$this->state = 'new_line';
8084	}
8085
8086	/**
8087	 * Deal with a new line, shifting data around as needed
8088	 *
8089	 * @access private
8090	 */
8091	function new_line()
8092	{
8093		$this->value = trim($this->value, "\x0D\x20");
8094		if ($this->name !== '' && $this->value !== '')
8095		{
8096			$this->name = strtolower($this->name);
8097			if (isset($this->headers[$this->name]))
8098			{
8099				$this->headers[$this->name] .= ', ' . $this->value;
8100			}
8101			else
8102			{
8103				$this->headers[$this->name] = $this->value;
8104			}
8105		}
8106		$this->name = '';
8107		$this->value = '';
8108		if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8109		{
8110			$this->position += 2;
8111			$this->state = 'body';
8112		}
8113		elseif ($this->data[$this->position] === "\x0A")
8114		{
8115			$this->position++;
8116			$this->state = 'body';
8117		}
8118		else
8119		{
8120			$this->state = 'name';
8121		}
8122	}
8123
8124	/**
8125	 * Parse a header name
8126	 *
8127	 * @access private
8128	 */
8129	function name()
8130	{
8131		$len = strcspn($this->data, "\x0A:", $this->position);
8132		if (isset($this->data[$this->position + $len]))
8133		{
8134			if ($this->data[$this->position + $len] === "\x0A")
8135			{
8136				$this->position += $len;
8137				$this->state = 'new_line';
8138			}
8139			else
8140			{
8141				$this->name = substr($this->data, $this->position, $len);
8142				$this->position += $len + 1;
8143				$this->state = 'value';
8144			}
8145		}
8146		else
8147		{
8148			$this->state = false;
8149		}
8150	}
8151
8152	/**
8153	 * Parse LWS, replacing consecutive LWS characters with a single space
8154	 *
8155	 * @access private
8156	 */
8157	function linear_whitespace()
8158	{
8159		do
8160		{
8161			if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8162			{
8163				$this->position += 2;
8164			}
8165			elseif ($this->data[$this->position] === "\x0A")
8166			{
8167				$this->position++;
8168			}
8169			$this->position += strspn($this->data, "\x09\x20", $this->position);
8170		} while ($this->has_data() && $this->is_linear_whitespace());
8171		$this->value .= "\x20";
8172	}
8173
8174	/**
8175	 * See what state to move to while within non-quoted header values
8176	 *
8177	 * @access private
8178	 */
8179	function value()
8180	{
8181		if ($this->is_linear_whitespace())
8182		{
8183			$this->linear_whitespace();
8184		}
8185		else
8186		{
8187			switch ($this->data[$this->position])
8188			{
8189				case '"':
8190					$this->position++;
8191					$this->state = 'quote';
8192					break;
8193
8194				case "\x0A":
8195					$this->position++;
8196					$this->state = 'new_line';
8197					break;
8198
8199				default:
8200					$this->state = 'value_char';
8201					break;
8202			}
8203		}
8204	}
8205
8206	/**
8207	 * Parse a header value while outside quotes
8208	 *
8209	 * @access private
8210	 */
8211	function value_char()
8212	{
8213		$len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8214		$this->value .= substr($this->data, $this->position, $len);
8215		$this->position += $len;
8216		$this->state = 'value';
8217	}
8218
8219	/**
8220	 * See what state to move to while within quoted header values
8221	 *
8222	 * @access private
8223	 */
8224	function quote()
8225	{
8226		if ($this->is_linear_whitespace())
8227		{
8228			$this->linear_whitespace();
8229		}
8230		else
8231		{
8232			switch ($this->data[$this->position])
8233			{
8234				case '"':
8235					$this->position++;
8236					$this->state = 'value';
8237					break;
8238
8239				case "\x0A":
8240					$this->position++;
8241					$this->state = 'new_line';
8242					break;
8243
8244				case '\\':
8245					$this->position++;
8246					$this->state = 'quote_escaped';
8247					break;
8248
8249				default:
8250					$this->state = 'quote_char';
8251					break;
8252			}
8253		}
8254	}
8255
8256	/**
8257	 * Parse a header value while within quotes
8258	 *
8259	 * @access private
8260	 */
8261	function quote_char()
8262	{
8263		$len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8264		$this->value .= substr($this->data, $this->position, $len);
8265		$this->position += $len;
8266		$this->state = 'value';
8267	}
8268
8269	/**
8270	 * Parse an escaped character within quotes
8271	 *
8272	 * @access private
8273	 */
8274	function quote_escaped()
8275	{
8276		$this->value .= $this->data[$this->position];
8277		$this->position++;
8278		$this->state = 'quote';
8279	}
8280
8281	/**
8282	 * Parse the body
8283	 *
8284	 * @access private
8285	 */
8286	function body()
8287	{
8288		$this->body = substr($this->data, $this->position);
8289		$this->state = 'emit';
8290	}
8291}
8292
8293/**
8294 * gzdecode
8295 *
8296 * @package SimplePie
8297 */
8298class SimplePie_gzdecode
8299{
8300	/**
8301	 * Compressed data
8302	 *
8303	 * @access private
8304	 * @see gzdecode::$data
8305	 */
8306	var $compressed_data;
8307
8308	/**
8309	 * Size of compressed data
8310	 *
8311	 * @access private
8312	 */
8313	var $compressed_size;
8314
8315	/**
8316	 * Minimum size of a valid gzip string
8317	 *
8318	 * @access private
8319	 */
8320	var $min_compressed_size = 18;
8321
8322	/**
8323	 * Current position of pointer
8324	 *
8325	 * @access private
8326	 */
8327	var $position = 0;
8328
8329	/**
8330	 * Flags (FLG)
8331	 *
8332	 * @access private
8333	 */
8334	var $flags;
8335
8336	/**
8337	 * Uncompressed data
8338	 *
8339	 * @access public
8340	 * @see gzdecode::$compressed_data
8341	 */
8342	var $data;
8343
8344	/**
8345	 * Modified time
8346	 *
8347	 * @access public
8348	 */
8349	var $MTIME;
8350
8351	/**
8352	 * Extra Flags
8353	 *
8354	 * @access public
8355	 */
8356	var $XFL;
8357
8358	/**
8359	 * Operating System
8360	 *
8361	 * @access public
8362	 */
8363	var $OS;
8364
8365	/**
8366	 * Subfield ID 1
8367	 *
8368	 * @access public
8369	 * @see gzdecode::$extra_field
8370	 * @see gzdecode::$SI2
8371	 */
8372	var $SI1;
8373
8374	/**
8375	 * Subfield ID 2
8376	 *
8377	 * @access public
8378	 * @see gzdecode::$extra_field
8379	 * @see gzdecode::$SI1
8380	 */
8381	var $SI2;
8382
8383	/**
8384	 * Extra field content
8385	 *
8386	 * @access public
8387	 * @see gzdecode::$SI1
8388	 * @see gzdecode::$SI2
8389	 */
8390	var $extra_field;
8391
8392	/**
8393	 * Original filename
8394	 *
8395	 * @access public
8396	 */
8397	var $filename;
8398
8399	/**
8400	 * Human readable comment
8401	 *
8402	 * @access public
8403	 */
8404	var $comment;
8405
8406	/**
8407	 * Don't allow anything to be set
8408	 *
8409	 * @access public
8410	 */
8411	function __set($name, $value)
8412	{
8413		trigger_error("Cannot write property $name", E_USER_ERROR);
8414	}
8415
8416	/**
8417	 * Set the compressed string and related properties
8418	 *
8419	 * @access public
8420	 */
8421	function SimplePie_gzdecode($data)
8422	{
8423		$this->compressed_data = $data;
8424		$this->compressed_size = strlen($data);
8425	}
8426
8427	/**
8428	 * Decode the GZIP stream
8429	 *
8430	 * @access public
8431	 */
8432	function parse()
8433	{
8434		if ($this->compressed_size >= $this->min_compressed_size)
8435		{
8436			// Check ID1, ID2, and CM
8437			if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8438			{
8439				return false;
8440			}
8441
8442			// Get the FLG (FLaGs)
8443			$this->flags = ord($this->compressed_data[3]);
8444
8445			// FLG bits above (1 << 4) are reserved
8446			if ($this->flags > 0x1F)
8447			{
8448				return false;
8449			}
8450
8451			// Advance the pointer after the above
8452			$this->position += 4;
8453
8454			// MTIME
8455			$mtime = substr($this->compressed_data, $this->position, 4);
8456			// Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8457			if (current(unpack('S', "\x00\x01")) === 1)
8458			{
8459				$mtime = strrev($mtime);
8460			}
8461			$this->MTIME = current(unpack('l', $mtime));
8462			$this->position += 4;
8463
8464			// Get the XFL (eXtra FLags)
8465			$this->XFL = ord($this->compressed_data[$this->position++]);
8466
8467			// Get the OS (Operating System)
8468			$this->OS = ord($this->compressed_data[$this->position++]);
8469
8470			// Parse the FEXTRA
8471			if ($this->flags & 4)
8472			{
8473				// Read subfield IDs
8474				$this->SI1 = $this->compressed_data[$this->position++];
8475				$this->SI2 = $this->compressed_data[$this->position++];
8476
8477				// SI2 set to zero is reserved for future use
8478				if ($this->SI2 === "\x00")
8479				{
8480					return false;
8481				}
8482
8483				// Get the length of the extra field
8484				$len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8485				$position += 2;
8486
8487				// Check the length of the string is still valid
8488				$this->min_compressed_size += $len + 4;
8489				if ($this->compressed_size >= $this->min_compressed_size)
8490				{
8491					// Set the extra field to the given data
8492					$this->extra_field = substr($this->compressed_data, $this->position, $len);
8493					$this->position += $len;
8494				}
8495				else
8496				{
8497					return false;
8498				}
8499			}
8500
8501			// Parse the FNAME
8502			if ($this->flags & 8)
8503			{
8504				// Get the length of the filename
8505				$len = strcspn($this->compressed_data, "\x00", $this->position);
8506
8507				// Check the length of the string is still valid
8508				$this->min_compressed_size += $len + 1;
8509				if ($this->compressed_size >= $this->min_compressed_size)
8510				{
8511					// Set the original filename to the given string
8512					$this->filename = substr($this->compressed_data, $this->position, $len);
8513					$this->position += $len + 1;
8514				}
8515				else
8516				{
8517					return false;
8518				}
8519			}
8520
8521			// Parse the FCOMMENT
8522			if ($this->flags & 16)
8523			{
8524				// Get the length of the comment
8525				$len = strcspn($this->compressed_data, "\x00", $this->position);
8526
8527				// Check the length of the string is still valid
8528				$this->min_compressed_size += $len + 1;
8529				if ($this->compressed_size >= $this->min_compressed_size)
8530				{
8531					// Set the original comment to the given string
8532					$this->comment = substr($this->compressed_data, $this->position, $len);
8533					$this->position += $len + 1;
8534				}
8535				else
8536				{
8537					return false;
8538				}
8539			}
8540
8541			// Parse the FHCRC
8542			if ($this->flags & 2)
8543			{
8544				// Check the length of the string is still valid
8545				$this->min_compressed_size += $len + 2;
8546				if ($this->compressed_size >= $this->min_compressed_size)
8547				{
8548					// Read the CRC
8549					$crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8550
8551					// Check the CRC matches
8552					if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8553					{
8554						$this->position += 2;
8555					}
8556					else
8557					{
8558						return false;
8559					}
8560				}
8561				else
8562				{
8563					return false;
8564				}
8565			}
8566
8567			// Decompress the actual data
8568			if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8569			{
8570				return false;
8571			}
8572			else
8573			{
8574				$this->position = $this->compressed_size - 8;
8575			}
8576
8577			// Check CRC of data
8578			$crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8579			$this->position += 4;
8580			/*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8581			{
8582				return false;
8583			}*/
8584
8585			// Check ISIZE of data
8586			$isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8587			$this->position += 4;
8588			if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8589			{
8590				return false;
8591			}
8592
8593			// Wow, against all odds, we've actually got a valid gzip string
8594			return true;
8595		}
8596		else
8597		{
8598			return false;
8599		}
8600	}
8601}
8602
8603class SimplePie_Cache
8604{
8605	/**
8606	 * Don't call the constructor. Please.
8607	 *
8608	 * @access private
8609	 */
8610	function SimplePie_Cache()
8611	{
8612		trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8613	}
8614
8615	/**
8616	 * Create a new SimplePie_Cache object
8617	 *
8618	 * @static
8619	 * @access public
8620	 */
8621	function create($location, $filename, $extension)
8622	{
8623		$location_iri =& new SimplePie_IRI($location);
8624		switch ($location_iri->get_scheme())
8625		{
8626			case 'mysql':
8627				if (extension_loaded('mysql'))
8628				{
8629					return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8630				}
8631				break;
8632
8633			default:
8634				return new SimplePie_Cache_File($location, $filename, $extension);
8635		}
8636	}
8637}
8638
8639class SimplePie_Cache_File
8640{
8641	var $location;
8642	var $filename;
8643	var $extension;
8644	var $name;
8645
8646	function SimplePie_Cache_File($location, $filename, $extension)
8647	{
8648		$this->location = $location;
8649		$this->filename = $filename;
8650		$this->extension = $extension;
8651		$this->name = "$this->location/$this->filename.$this->extension";
8652	}
8653
8654	function save($data)
8655	{
8656		if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8657		{
8658			if (is_a($data, 'SimplePie'))
8659			{
8660				$data = $data->data;
8661			}
8662
8663			$data = serialize($data);
8664
8665			if (function_exists('file_put_contents'))
8666			{
8667				return (bool) file_put_contents($this->name, $data);
8668			}
8669			else
8670			{
8671				$fp = fopen($this->name, 'wb');
8672				if ($fp)
8673				{
8674					fwrite($fp, $data);
8675					fclose($fp);
8676					return true;
8677				}
8678			}
8679		}
8680		return false;
8681	}
8682
8683	function load()
8684	{
8685		if (file_exists($this->name) && is_readable($this->name))
8686		{
8687			return unserialize(file_get_contents($this->name));
8688		}
8689		return false;
8690	}
8691
8692	function mtime()
8693	{
8694		if (file_exists($this->name))
8695		{
8696			return filemtime($this->name);
8697		}
8698		return false;
8699	}
8700
8701	function touch()
8702	{
8703		if (file_exists($this->name))
8704		{
8705			return touch($this->name);
8706		}
8707		return false;
8708	}
8709
8710	function unlink()
8711	{
8712		if (file_exists($this->name))
8713		{
8714			return unlink($this->name);
8715		}
8716		return false;
8717	}
8718}
8719
8720class SimplePie_Cache_DB
8721{
8722	function prepare_simplepie_object_for_cache($data)
8723	{
8724		$items = $data->get_items();
8725		$items_by_id = array();
8726
8727		if (!empty($items))
8728		{
8729			foreach ($items as $item)
8730			{
8731				$items_by_id[$item->get_id()] = $item;
8732			}
8733
8734			if (count($items_by_id) !== count($items))
8735			{
8736				$items_by_id = array();
8737				foreach ($items as $item)
8738				{
8739					$items_by_id[$item->get_id(true)] = $item;
8740				}
8741			}
8742
8743			if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8744			{
8745				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8746			}
8747			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8748			{
8749				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8750			}
8751			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8752			{
8753				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8754			}
8755			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8756			{
8757				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8758			}
8759			else
8760			{
8761				$channel = null;
8762			}
8763
8764			if ($channel !== null)
8765			{
8766				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8767				{
8768					unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8769				}
8770				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8771				{
8772					unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8773				}
8774				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8775				{
8776					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8777				}
8778				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8779				{
8780					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8781				}
8782				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8783				{
8784					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8785				}
8786			}
8787			if (isset($data->data['items']))
8788			{
8789				unset($data->data['items']);
8790			}
8791			if (isset($data->data['ordered_items']))
8792			{
8793				unset($data->data['ordered_items']);
8794			}
8795		}
8796		return array(serialize($data->data), $items_by_id);
8797	}
8798}
8799
8800class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8801{
8802	var $mysql;
8803	var $options;
8804	var $id;
8805
8806	function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8807	{
8808		$host = $mysql_location->get_host();
8809		if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8810		{
8811			$server = ':' . substr($host, 5, -1);
8812		}
8813		else
8814		{
8815			$server = $host;
8816			if ($mysql_location->get_port() !== null)
8817			{
8818				$server .= ':' . $mysql_location->get_port();
8819			}
8820		}
8821
8822		if (strpos($mysql_location->get_userinfo(), ':') !== false)
8823		{
8824			list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8825		}
8826		else
8827		{
8828			$username = $mysql_location->get_userinfo();
8829			$password = null;
8830		}
8831
8832		if ($this->mysql = mysql_connect($server, $username, $password))
8833		{
8834			$this->id = $name . $extension;
8835			$this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8836			if (!isset($this->options['prefix'][0]))
8837			{
8838				$this->options['prefix'][0] = '';
8839			}
8840
8841			if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8842				&& mysql_query('SET NAMES utf8')
8843				&& ($query = mysql_unbuffered_query('SHOW TABLES')))
8844			{
8845				$db = array();
8846				while ($row = mysql_fetch_row($query))
8847				{
8848					$db[] = $row[0];
8849				}
8850
8851				if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8852				{
8853					if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
8854					{
8855						$this->mysql = null;
8856					}
8857				}
8858
8859				if (!in_array($this->options['prefix'][0] . 'items', $db))
8860				{
8861					if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
8862					{
8863						$this->mysql = null;
8864					}
8865				}
8866			}
8867			else
8868			{
8869				$this->mysql = null;
8870			}
8871		}
8872	}
8873
8874	function save($data)
8875	{
8876		if ($this->mysql)
8877		{
8878			$feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8879
8880			if (is_a($data, 'SimplePie'))
8881			{
8882				if (SIMPLEPIE_PHP5)
8883				{
8884					// This keyword needs to defy coding standards for PHP4 compatibility
8885					$data = clone($data);
8886				}
8887
8888				$prepared = $this->prepare_simplepie_object_for_cache($data);
8889
8890				if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8891				{
8892					if (mysql_num_rows($query))
8893					{
8894						$items = count($prepared[1]);
8895						if ($items)
8896						{
8897							$sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8898						}
8899						else
8900						{
8901							$sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8902						}
8903
8904						if (!mysql_query($sql, $this->mysql))
8905						{
8906							return false;
8907						}
8908					}
8909					elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
8910					{
8911						return false;
8912					}
8913
8914					$ids = array_keys($prepared[1]);
8915					if (!empty($ids))
8916					{
8917						foreach ($ids as $id)
8918						{
8919							$database_ids[] = mysql_real_escape_string($id);
8920						}
8921
8922						if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
8923						{
8924							$existing_ids = array();
8925							while ($row = mysql_fetch_row($query))
8926							{
8927								$existing_ids[] = $row[0];
8928							}
8929
8930							$new_ids = array_diff($ids, $existing_ids);
8931
8932							foreach ($new_ids as $new_id)
8933							{
8934								if (!($date = $prepared[1][$new_id]->get_date('U')))
8935								{
8936									$date = time();
8937								}
8938
8939								if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
8940								{
8941									return false;
8942								}
8943							}
8944							return true;
8945						}
8946					}
8947					else
8948					{
8949						return true;
8950					}
8951				}
8952			}
8953			elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8954			{
8955				if (mysql_num_rows($query))
8956				{
8957					if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
8958					{
8959						return true;
8960					}
8961				}
8962				elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
8963				{
8964					return true;
8965				}
8966			}
8967		}
8968		return false;
8969	}
8970
8971	function load()
8972	{
8973		if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
8974		{
8975			$data = unserialize($row[1]);
8976
8977			if (isset($this->options['items'][0]))
8978			{
8979				$items = (int) $this->options['items'][0];
8980			}
8981			else
8982			{
8983				$items = (int) $row[0];
8984			}
8985
8986			if ($items !== 0)
8987			{
8988				if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8989				{
8990					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8991				}
8992				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8993				{
8994					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8995				}
8996				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8997				{
8998					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8999				}
9000				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9001				{
9002					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9003				}
9004				else
9005				{
9006					$feed = null;
9007				}
9008
9009				if ($feed !== null)
9010				{
9011					$sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9012					if ($items > 0)
9013					{
9014						$sql .= ' LIMIT ' . $items;
9015					}
9016
9017					if ($query = mysql_unbuffered_query($sql, $this->mysql))
9018					{
9019						while ($row = mysql_fetch_row($query))
9020						{
9021							$feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9022						}
9023					}
9024					else
9025					{
9026						return false;
9027					}
9028				}
9029			}
9030			return $data;
9031		}
9032		return false;
9033	}
9034
9035	function mtime()
9036	{
9037		if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9038		{
9039			return $row[0];
9040		}
9041		else
9042		{
9043			return false;
9044		}
9045	}
9046
9047	function touch()
9048	{
9049		if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
9050		{
9051			return true;
9052		}
9053		else
9054		{
9055			return false;
9056		}
9057	}
9058
9059	function unlink()
9060	{
9061		if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
9062		{
9063			return true;
9064		}
9065		else
9066		{
9067			return false;
9068		}
9069	}
9070}
9071
9072class SimplePie_Misc
9073{
9074	function time_hms($seconds)
9075	{
9076		$time = '';
9077
9078		$hours = floor($seconds / 3600);
9079		$remainder = $seconds % 3600;
9080		if ($hours > 0)
9081		{
9082			$time .= $hours.':';
9083		}
9084
9085		$minutes = floor($remainder / 60);
9086		$seconds = $remainder % 60;
9087		if ($minutes < 10 && $hours > 0)
9088		{
9089			$minutes = '0' . $minutes;
9090		}
9091		if ($seconds < 10)
9092		{
9093			$seconds = '0' . $seconds;
9094		}
9095
9096		$time .= $minutes.':';
9097		$time .= $seconds;
9098
9099		return $time;
9100	}
9101
9102	function absolutize_url($relative, $base)
9103	{
9104		$iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9105		return $iri->get_iri();
9106	}
9107
9108	function remove_dot_segments($input)
9109	{
9110		$output = '';
9111		while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9112		{
9113			// A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9114			if (strpos($input, '../') === 0)
9115			{
9116				$input = substr($input, 3);
9117			}
9118			elseif (strpos($input, './') === 0)
9119			{
9120				$input = substr($input, 2);
9121			}
9122			// B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
9123			elseif (strpos($input, '/./') === 0)
9124			{
9125				$input = substr_replace($input, '/', 0, 3);
9126			}
9127			elseif ($input === '/.')
9128			{
9129				$input = '/';
9130			}
9131			// C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
9132			elseif (strpos($input, '/../') === 0)
9133			{
9134				$input = substr_replace($input, '/', 0, 4);
9135				$output = substr_replace($output, '', strrpos($output, '/'));
9136			}
9137			elseif ($input === '/..')
9138			{
9139				$input = '/';
9140				$output = substr_replace($output, '', strrpos($output, '/'));
9141			}
9142			// D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9143			elseif ($input === '.' || $input === '..')
9144			{
9145				$input = '';
9146			}
9147			// E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
9148			elseif (($pos = strpos($input, '/', 1)) !== false)
9149			{
9150				$output .= substr($input, 0, $pos);
9151				$input = substr_replace($input, '', 0, $pos);
9152			}
9153			else
9154			{
9155				$output .= $input;
9156				$input = '';
9157			}
9158		}
9159		return $output . $input;
9160	}
9161
9162	function get_element($realname, $string)
9163	{
9164		$return = array();
9165		$name = preg_quote($realname, '/');
9166		if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9167		{
9168			for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9169			{
9170				$return[$i]['tag'] = $realname;
9171				$return[$i]['full'] = $matches[$i][0][0];
9172				$return[$i]['offset'] = $matches[$i][0][1];
9173				if (strlen($matches[$i][3][0]) <= 2)
9174				{
9175					$return[$i]['self_closing'] = true;
9176				}
9177				else
9178				{
9179					$return[$i]['self_closing'] = false;
9180					$return[$i]['content'] = $matches[$i][4][0];
9181				}
9182				$return[$i]['attribs'] = array();
9183				if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
9184				{
9185					for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9186					{
9187						if (count($attribs[$j]) === 2)
9188						{
9189							$attribs[$j][2] = $attribs[$j][1];
9190						}
9191						$return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9192					}
9193				}
9194			}
9195		}
9196		return $return;
9197	}
9198
9199	function element_implode($element)
9200	{
9201		$full = "<$element[tag]";
9202		foreach ($element['attribs'] as $key => $value)
9203		{
9204			$key = strtolower($key);
9205			$full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9206		}
9207		if ($element['self_closing'])
9208		{
9209			$full .= ' />';
9210		}
9211		else
9212		{
9213			$full .= ">$element[content]</$element[tag]>";
9214		}
9215		return $full;
9216	}
9217
9218	function error($message, $level, $file, $line)
9219	{
9220		if ((ini_get('error_reporting') & $level) > 0)
9221		{
9222			switch ($level)
9223			{
9224				case E_USER_ERROR:
9225					$note = 'PHP Error';
9226					break;
9227				case E_USER_WARNING:
9228					$note = 'PHP Warning';
9229					break;
9230				case E_USER_NOTICE:
9231					$note = 'PHP Notice';
9232					break;
9233				default:
9234					$note = 'Unknown Error';
9235					break;
9236			}
9237			error_log("$note: $message in $file on line $line", 0);
9238		}
9239		return $message;
9240	}
9241
9242	/**
9243	 * If a file has been cached, retrieve and display it.
9244	 *
9245	 * This is most useful for caching images (get_favicon(), etc.),
9246	 * however it works for all cached files.  This WILL NOT display ANY
9247	 * file/image/page/whatever, but rather only display what has already
9248	 * been cached by SimplePie.
9249	 *
9250	 * @access public
9251	 * @see SimplePie::get_favicon()
9252	 * @param str $identifier_url URL that is used to identify the content.
9253	 * This may or may not be the actual URL of the live content.
9254	 * @param str $cache_location Location of SimplePie's cache.  Defaults
9255	 * to './cache'.
9256	 * @param str $cache_extension The file extension that the file was
9257	 * cached with.  Defaults to 'spc'.
9258	 * @param str $cache_class Name of the cache-handling class being used
9259	 * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9260	 * as-is unless you've overloaded the class.
9261	 * @param str $cache_name_function Obsolete. Exists for backwards
9262	 * compatibility reasons only.
9263	 */
9264	function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9265	{
9266		$cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9267
9268		if ($file = $cache->load())
9269		{
9270			if (isset($file['headers']['content-type']))
9271			{
9272				header('Content-type:' . $file['headers']['content-type']);
9273			}
9274			else
9275			{
9276				header('Content-type: application/octet-stream');
9277			}
9278			header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9279			echo $file['body'];
9280			exit;
9281		}
9282
9283		die('Cached file for ' . $identifier_url . ' cannot be found.');
9284	}
9285
9286	function fix_protocol($url, $http = 1)
9287	{
9288		$url = SimplePie_Misc::normalize_url($url);
9289		$parsed = SimplePie_Misc::parse_url($url);
9290		if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9291		{
9292			return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9293		}
9294
9295		if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9296		{
9297			return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9298		}
9299
9300		if ($http === 2 && $parsed['scheme'] !== '')
9301		{
9302			return "feed:$url";
9303		}
9304		elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9305		{
9306			return substr_replace($url, 'podcast', 0, 4);
9307		}
9308		elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9309		{
9310			return substr_replace($url, 'itpc', 0, 4);
9311		}
9312		else
9313		{
9314			return $url;
9315		}
9316	}
9317
9318	function parse_url($url)
9319	{
9320		$iri =& new SimplePie_IRI($url);
9321		return array(
9322			'scheme' => (string) $iri->get_scheme(),
9323			'authority' => (string) $iri->get_authority(),
9324			'path' => (string) $iri->get_path(),
9325			'query' => (string) $iri->get_query(),
9326			'fragment' => (string) $iri->get_fragment()
9327		);
9328	}
9329
9330	function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9331	{
9332		$iri =& new SimplePie_IRI('');
9333		$iri->set_scheme($scheme);
9334		$iri->set_authority($authority);
9335		$iri->set_path($path);
9336		$iri->set_query($query);
9337		$iri->set_fragment($fragment);
9338		return $iri->get_iri();
9339	}
9340
9341	function normalize_url($url)
9342	{
9343		$iri =& new SimplePie_IRI($url);
9344		return $iri->get_iri();
9345	}
9346
9347	function percent_encoding_normalization($match)
9348	{
9349		$integer = hexdec($match[1]);
9350		if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9351		{
9352			return chr($integer);
9353		}
9354		else
9355		{
9356			return strtoupper($match[0]);
9357		}
9358	}
9359
9360	/**
9361	 * Remove bad UTF-8 bytes
9362	 *
9363	 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9364	 * FAQ: Multilingual Forms (modified to include full ASCII range)
9365	 *
9366	 * @author Geoffrey Sneddon
9367	 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9368	 * @param string $str String to remove bad UTF-8 bytes from
9369	 * @return string UTF-8 string
9370	 */
9371	function utf8_bad_replace($str)
9372	{
9373		if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9374		{
9375			return $return;
9376		}
9377		elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9378		{
9379			return $return;
9380		}
9381		elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
9382		{
9383			return implode("\xEF\xBF\xBD", $matches[0]);
9384		}
9385		elseif ($str !== '')
9386		{
9387			return "\xEF\xBF\xBD";
9388		}
9389		else
9390		{
9391			return '';
9392		}
9393	}
9394
9395	/**
9396	 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9397	 *
9398	 * @static
9399	 * @access public
9400	 * @param string $string Windows-1252 encoded string
9401	 * @return string UTF-8 encoded string
9402	 */
9403	function windows_1252_to_utf8($string)
9404	{
9405		static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
9406
9407		return strtr($string, $convert_table);
9408	}
9409
9410	function change_encoding($data, $input, $output)
9411	{
9412		$input = SimplePie_Misc::encoding($input);
9413		$output = SimplePie_Misc::encoding($output);
9414
9415		// We fail to fail on non US-ASCII bytes
9416		if ($input === 'US-ASCII')
9417		{
9418			static $non_ascii_octects = '';
9419			if (!$non_ascii_octects)
9420			{
9421				for ($i = 0x80; $i <= 0xFF; $i++)
9422				{
9423					$non_ascii_octects .= chr($i);
9424				}
9425			}
9426			$data = substr($data, 0, strcspn($data, $non_ascii_octects));
9427		}
9428
9429		// This is first, as behaviour of this is completely predictable
9430		if ($input === 'windows-1252' && $output === 'UTF-8')
9431		{
9432			return SimplePie_Misc::windows_1252_to_utf8($data);
9433		}
9434		// This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9435		elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9436		{
9437			return $return;
9438		}
9439		// This is last, as behaviour of this varies with OS userland and PHP version
9440		elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9441		{
9442			return $return;
9443		}
9444		// If we can't do anything, just fail
9445		else
9446		{
9447			return false;
9448		}
9449	}
9450
9451	function encoding($charset)
9452	{
9453		// Normalization from UTS #22
9454		switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9455		{
9456			case 'adobestandardencoding':
9457			case 'csadobestandardencoding':
9458				return 'Adobe-Standard-Encoding';
9459
9460			case 'adobesymbolencoding':
9461			case 'cshppsmath':
9462				return 'Adobe-Symbol-Encoding';
9463
9464			case 'ami1251':
9465			case 'amiga1251':
9466				return 'Amiga-1251';
9467
9468			case 'ansix31101983':
9469			case 'csat5001983':
9470			case 'csiso99naplps':
9471			case 'isoir99':
9472			case 'naplps':
9473				return 'ANSI_X3.110-1983';
9474
9475			case 'arabic7':
9476			case 'asmo449':
9477			case 'csiso89asmo449':
9478			case 'iso9036':
9479			case 'isoir89':
9480				return 'ASMO_449';
9481
9482			case 'big5':
9483			case 'csbig5':
9484			case 'xxbig5':
9485				return 'Big5';
9486
9487			case 'big5hkscs':
9488				return 'Big5-HKSCS';
9489
9490			case 'bocu1':
9491			case 'csbocu1':
9492				return 'BOCU-1';
9493
9494			case 'brf':
9495			case 'csbrf':
9496				return 'BRF';
9497
9498			case 'bs4730':
9499			case 'csiso4unitedkingdom':
9500			case 'gb':
9501			case 'iso646gb':
9502			case 'isoir4':
9503			case 'uk':
9504				return 'BS_4730';
9505
9506			case 'bsviewdata':
9507			case 'csiso47bsviewdata':
9508			case 'isoir47':
9509				return 'BS_viewdata';
9510
9511			case 'cesu8':
9512			case 'cscesu8':
9513				return 'CESU-8';
9514
9515			case 'ca':
9516			case 'csa71':
9517			case 'csaz243419851':
9518			case 'csiso121canadian1':
9519			case 'iso646ca':
9520			case 'isoir121':
9521				return 'CSA_Z243.4-1985-1';
9522
9523			case 'csa72':
9524			case 'csaz243419852':
9525			case 'csiso122canadian2':
9526			case 'iso646ca2':
9527			case 'isoir122':
9528				return 'CSA_Z243.4-1985-2';
9529
9530			case 'csaz24341985gr':
9531			case 'csiso123csaz24341985gr':
9532			case 'isoir123':
9533				return 'CSA_Z243.4-1985-gr';
9534
9535			case 'csiso139csn369103':
9536			case 'csn369103':
9537			case 'isoir139':
9538				return 'CSN_369103';
9539
9540			case 'csdecmcs':
9541			case 'dec':
9542			case 'decmcs':
9543				return 'DEC-MCS';
9544
9545			case 'csiso21german':
9546			case 'de':
9547			case 'din66003':
9548			case 'iso646de':
9549			case 'isoir21':
9550				return 'DIN_66003';
9551
9552			case 'csdkus':
9553			case 'dkus':
9554				return 'dk-us';
9555
9556			case 'csiso646danish':
9557			case 'dk':
9558			case 'ds2089':
9559			case 'iso646dk':
9560				return 'DS_2089';
9561
9562			case 'csibmebcdicatde':
9563			case 'ebcdicatde':
9564				return 'EBCDIC-AT-DE';
9565
9566			case 'csebcdicatdea':
9567			case 'ebcdicatdea':
9568				return 'EBCDIC-AT-DE-A';
9569
9570			case 'csebcdiccafr':
9571			case 'ebcdiccafr':
9572				return 'EBCDIC-CA-FR';
9573
9574			case 'csebcdicdkno':
9575			case 'ebcdicdkno':
9576				return 'EBCDIC-DK-NO';
9577
9578			case 'csebcdicdknoa':
9579			case 'ebcdicdknoa':
9580				return 'EBCDIC-DK-NO-A';
9581
9582			case 'csebcdices':
9583			case 'ebcdices':
9584				return 'EBCDIC-ES';
9585
9586			case 'csebcdicesa':
9587			case 'ebcdicesa':
9588				return 'EBCDIC-ES-A';
9589
9590			case 'csebcdicess':
9591			case 'ebcdicess':
9592				return 'EBCDIC-ES-S';
9593
9594			case 'csebcdicfise':
9595			case 'ebcdicfise':
9596				return 'EBCDIC-FI-SE';
9597
9598			case 'csebcdicfisea':
9599			case 'ebcdicfisea':
9600				return 'EBCDIC-FI-SE-A';
9601
9602			case 'csebcdicfr':
9603			case 'ebcdicfr':
9604				return 'EBCDIC-FR';
9605
9606			case 'csebcdicit':
9607			case 'ebcdicit':
9608				return 'EBCDIC-IT';
9609
9610			case 'csebcdicpt':
9611			case 'ebcdicpt':
9612				return 'EBCDIC-PT';
9613
9614			case 'csebcdicuk':
9615			case 'ebcdicuk':
9616				return 'EBCDIC-UK';
9617
9618			case 'csebcdicus':
9619			case 'ebcdicus':
9620				return 'EBCDIC-US';
9621
9622			case 'csiso111ecmacyrillic':
9623			case 'ecmacyrillic':
9624			case 'isoir111':
9625			case 'koi8e':
9626				return 'ECMA-cyrillic';
9627
9628			case 'csiso17spanish':
9629			case 'es':
9630			case 'iso646es':
9631			case 'isoir17':
9632				return 'ES';
9633
9634			case 'csiso85spanish2':
9635			case 'es2':
9636			case 'iso646es2':
9637			case 'isoir85':
9638				return 'ES2';
9639
9640			case 'cseucfixwidjapanese':
9641			case 'extendedunixcodefixedwidthforjapanese':
9642				return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9643
9644			case 'cseucpkdfmtjapanese':
9645			case 'eucjp':
9646			case 'extendedunixcodepackedformatforjapanese':
9647				return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9648
9649			case 'gb18030':
9650				return 'GB18030';
9651
9652			case 'chinese':
9653			case 'cp936':
9654			case 'csgb2312':
9655			case 'csiso58gb231280':
9656			case 'gb2312':
9657			case 'gb231280':
9658			case 'gbk':
9659			case 'isoir58':
9660			case 'ms936':
9661			case 'windows936':
9662				return 'GBK';
9663
9664			case 'cn':
9665			case 'csiso57gb1988':
9666			case 'gb198880':
9667			case 'iso646cn':
9668			case 'isoir57':
9669				return 'GB_1988-80';
9670
9671			case 'csiso153gost1976874':
9672			case 'gost1976874':
9673			case 'isoir153':
9674			case 'stsev35888':
9675				return 'GOST_19768-74';
9676
9677			case 'csiso150':
9678			case 'csiso150greekccitt':
9679			case 'greekccitt':
9680			case 'isoir150':
9681				return 'greek-ccitt';
9682
9683			case 'csiso88greek7':
9684			case 'greek7':
9685			case 'isoir88':
9686				return 'greek7';
9687
9688			case 'csiso18greek7old':
9689			case 'greek7old':
9690			case 'isoir18':
9691				return 'greek7-old';
9692
9693			case 'cshpdesktop':
9694			case 'hpdesktop':
9695				return 'HP-DeskTop';
9696
9697			case 'cshplegal':
9698			case 'hplegal':
9699				return 'HP-Legal';
9700
9701			case 'cshpmath8':
9702			case 'hpmath8':
9703				return 'HP-Math8';
9704
9705			case 'cshppifont':
9706			case 'hppifont':
9707				return 'HP-Pi-font';
9708
9709			case 'cshproman8':
9710			case 'hproman8':
9711			case 'r8':
9712			case 'roman8':
9713				return 'hp-roman8';
9714
9715			case 'hzgb2312':
9716				return 'HZ-GB-2312';
9717
9718			case 'csibmsymbols':
9719			case 'ibmsymbols':
9720				return 'IBM-Symbols';
9721
9722			case 'csibmthai':
9723			case 'ibmthai':
9724				return 'IBM-Thai';
9725
9726			case 'ccsid858':
9727			case 'cp858':
9728			case 'ibm858':
9729			case 'pcmultilingual850euro':
9730				return 'IBM00858';
9731
9732			case 'ccsid924':
9733			case 'cp924':
9734			case 'ebcdiclatin9euro':
9735			case 'ibm924':
9736				return 'IBM00924';
9737
9738			case 'ccsid1140':
9739			case 'cp1140':
9740			case 'ebcdicus37euro':
9741			case 'ibm1140':
9742				return 'IBM01140';
9743
9744			case 'ccsid1141':
9745			case 'cp1141':
9746			case 'ebcdicde273euro':
9747			case 'ibm1141':
9748				return 'IBM01141';
9749
9750			case 'ccsid1142':
9751			case 'cp1142':
9752			case 'ebcdicdk277euro':
9753			case 'ebcdicno277euro':
9754			case 'ibm1142':
9755				return 'IBM01142';
9756
9757			case 'ccsid1143':
9758			case 'cp1143':
9759			case 'ebcdicfi278euro':
9760			case 'ebcdicse278euro':
9761			case 'ibm1143':
9762				return 'IBM01143';
9763
9764			case 'ccsid1144':
9765			case 'cp1144':
9766			case 'ebcdicit280euro':
9767			case 'ibm1144':
9768				return 'IBM01144';
9769
9770			case 'ccsid1145':
9771			case 'cp1145':
9772			case 'ebcdices284euro':
9773			case 'ibm1145':
9774				return 'IBM01145';
9775
9776			case 'ccsid1146':
9777			case 'cp1146':
9778			case 'ebcdicgb285euro':
9779			case 'ibm1146':
9780				return 'IBM01146';
9781
9782			case 'ccsid1147':
9783			case 'cp1147':
9784			case 'ebcdicfr297euro':
9785			case 'ibm1147':
9786				return 'IBM01147';
9787
9788			case 'ccsid1148':
9789			case 'cp1148':
9790			case 'ebcdicinternational500euro':
9791			case 'ibm1148':
9792				return 'IBM01148';
9793
9794			case 'ccsid1149':
9795			case 'cp1149':
9796			case 'ebcdicis871euro':
9797			case 'ibm1149':
9798				return 'IBM01149';
9799
9800			case 'cp37':
9801			case 'csibm37':
9802			case 'ebcdiccpca':
9803			case 'ebcdiccpnl':
9804			case 'ebcdiccpus':
9805			case 'ebcdiccpwt':
9806			case 'ibm37':
9807				return 'IBM037';
9808
9809			case 'cp38':
9810			case 'csibm38':
9811			case 'ebcdicint':
9812			case 'ibm38':
9813				return 'IBM038';
9814
9815			case 'cp273':
9816			case 'csibm273':
9817			case 'ibm273':
9818				return 'IBM273';
9819
9820			case 'cp274':
9821			case 'csibm274':
9822			case 'ebcdicbe':
9823			case 'ibm274':
9824				return 'IBM274';
9825
9826			case 'cp275':
9827			case 'csibm275':
9828			case 'ebcdicbr':
9829			case 'ibm275':
9830				return 'IBM275';
9831
9832			case 'csibm277':
9833			case 'ebcdiccpdk':
9834			case 'ebcdiccpno':
9835			case 'ibm277':
9836				return 'IBM277';
9837
9838			case 'cp278':
9839			case 'csibm278':
9840			case 'ebcdiccpfi':
9841			case 'ebcdiccpse':
9842			case 'ibm278':
9843				return 'IBM278';
9844
9845			case 'cp280':
9846			case 'csibm280':
9847			case 'ebcdiccpit':
9848			case 'ibm280':
9849				return 'IBM280';
9850
9851			case 'cp281':
9852			case 'csibm281':
9853			case 'ebcdicjpe':
9854			case 'ibm281':
9855				return 'IBM281';
9856
9857			case 'cp284':
9858			case 'csibm284':
9859			case 'ebcdiccpes':
9860			case 'ibm284':
9861				return 'IBM284';
9862
9863			case 'cp285':
9864			case 'csibm285':
9865			case 'ebcdiccpgb':
9866			case 'ibm285':
9867				return 'IBM285';
9868
9869			case 'cp290':
9870			case 'csibm290':
9871			case 'ebcdicjpkana':
9872			case 'ibm290':
9873				return 'IBM290';
9874
9875			case 'cp297':
9876			case 'csibm297':
9877			case 'ebcdiccpfr':
9878			case 'ibm297':
9879				return 'IBM297';
9880
9881			case 'cp420':
9882			case 'csibm420':
9883			case 'ebcdiccpar1':
9884			case 'ibm420':
9885				return 'IBM420';
9886
9887			case 'cp423':
9888			case 'csibm423':
9889			case 'ebcdiccpgr':
9890			case 'ibm423':
9891				return 'IBM423';
9892
9893			case 'cp424':
9894			case 'csibm424':
9895			case 'ebcdiccphe':
9896			case 'ibm424':
9897				return 'IBM424';
9898
9899			case '437':
9900			case 'cp437':
9901			case 'cspc8codepage437':
9902			case 'ibm437':
9903				return 'IBM437';
9904
9905			case 'cp500':
9906			case 'csibm500':
9907			case 'ebcdiccpbe':
9908			case 'ebcdiccpch':
9909			case 'ibm500':
9910				return 'IBM500';
9911
9912			case 'cp775':
9913			case 'cspc775baltic':
9914			case 'ibm775':
9915				return 'IBM775';
9916
9917			case '850':
9918			case 'cp850':
9919			case 'cspc850multilingual':
9920			case 'ibm850':
9921				return 'IBM850';
9922
9923			case '851':
9924			case 'cp851':
9925			case 'csibm851':
9926			case 'ibm851':
9927				return 'IBM851';
9928
9929			case '852':
9930			case 'cp852':
9931			case 'cspcp852':
9932			case 'ibm852':
9933				return 'IBM852';
9934
9935			case '855':
9936			case 'cp855':
9937			case 'csibm855':
9938			case 'ibm855':
9939				return 'IBM855';
9940
9941			case '857':
9942			case 'cp857':
9943			case 'csibm857':
9944			case 'ibm857':
9945				return 'IBM857';
9946
9947			case '860':
9948			case 'cp860':
9949			case 'csibm860':
9950			case 'ibm860':
9951				return 'IBM860';
9952
9953			case '861':
9954			case 'cp861':
9955			case 'cpis':
9956			case 'csibm861':
9957			case 'ibm861':
9958				return 'IBM861';
9959
9960			case '862':
9961			case 'cp862':
9962			case 'cspc862latinhebrew':
9963			case 'ibm862':
9964				return 'IBM862';
9965
9966			case '863':
9967			case 'cp863':
9968			case 'csibm863':
9969			case 'ibm863':
9970				return 'IBM863';
9971
9972			case 'cp864':
9973			case 'csibm864':
9974			case 'ibm864':
9975				return 'IBM864';
9976
9977			case '865':
9978			case 'cp865':
9979			case 'csibm865':
9980			case 'ibm865':
9981				return 'IBM865';
9982
9983			case '866':
9984			case 'cp866':
9985			case 'csibm866':
9986			case 'ibm866':
9987				return 'IBM866';
9988
9989			case 'cp868':
9990			case 'cpar':
9991			case 'csibm868':
9992			case 'ibm868':
9993				return 'IBM868';
9994
9995			case '869':
9996			case 'cp869':
9997			case 'cpgr':
9998			case 'csibm869':
9999			case 'ibm869':
10000				return 'IBM869';
10001
10002			case 'cp870':
10003			case 'csibm870':
10004			case 'ebcdiccproece':
10005			case 'ebcdiccpyu':
10006			case 'ibm870':
10007				return 'IBM870';
10008
10009			case 'cp871':
10010			case 'csibm871':
10011			case 'ebcdiccpis':
10012			case 'ibm871':
10013				return 'IBM871';
10014
10015			case 'cp880':
10016			case 'csibm880':
10017			case 'ebcdiccyrillic':
10018			case 'ibm880':
10019				return 'IBM880';
10020
10021			case 'cp891':
10022			case 'csibm891':
10023			case 'ibm891':
10024				return 'IBM891';
10025
10026			case 'cp903':
10027			case 'csibm903':
10028			case 'ibm903':
10029				return 'IBM903';
10030
10031			case '904':
10032			case 'cp904':
10033			case 'csibbm904':
10034			case 'ibm904':
10035				return 'IBM904';
10036
10037			case 'cp905':
10038			case 'csibm905':
10039			case 'ebcdiccptr':
10040			case 'ibm905':
10041				return 'IBM905';
10042
10043			case 'cp918':
10044			case 'csibm918':
10045			case 'ebcdiccpar2':
10046			case 'ibm918':
10047				return 'IBM918';
10048
10049			case 'cp1026':
10050			case 'csibm1026':
10051			case 'ibm1026':
10052				return 'IBM1026';
10053
10054			case 'ibm1047':
10055				return 'IBM1047';
10056
10057			case 'csiso143iecp271':
10058			case 'iecp271':
10059			case 'isoir143':
10060				return 'IEC_P27-1';
10061
10062			case 'csiso49inis':
10063			case 'inis':
10064			case 'isoir49':
10065				return 'INIS';
10066
10067			case 'csiso50inis8':
10068			case 'inis8':
10069			case 'isoir50':
10070				return 'INIS-8';
10071
10072			case 'csiso51iniscyrillic':
10073			case 'iniscyrillic':
10074			case 'isoir51':
10075				return 'INIS-cyrillic';
10076
10077			case 'csinvariant':
10078			case 'invariant':
10079				return 'INVARIANT';
10080
10081			case 'iso2022cn':
10082				return 'ISO-2022-CN';
10083
10084			case 'iso2022cnext':
10085				return 'ISO-2022-CN-EXT';
10086
10087			case 'csiso2022jp':
10088			case 'iso2022jp':
10089				return 'ISO-2022-JP';
10090
10091			case 'csiso2022jp2':
10092			case 'iso2022jp2':
10093				return 'ISO-2022-JP-2';
10094
10095			case 'csiso2022kr':
10096			case 'iso2022kr':
10097				return 'ISO-2022-KR';
10098
10099			case 'cswindows30latin1':
10100			case 'iso88591windows30latin1':
10101				return 'ISO-8859-1-Windows-3.0-Latin-1';
10102
10103			case 'cswindows31latin1':
10104			case 'iso88591windows31latin1':
10105				return 'ISO-8859-1-Windows-3.1-Latin-1';
10106
10107			case 'csisolatin2':
10108			case 'iso88592':
10109			case 'iso885921987':
10110			case 'isoir101':
10111			case 'l2':
10112			case 'latin2':
10113				return 'ISO-8859-2';
10114
10115			case 'cswindows31latin2':
10116			case 'iso88592windowslatin2':
10117				return 'ISO-8859-2-Windows-Latin-2';
10118
10119			case 'csisolatin3':
10120			case 'iso88593':
10121			case 'iso885931988':
10122			case 'isoir109':
10123			case 'l3':
10124			case 'latin3':
10125				return 'ISO-8859-3';
10126
10127			case 'csisolatin4':
10128			case 'iso88594':
10129			case 'iso885941988':
10130			case 'isoir110':
10131			case 'l4':
10132			case 'latin4':
10133				return 'ISO-8859-4';
10134
10135			case 'csisolatincyrillic':
10136			case 'cyrillic':
10137			case 'iso88595':
10138			case 'iso885951988':
10139			case 'isoir144':
10140				return 'ISO-8859-5';
10141
10142			case 'arabic':
10143			case 'asmo708':
10144			case 'csisolatinarabic':
10145			case 'ecma114':
10146			case 'iso88596':
10147			case 'iso885961987':
10148			case 'isoir127':
10149				return 'ISO-8859-6';
10150
10151			case 'csiso88596e':
10152			case 'iso88596e':
10153				return 'ISO-8859-6-E';
10154
10155			case 'csiso88596i':
10156			case 'iso88596i':
10157				return 'ISO-8859-6-I';
10158
10159			case 'csisolatingreek':
10160			case 'ecma118':
10161			case 'elot928':
10162			case 'greek':
10163			case 'greek8':
10164			case 'iso88597':
10165			case 'iso885971987':
10166			case 'isoir126':
10167				return 'ISO-8859-7';
10168
10169			case 'csisolatinhebrew':
10170			case 'hebrew':
10171			case 'iso88598':
10172			case 'iso885981988':
10173			case 'isoir138':
10174				return 'ISO-8859-8';
10175
10176			case 'csiso88598e':
10177			case 'iso88598e':
10178				return 'ISO-8859-8-E';
10179
10180			case 'csiso88598i':
10181			case 'iso88598i':
10182				return 'ISO-8859-8-I';
10183
10184			case 'cswindows31latin5':
10185			case 'iso88599windowslatin5':
10186				return 'ISO-8859-9-Windows-Latin-5';
10187
10188			case 'csisolatin6':
10189			case 'iso885910':
10190			case 'iso8859101992':
10191			case 'isoir157':
10192			case 'l6':
10193			case 'latin6':
10194				return 'ISO-8859-10';
10195
10196			case 'iso885913':
10197				return 'ISO-8859-13';
10198
10199			case 'iso885914':
10200			case 'iso8859141998':
10201			case 'isoceltic':
10202			case 'isoir199':
10203			case 'l8':
10204			case 'latin8':
10205				return 'ISO-8859-14';
10206
10207			case 'iso885915':
10208			case 'latin9':
10209				return 'ISO-8859-15';
10210
10211			case 'iso885916':
10212			case 'iso8859162001':
10213			case 'isoir226':
10214			case 'l10':
10215			case 'latin10':
10216				return 'ISO-8859-16';
10217
10218			case 'iso10646j1':
10219				return 'ISO-10646-J-1';
10220
10221			case 'csunicode':
10222			case 'iso10646ucs2':
10223				return 'ISO-10646-UCS-2';
10224
10225			case 'csucs4':
10226			case 'iso10646ucs4':
10227				return 'ISO-10646-UCS-4';
10228
10229			case 'csunicodeascii':
10230			case 'iso10646ucsbasic':
10231				return 'ISO-10646-UCS-Basic';
10232
10233			case 'csunicodelatin1':
10234			case 'iso10646':
10235			case 'iso10646unicodelatin1':
10236				return 'ISO-10646-Unicode-Latin1';
10237
10238			case 'csiso10646utf1':
10239			case 'iso10646utf1':
10240				return 'ISO-10646-UTF-1';
10241
10242			case 'csiso115481':
10243			case 'iso115481':
10244			case 'isotr115481':
10245				return 'ISO-11548-1';
10246
10247			case 'csiso90':
10248			case 'isoir90':
10249				return 'iso-ir-90';
10250
10251			case 'csunicodeibm1261':
10252			case 'isounicodeibm1261':
10253				return 'ISO-Unicode-IBM-1261';
10254
10255			case 'csunicodeibm1264':
10256			case 'isounicodeibm1264':
10257				return 'ISO-Unicode-IBM-1264';
10258
10259			case 'csunicodeibm1265':
10260			case 'isounicodeibm1265':
10261				return 'ISO-Unicode-IBM-1265';
10262
10263			case 'csunicodeibm1268':
10264			case 'isounicodeibm1268':
10265				return 'ISO-Unicode-IBM-1268';
10266
10267			case 'csunicodeibm1276':
10268			case 'isounicodeibm1276':
10269				return 'ISO-Unicode-IBM-1276';
10270
10271			case 'csiso646basic1983':
10272			case 'iso646basic1983':
10273			case 'ref':
10274				return 'ISO_646.basic:1983';
10275
10276			case 'csiso2intlrefversion':
10277			case 'irv':
10278			case 'iso646irv1983':
10279			case 'isoir2':
10280				return 'ISO_646.irv:1983';
10281
10282			case 'csiso2033':
10283			case 'e13b':
10284			case 'iso20331983':
10285			case 'isoir98':
10286				return 'ISO_2033-1983';
10287
10288			case 'csiso5427cyrillic':
10289			case 'iso5427':
10290			case 'isoir37':
10291				return 'ISO_5427';
10292
10293			case 'iso5427cyrillic1981':
10294			case 'iso54271981':
10295			case 'isoir54':
10296				return 'ISO_5427:1981';
10297
10298			case 'csiso5428greek':
10299			case 'iso54281980':
10300			case 'isoir55':
10301				return 'ISO_5428:1980';
10302
10303			case 'csiso6937add':
10304			case 'iso6937225':
10305			case 'isoir152':
10306				return 'ISO_6937-2-25';
10307
10308			case 'csisotextcomm':
10309			case 'iso69372add':
10310			case 'isoir142':
10311				return 'ISO_6937-2-add';
10312
10313			case 'csiso8859supp':
10314			case 'iso8859supp':
10315			case 'isoir154':
10316			case 'latin125':
10317				return 'ISO_8859-supp';
10318
10319			case 'csiso10367box':
10320			case 'iso10367box':
10321			case 'isoir155':
10322				return 'ISO_10367-box';
10323
10324			case 'csiso15italian':
10325			case 'iso646it':
10326			case 'isoir15':
10327			case 'it':
10328				return 'IT';
10329
10330			case 'csiso13jisc6220jp':
10331			case 'isoir13':
10332			case 'jisc62201969':
10333			case 'jisc62201969jp':
10334			case 'katakana':
10335			case 'x2017':
10336				return 'JIS_C6220-1969-jp';
10337
10338			case 'csiso14jisc6220ro':
10339			case 'iso646jp':
10340			case 'isoir14':
10341			case 'jisc62201969ro':
10342			case 'jp':
10343				return 'JIS_C6220-1969-ro';
10344
10345			case 'csiso42jisc62261978':
10346			case 'isoir42':
10347			case 'jisc62261978':
10348				return 'JIS_C6226-1978';
10349
10350			case 'csiso87jisx208':
10351			case 'isoir87':
10352			case 'jisc62261983':
10353			case 'jisx2081983':
10354			case 'x208':
10355				return 'JIS_C6226-1983';
10356
10357			case 'csiso91jisc62291984a':
10358			case 'isoir91':
10359			case 'jisc62291984a':
10360			case 'jpocra':
10361				return 'JIS_C6229-1984-a';
10362
10363			case 'csiso92jisc62991984b':
10364			case 'iso646jpocrb':
10365			case 'isoir92':
10366			case 'jisc62291984b':
10367			case 'jpocrb':
10368				return 'JIS_C6229-1984-b';
10369
10370			case 'csiso93jis62291984badd':
10371			case 'isoir93':
10372			case 'jisc62291984badd':
10373			case 'jpocrbadd':
10374				return 'JIS_C6229-1984-b-add';
10375
10376			case 'csiso94jis62291984hand':
10377			case 'isoir94':
10378			case 'jisc62291984hand':
10379			case 'jpocrhand':
10380				return 'JIS_C6229-1984-hand';
10381
10382			case 'csiso95jis62291984handadd':
10383			case 'isoir95':
10384			case 'jisc62291984handadd':
10385			case 'jpocrhandadd':
10386				return 'JIS_C6229-1984-hand-add';
10387
10388			case 'csiso96jisc62291984kana':
10389			case 'isoir96':
10390			case 'jisc62291984kana':
10391				return 'JIS_C6229-1984-kana';
10392
10393			case 'csjisencoding':
10394			case 'jisencoding':
10395				return 'JIS_Encoding';
10396
10397			case 'cshalfwidthkatakana':
10398			case 'jisx201':
10399			case 'x201':
10400				return 'JIS_X0201';
10401
10402			case 'csiso159jisx2121990':
10403			case 'isoir159':
10404			case 'jisx2121990':
10405			case 'x212':
10406				return 'JIS_X0212-1990';
10407
10408			case 'csiso141jusib1002':
10409			case 'iso646yu':
10410			case 'isoir141':
10411			case 'js':
10412			case 'jusib1002':
10413			case 'yu':
10414				return 'JUS_I.B1.002';
10415
10416			case 'csiso147macedonian':
10417			case 'isoir147':
10418			case 'jusib1003mac':
10419			case 'macedonian':
10420				return 'JUS_I.B1.003-mac';
10421
10422			case 'csiso146serbian':
10423			case 'isoir146':
10424			case 'jusib1003serb':
10425			case 'serbian':
10426				return 'JUS_I.B1.003-serb';
10427
10428			case 'koi7switched':
10429				return 'KOI7-switched';
10430
10431			case 'cskoi8r':
10432			case 'koi8r':
10433				return 'KOI8-R';
10434
10435			case 'koi8u':
10436				return 'KOI8-U';
10437
10438			case 'csksc5636':
10439			case 'iso646kr':
10440			case 'ksc5636':
10441				return 'KSC5636';
10442
10443			case 'cskz1048':
10444			case 'kz1048':
10445			case 'rk1048':
10446			case 'strk10482002':
10447				return 'KZ-1048';
10448
10449			case 'csiso19latingreek':
10450			case 'isoir19':
10451			case 'latingreek':
10452				return 'latin-greek';
10453
10454			case 'csiso27latingreek1':
10455			case 'isoir27':
10456			case 'latingreek1':
10457				return 'Latin-greek-1';
10458
10459			case 'csiso158lap':
10460			case 'isoir158':
10461			case 'lap':
10462			case 'latinlap':
10463				return 'latin-lap';
10464
10465			case 'csmacintosh':
10466			case 'mac':
10467			case 'macintosh':
10468				return 'macintosh';
10469
10470			case 'csmicrosoftpublishing':
10471			case 'microsoftpublishing':
10472				return 'Microsoft-Publishing';
10473
10474			case 'csmnem':
10475			case 'mnem':
10476				return 'MNEM';
10477
10478			case 'csmnemonic':
10479			case 'mnemonic':
10480				return 'MNEMONIC';
10481
10482			case 'csiso86hungarian':
10483			case 'hu':
10484			case 'iso646hu':
10485			case 'isoir86':
10486			case 'msz77953':
10487				return 'MSZ_7795.3';
10488
10489			case 'csnatsdano':
10490			case 'isoir91':
10491			case 'natsdano':
10492				return 'NATS-DANO';
10493
10494			case 'csnatsdanoadd':
10495			case 'isoir92':
10496			case 'natsdanoadd':
10497				return 'NATS-DANO-ADD';
10498
10499			case 'csnatssefi':
10500			case 'isoir81':
10501			case 'natssefi':
10502				return 'NATS-SEFI';
10503
10504			case 'csnatssefiadd':
10505			case 'isoir82':
10506			case 'natssefiadd':
10507				return 'NATS-SEFI-ADD';
10508
10509			case 'csiso151cuba':
10510			case 'cuba':
10511			case 'iso646cu':
10512			case 'isoir151':
10513			case 'ncnc1081':
10514				return 'NC_NC00-10:81';
10515
10516			case 'csiso69french':
10517			case 'fr':
10518			case 'iso646fr':
10519			case 'isoir69':
10520			case 'nfz62010':
10521				return 'NF_Z_62-010';
10522
10523			case 'csiso25french':
10524			case 'iso646fr1':
10525			case 'isoir25':
10526			case 'nfz620101973':
10527				return 'NF_Z_62-010_(1973)';
10528
10529			case 'csiso60danishnorwegian':
10530			case 'csiso60norwegian1':
10531			case 'iso646no':
10532			case 'isoir60':
10533			case 'no':
10534			case 'ns45511':
10535				return 'NS_4551-1';
10536
10537			case 'csiso61norwegian2':
10538			case 'iso646no2':
10539			case 'isoir61':
10540			case 'no2':
10541			case 'ns45512':
10542				return 'NS_4551-2';
10543
10544			case 'osdebcdicdf3irv':
10545				return 'OSD_EBCDIC_DF03_IRV';
10546
10547			case 'osdebcdicdf41':
10548				return 'OSD_EBCDIC_DF04_1';
10549
10550			case 'osdebcdicdf415':
10551				return 'OSD_EBCDIC_DF04_15';
10552
10553			case 'cspc8danishnorwegian':
10554			case 'pc8danishnorwegian':
10555				return 'PC8-Danish-Norwegian';
10556
10557			case 'cspc8turkish':
10558			case 'pc8turkish':
10559				return 'PC8-Turkish';
10560
10561			case 'csiso16portuguese':
10562			case 'iso646pt':
10563			case 'isoir16':
10564			case 'pt':
10565				return 'PT';
10566
10567			case 'csiso84portuguese2':
10568			case 'iso646pt2':
10569			case 'isoir84':
10570			case 'pt2':
10571				return 'PT2';
10572
10573			case 'cp154':
10574			case 'csptcp154':
10575			case 'cyrillicasian':
10576			case 'pt154':
10577			case 'ptcp154':
10578				return 'PTCP154';
10579
10580			case 'scsu':
10581				return 'SCSU';
10582
10583			case 'csiso10swedish':
10584			case 'fi':
10585			case 'iso646fi':
10586			case 'iso646se':
10587			case 'isoir10':
10588			case 'se':
10589			case 'sen850200b':
10590				return 'SEN_850200_B';
10591
10592			case 'csiso11swedishfornames':
10593			case 'iso646se2':
10594			case 'isoir11':
10595			case 'se2':
10596			case 'sen850200c':
10597				return 'SEN_850200_C';
10598
10599			case 'csshiftjis':
10600			case 'mskanji':
10601			case 'shiftjis':
10602				return 'Shift_JIS';
10603
10604			case 'csiso102t617bit':
10605			case 'isoir102':
10606			case 't617bit':
10607				return 'T.61-7bit';
10608
10609			case 'csiso103t618bit':
10610			case 'isoir103':
10611			case 't61':
10612			case 't618bit':
10613				return 'T.61-8bit';
10614
10615			case 'csiso128t101g2':
10616			case 'isoir128':
10617			case 't101g2':
10618				return 'T.101-G2';
10619
10620			case 'cstscii':
10621			case 'tscii':
10622				return 'TSCII';
10623
10624			case 'csunicode11':
10625			case 'unicode11':
10626				return 'UNICODE-1-1';
10627
10628			case 'csunicode11utf7':
10629			case 'unicode11utf7':
10630				return 'UNICODE-1-1-UTF-7';
10631
10632			case 'csunknown8bit':
10633			case 'unknown8bit':
10634				return 'UNKNOWN-8BIT';
10635
10636			case 'ansix341968':
10637			case 'ansix341986':
10638			case 'ascii':
10639			case 'cp367':
10640			case 'csascii':
10641			case 'ibm367':
10642			case 'iso646irv1991':
10643			case 'iso646us':
10644			case 'isoir6':
10645			case 'us':
10646			case 'usascii':
10647				return 'US-ASCII';
10648
10649			case 'csusdk':
10650			case 'usdk':
10651				return 'us-dk';
10652
10653			case 'utf7':
10654				return 'UTF-7';
10655
10656			case 'utf8':
10657				return 'UTF-8';
10658
10659			case 'utf16':
10660				return 'UTF-16';
10661
10662			case 'utf16be':
10663				return 'UTF-16BE';
10664
10665			case 'utf16le':
10666				return 'UTF-16LE';
10667
10668			case 'utf32':
10669				return 'UTF-32';
10670
10671			case 'utf32be':
10672				return 'UTF-32BE';
10673
10674			case 'utf32le':
10675				return 'UTF-32LE';
10676
10677			case 'csventurainternational':
10678			case 'venturainternational':
10679				return 'Ventura-International';
10680
10681			case 'csventuramath':
10682			case 'venturamath':
10683				return 'Ventura-Math';
10684
10685			case 'csventuraus':
10686			case 'venturaus':
10687				return 'Ventura-US';
10688
10689			case 'csiso70videotexsupp1':
10690			case 'isoir70':
10691			case 'videotexsuppl':
10692				return 'videotex-suppl';
10693
10694			case 'csviqr':
10695			case 'viqr':
10696				return 'VIQR';
10697
10698			case 'csviscii':
10699			case 'viscii':
10700				return 'VISCII';
10701
10702			case 'cswindows31j':
10703			case 'windows31j':
10704				return 'Windows-31J';
10705
10706			case 'iso885911':
10707			case 'tis620':
10708				return 'windows-874';
10709
10710			case 'cseuckr':
10711			case 'csksc56011987':
10712			case 'euckr':
10713			case 'isoir149':
10714			case 'korean':
10715			case 'ksc5601':
10716			case 'ksc56011987':
10717			case 'ksc56011989':
10718			case 'windows949':
10719				return 'windows-949';
10720
10721			case 'windows1250':
10722				return 'windows-1250';
10723
10724			case 'windows1251':
10725				return 'windows-1251';
10726
10727			case 'cp819':
10728			case 'csisolatin1':
10729			case 'ibm819':
10730			case 'iso88591':
10731			case 'iso885911987':
10732			case 'isoir100':
10733			case 'l1':
10734			case 'latin1':
10735			case 'windows1252':
10736				return 'windows-1252';
10737
10738			case 'windows1253':
10739				return 'windows-1253';
10740
10741			case 'csisolatin5':
10742			case 'iso88599':
10743			case 'iso885991989':
10744			case 'isoir148':
10745			case 'l5':
10746			case 'latin5':
10747			case 'windows1254':
10748				return 'windows-1254';
10749
10750			case 'windows1255':
10751				return 'windows-1255';
10752
10753			case 'windows1256':
10754				return 'windows-1256';
10755
10756			case 'windows1257':
10757				return 'windows-1257';
10758
10759			case 'windows1258':
10760				return 'windows-1258';
10761
10762			default:
10763				return $charset;
10764		}
10765	}
10766
10767	function get_curl_version()
10768	{
10769		if (is_array($curl = curl_version()))
10770		{
10771			$curl = $curl['version'];
10772		}
10773		elseif (substr($curl, 0, 5) === 'curl/')
10774		{
10775			$curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10776		}
10777		elseif (substr($curl, 0, 8) === 'libcurl/')
10778		{
10779			$curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10780		}
10781		else
10782		{
10783			$curl = 0;
10784		}
10785		return $curl;
10786	}
10787
10788	function is_subclass_of($class1, $class2)
10789	{
10790		if (func_num_args() !== 2)
10791		{
10792			trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10793		}
10794		elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10795		{
10796			return is_subclass_of($class1, $class2);
10797		}
10798		elseif (is_string($class1) && is_string($class2))
10799		{
10800			if (class_exists($class1))
10801			{
10802				if (class_exists($class2))
10803				{
10804					$class2 = strtolower($class2);
10805					while ($class1 = strtolower(get_parent_class($class1)))
10806					{
10807						if ($class1 === $class2)
10808						{
10809							return true;
10810						}
10811					}
10812				}
10813			}
10814			else
10815			{
10816				trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10817			}
10818		}
10819		return false;
10820	}
10821
10822	/**
10823	 * Strip HTML comments
10824	 *
10825	 * @access public
10826	 * @param string $data Data to strip comments from
10827	 * @return string Comment stripped string
10828	 */
10829	function strip_comments($data)
10830	{
10831		$output = '';
10832		while (($start = strpos($data, '<!--')) !== false)
10833		{
10834			$output .= substr($data, 0, $start);
10835			if (($end = strpos($data, '-->', $start)) !== false)
10836			{
10837				$data = substr_replace($data, '', 0, $end + 3);
10838			}
10839			else
10840			{
10841				$data = '';
10842			}
10843		}
10844		return $output . $data;
10845	}
10846
10847	function parse_date($dt)
10848	{
10849		$parser = SimplePie_Parse_Date::get();
10850		return $parser->parse($dt);
10851	}
10852
10853	/**
10854	 * Decode HTML entities
10855	 *
10856	 * @static
10857	 * @access public
10858	 * @param string $data Input data
10859	 * @return string Output data
10860	 */
10861	function entities_decode($data)
10862	{
10863		$decoder =& new SimplePie_Decode_HTML_Entities($data);
10864		return $decoder->parse();
10865	}
10866
10867	/**
10868	 * Remove RFC822 comments
10869	 *
10870	 * @access public
10871	 * @param string $data Data to strip comments from
10872	 * @return string Comment stripped string
10873	 */
10874	function uncomment_rfc822($string)
10875	{
10876		$string = (string) $string;
10877		$position = 0;
10878		$length = strlen($string);
10879		$depth = 0;
10880
10881		$output = '';
10882
10883		while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10884		{
10885			$output .= substr($string, $position, $pos - $position);
10886			$position = $pos + 1;
10887			if ($string[$pos - 1] !== '\\')
10888			{
10889				$depth++;
10890				while ($depth && $position < $length)
10891				{
10892					$position += strcspn($string, '()', $position);
10893					if ($string[$position - 1] === '\\')
10894					{
10895						$position++;
10896						continue;
10897					}
10898					elseif (isset($string[$position]))
10899					{
10900						switch ($string[$position])
10901						{
10902							case '(':
10903								$depth++;
10904								break;
10905
10906							case ')':
10907								$depth--;
10908								break;
10909						}
10910						$position++;
10911					}
10912					else
10913					{
10914						break;
10915					}
10916				}
10917			}
10918			else
10919			{
10920				$output .= '(';
10921			}
10922		}
10923		$output .= substr($string, $position);
10924
10925		return $output;
10926	}
10927
10928	function parse_mime($mime)
10929	{
10930		if (($pos = strpos($mime, ';')) === false)
10931		{
10932			return trim($mime);
10933		}
10934		else
10935		{
10936			return trim(substr($mime, 0, $pos));
10937		}
10938	}
10939
10940	function htmlspecialchars_decode($string, $quote_style)
10941	{
10942		if (function_exists('htmlspecialchars_decode'))
10943		{
10944			return htmlspecialchars_decode($string, $quote_style);
10945		}
10946		else
10947		{
10948			return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10949		}
10950	}
10951
10952	function atom_03_construct_type($attribs)
10953	{
10954		if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10955		{
10956			$mode = SIMPLEPIE_CONSTRUCT_BASE64;
10957		}
10958		else
10959		{
10960			$mode = SIMPLEPIE_CONSTRUCT_NONE;
10961		}
10962		if (isset($attribs['']['type']))
10963		{
10964			switch (strtolower(trim($attribs['']['type'])))
10965			{
10966				case 'text':
10967				case 'text/plain':
10968					return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10969
10970				case 'html':
10971				case 'text/html':
10972					return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10973
10974				case 'xhtml':
10975				case 'application/xhtml+xml':
10976					return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10977
10978				default:
10979					return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10980			}
10981		}
10982		else
10983		{
10984			return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10985		}
10986	}
10987
10988	function atom_10_construct_type($attribs)
10989	{
10990		if (isset($attribs['']['type']))
10991		{
10992			switch (strtolower(trim($attribs['']['type'])))
10993			{
10994				case 'text':
10995					return SIMPLEPIE_CONSTRUCT_TEXT;
10996
10997				case 'html':
10998					return SIMPLEPIE_CONSTRUCT_HTML;
10999
11000				case 'xhtml':
11001					return SIMPLEPIE_CONSTRUCT_XHTML;
11002
11003				default:
11004					return SIMPLEPIE_CONSTRUCT_NONE;
11005			}
11006		}
11007		return SIMPLEPIE_CONSTRUCT_TEXT;
11008	}
11009
11010	function atom_10_content_construct_type($attribs)
11011	{
11012		if (isset($attribs['']['type']))
11013		{
11014			$type = strtolower(trim($attribs['']['type']));
11015			switch ($type)
11016			{
11017				case 'text':
11018					return SIMPLEPIE_CONSTRUCT_TEXT;
11019
11020				case 'html':
11021					return SIMPLEPIE_CONSTRUCT_HTML;
11022
11023				case 'xhtml':
11024					return SIMPLEPIE_CONSTRUCT_XHTML;
11025			}
11026			if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11027			{
11028				return SIMPLEPIE_CONSTRUCT_NONE;
11029			}
11030			else
11031			{
11032				return SIMPLEPIE_CONSTRUCT_BASE64;
11033			}
11034		}
11035		else
11036		{
11037			return SIMPLEPIE_CONSTRUCT_TEXT;
11038		}
11039	}
11040
11041	function is_isegment_nz_nc($string)
11042	{
11043		return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
11044	}
11045
11046	function space_seperated_tokens($string)
11047	{
11048		$space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11049		$string_length = strlen($string);
11050
11051		$position = strspn($string, $space_characters);
11052		$tokens = array();
11053
11054		while ($position < $string_length)
11055		{
11056			$len = strcspn($string, $space_characters, $position);
11057			$tokens[] = substr($string, $position, $len);
11058			$position += $len;
11059			$position += strspn($string, $space_characters, $position);
11060		}
11061
11062		return $tokens;
11063	}
11064
11065	function array_unique($array)
11066	{
11067		if (version_compare(PHP_VERSION, '5.2', '>='))
11068		{
11069			return array_unique($array);
11070		}
11071		else
11072		{
11073			$array = (array) $array;
11074			$new_array = array();
11075			$new_array_strings = array();
11076			foreach ($array as $key => $value)
11077			{
11078				if (is_object($value))
11079				{
11080					if (method_exists($value, '__toString'))
11081					{
11082						$cmp = $value->__toString();
11083					}
11084					else
11085					{
11086						trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11087					}
11088				}
11089				elseif (is_array($value))
11090				{
11091					$cmp = (string) reset($value);
11092				}
11093				else
11094				{
11095					$cmp = (string) $value;
11096				}
11097				if (!in_array($cmp, $new_array_strings))
11098				{
11099					$new_array[$key] = $value;
11100					$new_array_strings[] = $cmp;
11101				}
11102			}
11103			return $new_array;
11104		}
11105	}
11106
11107	/**
11108	 * Converts a unicode codepoint to a UTF-8 character
11109	 *
11110	 * @static
11111	 * @access public
11112	 * @param int $codepoint Unicode codepoint
11113	 * @return string UTF-8 character
11114	 */
11115	function codepoint_to_utf8($codepoint)
11116	{
11117		$codepoint = (int) $codepoint;
11118		if ($codepoint < 0)
11119		{
11120			return false;
11121		}
11122		else if ($codepoint <= 0x7f)
11123		{
11124			return chr($codepoint);
11125		}
11126		else if ($codepoint <= 0x7ff)
11127		{
11128			return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11129		}
11130		else if ($codepoint <= 0xffff)
11131		{
11132			return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11133		}
11134		else if ($codepoint <= 0x10ffff)
11135		{
11136			return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11137		}
11138		else
11139		{
11140			// U+FFFD REPLACEMENT CHARACTER
11141			return "\xEF\xBF\xBD";
11142		}
11143	}
11144
11145	/**
11146	 * Re-implementation of PHP 5's stripos()
11147	 *
11148	 * Returns the numeric position of the first occurrence of needle in the
11149	 * haystack string.
11150	 *
11151	 * @static
11152	 * @access string
11153	 * @param object $haystack
11154	 * @param string $needle Note that the needle may be a string of one or more
11155	 *     characters. If needle is not a string, it is converted to an integer
11156	 *     and applied as the ordinal value of a character.
11157	 * @param int $offset The optional offset parameter allows you to specify which
11158	 *     character in haystack to start searching. The position returned is still
11159	 *     relative to the beginning of haystack.
11160	 * @return bool If needle is not found, stripos() will return boolean false.
11161	 */
11162	function stripos($haystack, $needle, $offset = 0)
11163	{
11164		if (function_exists('stripos'))
11165		{
11166			return stripos($haystack, $needle, $offset);
11167		}
11168		else
11169		{
11170			if (is_string($needle))
11171			{
11172				$needle = strtolower($needle);
11173			}
11174			elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11175			{
11176				$needle = strtolower(chr($needle));
11177			}
11178			else
11179			{
11180				trigger_error('needle is not a string or an integer', E_USER_WARNING);
11181				return false;
11182			}
11183
11184			return strpos(strtolower($haystack), $needle, $offset);
11185		}
11186	}
11187
11188	/**
11189	 * Similar to parse_str()
11190	 *
11191	 * Returns an associative array of name/value pairs, where the value is an
11192	 * array of values that have used the same name
11193	 *
11194	 * @static
11195	 * @access string
11196	 * @param string $str The input string.
11197	 * @return array
11198	 */
11199	function parse_str($str)
11200	{
11201		$return = array();
11202		$str = explode('&', $str);
11203
11204		foreach ($str as $section)
11205		{
11206			if (strpos($section, '=') !== false)
11207			{
11208				list($name, $value) = explode('=', $section, 2);
11209				$return[urldecode($name)][] = urldecode($value);
11210			}
11211			else
11212			{
11213				$return[urldecode($section)][] = null;
11214			}
11215		}
11216
11217		return $return;
11218	}
11219
11220	/**
11221	 * Detect XML encoding, as per XML 1.0 Appendix F.1
11222	 *
11223	 * @todo Add support for EBCDIC
11224	 * @param string $data XML data
11225	 * @return array Possible encodings
11226	 */
11227	function xml_encoding($data)
11228	{
11229		// UTF-32 Big Endian BOM
11230		if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11231		{
11232			$encoding[] = 'UTF-32BE';
11233		}
11234		// UTF-32 Little Endian BOM
11235		elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11236		{
11237			$encoding[] = 'UTF-32LE';
11238		}
11239		// UTF-16 Big Endian BOM
11240		elseif (substr($data, 0, 2) === "\xFE\xFF")
11241		{
11242			$encoding[] = 'UTF-16BE';
11243		}
11244		// UTF-16 Little Endian BOM
11245		elseif (substr($data, 0, 2) === "\xFF\xFE")
11246		{
11247			$encoding[] = 'UTF-16LE';
11248		}
11249		// UTF-8 BOM
11250		elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11251		{
11252			$encoding[] = 'UTF-8';
11253		}
11254		// UTF-32 Big Endian Without BOM
11255		elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
11256		{
11257			if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11258			{
11259				$parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11260				if ($parser->parse())
11261				{
11262					$encoding[] = $parser->encoding;
11263				}
11264			}
11265			$encoding[] = 'UTF-32BE';
11266		}
11267		// UTF-32 Little Endian Without BOM
11268		elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
11269		{
11270			if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11271			{
11272				$parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11273				if ($parser->parse())
11274				{
11275					$encoding[] = $parser->encoding;
11276				}
11277			}
11278			$encoding[] = 'UTF-32LE';
11279		}
11280		// UTF-16 Big Endian Without BOM
11281		elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11282		{
11283			if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11284			{
11285				$parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11286				if ($parser->parse())
11287				{
11288					$encoding[] = $parser->encoding;
11289				}
11290			}
11291			$encoding[] = 'UTF-16BE';
11292		}
11293		// UTF-16 Little Endian Without BOM
11294		elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11295		{
11296			if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11297			{
11298				$parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11299				if ($parser->parse())
11300				{
11301					$encoding[] = $parser->encoding;
11302				}
11303			}
11304			$encoding[] = 'UTF-16LE';
11305		}
11306		// US-ASCII (or superset)
11307		elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11308		{
11309			if ($pos = strpos($data, "\x3F\x3E"))
11310			{
11311				$parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11312				if ($parser->parse())
11313				{
11314					$encoding[] = $parser->encoding;
11315				}
11316			}
11317			$encoding[] = 'UTF-8';
11318		}
11319		// Fallback to UTF-8
11320		else
11321		{
11322			$encoding[] = 'UTF-8';
11323		}
11324		return $encoding;
11325	}
11326
11327	function output_javascript()
11328	{
11329		if (function_exists('ob_gzhandler'))
11330		{
11331			ob_start('ob_gzhandler');
11332		}
11333		header('Content-type: text/javascript; charset: UTF-8');
11334		header('Cache-Control: must-revalidate');
11335		header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11336		?>
11337function embed_odeo(link) {
11338	document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
11339}
11340
11341function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11342	if (placeholder != '') {
11343		document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
11344	}
11345	else {
11346		document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
11347	}
11348}
11349
11350function embed_flash(bgcolor, width, height, link, loop, type) {
11351	document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
11352}
11353
11354function embed_flv(width, height, link, placeholder, loop, player) {
11355	document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
11356}
11357
11358function embed_wmedia(width, height, link) {
11359	document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11360}
11361		<?php
11362	}
11363}
11364
11365/**
11366 * Decode HTML Entities
11367 *
11368 * This implements HTML5 as of revision 967 (2007-06-28)
11369 *
11370 * @package SimplePie
11371 */
11372class SimplePie_Decode_HTML_Entities
11373{
11374	/**
11375	 * Data to be parsed
11376	 *
11377	 * @access private
11378	 * @var string
11379	 */
11380	var $data = '';
11381
11382	/**
11383	 * Currently consumed bytes
11384	 *
11385	 * @access private
11386	 * @var string
11387	 */
11388	var $consumed = '';
11389
11390	/**
11391	 * Position of the current byte being parsed
11392	 *
11393	 * @access private
11394	 * @var int
11395	 */
11396	var $position = 0;
11397
11398	/**
11399	 * Create an instance of the class with the input data
11400	 *
11401	 * @access public
11402	 * @param string $data Input data
11403	 */
11404	function SimplePie_Decode_HTML_Entities($data)
11405	{
11406		$this->data = $data;
11407	}
11408
11409	/**
11410	 * Parse the input data
11411	 *
11412	 * @access public
11413	 * @return string Output data
11414	 */
11415	function parse()
11416	{
11417		while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11418		{
11419			$this->consume();
11420			$this->entity();
11421			$this->consumed = '';
11422		}
11423		return $this->data;
11424	}
11425
11426	/**
11427	 * Consume the next byte
11428	 *
11429	 * @access private
11430	 * @return mixed The next byte, or false, if there is no more data
11431	 */
11432	function consume()
11433	{
11434		if (isset($this->data[$this->position]))
11435		{
11436			$this->consumed .= $this->data[$this->position];
11437			return $this->data[$this->position++];
11438		}
11439		else
11440		{
11441			return false;
11442		}
11443	}
11444
11445	/**
11446	 * Consume a range of characters
11447	 *
11448	 * @access private
11449	 * @param string $chars Characters to consume
11450	 * @return mixed A series of characters that match the range, or false
11451	 */
11452	function consume_range($chars)
11453	{
11454		if ($len = strspn($this->data, $chars, $this->position))
11455		{
11456			$data = substr($this->data, $this->position, $len);
11457			$this->consumed .= $data;
11458			$this->position += $len;
11459			return $data;
11460		}
11461		else
11462		{
11463			return false;
11464		}
11465	}
11466
11467	/**
11468	 * Unconsume one byte
11469	 *
11470	 * @access private
11471	 */
11472	function unconsume()
11473	{
11474		$this->consumed = substr($this->consumed, 0, -1);
11475		$this->position--;
11476	}
11477
11478	/**
11479	 * Decode an entity
11480	 *
11481	 * @access private
11482	 */
11483	function entity()
11484	{
11485		switch ($this->consume())
11486		{
11487			case "\x09":
11488			case "\x0A":
11489			case "\x0B":
11490			case "\x0B":
11491			case "\x0C":
11492			case "\x20":
11493			case "\x3C":
11494			case "\x26":
11495			case false:
11496				break;
11497
11498			case "\x23":
11499				switch ($this->consume())
11500				{
11501					case "\x78":
11502					case "\x58":
11503						$range = '0123456789ABCDEFabcdef';
11504						$hex = true;
11505						break;
11506
11507					default:
11508						$range = '0123456789';
11509						$hex = false;
11510						$this->unconsume();
11511						break;
11512				}
11513
11514				if ($codepoint = $this->consume_range($range))
11515				{
11516					static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
11517
11518					if ($hex)
11519					{
11520						$codepoint = hexdec($codepoint);
11521					}
11522					else
11523					{
11524						$codepoint = intval($codepoint);
11525					}
11526
11527					if (isset($windows_1252_specials[$codepoint]))
11528					{
11529						$replacement = $windows_1252_specials[$codepoint];
11530					}
11531					else
11532					{
11533						$replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11534					}
11535
11536					if (!in_array($this->consume(), array(';', false), true))
11537					{
11538						$this->unconsume();
11539					}
11540
11541					$consumed_length = strlen($this->consumed);
11542					$this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11543					$this->position += strlen($replacement) - $consumed_length;
11544				}
11545				break;
11546
11547			default:
11548				static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
11549
11550				for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11551				{
11552					$consumed = substr($this->consumed, 1);
11553					if (isset($entities[$consumed]))
11554					{
11555						$match = $consumed;
11556					}
11557				}
11558
11559				if ($match !== null)
11560				{
11561 					$this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11562					$this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11563				}
11564				break;
11565		}
11566	}
11567}
11568
11569/**
11570 * IRI parser/serialiser
11571 *
11572 * @package SimplePie
11573 */
11574class SimplePie_IRI
11575{
11576	/**
11577	 * Scheme
11578	 *
11579	 * @access private
11580	 * @var string
11581	 */
11582	var $scheme;
11583
11584	/**
11585	 * User Information
11586	 *
11587	 * @access private
11588	 * @var string
11589	 */
11590	var $userinfo;
11591
11592	/**
11593	 * Host
11594	 *
11595	 * @access private
11596	 * @var string
11597	 */
11598	var $host;
11599
11600	/**
11601	 * Port
11602	 *
11603	 * @access private
11604	 * @var string
11605	 */
11606	var $port;
11607
11608	/**
11609	 * Path
11610	 *
11611	 * @access private
11612	 * @var string
11613	 */
11614	var $path;
11615
11616	/**
11617	 * Query
11618	 *
11619	 * @access private
11620	 * @var string
11621	 */
11622	var $query;
11623
11624	/**
11625	 * Fragment
11626	 *
11627	 * @access private
11628	 * @var string
11629	 */
11630	var $fragment;
11631
11632	/**
11633	 * Whether the object represents a valid IRI
11634	 *
11635	 * @access private
11636	 * @var array
11637	 */
11638	var $valid = array();
11639
11640	/**
11641	 * Return the entire IRI when you try and read the object as a string
11642	 *
11643	 * @access public
11644	 * @return string
11645	 */
11646	function __toString()
11647	{
11648		return $this->get_iri();
11649	}
11650
11651	/**
11652	 * Create a new IRI object, from a specified string
11653	 *
11654	 * @access public
11655	 * @param string $iri
11656	 * @return SimplePie_IRI
11657	 */
11658	function SimplePie_IRI($iri)
11659	{
11660		$iri = (string) $iri;
11661		if ($iri !== '')
11662		{
11663			$parsed = $this->parse_iri($iri);
11664			$this->set_scheme($parsed['scheme']);
11665			$this->set_authority($parsed['authority']);
11666			$this->set_path($parsed['path']);
11667			$this->set_query($parsed['query']);
11668			$this->set_fragment($parsed['fragment']);
11669		}
11670	}
11671
11672	/**
11673	 * Create a new IRI object by resolving a relative IRI
11674	 *
11675	 * @static
11676	 * @access public
11677	 * @param SimplePie_IRI $base Base IRI
11678	 * @param string $relative Relative IRI
11679	 * @return SimplePie_IRI
11680	 */
11681	function absolutize($base, $relative)
11682	{
11683		$relative = (string) $relative;
11684		if ($relative !== '')
11685		{
11686			$relative =& new SimplePie_IRI($relative);
11687			if ($relative->get_scheme() !== null)
11688			{
11689				$target = $relative;
11690			}
11691			elseif ($base->get_iri() !== null)
11692			{
11693				if ($relative->get_authority() !== null)
11694				{
11695					$target = $relative;
11696					$target->set_scheme($base->get_scheme());
11697				}
11698				else
11699				{
11700					$target =& new SimplePie_IRI('');
11701					$target->set_scheme($base->get_scheme());
11702					$target->set_userinfo($base->get_userinfo());
11703					$target->set_host($base->get_host());
11704					$target->set_port($base->get_port());
11705					if ($relative->get_path() !== null)
11706					{
11707						if (strpos($relative->get_path(), '/') === 0)
11708						{
11709							$target->set_path($relative->get_path());
11710						}
11711						elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11712						{
11713							$target->set_path('/' . $relative->get_path());
11714						}
11715						elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11716						{
11717							$target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11718						}
11719						else
11720						{
11721							$target->set_path($relative->get_path());
11722						}
11723						$target->set_query($relative->get_query());
11724					}
11725					else
11726					{
11727						$target->set_path($base->get_path());
11728						if ($relative->get_query() !== null)
11729						{
11730							$target->set_query($relative->get_query());
11731						}
11732						elseif ($base->get_query() !== null)
11733						{
11734							$target->set_query($base->get_query());
11735						}
11736					}
11737				}
11738				$target->set_fragment($relative->get_fragment());
11739			}
11740			else
11741			{
11742				// No base URL, just return the relative URL
11743				$target = $relative;
11744			}
11745		}
11746		else
11747		{
11748			$target = $base;
11749		}
11750		return $target;
11751	}
11752
11753	/**
11754	 * Parse an IRI into scheme/authority/path/query/fragment segments
11755	 *
11756	 * @access private
11757	 * @param string $iri
11758	 * @return array
11759	 */
11760	function parse_iri($iri)
11761	{
11762		preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11763		for ($i = count($match); $i <= 9; $i++)
11764		{
11765			$match[$i] = '';
11766		}
11767		return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11768	}
11769
11770	/**
11771	 * Remove dot segments from a path
11772	 *
11773	 * @access private
11774	 * @param string $input
11775	 * @return string
11776	 */
11777	function remove_dot_segments($input)
11778	{
11779		$output = '';
11780		while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11781		{
11782			// A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11783			if (strpos($input, '../') === 0)
11784			{
11785				$input = substr($input, 3);
11786			}
11787			elseif (strpos($input, './') === 0)
11788			{
11789				$input = substr($input, 2);
11790			}
11791			// B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
11792			elseif (strpos($input, '/./') === 0)
11793			{
11794				$input = substr_replace($input, '/', 0, 3);
11795			}
11796			elseif ($input === '/.')
11797			{
11798				$input = '/';
11799			}
11800			// C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
11801			elseif (strpos($input, '/../') === 0)
11802			{
11803				$input = substr_replace($input, '/', 0, 4);
11804				$output = substr_replace($output, '', strrpos($output, '/'));
11805			}
11806			elseif ($input === '/..')
11807			{
11808				$input = '/';
11809				$output = substr_replace($output, '', strrpos($output, '/'));
11810			}
11811			// D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11812			elseif ($input === '.' || $input === '..')
11813			{
11814				$input = '';
11815			}
11816			// E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
11817			elseif (($pos = strpos($input, '/', 1)) !== false)
11818			{
11819				$output .= substr($input, 0, $pos);
11820				$input = substr_replace($input, '', 0, $pos);
11821			}
11822			else
11823			{
11824				$output .= $input;
11825				$input = '';
11826			}
11827		}
11828		return $output . $input;
11829	}
11830
11831	/**
11832	 * Replace invalid character with percent encoding
11833	 *
11834	 * @access private
11835	 * @param string $string Input string
11836	 * @param string $valid_chars Valid characters
11837	 * @param int $case Normalise case
11838	 * @return string
11839	 */
11840	function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11841	{
11842		// Normalise case
11843		if ($case & SIMPLEPIE_LOWERCASE)
11844		{
11845			$string = strtolower($string);
11846		}
11847		elseif ($case & SIMPLEPIE_UPPERCASE)
11848		{
11849			$string = strtoupper($string);
11850		}
11851
11852		// Store position and string length (to avoid constantly recalculating this)
11853		$position = 0;
11854		$strlen = strlen($string);
11855
11856		// Loop as long as we have invalid characters, advancing the position to the next invalid character
11857		while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11858		{
11859			// If we have a % character
11860			if ($string[$position] === '%')
11861			{
11862				// If we have a pct-encoded section
11863				if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11864				{
11865					// Get the the represented character
11866					$chr = chr(hexdec(substr($string, $position + 1, 2)));
11867
11868					// If the character is valid, replace the pct-encoded with the actual character while normalising case
11869					if (strpos($valid_chars, $chr) !== false)
11870					{
11871						if ($case & SIMPLEPIE_LOWERCASE)
11872						{
11873							$chr = strtolower($chr);
11874						}
11875						elseif ($case & SIMPLEPIE_UPPERCASE)
11876						{
11877							$chr = strtoupper($chr);
11878						}
11879						$string = substr_replace($string, $chr, $position, 3);
11880						$strlen -= 2;
11881						$position++;
11882					}
11883
11884					// Otherwise just normalise the pct-encoded to uppercase
11885					else
11886					{
11887						$string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11888						$position += 3;
11889					}
11890				}
11891				// If we don't have a pct-encoded section, just replace the % with its own esccaped form
11892				else
11893				{
11894					$string = substr_replace($string, '%25', $position, 1);
11895					$strlen += 2;
11896					$position += 3;
11897				}
11898			}
11899			// If we have an invalid character, change into its pct-encoded form
11900			else
11901			{
11902				$replacement = sprintf("%%%02X", ord($string[$position]));
11903				$string = str_replace($string[$position], $replacement, $string);
11904				$strlen = strlen($string);
11905			}
11906		}
11907		return $string;
11908	}
11909
11910	/**
11911	 * Check if the object represents a valid IRI
11912	 *
11913	 * @access public
11914	 * @return bool
11915	 */
11916	function is_valid()
11917	{
11918		return array_sum($this->valid) === count($this->valid);
11919	}
11920
11921	/**
11922	 * Set the scheme. Returns true on success, false on failure (if there are
11923	 * any invalid characters).
11924	 *
11925	 * @access public
11926	 * @param string $scheme
11927	 * @return bool
11928	 */
11929	function set_scheme($scheme)
11930	{
11931		if ($scheme === null || $scheme === '')
11932		{
11933			$this->scheme = null;
11934		}
11935		else
11936		{
11937			$len = strlen($scheme);
11938			switch (true)
11939			{
11940				case $len > 1:
11941					if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11942					{
11943						$this->scheme = null;
11944						$this->valid[__FUNCTION__] = false;
11945						return false;
11946					}
11947
11948				case $len > 0:
11949					if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11950					{
11951						$this->scheme = null;
11952						$this->valid[__FUNCTION__] = false;
11953						return false;
11954					}
11955			}
11956			$this->scheme = strtolower($scheme);
11957		}
11958		$this->valid[__FUNCTION__] = true;
11959		return true;
11960	}
11961
11962	/**
11963	 * Set the authority. Returns true on success, false on failure (if there are
11964	 * any invalid characters).
11965	 *
11966	 * @access public
11967	 * @param string $authority
11968	 * @return bool
11969	 */
11970	function set_authority($authority)
11971	{
11972		if (($userinfo_end = strrpos($authority, '@')) !== false)
11973		{
11974			$userinfo = substr($authority, 0, $userinfo_end);
11975			$authority = substr($authority, $userinfo_end + 1);
11976		}
11977		else
11978		{
11979			$userinfo = null;
11980		}
11981
11982		if (($port_start = strpos($authority, ':')) !== false)
11983		{
11984			$port = substr($authority, $port_start + 1);
11985			$authority = substr($authority, 0, $port_start);
11986		}
11987		else
11988		{
11989			$port = null;
11990		}
11991
11992		return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
11993	}
11994
11995	/**
11996	 * Set the userinfo.
11997	 *
11998	 * @access public
11999	 * @param string $userinfo
12000	 * @return bool
12001	 */
12002	function set_userinfo($userinfo)
12003	{
12004		if ($userinfo === null || $userinfo === '')
12005		{
12006			$this->userinfo = null;
12007		}
12008		else
12009		{
12010			$this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12011		}
12012		$this->valid[__FUNCTION__] = true;
12013		return true;
12014	}
12015
12016	/**
12017	 * Set the host. Returns true on success, false on failure (if there are
12018	 * any invalid characters).
12019	 *
12020	 * @access public
12021	 * @param string $host
12022	 * @return bool
12023	 */
12024	function set_host($host)
12025	{
12026		if ($host === null || $host === '')
12027		{
12028			$this->host = null;
12029			$this->valid[__FUNCTION__] = true;
12030			return true;
12031		}
12032		elseif ($host[0] === '[' && substr($host, -1) === ']')
12033		{
12034			if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12035			{
12036				$this->host = $host;
12037				$this->valid[__FUNCTION__] = true;
12038				return true;
12039			}
12040			else
12041			{
12042				$this->host = null;
12043				$this->valid[__FUNCTION__] = false;
12044				return false;
12045			}
12046		}
12047		else
12048		{
12049			$this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12050			$this->valid[__FUNCTION__] = true;
12051			return true;
12052		}
12053	}
12054
12055	/**
12056	 * Set the port. Returns true on success, false on failure (if there are
12057	 * any invalid characters).
12058	 *
12059	 * @access public
12060	 * @param string $port
12061	 * @return bool
12062	 */
12063	function set_port($port)
12064	{
12065		if ($port === null || $port === '')
12066		{
12067			$this->port = null;
12068			$this->valid[__FUNCTION__] = true;
12069			return true;
12070		}
12071		elseif (strspn($port, '0123456789') === strlen($port))
12072		{
12073			$this->port = (int) $port;
12074			$this->valid[__FUNCTION__] = true;
12075			return true;
12076		}
12077		else
12078		{
12079			$this->port = null;
12080			$this->valid[__FUNCTION__] = false;
12081			return false;
12082		}
12083	}
12084
12085	/**
12086	 * Set the path.
12087	 *
12088	 * @access public
12089	 * @param string $path
12090	 * @return bool
12091	 */
12092	function set_path($path)
12093	{
12094		if ($path === null || $path === '')
12095		{
12096			$this->path = null;
12097			$this->valid[__FUNCTION__] = true;
12098			return true;
12099		}
12100		elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12101		{
12102			$this->path = null;
12103			$this->valid[__FUNCTION__] = false;
12104			return false;
12105		}
12106		else
12107		{
12108			$this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12109			if ($this->scheme !== null)
12110			{
12111				$this->path = $this->remove_dot_segments($this->path);
12112			}
12113			$this->valid[__FUNCTION__] = true;
12114			return true;
12115		}
12116	}
12117
12118	/**
12119	 * Set the query.
12120	 *
12121	 * @access public
12122	 * @param string $query
12123	 * @return bool
12124	 */
12125	function set_query($query)
12126	{
12127		if ($query === null || $query === '')
12128		{
12129			$this->query = null;
12130		}
12131		else
12132		{
12133			$this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12134		}
12135		$this->valid[__FUNCTION__] = true;
12136		return true;
12137	}
12138
12139	/**
12140	 * Set the fragment.
12141	 *
12142	 * @access public
12143	 * @param string $fragment
12144	 * @return bool
12145	 */
12146	function set_fragment($fragment)
12147	{
12148		if ($fragment === null || $fragment === '')
12149		{
12150			$this->fragment = null;
12151		}
12152		else
12153		{
12154			$this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12155		}
12156		$this->valid[__FUNCTION__] = true;
12157		return true;
12158	}
12159
12160	/**
12161	 * Get the complete IRI
12162	 *
12163	 * @access public
12164	 * @return string
12165	 */
12166	function get_iri()
12167	{
12168		$iri = '';
12169		if ($this->scheme !== null)
12170		{
12171			$iri .= $this->scheme . ':';
12172		}
12173		if (($authority = $this->get_authority()) !== null)
12174		{
12175			$iri .= '//' . $authority;
12176		}
12177		if ($this->path !== null)
12178		{
12179			$iri .= $this->path;
12180		}
12181		if ($this->query !== null)
12182		{
12183			$iri .= '?' . $this->query;
12184		}
12185		if ($this->fragment !== null)
12186		{
12187			$iri .= '#' . $this->fragment;
12188		}
12189
12190		if ($iri !== '')
12191		{
12192			return $iri;
12193		}
12194		else
12195		{
12196			return null;
12197		}
12198	}
12199
12200	/**
12201	 * Get the scheme
12202	 *
12203	 * @access public
12204	 * @return string
12205	 */
12206	function get_scheme()
12207	{
12208		return $this->scheme;
12209	}
12210
12211	/**
12212	 * Get the complete authority
12213	 *
12214	 * @access public
12215	 * @return string
12216	 */
12217	function get_authority()
12218	{
12219		$authority = '';
12220		if ($this->userinfo !== null)
12221		{
12222			$authority .= $this->userinfo . '@';
12223		}
12224		if ($this->host !== null)
12225		{
12226			$authority .= $this->host;
12227		}
12228		if ($this->port !== null)
12229		{
12230			$authority .= ':' . $this->port;
12231		}
12232
12233		if ($authority !== '')
12234		{
12235			return $authority;
12236		}
12237		else
12238		{
12239			return null;
12240		}
12241	}
12242
12243	/**
12244	 * Get the user information
12245	 *
12246	 * @access public
12247	 * @return string
12248	 */
12249	function get_userinfo()
12250	{
12251		return $this->userinfo;
12252	}
12253
12254	/**
12255	 * Get the host
12256	 *
12257	 * @access public
12258	 * @return string
12259	 */
12260	function get_host()
12261	{
12262		return $this->host;
12263	}
12264
12265	/**
12266	 * Get the port
12267	 *
12268	 * @access public
12269	 * @return string
12270	 */
12271	function get_port()
12272	{
12273		return $this->port;
12274	}
12275
12276	/**
12277	 * Get the path
12278	 *
12279	 * @access public
12280	 * @return string
12281	 */
12282	function get_path()
12283	{
12284		return $this->path;
12285	}
12286
12287	/**
12288	 * Get the query
12289	 *
12290	 * @access public
12291	 * @return string
12292	 */
12293	function get_query()
12294	{
12295		return $this->query;
12296	}
12297
12298	/**
12299	 * Get the fragment
12300	 *
12301	 * @access public
12302	 * @return string
12303	 */
12304	function get_fragment()
12305	{
12306		return $this->fragment;
12307	}
12308}
12309
12310/**
12311 * Class to validate and to work with IPv6 addresses.
12312 *
12313 * @package SimplePie
12314 * @copyright 2003-2005 The PHP Group
12315 * @license http://www.opensource.org/licenses/bsd-license.php
12316 * @link http://pear.php.net/package/Net_IPv6
12317 * @author Alexander Merz <alexander.merz@web.de>
12318 * @author elfrink at introweb dot nl
12319 * @author Josh Peck <jmp at joshpeck dot org>
12320 * @author Geoffrey Sneddon <geoffers@gmail.com>
12321 */
12322class SimplePie_Net_IPv6
12323{
12324	/**
12325	 * Removes a possible existing netmask specification of an IP address.
12326	 *
12327	 * @param string $ip the (compressed) IP as Hex representation
12328	 * @return string the IP the without netmask
12329	 * @since 1.1.0
12330	 * @access public
12331	 * @static
12332	 */
12333	function removeNetmaskSpec($ip)
12334	{
12335		if (strpos($ip, '/') !== false)
12336		{
12337			list($addr, $nm) = explode('/', $ip);
12338		}
12339		else
12340		{
12341			$addr = $ip;
12342		}
12343		return $addr;
12344	}
12345
12346	/**
12347	 * Uncompresses an IPv6 address
12348	 *
12349	 * RFC 2373 allows you to compress zeros in an address to '::'. This
12350	 * function expects an valid IPv6 address and expands the '::' to
12351	 * the required zeros.
12352	 *
12353	 * Example:	 FF01::101	->	FF01:0:0:0:0:0:0:101
12354	 *			 ::1		->	0:0:0:0:0:0:0:1
12355	 *
12356	 * @access public
12357	 * @static
12358	 * @param string $ip a valid IPv6-address (hex format)
12359	 * @return string the uncompressed IPv6-address (hex format)
12360	 */
12361	function Uncompress($ip)
12362	{
12363		$uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12364		$c1 = -1;
12365		$c2 = -1;
12366		if (strpos($ip, '::') !== false)
12367		{
12368			list($ip1, $ip2) = explode('::', $ip);
12369			if ($ip1 === '')
12370			{
12371				$c1 = -1;
12372			}
12373			else
12374			{
12375				$pos = 0;
12376				if (($pos = substr_count($ip1, ':')) > 0)
12377				{
12378					$c1 = $pos;
12379				}
12380				else
12381				{
12382					$c1 = 0;
12383				}
12384			}
12385			if ($ip2 === '')
12386			{
12387				$c2 = -1;
12388			}
12389			else
12390			{
12391				$pos = 0;
12392				if (($pos = substr_count($ip2, ':')) > 0)
12393				{
12394					$c2 = $pos;
12395				}
12396				else
12397				{
12398					$c2 = 0;
12399				}
12400			}
12401			if (strstr($ip2, '.'))
12402			{
12403				$c2++;
12404			}
12405			// ::
12406			if ($c1 === -1 && $c2 === -1)
12407			{
12408				$uip = '0:0:0:0:0:0:0:0';
12409			}
12410			// ::xxx
12411			else if ($c1 === -1)
12412			{
12413				$fill = str_repeat('0:', 7 - $c2);
12414				$uip =	str_replace('::', $fill, $uip);
12415			}
12416			// xxx::
12417			else if ($c2 === -1)
12418			{
12419				$fill = str_repeat(':0', 7 - $c1);
12420				$uip =	str_replace('::', $fill, $uip);
12421			}
12422			// xxx::xxx
12423			else
12424			{
12425				$fill = str_repeat(':0:', 6 - $c2 - $c1);
12426				$uip =	str_replace('::', $fill, $uip);
12427				$uip =	str_replace('::', ':', $uip);
12428			}
12429		}
12430		return $uip;
12431	}
12432
12433	/**
12434	 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12435	 *
12436	 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12437	 * an IPv4 compatible address
12438	 *
12439	 * Example:	 0:0:0:0:0:0:13.1.68.3
12440	 *			 0:0:0:0:0:FFFF:129.144.52.38
12441	 *
12442	 * @access public
12443	 * @static
12444	 * @param string $ip a valid IPv6-address (hex format)
12445	 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12446	 */
12447	function SplitV64($ip)
12448	{
12449		$ip = SimplePie_Net_IPv6::Uncompress($ip);
12450		if (strstr($ip, '.'))
12451		{
12452			$pos = strrpos($ip, ':');
12453			$ip[$pos] = '_';
12454			$ipPart = explode('_', $ip);
12455			return $ipPart;
12456		}
12457		else
12458		{
12459			return array($ip, '');
12460		}
12461	}
12462
12463	/**
12464	 * Checks an IPv6 address
12465	 *
12466	 * Checks if the given IP is IPv6-compatible
12467	 *
12468	 * @access public
12469	 * @static
12470	 * @param string $ip a valid IPv6-address
12471	 * @return bool true if $ip is an IPv6 address
12472	 */
12473	function checkIPv6($ip)
12474	{
12475		$ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12476		$count = 0;
12477		if (!empty($ipPart[0]))
12478		{
12479			$ipv6 = explode(':', $ipPart[0]);
12480			for ($i = 0; $i < count($ipv6); $i++)
12481			{
12482				$dec = hexdec($ipv6[$i]);
12483				$hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12484				if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12485				{
12486					$count++;
12487				}
12488			}
12489			if ($count === 8)
12490			{
12491				return true;
12492			}
12493			elseif ($count === 6 && !empty($ipPart[1]))
12494			{
12495				$ipv4 = explode('.', $ipPart[1]);
12496				$count = 0;
12497				foreach ($ipv4 as $ipv4_part)
12498				{
12499					if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12500					{
12501						$count++;
12502					}
12503				}
12504				if ($count === 4)
12505				{
12506					return true;
12507				}
12508			}
12509			else
12510			{
12511				return false;
12512			}
12513
12514		}
12515		else
12516		{
12517			return false;
12518		}
12519	}
12520}
12521
12522/**
12523 * Date Parser
12524 *
12525 * @package SimplePie
12526 */
12527class SimplePie_Parse_Date
12528{
12529	/**
12530	 * Input data
12531	 *
12532	 * @access protected
12533	 * @var string
12534	 */
12535	var $date;
12536
12537	/**
12538	 * List of days, calendar day name => ordinal day number in the week
12539	 *
12540	 * @access protected
12541	 * @var array
12542	 */
12543	var $day = array(
12544		// English
12545		'mon' => 1,
12546		'monday' => 1,
12547		'tue' => 2,
12548		'tuesday' => 2,
12549		'wed' => 3,
12550		'wednesday' => 3,
12551		'thu' => 4,
12552		'thursday' => 4,
12553		'fri' => 5,
12554		'friday' => 5,
12555		'sat' => 6,
12556		'saturday' => 6,
12557		'sun' => 7,
12558		'sunday' => 7,
12559		// Dutch
12560		'maandag' => 1,
12561		'dinsdag' => 2,
12562		'woensdag' => 3,
12563		'donderdag' => 4,
12564		'vrijdag' => 5,
12565		'zaterdag' => 6,
12566		'zondag' => 7,
12567		// French
12568		'lundi' => 1,
12569		'mardi' => 2,
12570		'mercredi' => 3,
12571		'jeudi' => 4,
12572		'vendredi' => 5,
12573		'samedi' => 6,
12574		'dimanche' => 7,
12575		// German
12576		'montag' => 1,
12577		'dienstag' => 2,
12578		'mittwoch' => 3,
12579		'donnerstag' => 4,
12580		'freitag' => 5,
12581		'samstag' => 6,
12582		'sonnabend' => 6,
12583		'sonntag' => 7,
12584		// Italian
12585		'lunedì' => 1,
12586		'martedì' => 2,
12587		'mercoledì' => 3,
12588		'giovedì' => 4,
12589		'venerdì' => 5,
12590		'sabato' => 6,
12591		'domenica' => 7,
12592		// Spanish
12593		'lunes' => 1,
12594		'martes' => 2,
12595		'miércoles' => 3,
12596		'jueves' => 4,
12597		'viernes' => 5,
12598		'sábado' => 6,
12599		'domingo' => 7,
12600		// Finnish
12601		'maanantai' => 1,
12602		'tiistai' => 2,
12603		'keskiviikko' => 3,
12604		'torstai' => 4,
12605		'perjantai' => 5,
12606		'lauantai' => 6,
12607		'sunnuntai' => 7,
12608		// Hungarian
12609		'hétfő' => 1,
12610		'kedd' => 2,
12611		'szerda' => 3,
12612		'csütörtok' => 4,
12613		'péntek' => 5,
12614		'szombat' => 6,
12615		'vasárnap' => 7,
12616		// Greek
12617		'Δευ' => 1,
12618		'Τρι' => 2,
12619		'Τετ' => 3,
12620		'Πεμ' => 4,
12621		'Παρ' => 5,
12622		'Σαβ' => 6,
12623		'Κυρ' => 7,
12624	);
12625
12626	/**
12627	 * List of months, calendar month name => calendar month number
12628	 *
12629	 * @access protected
12630	 * @var array
12631	 */
12632	var $month = array(
12633		// English
12634		'jan' => 1,
12635		'january' => 1,
12636		'feb' => 2,
12637		'february' => 2,
12638		'mar' => 3,
12639		'march' => 3,
12640		'apr' => 4,
12641		'april' => 4,
12642		'may' => 5,
12643		// No long form of May
12644		'jun' => 6,
12645		'june' => 6,
12646		'jul' => 7,
12647		'july' => 7,
12648		'aug' => 8,
12649		'august' => 8,
12650		'sep' => 9,
12651		'september' => 8,
12652		'oct' => 10,
12653		'october' => 10,
12654		'nov' => 11,
12655		'november' => 11,
12656		'dec' => 12,
12657		'december' => 12,
12658		// Dutch
12659		'januari' => 1,
12660		'februari' => 2,
12661		'maart' => 3,
12662		'april' => 4,
12663		'mei' => 5,
12664		'juni' => 6,
12665		'juli' => 7,
12666		'augustus' => 8,
12667		'september' => 9,
12668		'oktober' => 10,
12669		'november' => 11,
12670		'december' => 12,
12671		// French
12672		'janvier' => 1,
12673		'février' => 2,
12674		'mars' => 3,
12675		'avril' => 4,
12676		'mai' => 5,
12677		'juin' => 6,
12678		'juillet' => 7,
12679		'août' => 8,
12680		'septembre' => 9,
12681		'octobre' => 10,
12682		'novembre' => 11,
12683		'décembre' => 12,
12684		// German
12685		'januar' => 1,
12686		'februar' => 2,
12687		'märz' => 3,
12688		'april' => 4,
12689		'mai' => 5,
12690		'juni' => 6,
12691		'juli' => 7,
12692		'august' => 8,
12693		'september' => 9,
12694		'oktober' => 10,
12695		'november' => 11,
12696		'dezember' => 12,
12697		// Italian
12698		'gennaio' => 1,
12699		'febbraio' => 2,
12700		'marzo' => 3,
12701		'aprile' => 4,
12702		'maggio' => 5,
12703		'giugno' => 6,
12704		'luglio' => 7,
12705		'agosto' => 8,
12706		'settembre' => 9,
12707		'ottobre' => 10,
12708		'novembre' => 11,
12709		'dicembre' => 12,
12710		// Spanish
12711		'enero' => 1,
12712		'febrero' => 2,
12713		'marzo' => 3,
12714		'abril' => 4,
12715		'mayo' => 5,
12716		'junio' => 6,
12717		'julio' => 7,
12718		'agosto' => 8,
12719		'septiembre' => 9,
12720		'setiembre' => 9,
12721		'octubre' => 10,
12722		'noviembre' => 11,
12723		'diciembre' => 12,
12724		// Finnish
12725		'tammikuu' => 1,
12726		'helmikuu' => 2,
12727		'maaliskuu' => 3,
12728		'huhtikuu' => 4,
12729		'toukokuu' => 5,
12730		'kesäkuu' => 6,
12731		'heinäkuu' => 7,
12732		'elokuu' => 8,
12733		'suuskuu' => 9,
12734		'lokakuu' => 10,
12735		'marras' => 11,
12736		'joulukuu' => 12,
12737		// Hungarian
12738		'január' => 1,
12739		'február' => 2,
12740		'március' => 3,
12741		'április' => 4,
12742		'május' => 5,
12743		'június' => 6,
12744		'július' => 7,
12745		'augusztus' => 8,
12746		'szeptember' => 9,
12747		'október' => 10,
12748		'november' => 11,
12749		'december' => 12,
12750		// Greek
12751		'Ιαν' => 1,
12752		'Φεβ' => 2,
12753		'Μάώ' => 3,
12754		'Μαώ' => 3,
12755		'Απρ' => 4,
12756		'Μάι' => 5,
12757		'Μαϊ' => 5,
12758		'Μαι' => 5,
12759		'Ιούν' => 6,
12760		'Ιον' => 6,
12761		'Ιούλ' => 7,
12762		'Ιολ' => 7,
12763		'Αύγ' => 8,
12764		'Αυγ' => 8,
12765		'Σεπ' => 9,
12766		'Οκτ' => 10,
12767		'Νοέ' => 11,
12768		'Δεκ' => 12,
12769	);
12770
12771	/**
12772	 * List of timezones, abbreviation => offset from UTC
12773	 *
12774	 * @access protected
12775	 * @var array
12776	 */
12777	var $timezone = array(
12778		'ACDT' => 37800,
12779		'ACIT' => 28800,
12780		'ACST' => 34200,
12781		'ACT' => -18000,
12782		'ACWDT' => 35100,
12783		'ACWST' => 31500,
12784		'AEDT' => 39600,
12785		'AEST' => 36000,
12786		'AFT' => 16200,
12787		'AKDT' => -28800,
12788		'AKST' => -32400,
12789		'AMDT' => 18000,
12790		'AMT' => -14400,
12791		'ANAST' => 46800,
12792		'ANAT' => 43200,
12793		'ART' => -10800,
12794		'AZOST' => -3600,
12795		'AZST' => 18000,
12796		'AZT' => 14400,
12797		'BIOT' => 21600,
12798		'BIT' => -43200,
12799		'BOT' => -14400,
12800		'BRST' => -7200,
12801		'BRT' => -10800,
12802		'BST' => 3600,
12803		'BTT' => 21600,
12804		'CAST' => 18000,
12805		'CAT' => 7200,
12806		'CCT' => 23400,
12807		'CDT' => -18000,
12808		'CEDT' => 7200,
12809		'CET' => 3600,
12810		'CGST' => -7200,
12811		'CGT' => -10800,
12812		'CHADT' => 49500,
12813		'CHAST' => 45900,
12814		'CIST' => -28800,
12815		'CKT' => -36000,
12816		'CLDT' => -10800,
12817		'CLST' => -14400,
12818		'COT' => -18000,
12819		'CST' => -21600,
12820		'CVT' => -3600,
12821		'CXT' => 25200,
12822		'DAVT' => 25200,
12823		'DTAT' => 36000,
12824		'EADT' => -18000,
12825		'EAST' => -21600,
12826		'EAT' => 10800,
12827		'ECT' => -18000,
12828		'EDT' => -14400,
12829		'EEST' => 10800,
12830		'EET' => 7200,
12831		'EGT' => -3600,
12832		'EKST' => 21600,
12833		'EST' => -18000,
12834		'FJT' => 43200,
12835		'FKDT' => -10800,
12836		'FKST' => -14400,
12837		'FNT' => -7200,
12838		'GALT' => -21600,
12839		'GEDT' => 14400,
12840		'GEST' => 10800,
12841		'GFT' => -10800,
12842		'GILT' => 43200,
12843		'GIT' => -32400,
12844		'GST' => 14400,
12845		'GST' => -7200,
12846		'GYT' => -14400,
12847		'HAA' => -10800,
12848		'HAC' => -18000,
12849		'HADT' => -32400,
12850		'HAE' => -14400,
12851		'HAP' => -25200,
12852		'HAR' => -21600,
12853		'HAST' => -36000,
12854		'HAT' => -9000,
12855		'HAY' => -28800,
12856		'HKST' => 28800,
12857		'HMT' => 18000,
12858		'HNA' => -14400,
12859		'HNC' => -21600,
12860		'HNE' => -18000,
12861		'HNP' => -28800,
12862		'HNR' => -25200,
12863		'HNT' => -12600,
12864		'HNY' => -32400,
12865		'IRDT' => 16200,
12866		'IRKST' => 32400,
12867		'IRKT' => 28800,
12868		'IRST' => 12600,
12869		'JFDT' => -10800,
12870		'JFST' => -14400,
12871		'JST' => 32400,
12872		'KGST' => 21600,
12873		'KGT' => 18000,
12874		'KOST' => 39600,
12875		'KOVST' => 28800,
12876		'KOVT' => 25200,
12877		'KRAST' => 28800,
12878		'KRAT' => 25200,
12879		'KST' => 32400,
12880		'LHDT' => 39600,
12881		'LHST' => 37800,
12882		'LINT' => 50400,
12883		'LKT' => 21600,
12884		'MAGST' => 43200,
12885		'MAGT' => 39600,
12886		'MAWT' => 21600,
12887		'MDT' => -21600,
12888		'MESZ' => 7200,
12889		'MEZ' => 3600,
12890		'MHT' => 43200,
12891		'MIT' => -34200,
12892		'MNST' => 32400,
12893		'MSDT' => 14400,
12894		'MSST' => 10800,
12895		'MST' => -25200,
12896		'MUT' => 14400,
12897		'MVT' => 18000,
12898		'MYT' => 28800,
12899		'NCT' => 39600,
12900		'NDT' => -9000,
12901		'NFT' => 41400,
12902		'NMIT' => 36000,
12903		'NOVST' => 25200,
12904		'NOVT' => 21600,
12905		'NPT' => 20700,
12906		'NRT' => 43200,
12907		'NST' => -12600,
12908		'NUT' => -39600,
12909		'NZDT' => 46800,
12910		'NZST' => 43200,
12911		'OMSST' => 25200,
12912		'OMST' => 21600,
12913		'PDT' => -25200,
12914		'PET' => -18000,
12915		'PETST' => 46800,
12916		'PETT' => 43200,
12917		'PGT' => 36000,
12918		'PHOT' => 46800,
12919		'PHT' => 28800,
12920		'PKT' => 18000,
12921		'PMDT' => -7200,
12922		'PMST' => -10800,
12923		'PONT' => 39600,
12924		'PST' => -28800,
12925		'PWT' => 32400,
12926		'PYST' => -10800,
12927		'PYT' => -14400,
12928		'RET' => 14400,
12929		'ROTT' => -10800,
12930		'SAMST' => 18000,
12931		'SAMT' => 14400,
12932		'SAST' => 7200,
12933		'SBT' => 39600,
12934		'SCDT' => 46800,
12935		'SCST' => 43200,
12936		'SCT' => 14400,
12937		'SEST' => 3600,
12938		'SGT' => 28800,
12939		'SIT' => 28800,
12940		'SRT' => -10800,
12941		'SST' => -39600,
12942		'SYST' => 10800,
12943		'SYT' => 7200,
12944		'TFT' => 18000,
12945		'THAT' => -36000,
12946		'TJT' => 18000,
12947		'TKT' => -36000,
12948		'TMT' => 18000,
12949		'TOT' => 46800,
12950		'TPT' => 32400,
12951		'TRUT' => 36000,
12952		'TVT' => 43200,
12953		'TWT' => 28800,
12954		'UYST' => -7200,
12955		'UYT' => -10800,
12956		'UZT' => 18000,
12957		'VET' => -14400,
12958		'VLAST' => 39600,
12959		'VLAT' => 36000,
12960		'VOST' => 21600,
12961		'VUT' => 39600,
12962		'WAST' => 7200,
12963		'WAT' => 3600,
12964		'WDT' => 32400,
12965		'WEST' => 3600,
12966		'WFT' => 43200,
12967		'WIB' => 25200,
12968		'WIT' => 32400,
12969		'WITA' => 28800,
12970		'WKST' => 18000,
12971		'WST' => 28800,
12972		'YAKST' => 36000,
12973		'YAKT' => 32400,
12974		'YAPT' => 36000,
12975		'YEKST' => 21600,
12976		'YEKT' => 18000,
12977	);
12978
12979	/**
12980	 * Cached PCRE for SimplePie_Parse_Date::$day
12981	 *
12982	 * @access protected
12983	 * @var string
12984	 */
12985	var $day_pcre;
12986
12987	/**
12988	 * Cached PCRE for SimplePie_Parse_Date::$month
12989	 *
12990	 * @access protected
12991	 * @var string
12992	 */
12993	var $month_pcre;
12994
12995	/**
12996	 * Array of user-added callback methods
12997	 *
12998	 * @access private
12999	 * @var array
13000	 */
13001	var $built_in = array();
13002
13003	/**
13004	 * Array of user-added callback methods
13005	 *
13006	 * @access private
13007	 * @var array
13008	 */
13009	var $user = array();
13010
13011	/**
13012	 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13013	 * self::month_pcre, and self::built_in
13014	 *
13015	 * @access private
13016	 */
13017	function SimplePie_Parse_Date()
13018	{
13019		$this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13020		$this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13021
13022		static $cache;
13023		if (!isset($cache[get_class($this)]))
13024		{
13025			$all_methods = get_class_methods($this);
13026
13027			foreach ($all_methods as $method)
13028			{
13029				if (strtolower(substr($method, 0, 5)) === 'date_')
13030				{
13031					$cache[get_class($this)][] = $method;
13032				}
13033			}
13034		}
13035
13036		foreach ($cache[get_class($this)] as $method)
13037		{
13038			$this->built_in[] = $method;
13039		}
13040	}
13041
13042	/**
13043	 * Get the object
13044	 *
13045	 * @access public
13046	 */
13047	function get()
13048	{
13049		static $object;
13050		if (!$object)
13051		{
13052			$object =& new SimplePie_Parse_Date;
13053		}
13054		return $object;
13055	}
13056
13057	/**
13058	 * Parse a date
13059	 *
13060	 * @final
13061	 * @access public
13062	 * @param string $date Date to parse
13063	 * @return int Timestamp corresponding to date string, or false on failure
13064	 */
13065	function parse($date)
13066	{
13067		foreach ($this->user as $method)
13068		{
13069			if (($returned = call_user_func($method, $date)) !== false)
13070			{
13071				return $returned;
13072			}
13073		}
13074
13075		foreach ($this->built_in as $method)
13076		{
13077			if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13078			{
13079				return $returned;
13080			}
13081		}
13082
13083		return false;
13084	}
13085
13086	/**
13087	 * Add a callback method to parse a date
13088	 *
13089	 * @final
13090	 * @access public
13091	 * @param callback $callback
13092	 */
13093	function add_callback($callback)
13094	{
13095		if (is_callable($callback))
13096		{
13097			$this->user[] = $callback;
13098		}
13099		else
13100		{
13101			trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13102		}
13103	}
13104
13105	/**
13106	 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13107	 * well as allowing any of upper or lower case "T", horizontal tabs, or
13108	 * spaces to be used as the time seperator (including more than one))
13109	 *
13110	 * @access protected
13111	 * @return int Timestamp
13112	 */
13113	function date_w3cdtf($date)
13114	{
13115		static $pcre;
13116		if (!$pcre)
13117		{
13118			$year = '([0-9]{4})';
13119			$month = $day = $hour = $minute = $second = '([0-9]{2})';
13120			$decimal = '([0-9]*)';
13121			$zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13122			$pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13123		}
13124		if (preg_match($pcre, $date, $match))
13125		{
13126			/*
13127			Capturing subpatterns:
13128			1: Year
13129			2: Month
13130			3: Day
13131			4: Hour
13132			5: Minute
13133			6: Second
13134			7: Decimal fraction of a second
13135			8: Zulu
13136			9: Timezone ±
13137			10: Timezone hours
13138			11: Timezone minutes
13139			*/
13140
13141			// Fill in empty matches
13142			for ($i = count($match); $i <= 3; $i++)
13143			{
13144				$match[$i] = '1';
13145			}
13146
13147			for ($i = count($match); $i <= 7; $i++)
13148			{
13149				$match[$i] = '0';
13150			}
13151
13152			// Numeric timezone
13153			if (isset($match[9]) && $match[9] !== '')
13154			{
13155				$timezone = $match[10] * 3600;
13156				$timezone += $match[11] * 60;
13157				if ($match[9] === '-')
13158				{
13159					$timezone = 0 - $timezone;
13160				}
13161			}
13162			else
13163			{
13164				$timezone = 0;
13165			}
13166
13167			// Convert the number of seconds to an integer, taking decimals into account
13168			$second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13169
13170			return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13171		}
13172		else
13173		{
13174			return false;
13175		}
13176	}
13177
13178	/**
13179	 * Remove RFC822 comments
13180	 *
13181	 * @access protected
13182	 * @param string $data Data to strip comments from
13183	 * @return string Comment stripped string
13184	 */
13185	function remove_rfc2822_comments($string)
13186	{
13187		$string = (string) $string;
13188		$position = 0;
13189		$length = strlen($string);
13190		$depth = 0;
13191
13192		$output = '';
13193
13194		while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13195		{
13196			$output .= substr($string, $position, $pos - $position);
13197			$position = $pos + 1;
13198			if ($string[$pos - 1] !== '\\')
13199			{
13200				$depth++;
13201				while ($depth && $position < $length)
13202				{
13203					$position += strcspn($string, '()', $position);
13204					if ($string[$position - 1] === '\\')
13205					{
13206						$position++;
13207						continue;
13208					}
13209					elseif (isset($string[$position]))
13210					{
13211						switch ($string[$position])
13212						{
13213							case '(':
13214								$depth++;
13215								break;
13216
13217							case ')':
13218								$depth--;
13219								break;
13220						}
13221						$position++;
13222					}
13223					else
13224					{
13225						break;
13226					}
13227				}
13228			}
13229			else
13230			{
13231				$output .= '(';
13232			}
13233		}
13234		$output .= substr($string, $position);
13235
13236		return $output;
13237	}
13238
13239	/**
13240	 * Parse RFC2822's date format
13241	 *
13242	 * @access protected
13243	 * @return int Timestamp
13244	 */
13245	function date_rfc2822($date)
13246	{
13247		static $pcre;
13248		if (!$pcre)
13249		{
13250			$wsp = '[\x09\x20]';
13251			$fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13252			$optional_fws = $fws . '?';
13253			$day_name = $this->day_pcre;
13254			$month = $this->month_pcre;
13255			$day = '([0-9]{1,2})';
13256			$hour = $minute = $second = '([0-9]{2})';
13257			$year = '([0-9]{2,4})';
13258			$num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13259			$character_zone = '([A-Z]{1,5})';
13260			$zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13261			$pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
13262		}
13263		if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13264		{
13265			/*
13266			Capturing subpatterns:
13267			1: Day name
13268			2: Day
13269			3: Month
13270			4: Year
13271			5: Hour
13272			6: Minute
13273			7: Second
13274			8: Timezone ±
13275			9: Timezone hours
13276			10: Timezone minutes
13277			11: Alphabetic timezone
13278			*/
13279
13280			// Find the month number
13281			$month = $this->month[strtolower($match[3])];
13282
13283			// Numeric timezone
13284			if ($match[8] !== '')
13285			{
13286				$timezone = $match[9] * 3600;
13287				$timezone += $match[10] * 60;
13288				if ($match[8] === '-')
13289				{
13290					$timezone = 0 - $timezone;
13291				}
13292			}
13293			// Character timezone
13294			elseif (isset($this->timezone[strtoupper($match[11])]))
13295			{
13296				$timezone = $this->timezone[strtoupper($match[11])];
13297			}
13298			// Assume everything else to be -0000
13299			else
13300			{
13301				$timezone = 0;
13302			}
13303
13304			// Deal with 2/3 digit years
13305			if ($match[4] < 50)
13306			{
13307				$match[4] += 2000;
13308			}
13309			elseif ($match[4] < 1000)
13310			{
13311				$match[4] += 1900;
13312			}
13313
13314			// Second is optional, if it is empty set it to zero
13315			if ($match[7] !== '')
13316			{
13317				$second = $match[7];
13318			}
13319			else
13320			{
13321				$second = 0;
13322			}
13323
13324			return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13325		}
13326		else
13327		{
13328			return false;
13329		}
13330	}
13331
13332	/**
13333	 * Parse RFC850's date format
13334	 *
13335	 * @access protected
13336	 * @return int Timestamp
13337	 */
13338	function date_rfc850($date)
13339	{
13340		static $pcre;
13341		if (!$pcre)
13342		{
13343			$space = '[\x09\x20]+';
13344			$day_name = $this->day_pcre;
13345			$month = $this->month_pcre;
13346			$day = '([0-9]{1,2})';
13347			$year = $hour = $minute = $second = '([0-9]{2})';
13348			$zone = '([A-Z]{1,5})';
13349			$pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13350		}
13351		if (preg_match($pcre, $date, $match))
13352		{
13353			/*
13354			Capturing subpatterns:
13355			1: Day name
13356			2: Day
13357			3: Month
13358			4: Year
13359			5: Hour
13360			6: Minute
13361			7: Second
13362			8: Timezone
13363			*/
13364
13365			// Month
13366			$month = $this->month[strtolower($match[3])];
13367
13368			// Character timezone
13369			if (isset($this->timezone[strtoupper($match[8])]))
13370			{
13371				$timezone = $this->timezone[strtoupper($match[8])];
13372			}
13373			// Assume everything else to be -0000
13374			else
13375			{
13376				$timezone = 0;
13377			}
13378
13379			// Deal with 2 digit year
13380			if ($match[4] < 50)
13381			{
13382				$match[4] += 2000;
13383			}
13384			else
13385			{
13386				$match[4] += 1900;
13387			}
13388
13389			return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13390		}
13391		else
13392		{
13393			return false;
13394		}
13395	}
13396
13397	/**
13398	 * Parse C99's asctime()'s date format
13399	 *
13400	 * @access protected
13401	 * @return int Timestamp
13402	 */
13403	function date_asctime($date)
13404	{
13405		static $pcre;
13406		if (!$pcre)
13407		{
13408			$space = '[\x09\x20]+';
13409			$wday_name = $this->day_pcre;
13410			$mon_name = $this->month_pcre;
13411			$day = '([0-9]{1,2})';
13412			$hour = $sec = $min = '([0-9]{2})';
13413			$year = '([0-9]{4})';
13414			$terminator = '\x0A?\x00?';
13415			$pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13416		}
13417		if (preg_match($pcre, $date, $match))
13418		{
13419			/*
13420			Capturing subpatterns:
13421			1: Day name
13422			2: Month
13423			3: Day
13424			4: Hour
13425			5: Minute
13426			6: Second
13427			7: Year
13428			*/
13429
13430			$month = $this->month[strtolower($match[2])];
13431			return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13432		}
13433		else
13434		{
13435			return false;
13436		}
13437	}
13438
13439	/**
13440	 * Parse dates using strtotime()
13441	 *
13442	 * @access protected
13443	 * @return int Timestamp
13444	 */
13445	function date_strtotime($date)
13446	{
13447		$strtotime = strtotime($date);
13448		if ($strtotime === -1 || $strtotime === false)
13449		{
13450			return false;
13451		}
13452		else
13453		{
13454			return $strtotime;
13455		}
13456	}
13457}
13458
13459/**
13460 * Content-type sniffing
13461 *
13462 * @package SimplePie
13463 */
13464class SimplePie_Content_Type_Sniffer
13465{
13466	/**
13467	 * File object
13468	 *
13469	 * @var SimplePie_File
13470	 * @access private
13471	 */
13472	var $file;
13473
13474	/**
13475	 * Create an instance of the class with the input file
13476	 *
13477	 * @access public
13478	 * @param SimplePie_Content_Type_Sniffer $file Input file
13479	 */
13480	function SimplePie_Content_Type_Sniffer($file)
13481	{
13482		$this->file = $file;
13483	}
13484
13485	/**
13486	 * Get the Content-Type of the specified file
13487	 *
13488	 * @access public
13489	 * @return string Actual Content-Type
13490	 */
13491	function get_type()
13492	{
13493		if (isset($this->file->headers['content-type']))
13494		{
13495			if (!isset($this->file->headers['content-encoding'])
13496				&& ($this->file->headers['content-type'] === 'text/plain'
13497					|| $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13498					|| $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13499			{
13500				return $this->text_or_binary();
13501			}
13502
13503			if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13504			{
13505				$official = substr($this->file->headers['content-type'], 0, $pos);
13506			}
13507			else
13508			{
13509				$official = $this->file->headers['content-type'];
13510			}
13511			$official = strtolower($official);
13512
13513			if ($official === 'unknown/unknown'
13514				|| $official === 'application/unknown')
13515			{
13516				return $this->unknown();
13517			}
13518			elseif (substr($official, -4) === '+xml'
13519				|| $official === 'text/xml'
13520				|| $official === 'application/xml')
13521			{
13522				return $official;
13523			}
13524			elseif (substr($official, 0, 6) === 'image/')
13525			{
13526				if ($return = $this->image())
13527				{
13528					return $return;
13529				}
13530				else
13531				{
13532					return $official;
13533				}
13534			}
13535			elseif ($official === 'text/html')
13536			{
13537				return $this->feed_or_html();
13538			}
13539			else
13540			{
13541				return $official;
13542			}
13543		}
13544		else
13545		{
13546			return $this->unknown();
13547		}
13548	}
13549
13550	/**
13551	 * Sniff text or binary
13552	 *
13553	 * @access private
13554	 * @return string Actual Content-Type
13555	 */
13556	function text_or_binary()
13557	{
13558		if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13559			|| substr($this->file->body, 0, 2) === "\xFF\xFE"
13560			|| substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13561			|| substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13562		{
13563			return 'text/plain';
13564		}
13565		elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13566		{
13567			return 'application/octect-stream';
13568		}
13569		else
13570		{
13571			return 'text/plain';
13572		}
13573	}
13574
13575	/**
13576	 * Sniff unknown
13577	 *
13578	 * @access private
13579	 * @return string Actual Content-Type
13580	 */
13581	function unknown()
13582	{
13583		$ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13584		if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13585			|| strtolower(substr($this->file->body, $ws, 5)) === '<html'
13586			|| strtolower(substr($this->file->body, $ws, 7)) === '<script')
13587		{
13588			return 'text/html';
13589		}
13590		elseif (substr($this->file->body, 0, 5) === '%PDF-')
13591		{
13592			return 'application/pdf';
13593		}
13594		elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13595		{
13596			return 'application/postscript';
13597		}
13598		elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13599			|| substr($this->file->body, 0, 6) === 'GIF89a')
13600		{
13601			return 'image/gif';
13602		}
13603		elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13604		{
13605			return 'image/png';
13606		}
13607		elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13608		{
13609			return 'image/jpeg';
13610		}
13611		elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13612		{
13613			return 'image/bmp';
13614		}
13615		else
13616		{
13617			return $this->text_or_binary();
13618		}
13619	}
13620
13621	/**
13622	 * Sniff images
13623	 *
13624	 * @access private
13625	 * @return string Actual Content-Type
13626	 */
13627	function image()
13628	{
13629		if (substr($this->file->body, 0, 6) === 'GIF87a'
13630			|| substr($this->file->body, 0, 6) === 'GIF89a')
13631		{
13632			return 'image/gif';
13633		}
13634		elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13635		{
13636			return 'image/png';
13637		}
13638		elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13639		{
13640			return 'image/jpeg';
13641		}
13642		elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13643		{
13644			return 'image/bmp';
13645		}
13646		else
13647		{
13648			return false;
13649		}
13650	}
13651
13652	/**
13653	 * Sniff HTML
13654	 *
13655	 * @access private
13656	 * @return string Actual Content-Type
13657	 */
13658	function feed_or_html()
13659	{
13660		$len = strlen($this->file->body);
13661		$pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13662
13663		while ($pos < $len)
13664		{
13665			switch ($this->file->body[$pos])
13666			{
13667				case "\x09":
13668				case "\x0A":
13669				case "\x0D":
13670				case "\x20":
13671					$pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13672					continue 2;
13673
13674				case '<':
13675					$pos++;
13676					break;
13677
13678				default:
13679					return 'text/html';
13680			}
13681
13682			if (substr($this->file->body, $pos, 3) === '!--')
13683			{
13684				$pos += 3;
13685				if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13686				{
13687					$pos += 3;
13688				}
13689				else
13690				{
13691					return 'text/html';
13692				}
13693			}
13694			elseif (substr($this->file->body, $pos, 1) === '!')
13695			{
13696				if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13697				{
13698					$pos++;
13699				}
13700				else
13701				{
13702					return 'text/html';
13703				}
13704			}
13705			elseif (substr($this->file->body, $pos, 1) === '?')
13706			{
13707				if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13708				{
13709					$pos += 2;
13710				}
13711				else
13712				{
13713					return 'text/html';
13714				}
13715			}
13716			elseif (substr($this->file->body, $pos, 3) === 'rss'
13717				|| substr($this->file->body, $pos, 7) === 'rdf:RDF')
13718			{
13719				return 'application/rss+xml';
13720			}
13721			elseif (substr($this->file->body, $pos, 4) === 'feed')
13722			{
13723				return 'application/atom+xml';
13724			}
13725			else
13726			{
13727				return 'text/html';
13728			}
13729		}
13730
13731		return 'text/html';
13732	}
13733}
13734
13735/**
13736 * Parses the XML Declaration
13737 *
13738 * @package SimplePie
13739 */
13740class SimplePie_XML_Declaration_Parser
13741{
13742	/**
13743	 * XML Version
13744	 *
13745	 * @access public
13746	 * @var string
13747	 */
13748	var $version = '1.0';
13749
13750	/**
13751	 * Encoding
13752	 *
13753	 * @access public
13754	 * @var string
13755	 */
13756	var $encoding = 'UTF-8';
13757
13758	/**
13759	 * Standalone
13760	 *
13761	 * @access public
13762	 * @var bool
13763	 */
13764	var $standalone = false;
13765
13766	/**
13767	 * Current state of the state machine
13768	 *
13769	 * @access private
13770	 * @var string
13771	 */
13772	var $state = 'before_version_name';
13773
13774	/**
13775	 * Input data
13776	 *
13777	 * @access private
13778	 * @var string
13779	 */
13780	var $data = '';
13781
13782	/**
13783	 * Input data length (to avoid calling strlen() everytime this is needed)
13784	 *
13785	 * @access private
13786	 * @var int
13787	 */
13788	var $data_length = 0;
13789
13790	/**
13791	 * Current position of the pointer
13792	 *
13793	 * @var int
13794	 * @access private
13795	 */
13796	var $position = 0;
13797
13798	/**
13799	 * Create an instance of the class with the input data
13800	 *
13801	 * @access public
13802	 * @param string $data Input data
13803	 */
13804	function SimplePie_XML_Declaration_Parser($data)
13805	{
13806		$this->data = $data;
13807		$this->data_length = strlen($this->data);
13808	}
13809
13810	/**
13811	 * Parse the input data
13812	 *
13813	 * @access public
13814	 * @return bool true on success, false on failure
13815	 */
13816	function parse()
13817	{
13818		while ($this->state && $this->state !== 'emit' && $this->has_data())
13819		{
13820			$state = $this->state;
13821			$this->$state();
13822		}
13823		$this->data = '';
13824		if ($this->state === 'emit')
13825		{
13826			return true;
13827		}
13828		else
13829		{
13830			$this->version = '';
13831			$this->encoding = '';
13832			$this->standalone = '';
13833			return false;
13834		}
13835	}
13836
13837	/**
13838	 * Check whether there is data beyond the pointer
13839	 *
13840	 * @access private
13841	 * @return bool true if there is further data, false if not
13842	 */
13843	function has_data()
13844	{
13845		return (bool) ($this->position < $this->data_length);
13846	}
13847
13848	/**
13849	 * Advance past any whitespace
13850	 *
13851	 * @return int Number of whitespace characters passed
13852	 */
13853	function skip_whitespace()
13854	{
13855		$whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13856		$this->position += $whitespace;
13857		return $whitespace;
13858	}
13859
13860	/**
13861	 * Read value
13862	 */
13863	function get_value()
13864	{
13865		$quote = substr($this->data, $this->position, 1);
13866		if ($quote === '"' || $quote === "'")
13867		{
13868			$this->position++;
13869			$len = strcspn($this->data, $quote, $this->position);
13870			if ($this->has_data())
13871			{
13872				$value = substr($this->data, $this->position, $len);
13873				$this->position += $len + 1;
13874				return $value;
13875			}
13876		}
13877		return false;
13878	}
13879
13880	function before_version_name()
13881	{
13882		if ($this->skip_whitespace())
13883		{
13884			$this->state = 'version_name';
13885		}
13886		else
13887		{
13888			$this->state = false;
13889		}
13890	}
13891
13892	function version_name()
13893	{
13894		if (substr($this->data, $this->position, 7) === 'version')
13895		{
13896			$this->position += 7;
13897			$this->skip_whitespace();
13898			$this->state = 'version_equals';
13899		}
13900		else
13901		{
13902			$this->state = false;
13903		}
13904	}
13905
13906	function version_equals()
13907	{
13908		if (substr($this->data, $this->position, 1) === '=')
13909		{
13910			$this->position++;
13911			$this->skip_whitespace();
13912			$this->state = 'version_value';
13913		}
13914		else
13915		{
13916			$this->state = false;
13917		}
13918	}
13919
13920	function version_value()
13921	{
13922		if ($this->version = $this->get_value())
13923		{
13924			$this->skip_whitespace();
13925			if ($this->has_data())
13926			{
13927				$this->state = 'encoding_name';
13928			}
13929			else
13930			{
13931				$this->state = 'emit';
13932			}
13933		}
13934		else
13935		{
13936			$this->state = 'standalone_name';
13937		}
13938	}
13939
13940	function encoding_name()
13941	{
13942		if (substr($this->data, $this->position, 8) === 'encoding')
13943		{
13944			$this->position += 8;
13945			$this->skip_whitespace();
13946			$this->state = 'encoding_equals';
13947		}
13948		else
13949		{
13950			$this->state = false;
13951		}
13952	}
13953
13954	function encoding_equals()
13955	{
13956		if (substr($this->data, $this->position, 1) === '=')
13957		{
13958			$this->position++;
13959			$this->skip_whitespace();
13960			$this->state = 'encoding_value';
13961		}
13962		else
13963		{
13964			$this->state = false;
13965		}
13966	}
13967
13968	function encoding_value()
13969	{
13970		if ($this->encoding = $this->get_value())
13971		{
13972			$this->skip_whitespace();
13973			if ($this->has_data())
13974			{
13975				$this->state = 'standalone_name';
13976			}
13977			else
13978			{
13979				$this->state = 'emit';
13980			}
13981		}
13982		else
13983		{
13984			$this->state = false;
13985		}
13986	}
13987
13988	function standalone_name()
13989	{
13990		if (substr($this->data, $this->position, 10) === 'standalone')
13991		{
13992			$this->position += 10;
13993			$this->skip_whitespace();
13994			$this->state = 'standalone_equals';
13995		}
13996		else
13997		{
13998			$this->state = false;
13999		}
14000	}
14001
14002	function standalone_equals()
14003	{
14004		if (substr($this->data, $this->position, 1) === '=')
14005		{
14006			$this->position++;
14007			$this->skip_whitespace();
14008			$this->state = 'standalone_value';
14009		}
14010		else
14011		{
14012			$this->state = false;
14013		}
14014	}
14015
14016	function standalone_value()
14017	{
14018		if ($standalone = $this->get_value())
14019		{
14020			switch ($standalone)
14021			{
14022				case 'yes':
14023					$this->standalone = true;
14024					break;
14025
14026				case 'no':
14027					$this->standalone = false;
14028					break;
14029
14030				default:
14031					$this->state = false;
14032					return;
14033			}
14034
14035			$this->skip_whitespace();
14036			if ($this->has_data())
14037			{
14038				$this->state = false;
14039			}
14040			else
14041			{
14042				$this->state = 'emit';
14043			}
14044		}
14045		else
14046		{
14047			$this->state = false;
14048		}
14049	}
14050}
14051
14052class SimplePie_Locator
14053{
14054	var $useragent;
14055	var $timeout;
14056	var $file;
14057	var $local = array();
14058	var $elsewhere = array();
14059	var $file_class = 'SimplePie_File';
14060	var $cached_entities = array();
14061	var $http_base;
14062	var $base;
14063	var $base_location = 0;
14064	var $checked_feeds = 0;
14065	var $max_checked_feeds = 10;
14066	var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14067
14068	function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14069	{
14070		$this->file =& $file;
14071		$this->file_class = $file_class;
14072		$this->useragent = $useragent;
14073		$this->timeout = $timeout;
14074		$this->max_checked_feeds = $max_checked_feeds;
14075		$this->content_type_sniffer_class = $content_type_sniffer_class;
14076	}
14077
14078	function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14079	{
14080		if ($this->is_feed($this->file))
14081		{
14082			return $this->file;
14083		}
14084
14085		if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14086		{
14087			$sniffer =& new $this->content_type_sniffer_class($this->file);
14088			if ($sniffer->get_type() !== 'text/html')
14089			{
14090				return null;
14091			}
14092		}
14093
14094		if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14095		{
14096			$this->get_base();
14097		}
14098
14099		if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14100		{
14101			return $working[0];
14102		}
14103
14104		if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14105		{
14106			if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14107			{
14108				return $working;
14109			}
14110
14111			if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14112			{
14113				return $working;
14114			}
14115
14116			if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14117			{
14118				return $working;
14119			}
14120
14121			if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14122			{
14123				return $working;
14124			}
14125		}
14126		return null;
14127	}
14128
14129	function is_feed(&$file)
14130	{
14131		if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14132		{
14133			$sniffer =& new $this->content_type_sniffer_class($file);
14134			$sniffed = $sniffer->get_type();
14135			if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14136			{
14137				return true;
14138			}
14139			else
14140			{
14141				return false;
14142			}
14143		}
14144		elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14145		{
14146			return true;
14147		}
14148		else
14149		{
14150			return false;
14151		}
14152	}
14153
14154	function get_base()
14155	{
14156		$this->http_base = $this->file->url;
14157		$this->base = $this->http_base;
14158		$elements = SimplePie_Misc::get_element('base', $this->file->body);
14159		foreach ($elements as $element)
14160		{
14161			if ($element['attribs']['href']['data'] !== '')
14162			{
14163				$this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14164				$this->base_location = $element['offset'];
14165				break;
14166			}
14167		}
14168	}
14169
14170	function autodiscovery()
14171	{
14172		$links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
14173		$done = array();
14174		$feeds = array();
14175		foreach ($links as $link)
14176		{
14177			if ($this->checked_feeds === $this->max_checked_feeds)
14178			{
14179				break;
14180			}
14181			if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14182			{
14183				$rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14184
14185				if ($this->base_location < $link['offset'])
14186				{
14187					$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14188				}
14189				else
14190				{
14191					$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14192				}
14193
14194				if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
14195				{
14196					$this->checked_feeds++;
14197					$feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14198					if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14199					{
14200						$feeds[$href] = $feed;
14201					}
14202				}
14203				$done[] = $href;
14204			}
14205		}
14206
14207		if (!empty($feeds))
14208		{
14209			return array_values($feeds);
14210		}
14211		else {
14212			return null;
14213		}
14214	}
14215
14216	function get_links()
14217	{
14218		$links = SimplePie_Misc::get_element('a', $this->file->body);
14219		foreach ($links as $link)
14220		{
14221			if (isset($link['attribs']['href']['data']))
14222			{
14223				$href = trim($link['attribs']['href']['data']);
14224				$parsed = SimplePie_Misc::parse_url($href);
14225				if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14226				{
14227					if ($this->base_location < $link['offset'])
14228					{
14229						$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14230					}
14231					else
14232					{
14233						$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14234					}
14235
14236					$current = SimplePie_Misc::parse_url($this->file->url);
14237
14238					if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14239					{
14240						$this->local[] = $href;
14241					}
14242					else
14243					{
14244						$this->elsewhere[] = $href;
14245					}
14246				}
14247			}
14248		}
14249		$this->local = array_unique($this->local);
14250		$this->elsewhere = array_unique($this->elsewhere);
14251		if (!empty($this->local) || !empty($this->elsewhere))
14252		{
14253			return true;
14254		}
14255		return null;
14256	}
14257
14258	function extension(&$array)
14259	{
14260		foreach ($array as $key => $value)
14261		{
14262			if ($this->checked_feeds === $this->max_checked_feeds)
14263			{
14264				break;
14265			}
14266			if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14267			{
14268				$this->checked_feeds++;
14269				$feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14270				if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14271				{
14272					return $feed;
14273				}
14274				else
14275				{
14276					unset($array[$key]);
14277				}
14278			}
14279		}
14280		return null;
14281	}
14282
14283	function body(&$array)
14284	{
14285		foreach ($array as $key => $value)
14286		{
14287			if ($this->checked_feeds === $this->max_checked_feeds)
14288			{
14289				break;
14290			}
14291			if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14292			{
14293				$this->checked_feeds++;
14294				$feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14295				if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14296				{
14297					return $feed;
14298				}
14299				else
14300				{
14301					unset($array[$key]);
14302				}
14303			}
14304		}
14305		return null;
14306	}
14307}
14308
14309class SimplePie_Parser
14310{
14311	var $error_code;
14312	var $error_string;
14313	var $current_line;
14314	var $current_column;
14315	var $current_byte;
14316	var $separator = ' ';
14317	var $namespace = array('');
14318	var $element = array('');
14319	var $xml_base = array('');
14320	var $xml_base_explicit = array(false);
14321	var $xml_lang = array('');
14322	var $data = array();
14323	var $datas = array(array());
14324	var $current_xhtml_construct = -1;
14325	var $encoding;
14326
14327	function parse(&$data, $encoding)
14328	{
14329		// Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14330		if (strtoupper($encoding) === 'US-ASCII')
14331		{
14332			$this->encoding = 'UTF-8';
14333		}
14334		else
14335		{
14336			$this->encoding = $encoding;
14337		}
14338
14339		// Strip BOM:
14340		// UTF-32 Big Endian BOM
14341		if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14342		{
14343			$data = substr($data, 4);
14344		}
14345		// UTF-32 Little Endian BOM
14346		elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14347		{
14348			$data = substr($data, 4);
14349		}
14350		// UTF-16 Big Endian BOM
14351		elseif (substr($data, 0, 2) === "\xFE\xFF")
14352		{
14353			$data = substr($data, 2);
14354		}
14355		// UTF-16 Little Endian BOM
14356		elseif (substr($data, 0, 2) === "\xFF\xFE")
14357		{
14358			$data = substr($data, 2);
14359		}
14360		// UTF-8 BOM
14361		elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14362		{
14363			$data = substr($data, 3);
14364		}
14365
14366		if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14367		{
14368			$declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14369			if ($declaration->parse())
14370			{
14371				$data = substr($data, $pos + 2);
14372				$data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14373			}
14374			else
14375			{
14376				$this->error_string = 'SimplePie bug! Please report this!';
14377				return false;
14378			}
14379		}
14380
14381		$return = true;
14382
14383		static $xml_is_sane = null;
14384		if ($xml_is_sane === null)
14385		{
14386			$parser_check = xml_parser_create();
14387			xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14388			xml_parser_free($parser_check);
14389			$xml_is_sane = isset($values[0]['value']);
14390		}
14391
14392		// Create the parser
14393		if ($xml_is_sane)
14394		{
14395			$xml = xml_parser_create_ns($this->encoding, $this->separator);
14396			xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14397			xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14398			xml_set_object($xml, $this);
14399			xml_set_character_data_handler($xml, 'cdata');
14400			xml_set_element_handler($xml, 'tag_open', 'tag_close');
14401
14402			// Parse!
14403			if (!xml_parse($xml, $data, true))
14404			{
14405				$this->error_code = xml_get_error_code($xml);
14406				$this->error_string = xml_error_string($this->error_code);
14407				$return = false;
14408			}
14409			$this->current_line = xml_get_current_line_number($xml);
14410			$this->current_column = xml_get_current_column_number($xml);
14411			$this->current_byte = xml_get_current_byte_index($xml);
14412			xml_parser_free($xml);
14413			return $return;
14414		}
14415		else
14416		{
14417			libxml_clear_errors();
14418			$xml =& new XMLReader();
14419			$xml->xml($data);
14420			while (@$xml->read())
14421			{
14422				switch ($xml->nodeType)
14423				{
14424
14425					case constant('XMLReader::END_ELEMENT'):
14426						if ($xml->namespaceURI !== '')
14427						{
14428							$tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14429						}
14430						else
14431						{
14432							$tagName = $xml->localName;
14433						}
14434						$this->tag_close(null, $tagName);
14435						break;
14436					case constant('XMLReader::ELEMENT'):
14437						$empty = $xml->isEmptyElement;
14438						if ($xml->namespaceURI !== '')
14439						{
14440							$tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14441						}
14442						else
14443						{
14444							$tagName = $xml->localName;
14445						}
14446						$attributes = array();
14447						while ($xml->moveToNextAttribute())
14448						{
14449							if ($xml->namespaceURI !== '')
14450							{
14451								$attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14452							}
14453							else
14454							{
14455								$attrName = $xml->localName;
14456							}
14457							$attributes[$attrName] = $xml->value;
14458						}
14459						$this->tag_open(null, $tagName, $attributes);
14460						if ($empty)
14461						{
14462							$this->tag_close(null, $tagName);
14463						}
14464						break;
14465					case constant('XMLReader::TEXT'):
14466
14467					case constant('XMLReader::CDATA'):
14468						$this->cdata(null, $xml->value);
14469						break;
14470				}
14471			}
14472			if ($error = libxml_get_last_error())
14473			{
14474				$this->error_code = $error->code;
14475				$this->error_string = $error->message;
14476				$this->current_line = $error->line;
14477				$this->current_column = $error->column;
14478				return false;
14479			}
14480			else
14481			{
14482				return true;
14483			}
14484		}
14485	}
14486
14487	function get_error_code()
14488	{
14489		return $this->error_code;
14490	}
14491
14492	function get_error_string()
14493	{
14494		return $this->error_string;
14495	}
14496
14497	function get_current_line()
14498	{
14499		return $this->current_line;
14500	}
14501
14502	function get_current_column()
14503	{
14504		return $this->current_column;
14505	}
14506
14507	function get_current_byte()
14508	{
14509		return $this->current_byte;
14510	}
14511
14512	function get_data()
14513	{
14514		return $this->data;
14515	}
14516
14517	function tag_open($parser, $tag, $attributes)
14518	{
14519		list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14520
14521		$attribs = array();
14522		foreach ($attributes as $name => $value)
14523		{
14524			list($attrib_namespace, $attribute) = $this->split_ns($name);
14525			$attribs[$attrib_namespace][$attribute] = $value;
14526		}
14527
14528		if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14529		{
14530			$this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14531			$this->xml_base_explicit[] = true;
14532		}
14533		else
14534		{
14535			$this->xml_base[] = end($this->xml_base);
14536			$this->xml_base_explicit[] = end($this->xml_base_explicit);
14537		}
14538
14539		if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14540		{
14541			$this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14542		}
14543		else
14544		{
14545			$this->xml_lang[] = end($this->xml_lang);
14546		}
14547
14548		if ($this->current_xhtml_construct >= 0)
14549		{
14550			$this->current_xhtml_construct++;
14551			if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14552			{
14553				$this->data['data'] .= '<' . end($this->element);
14554				if (isset($attribs['']))
14555				{
14556					foreach ($attribs[''] as $name => $value)
14557					{
14558						$this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14559					}
14560				}
14561				$this->data['data'] .= '>';
14562			}
14563		}
14564		else
14565		{
14566			$this->datas[] =& $this->data;
14567			$this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14568			$this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
14569			if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
14570			|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml'))
14571			{
14572				$this->current_xhtml_construct = 0;
14573			}
14574		}
14575	}
14576
14577	function cdata($parser, $cdata)
14578	{
14579		if ($this->current_xhtml_construct >= 0)
14580		{
14581			$this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14582		}
14583		else
14584		{
14585			$this->data['data'] .= $cdata;
14586		}
14587	}
14588
14589	function tag_close($parser, $tag)
14590	{
14591		if ($this->current_xhtml_construct >= 0)
14592		{
14593			$this->current_xhtml_construct--;
14594			if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
14595			{
14596				$this->data['data'] .= '</' . end($this->element) . '>';
14597			}
14598		}
14599		if ($this->current_xhtml_construct === -1)
14600		{
14601			$this->data =& $this->datas[count($this->datas) - 1];
14602			array_pop($this->datas);
14603		}
14604
14605		array_pop($this->element);
14606		array_pop($this->namespace);
14607		array_pop($this->xml_base);
14608		array_pop($this->xml_base_explicit);
14609		array_pop($this->xml_lang);
14610	}
14611
14612	function split_ns($string)
14613	{
14614		static $cache = array();
14615		if (!isset($cache[$string]))
14616		{
14617			if ($pos = strpos($string, $this->separator))
14618			{
14619				static $separator_length;
14620				if (!$separator_length)
14621				{
14622					$separator_length = strlen($this->separator);
14623				}
14624				$namespace = substr($string, 0, $pos);
14625				$local_name = substr($string, $pos + $separator_length);
14626				if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14627				{
14628					$namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14629				}
14630
14631				// Normalize the Media RSS namespaces
14632				if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14633				{
14634					$namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14635				}
14636				$cache[$string] = array($namespace, $local_name);
14637			}
14638			else
14639			{
14640				$cache[$string] = array('', $string);
14641			}
14642		}
14643		return $cache[$string];
14644	}
14645}
14646
14647/**
14648 * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
14649 */
14650class SimplePie_Sanitize
14651{
14652	// Private vars
14653	var $base;
14654
14655	// Options
14656	var $remove_div = true;
14657	var $image_handler = '';
14658	var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14659	var $encode_instead_of_strip = false;
14660	var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14661	var $strip_comments = false;
14662	var $output_encoding = 'UTF-8';
14663	var $enable_cache = true;
14664	var $cache_location = './cache';
14665	var $cache_name_function = 'md5';
14666	var $cache_class = 'SimplePie_Cache';
14667	var $file_class = 'SimplePie_File';
14668	var $timeout = 10;
14669	var $useragent = '';
14670	var $force_fsockopen = false;
14671
14672	var $replace_url_attributes = array(
14673		'a' => 'href',
14674		'area' => 'href',
14675		'blockquote' => 'cite',
14676		'del' => 'cite',
14677		'form' => 'action',
14678		'img' => array('longdesc', 'src'),
14679		'input' => 'src',
14680		'ins' => 'cite',
14681		'q' => 'cite'
14682	);
14683
14684	function remove_div($enable = true)
14685	{
14686		$this->remove_div = (bool) $enable;
14687	}
14688
14689	function set_image_handler($page = false)
14690	{
14691		if ($page)
14692		{
14693			$this->image_handler = (string) $page;
14694		}
14695		else
14696		{
14697			$this->image_handler = false;
14698		}
14699	}
14700
14701	function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14702	{
14703		if (isset($enable_cache))
14704		{
14705			$this->enable_cache = (bool) $enable_cache;
14706		}
14707
14708		if ($cache_location)
14709		{
14710			$this->cache_location = (string) $cache_location;
14711		}
14712
14713		if ($cache_name_function)
14714		{
14715			$this->cache_name_function = (string) $cache_name_function;
14716		}
14717
14718		if ($cache_class)
14719		{
14720			$this->cache_class = (string) $cache_class;
14721		}
14722	}
14723
14724	function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14725	{
14726		if ($file_class)
14727		{
14728			$this->file_class = (string) $file_class;
14729		}
14730
14731		if ($timeout)
14732		{
14733			$this->timeout = (string) $timeout;
14734		}
14735
14736		if ($useragent)
14737		{
14738			$this->useragent = (string) $useragent;
14739		}
14740
14741		if ($force_fsockopen)
14742		{
14743			$this->force_fsockopen = (string) $force_fsockopen;
14744		}
14745	}
14746
14747	function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14748	{
14749		if ($tags)
14750		{
14751			if (is_array($tags))
14752			{
14753				$this->strip_htmltags = $tags;
14754			}
14755			else
14756			{
14757				$this->strip_htmltags = explode(',', $tags);
14758			}
14759		}
14760		else
14761		{
14762			$this->strip_htmltags = false;
14763		}
14764	}
14765
14766	function encode_instead_of_strip($encode = false)
14767	{
14768		$this->encode_instead_of_strip = (bool) $encode;
14769	}
14770
14771	function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14772	{
14773		if ($attribs)
14774		{
14775			if (is_array($attribs))
14776			{
14777				$this->strip_attributes = $attribs;
14778			}
14779			else
14780			{
14781				$this->strip_attributes = explode(',', $attribs);
14782			}
14783		}
14784		else
14785		{
14786			$this->strip_attributes = false;
14787		}
14788	}
14789
14790	function strip_comments($strip = false)
14791	{
14792		$this->strip_comments = (bool) $strip;
14793	}
14794
14795	function set_output_encoding($encoding = 'UTF-8')
14796	{
14797		$this->output_encoding = (string) $encoding;
14798	}
14799
14800	/**
14801	 * Set element/attribute key/value pairs of HTML attributes
14802	 * containing URLs that need to be resolved relative to the feed
14803	 *
14804	 * @access public
14805	 * @since 1.0
14806	 * @param array $element_attribute Element/attribute key/value pairs
14807	 */
14808	function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
14809	{
14810		$this->replace_url_attributes = (array) $element_attribute;
14811	}
14812
14813	function sanitize($data, $type, $base = '')
14814	{
14815		$data = trim($data);
14816		if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14817		{
14818			if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14819			{
14820				if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
14821				{
14822					$type |= SIMPLEPIE_CONSTRUCT_HTML;
14823				}
14824				else
14825				{
14826					$type |= SIMPLEPIE_CONSTRUCT_TEXT;
14827				}
14828			}
14829
14830			if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14831			{
14832				$data = base64_decode($data);
14833			}
14834
14835			if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14836			{
14837				if ($this->remove_div)
14838				{
14839					$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14840					$data = preg_replace('/<\/div>$/', '', $data);
14841				}
14842				else
14843				{
14844					$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14845				}
14846			}
14847
14848			if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14849			{
14850				// Strip comments
14851				if ($this->strip_comments)
14852				{
14853					$data = SimplePie_Misc::strip_comments($data);
14854				}
14855
14856				// Strip out HTML tags and attributes that might cause various security problems.
14857				// Based on recommendations by Mark Pilgrim at:
14858				// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14859				if ($this->strip_htmltags)
14860				{
14861					foreach ($this->strip_htmltags as $tag)
14862					{
14863						$pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14864						while (preg_match($pcre, $data))
14865						{
14866							$data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14867						}
14868					}
14869				}
14870
14871				if ($this->strip_attributes)
14872				{
14873					foreach ($this->strip_attributes as $attrib)
14874					{
14875						$data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
14876					}
14877				}
14878
14879				// Replace relative URLs
14880				$this->base = $base;
14881				foreach ($this->replace_url_attributes as $element => $attributes)
14882				{
14883					$data = $this->replace_urls($data, $element, $attributes);
14884				}
14885
14886				// If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14887				if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14888				{
14889					$images = SimplePie_Misc::get_element('img', $data);
14890					foreach ($images as $img)
14891					{
14892						if (isset($img['attribs']['src']['data']))
14893						{
14894							$image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14895							$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14896
14897							if ($cache->load())
14898							{
14899								$img['attribs']['src']['data'] = $this->image_handler . $image_url;
14900								$data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14901							}
14902							else
14903							{
14904								$file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14905								$headers = $file->headers;
14906
14907								if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14908								{
14909									if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14910									{
14911										$img['attribs']['src']['data'] = $this->image_handler . $image_url;
14912										$data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14913									}
14914									else
14915									{
14916										trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
14917									}
14918								}
14919							}
14920						}
14921					}
14922				}
14923
14924				// Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14925				$data = trim($data);
14926			}
14927
14928			if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14929			{
14930				$data = SimplePie_Misc::absolutize_url($data, $base);
14931			}
14932
14933			if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14934			{
14935				$data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14936			}
14937
14938			if ($this->output_encoding !== 'UTF-8')
14939			{
14940				$data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14941			}
14942		}
14943		return $data;
14944	}
14945
14946	function replace_urls($data, $tag, $attributes)
14947	{
14948		if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14949		{
14950			$elements = SimplePie_Misc::get_element($tag, $data);
14951			foreach ($elements as $element)
14952			{
14953				if (is_array($attributes))
14954				{
14955					foreach ($attributes as $attribute)
14956					{
14957						if (isset($element['attribs'][$attribute]['data']))
14958						{
14959							$element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14960							$new_element = SimplePie_Misc::element_implode($element);
14961							$data = str_replace($element['full'], $new_element, $data);
14962							$element['full'] = $new_element;
14963						}
14964					}
14965				}
14966				elseif (isset($element['attribs'][$attributes]['data']))
14967				{
14968					$element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14969					$data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14970				}
14971			}
14972		}
14973		return $data;
14974	}
14975
14976	function do_strip_htmltags($match)
14977	{
14978		if ($this->encode_instead_of_strip)
14979		{
14980			if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14981			{
14982				$match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
14983				$match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
14984				return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
14985			}
14986			else
14987			{
14988				return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
14989			}
14990		}
14991		elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14992		{
14993			return $match[4];
14994		}
14995		else
14996		{
14997			return '';
14998		}
14999	}
15000}
15001endif;
15002?>
15003