]> git.mxchange.org Git - friendica.git/blob - simplepie/simplepie.inc
sorting out visitor sessions
[friendica.git] / simplepie / simplepie.inc
1 <?php
2 /**
3  * SimplePie
4  *
5  * A PHP-Based RSS and Atom Feed Framework.
6  * Takes the hard work out of managing a complete RSS/Atom solution.
7  *
8  * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification, are
12  * permitted provided that the following conditions are met:
13  *
14  *      * Redistributions of source code must retain the above copyright notice, this list of
15  *        conditions and the following disclaimer.
16  *
17  *      * Redistributions in binary form must reproduce the above copyright notice, this list
18  *        of conditions and the following disclaimer in the documentation and/or other materials
19  *        provided with the distribution.
20  *
21  *      * Neither the name of the SimplePie Team nor the names of its contributors may be used
22  *        to endorse or promote products derived from this software without specific prior
23  *        written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * @package SimplePie
36  * @version 1.2.1-dev
37  * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
38  * @author Ryan Parman
39  * @author Geoffrey Sneddon
40  * @link http://simplepie.org/ SimplePie
41  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43  * @todo phpDoc comments
44  */
45
46 /**
47  * SimplePie Name
48  */
49 define('SIMPLEPIE_NAME', 'SimplePie');
50
51 /**
52  * SimplePie Version
53  */
54 define('SIMPLEPIE_VERSION', '1.2.1-dev');
55
56 /**
57  * SimplePie Build
58  * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
59  */
60 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
61
62 /**
63  * SimplePie Website URL
64  */
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
66
67 /**
68  * SimplePie Useragent
69  * @see SimplePie::set_useragent()
70  */
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
72
73 /**
74  * SimplePie Linkback
75  */
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
77
78 /**
79  * No Autodiscovery
80  * @see SimplePie::set_autodiscovery_level()
81  */
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
83
84 /**
85  * Feed Link Element Autodiscovery
86  * @see SimplePie::set_autodiscovery_level()
87  */
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
89
90 /**
91  * Local Feed Extension Autodiscovery
92  * @see SimplePie::set_autodiscovery_level()
93  */
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
95
96 /**
97  * Local Feed Body Autodiscovery
98  * @see SimplePie::set_autodiscovery_level()
99  */
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
101
102 /**
103  * Remote Feed Extension Autodiscovery
104  * @see SimplePie::set_autodiscovery_level()
105  */
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
107
108 /**
109  * Remote Feed Body Autodiscovery
110  * @see SimplePie::set_autodiscovery_level()
111  */
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
113
114 /**
115  * All Feed Autodiscovery
116  * @see SimplePie::set_autodiscovery_level()
117  */
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
119
120 /**
121  * No known feed type
122  */
123 define('SIMPLEPIE_TYPE_NONE', 0);
124
125 /**
126  * RSS 0.90
127  */
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
129
130 /**
131  * RSS 0.91 (Netscape)
132  */
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
134
135 /**
136  * RSS 0.91 (Userland)
137  */
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
139
140 /**
141  * RSS 0.91 (both Netscape and Userland)
142  */
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
144
145 /**
146  * RSS 0.92
147  */
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
149
150 /**
151  * RSS 0.93
152  */
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
154
155 /**
156  * RSS 0.94
157  */
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
159
160 /**
161  * RSS 1.0
162  */
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
164
165 /**
166  * RSS 2.0
167  */
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
169
170 /**
171  * RDF-based RSS
172  */
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
174
175 /**
176  * Non-RDF-based RSS (truly intended as syndication format)
177  */
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
179
180 /**
181  * All RSS
182  */
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
184
185 /**
186  * Atom 0.3
187  */
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
189
190 /**
191  * Atom 1.0
192  */
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
194
195 /**
196  * All Atom
197  */
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
199
200 /**
201  * All feed types
202  */
203 define('SIMPLEPIE_TYPE_ALL', 1023);
204
205 /**
206  * No construct
207  */
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
209
210 /**
211  * Text construct
212  */
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
214
215 /**
216  * HTML construct
217  */
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
219
220 /**
221  * XHTML construct
222  */
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
224
225 /**
226  * base64-encoded construct
227  */
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
229
230 /**
231  * IRI construct
232  */
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
234
235 /**
236  * A construct that might be HTML
237  */
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
239
240 /**
241  * All constructs
242  */
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
244
245 /**
246  * Don't change case
247  */
248 define('SIMPLEPIE_SAME_CASE', 1);
249
250 /**
251  * Change to lowercase
252  */
253 define('SIMPLEPIE_LOWERCASE', 2);
254
255 /**
256  * Change to uppercase
257  */
258 define('SIMPLEPIE_UPPERCASE', 4);
259
260 /**
261  * PCRE for HTML attributes
262  */
263 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
264
265 /**
266  * PCRE for XML attributes
267  */
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
269
270 /**
271  * XML Namespace
272  */
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
274
275 /**
276  * Atom 1.0 Namespace
277  */
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
279
280 /**
281  * Atom 0.3 Namespace
282  */
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
284
285 /**
286  * RDF Namespace
287  */
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
289
290 /**
291  * RSS 0.90 Namespace
292  */
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
294
295 /**
296  * RSS 1.0 Namespace
297  */
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
299
300 /**
301  * RSS 1.0 Content Module Namespace
302  */
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
304
305 /**
306  * RSS 2.0 Namespace
307  * (Stupid, I know, but I'm certain it will confuse people less with support.)
308  */
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
310
311 /**
312  * DC 1.0 Namespace
313  */
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
315
316 /**
317  * DC 1.1 Namespace
318  */
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
320
321 /**
322  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
323  */
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
325
326 /**
327  * GeoRSS Namespace
328  */
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
330
331 /**
332  * Media RSS Namespace
333  */
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
335
336 /**
337  * Wrong Media RSS Namespace
338  */
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
340
341 /**
342  * iTunes RSS Namespace
343  */
344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
345
346 /**
347  * XHTML Namespace
348  */
349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
350
351 /**
352  * IANA Link Relations Registry
353  */
354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
355
356 /**
357  * Whether we're running on PHP5
358  */
359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
360
361 /**
362  * No file source
363  */
364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
365
366 /**
367  * Remote file source
368  */
369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
370
371 /**
372  * Local file source
373  */
374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
375
376 /**
377  * fsockopen() file source
378  */
379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
380
381 /**
382  * cURL file source
383  */
384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
385
386 /**
387  * file_get_contents() file source
388  */
389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
390
391 /**
392  * SimplePie
393  *
394  * @package SimplePie
395  */
396 class SimplePie
397 {
398         /**
399          * @var array Raw data
400          * @access private
401          */
402         var $data = array();
403
404         /**
405          * @var mixed Error string
406          * @access private
407          */
408         var $error;
409
410         /**
411          * @var object Instance of SimplePie_Sanitize (or other class)
412          * @see SimplePie::set_sanitize_class()
413          * @access private
414          */
415         var $sanitize;
416
417         /**
418          * @var string SimplePie Useragent
419          * @see SimplePie::set_useragent()
420          * @access private
421          */
422         var $useragent = SIMPLEPIE_USERAGENT;
423
424         /**
425          * @var string Feed URL
426          * @see SimplePie::set_feed_url()
427          * @access private
428          */
429         var $feed_url;
430
431         /**
432          * @var object Instance of SimplePie_File to use as a feed
433          * @see SimplePie::set_file()
434          * @access private
435          */
436         var $file;
437
438         /**
439          * @var string Raw feed data
440          * @see SimplePie::set_raw_data()
441          * @access private
442          */
443         var $raw_data;
444
445         /**
446          * @var int Timeout for fetching remote files
447          * @see SimplePie::set_timeout()
448          * @access private
449          */
450         var $timeout = 10;
451
452         /**
453          * @var bool Forces fsockopen() to be used for remote files instead
454          * of cURL, even if a new enough version is installed
455          * @see SimplePie::force_fsockopen()
456          * @access private
457          */
458         var $force_fsockopen = false;
459
460         /**
461          * @var bool Force the given data/URL to be treated as a feed no matter what
462          * it appears like
463          * @see SimplePie::force_feed()
464          * @access private
465          */
466         var $force_feed = false;
467
468         /**
469          * @var bool Enable/Disable XML dump
470          * @see SimplePie::enable_xml_dump()
471          * @access private
472          */
473         var $xml_dump = false;
474
475         /**
476          * @var bool Enable/Disable Caching
477          * @see SimplePie::enable_cache()
478          * @access private
479          */
480         var $cache = true;
481
482         /**
483          * @var int Cache duration (in seconds)
484          * @see SimplePie::set_cache_duration()
485          * @access private
486          */
487         var $cache_duration = 3600;
488
489         /**
490          * @var int Auto-discovery cache duration (in seconds)
491          * @see SimplePie::set_autodiscovery_cache_duration()
492          * @access private
493          */
494         var $autodiscovery_cache_duration = 604800; // 7 Days.
495
496         /**
497          * @var string Cache location (relative to executing script)
498          * @see SimplePie::set_cache_location()
499          * @access private
500          */
501         var $cache_location = './cache';
502
503         /**
504          * @var string Function that creates the cache filename
505          * @see SimplePie::set_cache_name_function()
506          * @access private
507          */
508         var $cache_name_function = 'md5';
509
510         /**
511          * @var bool Reorder feed by date descending
512          * @see SimplePie::enable_order_by_date()
513          * @access private
514          */
515         var $order_by_date = true;
516
517         /**
518          * @var mixed Force input encoding to be set to the follow value
519          * (false, or anything type-cast to false, disables this feature)
520          * @see SimplePie::set_input_encoding()
521          * @access private
522          */
523         var $input_encoding = false;
524
525         /**
526          * @var int Feed Autodiscovery Level
527          * @see SimplePie::set_autodiscovery_level()
528          * @access private
529          */
530         var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
531
532         /**
533          * @var string Class used for caching feeds
534          * @see SimplePie::set_cache_class()
535          * @access private
536          */
537         var $cache_class = 'SimplePie_Cache';
538
539         /**
540          * @var string Class used for locating feeds
541          * @see SimplePie::set_locator_class()
542          * @access private
543          */
544         var $locator_class = 'SimplePie_Locator';
545
546         /**
547          * @var string Class used for parsing feeds
548          * @see SimplePie::set_parser_class()
549          * @access private
550          */
551         var $parser_class = 'SimplePie_Parser';
552
553         /**
554          * @var string Class used for fetching feeds
555          * @see SimplePie::set_file_class()
556          * @access private
557          */
558         var $file_class = 'SimplePie_File';
559
560         /**
561          * @var string Class used for items
562          * @see SimplePie::set_item_class()
563          * @access private
564          */
565         var $item_class = 'SimplePie_Item';
566
567         /**
568          * @var string Class used for authors
569          * @see SimplePie::set_author_class()
570          * @access private
571          */
572         var $author_class = 'SimplePie_Author';
573
574         /**
575          * @var string Class used for categories
576          * @see SimplePie::set_category_class()
577          * @access private
578          */
579         var $category_class = 'SimplePie_Category';
580
581         /**
582          * @var string Class used for enclosures
583          * @see SimplePie::set_enclosures_class()
584          * @access private
585          */
586         var $enclosure_class = 'SimplePie_Enclosure';
587
588         /**
589          * @var string Class used for Media RSS <media:text> captions
590          * @see SimplePie::set_caption_class()
591          * @access private
592          */
593         var $caption_class = 'SimplePie_Caption';
594
595         /**
596          * @var string Class used for Media RSS <media:copyright>
597          * @see SimplePie::set_copyright_class()
598          * @access private
599          */
600         var $copyright_class = 'SimplePie_Copyright';
601
602         /**
603          * @var string Class used for Media RSS <media:credit>
604          * @see SimplePie::set_credit_class()
605          * @access private
606          */
607         var $credit_class = 'SimplePie_Credit';
608
609         /**
610          * @var string Class used for Media RSS <media:rating>
611          * @see SimplePie::set_rating_class()
612          * @access private
613          */
614         var $rating_class = 'SimplePie_Rating';
615
616         /**
617          * @var string Class used for Media RSS <media:restriction>
618          * @see SimplePie::set_restriction_class()
619          * @access private
620          */
621         var $restriction_class = 'SimplePie_Restriction';
622
623         /**
624          * @var string Class used for content-type sniffing
625          * @see SimplePie::set_content_type_sniffer_class()
626          * @access private
627          */
628         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
629
630         /**
631          * @var string Class used for item sources.
632          * @see SimplePie::set_source_class()
633          * @access private
634          */
635         var $source_class = 'SimplePie_Source';
636
637         /**
638          * @var mixed Set javascript query string parameter (false, or
639          * anything type-cast to false, disables this feature)
640          * @see SimplePie::set_javascript()
641          * @access private
642          */
643         var $javascript = 'js';
644
645         /**
646          * @var int Maximum number of feeds to check with autodiscovery
647          * @see SimplePie::set_max_checked_feeds()
648          * @access private
649          */
650         var $max_checked_feeds = 10;
651
652         /**
653          * @var array All the feeds found during the autodiscovery process
654          * @see SimplePie::get_all_discovered_feeds()
655          * @access private
656          */
657         var $all_discovered_feeds = array();
658
659         /**
660          * @var string Web-accessible path to the handler_favicon.php file.
661          * @see SimplePie::set_favicon_handler()
662          * @access private
663          */
664         var $favicon_handler = '';
665
666         /**
667          * @var string Web-accessible path to the handler_image.php file.
668          * @see SimplePie::set_image_handler()
669          * @access private
670          */
671         var $image_handler = '';
672
673         /**
674          * @var array Stores the URLs when multiple feeds are being initialized.
675          * @see SimplePie::set_feed_url()
676          * @access private
677          */
678         var $multifeed_url = array();
679
680         /**
681          * @var array Stores SimplePie objects when multiple feeds initialized.
682          * @access private
683          */
684         var $multifeed_objects = array();
685
686         /**
687          * @var array Stores the get_object_vars() array for use with multifeeds.
688          * @see SimplePie::set_feed_url()
689          * @access private
690          */
691         var $config_settings = null;
692
693         /**
694          * @var integer Stores the number of items to return per-feed with multifeeds.
695          * @see SimplePie::set_item_limit()
696          * @access private
697          */
698         var $item_limit = 0;
699
700         /**
701          * @var array Stores the default attributes to be stripped by strip_attributes().
702          * @see SimplePie::strip_attributes()
703          * @access private
704          */
705         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
706
707         /**
708          * @var array Stores the default tags to be stripped by strip_htmltags().
709          * @see SimplePie::strip_htmltags()
710          * @access private
711          */
712         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
713
714         /**
715          * The SimplePie class contains feed level data and options
716          *
717          * There are two ways that you can create a new SimplePie object. The first
718          * is by passing a feed URL as a parameter to the SimplePie constructor
719          * (as well as optionally setting the cache location and cache expiry). This
720          * will initialise the whole feed with all of the default settings, and you
721          * can begin accessing methods and properties immediately.
722          *
723          * The second way is to create the SimplePie object with no parameters
724          * at all. This will enable you to set configuration options. After setting
725          * them, you must initialise the feed using $feed->init(). At that point the
726          * object's methods and properties will be available to you. This format is
727          * what is used throughout this documentation.
728          *
729          * @access public
730          * @since 1.0 Preview Release
731          * @param string $feed_url This is the URL you want to parse.
732          * @param string $cache_location This is where you want the cache to be stored.
733          * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
734          */
735         function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
736         {
737                 // Other objects, instances created here so we can set options on them
738                 $this->sanitize = new SimplePie_Sanitize;
739
740                 // Set options if they're passed to the constructor
741                 if ($cache_location !== null)
742                 {
743                         $this->set_cache_location($cache_location);
744                 }
745
746                 if ($cache_duration !== null)
747                 {
748                         $this->set_cache_duration($cache_duration);
749                 }
750
751                 // Only init the script if we're passed a feed URL
752                 if ($feed_url !== null)
753                 {
754                         $this->set_feed_url($feed_url);
755                         $this->init();
756                 }
757         }
758
759         /**
760          * Used for converting object to a string
761          */
762         function __toString()
763         {
764                 return md5(serialize($this->data));
765         }
766
767         /**
768          * Remove items that link back to this before destroying this object
769          */
770         function __destruct()
771         {
772                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
773                 {
774                         if (!empty($this->data['items']))
775                         {
776                                 foreach ($this->data['items'] as $item)
777                                 {
778                                         $item->__destruct();
779                                 }
780                                 unset($item, $this->data['items']);
781                         }
782                         if (!empty($this->data['ordered_items']))
783                         {
784                                 foreach ($this->data['ordered_items'] as $item)
785                                 {
786                                         $item->__destruct();
787                                 }
788                                 unset($item, $this->data['ordered_items']);
789                         }
790                 }
791         }
792
793         /**
794          * Force the given data/URL to be treated as a feed no matter what it
795          * appears like
796          *
797          * @access public
798          * @since 1.1
799          * @param bool $enable Force the given data/URL to be treated as a feed
800          */
801         function force_feed($enable = false)
802         {
803                 $this->force_feed = (bool) $enable;
804         }
805
806         /**
807          * This is the URL of the feed you want to parse.
808          *
809          * This allows you to enter the URL of the feed you want to parse, or the
810          * website you want to try to use auto-discovery on. This takes priority
811          * over any set raw data.
812          *
813          * You can set multiple feeds to mash together by passing an array instead
814          * of a string for the $url. Remember that with each additional feed comes
815          * additional processing and resources.
816          *
817          * @access public
818          * @since 1.0 Preview Release
819          * @param mixed $url This is the URL (or array of URLs) that you want to parse.
820          * @see SimplePie::set_raw_data()
821          */
822         function set_feed_url($url)
823         {
824                 if (is_array($url))
825                 {
826                         $this->multifeed_url = array();
827                         foreach ($url as $value)
828                         {
829                                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
830                         }
831                 }
832                 else
833                 {
834                         $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
835                 }
836         }
837
838         /**
839          * Provides an instance of SimplePie_File to use as a feed
840          *
841          * @access public
842          * @param object &$file Instance of SimplePie_File (or subclass)
843          * @return bool True on success, false on failure
844          */
845         function set_file(&$file)
846         {
847                 if (is_a($file, 'SimplePie_File'))
848                 {
849                         $this->feed_url = $file->url;
850                         $this->file =& $file;
851                         return true;
852                 }
853                 return false;
854         }
855
856         /**
857          * Allows you to use a string of RSS/Atom data instead of a remote feed.
858          *
859          * If you have a feed available as a string in PHP, you can tell SimplePie
860          * to parse that data string instead of a remote feed. Any set feed URL
861          * takes precedence.
862          *
863          * @access public
864          * @since 1.0 Beta 3
865          * @param string $data RSS or Atom data as a string.
866          * @see SimplePie::set_feed_url()
867          */
868         function set_raw_data($data)
869         {
870                 $this->raw_data = $data;
871         }
872
873         /**
874          * Allows you to override the default timeout for fetching remote feeds.
875          *
876          * This allows you to change the maximum time the feed's server to respond
877          * and send the feed back.
878          *
879          * @access public
880          * @since 1.0 Beta 3
881          * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
882          */
883         function set_timeout($timeout = 10)
884         {
885                 $this->timeout = (int) $timeout;
886         }
887
888         /**
889          * Forces SimplePie to use fsockopen() instead of the preferred cURL
890          * functions.
891          *
892          * @access public
893          * @since 1.0 Beta 3
894          * @param bool $enable Force fsockopen() to be used
895          */
896         function force_fsockopen($enable = false)
897         {
898                 $this->force_fsockopen = (bool) $enable;
899         }
900
901         /**
902          * Outputs the raw XML content of the feed, after it has gone through
903          * SimplePie's filters.
904          *
905          * Used only for debugging, this function will output the XML content as
906          * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
907          * before trying to parse it. Many parts of the feed are re-written in
908          * memory, and in the end, you have a parsable feed. XML dump shows you the
909          * actual XML that SimplePie tries to parse, which may or may not be very
910          * different from the original feed.
911          *
912          * @access public
913          * @since 1.0 Preview Release
914          * @param bool $enable Enable XML dump
915          */
916         function enable_xml_dump($enable = false)
917         {
918                 $this->xml_dump = (bool) $enable;
919         }
920
921         /**
922          * Enables/disables caching in SimplePie.
923          *
924          * This option allows you to disable caching all-together in SimplePie.
925          * However, disabling the cache can lead to longer load times.
926          *
927          * @access public
928          * @since 1.0 Preview Release
929          * @param bool $enable Enable caching
930          */
931         function enable_cache($enable = true)
932         {
933                 $this->cache = (bool) $enable;
934         }
935
936         /**
937          * Set the length of time (in seconds) that the contents of a feed
938          * will be cached.
939          *
940          * @access public
941          * @param int $seconds The feed content cache duration.
942          */
943         function set_cache_duration($seconds = 3600)
944         {
945                 $this->cache_duration = (int) $seconds;
946         }
947
948         /**
949          * Set the length of time (in seconds) that the autodiscovered feed
950          * URL will be cached.
951          *
952          * @access public
953          * @param int $seconds The autodiscovered feed URL cache duration.
954          */
955         function set_autodiscovery_cache_duration($seconds = 604800)
956         {
957                 $this->autodiscovery_cache_duration = (int) $seconds;
958         }
959
960         /**
961          * Set the file system location where the cached files should be stored.
962          *
963          * @access public
964          * @param string $location The file system location.
965          */
966         function set_cache_location($location = './cache')
967         {
968                 $this->cache_location = (string) $location;
969         }
970
971         /**
972          * Determines whether feed items should be sorted into reverse chronological order.
973          *
974          * @access public
975          * @param bool $enable Sort as reverse chronological order.
976          */
977         function enable_order_by_date($enable = true)
978         {
979                 $this->order_by_date = (bool) $enable;
980         }
981
982         /**
983          * Allows you to override the character encoding reported by the feed.
984          *
985          * @access public
986          * @param string $encoding Character encoding.
987          */
988         function set_input_encoding($encoding = false)
989         {
990                 if ($encoding)
991                 {
992                         $this->input_encoding = (string) $encoding;
993                 }
994                 else
995                 {
996                         $this->input_encoding = false;
997                 }
998         }
999
1000         /**
1001          * Set how much feed autodiscovery to do
1002          *
1003          * @access public
1004          * @see SIMPLEPIE_LOCATOR_NONE
1005          * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1006          * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1007          * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1008          * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1009          * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1010          * @see SIMPLEPIE_LOCATOR_ALL
1011          * @param int $level Feed Autodiscovery Level (level can be a
1012          * combination of the above constants, see bitwise OR operator)
1013          */
1014         function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1015         {
1016                 $this->autodiscovery = (int) $level;
1017         }
1018
1019         /**
1020          * Allows you to change which class SimplePie uses for caching.
1021          * Useful when you are overloading or extending SimplePie's default classes.
1022          *
1023          * @access public
1024          * @param string $class Name of custom class.
1025          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1026          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1027          */
1028         function set_cache_class($class = 'SimplePie_Cache')
1029         {
1030                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1031                 {
1032                         $this->cache_class = $class;
1033                         return true;
1034                 }
1035                 return false;
1036         }
1037
1038         /**
1039          * Allows you to change which class SimplePie uses for auto-discovery.
1040          * Useful when you are overloading or extending SimplePie's default classes.
1041          *
1042          * @access public
1043          * @param string $class Name of custom class.
1044          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1045          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1046          */
1047         function set_locator_class($class = 'SimplePie_Locator')
1048         {
1049                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1050                 {
1051                         $this->locator_class = $class;
1052                         return true;
1053                 }
1054                 return false;
1055         }
1056
1057         /**
1058          * Allows you to change which class SimplePie uses for XML parsing.
1059          * Useful when you are overloading or extending SimplePie's default classes.
1060          *
1061          * @access public
1062          * @param string $class Name of custom class.
1063          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1064          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1065          */
1066         function set_parser_class($class = 'SimplePie_Parser')
1067         {
1068                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1069                 {
1070                         $this->parser_class = $class;
1071                         return true;
1072                 }
1073                 return false;
1074         }
1075
1076         /**
1077          * Allows you to change which class SimplePie uses for remote file fetching.
1078          * Useful when you are overloading or extending SimplePie's default classes.
1079          *
1080          * @access public
1081          * @param string $class Name of custom class.
1082          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1083          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1084          */
1085         function set_file_class($class = 'SimplePie_File')
1086         {
1087                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1088                 {
1089                         $this->file_class = $class;
1090                         return true;
1091                 }
1092                 return false;
1093         }
1094
1095         /**
1096          * Allows you to change which class SimplePie uses for data sanitization.
1097          * Useful when you are overloading or extending SimplePie's default classes.
1098          *
1099          * @access public
1100          * @param string $class Name of custom class.
1101          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1102          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1103          */
1104         function set_sanitize_class($class = 'SimplePie_Sanitize')
1105         {
1106                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1107                 {
1108                         $this->sanitize = new $class;
1109                         return true;
1110                 }
1111                 return false;
1112         }
1113
1114         /**
1115          * Allows you to change which class SimplePie uses for handling feed items.
1116          * Useful when you are overloading or extending SimplePie's default classes.
1117          *
1118          * @access public
1119          * @param string $class Name of custom class.
1120          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1121          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1122          */
1123         function set_item_class($class = 'SimplePie_Item')
1124         {
1125                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1126                 {
1127                         $this->item_class = $class;
1128                         return true;
1129                 }
1130                 return false;
1131         }
1132
1133         /**
1134          * Allows you to change which class SimplePie uses for handling author data.
1135          * Useful when you are overloading or extending SimplePie's default classes.
1136          *
1137          * @access public
1138          * @param string $class Name of custom class.
1139          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1140          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1141          */
1142         function set_author_class($class = 'SimplePie_Author')
1143         {
1144                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1145                 {
1146                         $this->author_class = $class;
1147                         return true;
1148                 }
1149                 return false;
1150         }
1151
1152         /**
1153          * Allows you to change which class SimplePie uses for handling category data.
1154          * Useful when you are overloading or extending SimplePie's default classes.
1155          *
1156          * @access public
1157          * @param string $class Name of custom class.
1158          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1159          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1160          */
1161         function set_category_class($class = 'SimplePie_Category')
1162         {
1163                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1164                 {
1165                         $this->category_class = $class;
1166                         return true;
1167                 }
1168                 return false;
1169         }
1170
1171         /**
1172          * Allows you to change which class SimplePie uses for feed enclosures.
1173          * Useful when you are overloading or extending SimplePie's default classes.
1174          *
1175          * @access public
1176          * @param string $class Name of custom class.
1177          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1178          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1179          */
1180         function set_enclosure_class($class = 'SimplePie_Enclosure')
1181         {
1182                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1183                 {
1184                         $this->enclosure_class = $class;
1185                         return true;
1186                 }
1187                 return false;
1188         }
1189
1190         /**
1191          * Allows you to change which class SimplePie uses for <media:text> captions
1192          * Useful when you are overloading or extending SimplePie's default classes.
1193          *
1194          * @access public
1195          * @param string $class Name of custom class.
1196          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1197          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1198          */
1199         function set_caption_class($class = 'SimplePie_Caption')
1200         {
1201                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1202                 {
1203                         $this->caption_class = $class;
1204                         return true;
1205                 }
1206                 return false;
1207         }
1208
1209         /**
1210          * Allows you to change which class SimplePie uses for <media:copyright>
1211          * Useful when you are overloading or extending SimplePie's default classes.
1212          *
1213          * @access public
1214          * @param string $class Name of custom class.
1215          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1216          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1217          */
1218         function set_copyright_class($class = 'SimplePie_Copyright')
1219         {
1220                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1221                 {
1222                         $this->copyright_class = $class;
1223                         return true;
1224                 }
1225                 return false;
1226         }
1227
1228         /**
1229          * Allows you to change which class SimplePie uses for <media:credit>
1230          * Useful when you are overloading or extending SimplePie's default classes.
1231          *
1232          * @access public
1233          * @param string $class Name of custom class.
1234          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1235          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1236          */
1237         function set_credit_class($class = 'SimplePie_Credit')
1238         {
1239                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1240                 {
1241                         $this->credit_class = $class;
1242                         return true;
1243                 }
1244                 return false;
1245         }
1246
1247         /**
1248          * Allows you to change which class SimplePie uses for <media:rating>
1249          * Useful when you are overloading or extending SimplePie's default classes.
1250          *
1251          * @access public
1252          * @param string $class Name of custom class.
1253          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1254          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1255          */
1256         function set_rating_class($class = 'SimplePie_Rating')
1257         {
1258                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1259                 {
1260                         $this->rating_class = $class;
1261                         return true;
1262                 }
1263                 return false;
1264         }
1265
1266         /**
1267          * Allows you to change which class SimplePie uses for <media:restriction>
1268          * Useful when you are overloading or extending SimplePie's default classes.
1269          *
1270          * @access public
1271          * @param string $class Name of custom class.
1272          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1273          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1274          */
1275         function set_restriction_class($class = 'SimplePie_Restriction')
1276         {
1277                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1278                 {
1279                         $this->restriction_class = $class;
1280                         return true;
1281                 }
1282                 return false;
1283         }
1284
1285         /**
1286          * Allows you to change which class SimplePie uses for content-type sniffing.
1287          * Useful when you are overloading or extending SimplePie's default classes.
1288          *
1289          * @access public
1290          * @param string $class Name of custom class.
1291          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1292          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1293          */
1294         function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1295         {
1296                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1297                 {
1298                         $this->content_type_sniffer_class = $class;
1299                         return true;
1300                 }
1301                 return false;
1302         }
1303
1304         /**
1305          * Allows you to change which class SimplePie uses item sources.
1306          * Useful when you are overloading or extending SimplePie's default classes.
1307          *
1308          * @access public
1309          * @param string $class Name of custom class.
1310          * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1311          * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1312          */
1313         function set_source_class($class = 'SimplePie_Source')
1314         {
1315                 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1316                 {
1317                         $this->source_class = $class;
1318                         return true;
1319                 }
1320                 return false;
1321         }
1322
1323         /**
1324          * Allows you to override the default user agent string.
1325          *
1326          * @access public
1327          * @param string $ua New user agent string.
1328          */
1329         function set_useragent($ua = SIMPLEPIE_USERAGENT)
1330         {
1331                 $this->useragent = (string) $ua;
1332         }
1333
1334         /**
1335          * Set callback function to create cache filename with
1336          *
1337          * @access public
1338          * @param mixed $function Callback function
1339          */
1340         function set_cache_name_function($function = 'md5')
1341         {
1342                 if (is_callable($function))
1343                 {
1344                         $this->cache_name_function = $function;
1345                 }
1346         }
1347
1348         /**
1349          * Set javascript query string parameter
1350          *
1351          * @access public
1352          * @param mixed $get Javascript query string parameter
1353          */
1354         function set_javascript($get = 'js')
1355         {
1356                 if ($get)
1357                 {
1358                         $this->javascript = (string) $get;
1359                 }
1360                 else
1361                 {
1362                         $this->javascript = false;
1363                 }
1364         }
1365
1366         /**
1367          * Set options to make SP as fast as possible.  Forgoes a
1368          * substantial amount of data sanitization in favor of speed.
1369          *
1370          * @access public
1371          * @param bool $set Whether to set them or not
1372          */
1373         function set_stupidly_fast($set = false)
1374         {
1375                 if ($set)
1376                 {
1377                         $this->enable_order_by_date(false);
1378                         $this->remove_div(false);
1379                         $this->strip_comments(false);
1380                         $this->strip_htmltags(false);
1381                         $this->strip_attributes(false);
1382                         $this->set_image_handler(false);
1383                 }
1384         }
1385
1386         /**
1387          * Set maximum number of feeds to check with autodiscovery
1388          *
1389          * @access public
1390          * @param int $max Maximum number of feeds to check
1391          */
1392         function set_max_checked_feeds($max = 10)
1393         {
1394                 $this->max_checked_feeds = (int) $max;
1395         }
1396
1397         function remove_div($enable = true)
1398         {
1399                 $this->sanitize->remove_div($enable);
1400         }
1401
1402         function strip_htmltags($tags = '', $encode = null)
1403         {
1404                 if ($tags === '')
1405                 {
1406                         $tags = $this->strip_htmltags;
1407                 }
1408                 $this->sanitize->strip_htmltags($tags);
1409                 if ($encode !== null)
1410                 {
1411                         $this->sanitize->encode_instead_of_strip($tags);
1412                 }
1413         }
1414
1415         function encode_instead_of_strip($enable = true)
1416         {
1417                 $this->sanitize->encode_instead_of_strip($enable);
1418         }
1419
1420         function strip_attributes($attribs = '')
1421         {
1422                 if ($attribs === '')
1423                 {
1424                         $attribs = $this->strip_attributes;
1425                 }
1426                 $this->sanitize->strip_attributes($attribs);
1427         }
1428
1429         function set_output_encoding($encoding = 'UTF-8')
1430         {
1431                 $this->sanitize->set_output_encoding($encoding);
1432         }
1433
1434         function strip_comments($strip = false)
1435         {
1436                 $this->sanitize->strip_comments($strip);
1437         }
1438
1439         /**
1440          * Set element/attribute key/value pairs of HTML attributes
1441          * containing URLs that need to be resolved relative to the feed
1442          *
1443          * @access public
1444          * @since 1.0
1445          * @param array $element_attribute Element/attribute key/value pairs
1446          */
1447         function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1448         {
1449                 $this->sanitize->set_url_replacements($element_attribute);
1450         }
1451
1452         /**
1453          * Set the handler to enable the display of cached favicons.
1454          *
1455          * @access public
1456          * @param str $page Web-accessible path to the handler_favicon.php file.
1457          * @param str $qs The query string that the value should be passed to.
1458          */
1459         function set_favicon_handler($page = false, $qs = 'i')
1460         {
1461                 if ($page !== false)
1462                 {
1463                         $this->favicon_handler = $page . '?' . $qs . '=';
1464                 }
1465                 else
1466                 {
1467                         $this->favicon_handler = '';
1468                 }
1469         }
1470
1471         /**
1472          * Set the handler to enable the display of cached images.
1473          *
1474          * @access public
1475          * @param str $page Web-accessible path to the handler_image.php file.
1476          * @param str $qs The query string that the value should be passed to.
1477          */
1478         function set_image_handler($page = false, $qs = 'i')
1479         {
1480                 if ($page !== false)
1481                 {
1482                         $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1483                 }
1484                 else
1485                 {
1486                         $this->image_handler = '';
1487                 }
1488         }
1489
1490         /**
1491          * Set the limit for items returned per-feed with multifeeds.
1492          *
1493          * @access public
1494          * @param integer $limit The maximum number of items to return.
1495          */
1496         function set_item_limit($limit = 0)
1497         {
1498                 $this->item_limit = (int) $limit;
1499         }
1500
1501         function init()
1502         {
1503                 // Check absolute bare minimum requirements.
1504                 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1505                 {
1506                         return false;
1507                 }
1508                 // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1509                 elseif (!extension_loaded('xmlreader'))
1510                 {
1511                         static $xml_is_sane = null;
1512                         if ($xml_is_sane === null)
1513                         {
1514                                 $parser_check = xml_parser_create();
1515                                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1516                                 xml_parser_free($parser_check);
1517                                 $xml_is_sane = isset($values[0]['value']);
1518                         }
1519                         if (!$xml_is_sane)
1520                         {
1521                                 return false;
1522                         }
1523                 }
1524
1525                 if (isset($_GET[$this->javascript]))
1526                 {
1527                         SimplePie_Misc::output_javascript();
1528                         exit;
1529                 }
1530
1531                 // Pass whatever was set with config options over to the sanitizer.
1532                 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1533                 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1534
1535                 if ($this->feed_url !== null || $this->raw_data !== null)
1536                 {
1537                         $this->data = array();
1538                         $this->multifeed_objects = array();
1539                         $cache = false;
1540
1541                         if ($this->feed_url !== null)
1542                         {
1543                                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1544                                 // Decide whether to enable caching
1545                                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1546                                 {
1547                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1548                                 }
1549                                 // If it's enabled and we don't want an XML dump, use the cache
1550                                 if ($cache && !$this->xml_dump)
1551                                 {
1552                                         // Load the Cache
1553                                         $this->data = $cache->load();
1554                                         if (!empty($this->data))
1555                                         {
1556                                                 // If the cache is for an outdated build of SimplePie
1557                                                 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1558                                                 {
1559                                                         $cache->unlink();
1560                                                         $this->data = array();
1561                                                 }
1562                                                 // If we've hit a collision just rerun it with caching disabled
1563                                                 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1564                                                 {
1565                                                         $cache = false;
1566                                                         $this->data = array();
1567                                                 }
1568                                                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1569                                                 elseif (isset($this->data['feed_url']))
1570                                                 {
1571                                                         // If the autodiscovery cache is still valid use it.
1572                                                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1573                                                         {
1574                                                                 // Do not need to do feed autodiscovery yet.
1575                                                                 if ($this->data['feed_url'] === $this->data['url'])
1576                                                                 {
1577                                                                         $cache->unlink();
1578                                                                         $this->data = array();
1579                                                                 }
1580                                                                 else
1581                                                                 {
1582                                                                         $this->set_feed_url($this->data['feed_url']);
1583                                                                         return $this->init();
1584                                                                 }
1585                                                         }
1586                                                 }
1587                                                 // Check if the cache has been updated
1588                                                 elseif ($cache->mtime() + $this->cache_duration < time())
1589                                                 {
1590                                                         // If we have last-modified and/or etag set
1591                                                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1592                                                         {
1593                                                                 $headers = array();
1594                                                                 if (isset($this->data['headers']['last-modified']))
1595                                                                 {
1596                                                                         $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1597                                                                 }
1598                                                                 if (isset($this->data['headers']['etag']))
1599                                                                 {
1600                                                                         $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1601                                                                 }
1602                                                                 $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1603                                                                 if ($file->success)
1604                                                                 {
1605                                                                         if ($file->status_code === 304)
1606                                                                         {
1607                                                                                 $cache->touch();
1608                                                                                 return true;
1609                                                                         }
1610                                                                         else
1611                                                                         {
1612                                                                                 $headers = $file->headers;
1613                                                                         }
1614                                                                 }
1615                                                                 else
1616                                                                 {
1617                                                                         unset($file);
1618                                                                 }
1619                                                         }
1620                                                 }
1621                                                 // If the cache is still valid, just return true
1622                                                 else
1623                                                 {
1624                                                         return true;
1625                                                 }
1626                                         }
1627                                         // If the cache is empty, delete it
1628                                         else
1629                                         {
1630                                                 $cache->unlink();
1631                                                 $this->data = array();
1632                                         }
1633                                 }
1634                                 // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
1635                                 if (!isset($file))
1636                                 {
1637                                         if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1638                                         {
1639                                                 $file =& $this->file;
1640                                         }
1641                                         else
1642                                         {
1643                                                 $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1644                                         }
1645                                 }
1646                                 // If the file connection has an error, set SimplePie::error to that and quit
1647                                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1648                                 {
1649                                         $this->error = $file->error;
1650                                         if (!empty($this->data))
1651                                         {
1652                                                 return true;
1653                                         }
1654                                         else
1655                                         {
1656                                                 return false;
1657                                         }
1658                                 }
1659
1660                                 if (!$this->force_feed)
1661                                 {
1662                                         // Check if the supplied URL is a feed, if it isn't, look for it.
1663                                         $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1664                                         if (!$locate->is_feed($file))
1665                                         {
1666                                                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1667                                                 unset($file);
1668                                                 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1669                                                 {
1670                                                         if ($cache)
1671                                                         {
1672                                                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673                                                                 if (!$cache->save($this))
1674                                                                 {
1675                                                                         trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1676                                                                 }
1677                                                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1678                                                         }
1679                                                         $this->feed_url = $file->url;
1680                                                 }
1681                                                 else
1682                                                 {
1683                                                         $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1684                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1685                                                         return false;
1686                                                 }
1687                                         }
1688                                         $locate = null;
1689                                 }
1690
1691                                 $headers = $file->headers;
1692                                 $data = $file->body;
1693                                 $sniffer = new $this->content_type_sniffer_class($file);
1694                                 $sniffed = $sniffer->get_type();
1695                         }
1696                         else
1697                         {
1698                                 $data = $this->raw_data;
1699                         }
1700
1701                         // Set up array of possible encodings
1702                         $encodings = array();
1703
1704                         // First check to see if input has been overridden.
1705                         if ($this->input_encoding !== false)
1706                         {
1707                                 $encodings[] = $this->input_encoding;
1708                         }
1709
1710                         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1711                         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1712
1713                         // RFC 3023 (only applies to sniffed content)
1714                         if (isset($sniffed))
1715                         {
1716                                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1717                                 {
1718                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1719                                         {
1720                                                 $encodings[] = strtoupper($charset[1]);
1721                                         }
1722                                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723                                         $encodings[] = 'UTF-8';
1724                                 }
1725                                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1726                                 {
1727                                         if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1728                                         {
1729                                                 $encodings[] = $charset[1];
1730                                         }
1731                                         $encodings[] = 'US-ASCII';
1732                                 }
1733                                 // Text MIME-type default
1734                                 elseif (substr($sniffed, 0, 5) === 'text/')
1735                                 {
1736                                         $encodings[] = 'US-ASCII';
1737                                 }
1738                         }
1739
1740                         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1741                         $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1742                         $encodings[] = 'UTF-8';
1743                         $encodings[] = 'ISO-8859-1';
1744
1745                         // There's no point in trying an encoding twice
1746                         $encodings = array_unique($encodings);
1747
1748                         // If we want the XML, just output that with the most likely encoding and quit
1749                         if ($this->xml_dump)
1750                         {
1751                                 header('Content-type: text/xml; charset=' . $encodings[0]);
1752                                 echo $data;
1753                                 exit;
1754                         }
1755
1756                         // Loop through each possible encoding, till we return something, or run out of possibilities
1757                         foreach ($encodings as $encoding)
1758                         {
1759                                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1760                                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1761                                 {
1762                                         // Create new parser
1763                                         $parser = new $this->parser_class();
1764
1765                                         // If it's parsed fine
1766                                         if ($parser->parse($utf8_data, 'UTF-8'))
1767                                         {
1768                                                 $this->data = $parser->get_data();
1769                                                 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1770                                                 {
1771                                                         if (isset($headers))
1772                                                         {
1773                                                                 $this->data['headers'] = $headers;
1774                                                         }
1775                                                         $this->data['build'] = SIMPLEPIE_BUILD;
1776
1777                                                         // Cache the file if caching is enabled
1778                                                         if ($cache && !$cache->save($this))
1779                                                         {
1780                                                                 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1781                                                         }
1782                                                         return true;
1783                                                 }
1784                                                 else
1785                                                 {
1786                                                         $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1787                                                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1788                                                         return false;
1789                                                 }
1790                                         }
1791                                 }
1792                         }
1793                         if (isset($parser))
1794                         {
1795                                 // We have an error, just set SimplePie_Misc::error to it and quit
1796                                 $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1797                         }
1798                         else
1799                         {
1800                                 $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1801                         }
1802                         SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1803                         return false;
1804                 }
1805                 elseif (!empty($this->multifeed_url))
1806                 {
1807                         $i = 0;
1808                         $success = 0;
1809                         $this->multifeed_objects = array();
1810                         foreach ($this->multifeed_url as $url)
1811                         {
1812                                 if (SIMPLEPIE_PHP5)
1813                                 {
1814                                         // This keyword needs to defy coding standards for PHP4 compatibility
1815                                         $this->multifeed_objects[$i] = clone($this);
1816                                 }
1817                                 else
1818                                 {
1819                                         $this->multifeed_objects[$i] = $this;
1820                                 }
1821                                 $this->multifeed_objects[$i]->set_feed_url($url);
1822                                 $success |= $this->multifeed_objects[$i]->init();
1823                                 $i++;
1824                         }
1825                         return (bool) $success;
1826                 }
1827                 else
1828                 {
1829                         return false;
1830                 }
1831         }
1832
1833         /**
1834          * Return the error message for the occured error
1835          *
1836          * @access public
1837          * @return string Error message
1838          */
1839         function error()
1840         {
1841                 return $this->error;
1842         }
1843
1844         function get_encoding()
1845         {
1846                 return $this->sanitize->output_encoding;
1847         }
1848
1849         function handle_content_type($mime = 'text/html')
1850         {
1851                 if (!headers_sent())
1852                 {
1853                         $header = "Content-type: $mime;";
1854                         if ($this->get_encoding())
1855                         {
1856                                 $header .= ' charset=' . $this->get_encoding();
1857                         }
1858                         else
1859                         {
1860                                 $header .= ' charset=UTF-8';
1861                         }
1862                         header($header);
1863                 }
1864         }
1865
1866         function get_type()
1867         {
1868                 if (!isset($this->data['type']))
1869                 {
1870                         $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1872                         {
1873                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1874                         }
1875                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1876                         {
1877                                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1878                         }
1879                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1880                         {
1881                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1882                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1883                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1884                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1885                                 {
1886                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1887                                 }
1888                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1889                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1890                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1891                                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1892                                 {
1893                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1894                                 }
1895                         }
1896                         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1897                         {
1898                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899                                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1900                                 {
1901                                         switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1902                                         {
1903                                                 case '0.91':
1904                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1905                                                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1906                                                         {
1907                                                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1908                                                                 {
1909                                                                         case '0':
1910                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1911                                                                                 break;
1912
1913                                                                         case '24':
1914                                                                                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1915                                                                                 break;
1916                                                                 }
1917                                                         }
1918                                                         break;
1919
1920                                                 case '0.92':
1921                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1922                                                         break;
1923
1924                                                 case '0.93':
1925                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1926                                                         break;
1927
1928                                                 case '0.94':
1929                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1930                                                         break;
1931
1932                                                 case '2.0':
1933                                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1934                                                         break;
1935                                         }
1936                                 }
1937                         }
1938                         else
1939                         {
1940                                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1941                         }
1942                 }
1943                 return $this->data['type'];
1944         }
1945
1946         /**
1947          * Returns the URL for the favicon of the feed's website.
1948          *
1949          * @todo Cache atom:icon
1950          * @access public
1951          * @since 1.0
1952          */
1953         function get_favicon()
1954         {
1955                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1956                 {
1957                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1958                 }
1959                 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1960                 {
1961                         $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1962
1963                         if ($this->cache && $this->favicon_handler)
1964                         {
1965                                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1966                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1967
1968                                 if ($cache->load())
1969                                 {
1970                                         return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1971                                 }
1972                                 else
1973                                 {
1974                                         $file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1975
1976                                         if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1977                                         {
1978                                                 $sniffer = new $this->content_type_sniffer_class($file);
1979                                                 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1980                                                 {
1981                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1982                                                         {
1983                                                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1984                                                         }
1985                                                         else
1986                                                         {
1987                                                                 trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1988                                                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1989                                                         }
1990                                                 }
1991                                                 // not an image
1992                                                 else
1993                                                 {
1994                                                         return false;
1995                                                 }
1996                                         }
1997                                 }
1998                         }
1999                         else
2000                         {
2001                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2002                         }
2003                 }
2004                 return false;
2005         }
2006
2007         /**
2008          * @todo If we have a perm redirect we should return the new URL
2009          * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2010          * @todo Also, |atom:link|@rel=self
2011          */
2012         function subscribe_url()
2013         {
2014                 if ($this->feed_url !== null)
2015                 {
2016                         return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2017                 }
2018                 else
2019                 {
2020                         return null;
2021                 }
2022         }
2023
2024         function subscribe_feed()
2025         {
2026                 if ($this->feed_url !== null)
2027                 {
2028                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2029                 }
2030                 else
2031                 {
2032                         return null;
2033                 }
2034         }
2035
2036         function subscribe_outlook()
2037         {
2038                 if ($this->feed_url !== null)
2039                 {
2040                         return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2041                 }
2042                 else
2043                 {
2044                         return null;
2045                 }
2046         }
2047
2048         function subscribe_podcast()
2049         {
2050                 if ($this->feed_url !== null)
2051                 {
2052                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2053                 }
2054                 else
2055                 {
2056                         return null;
2057                 }
2058         }
2059
2060         function subscribe_itunes()
2061         {
2062                 if ($this->feed_url !== null)
2063                 {
2064                         return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2065                 }
2066                 else
2067                 {
2068                         return null;
2069                 }
2070         }
2071
2072         /**
2073          * Creates the subscribe_* methods' return data
2074          *
2075          * @access private
2076          * @param string $feed_url String to prefix to the feed URL
2077          * @param string $site_url String to prefix to the site URL (and
2078          * suffix to the feed URL)
2079          * @return mixed URL if feed exists, false otherwise
2080          */
2081         function subscribe_service($feed_url, $site_url = null)
2082         {
2083                 if ($this->subscribe_url())
2084                 {
2085                         $return = $feed_url . rawurlencode($this->feed_url);
2086                         if ($site_url !== null && $this->get_link() !== null)
2087                         {
2088                                 $return .= $site_url . rawurlencode($this->get_link());
2089                         }
2090                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2091                 }
2092                 else
2093                 {
2094                         return null;
2095                 }
2096         }
2097
2098         function subscribe_aol()
2099         {
2100                 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2101         }
2102
2103         function subscribe_bloglines()
2104         {
2105                 return $this->subscribe_service('http://www.bloglines.com/sub/');
2106         }
2107
2108         function subscribe_eskobo()
2109         {
2110                 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2111         }
2112
2113         function subscribe_feedfeeds()
2114         {
2115                 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2116         }
2117
2118         function subscribe_feedster()
2119         {
2120                 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2121         }
2122
2123         function subscribe_google()
2124         {
2125                 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2126         }
2127
2128         function subscribe_gritwire()
2129         {
2130                 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2131         }
2132
2133         function subscribe_msn()
2134         {
2135                 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2136         }
2137
2138         function subscribe_netvibes()
2139         {
2140                 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2141         }
2142
2143         function subscribe_newsburst()
2144         {
2145                 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2146         }
2147
2148         function subscribe_newsgator()
2149         {
2150                 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2151         }
2152
2153         function subscribe_odeo()
2154         {
2155                 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2156         }
2157
2158         function subscribe_podnova()
2159         {
2160                 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2161         }
2162
2163         function subscribe_rojo()
2164         {
2165                 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2166         }
2167
2168         function subscribe_yahoo()
2169         {
2170                 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2171         }
2172
2173         function get_feed_tags($namespace, $tag)
2174         {
2175                 $type = $this->get_type();
2176                 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2177                 {
2178                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2179                         {
2180                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2181                         }
2182                 }
2183                 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2184                 {
2185                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2186                         {
2187                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2188                         }
2189                 }
2190                 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2191                 {
2192                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2193                         {
2194                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2195                         }
2196                 }
2197                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2198                 {
2199                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2200                         {
2201                                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2202                         }
2203                 }
2204                 return null;
2205         }
2206
2207         function get_channel_tags($namespace, $tag)
2208         {
2209                 $type = $this->get_type();
2210                 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2211                 {
2212                         if ($return = $this->get_feed_tags($namespace, $tag))
2213                         {
2214                                 return $return;
2215                         }
2216                 }
2217                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2218                 {
2219                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2220                         {
2221                                 if (isset($channel[0]['child'][$namespace][$tag]))
2222                                 {
2223                                         return $channel[0]['child'][$namespace][$tag];
2224                                 }
2225                         }
2226                 }
2227                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2228                 {
2229                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2230                         {
2231                                 if (isset($channel[0]['child'][$namespace][$tag]))
2232                                 {
2233                                         return $channel[0]['child'][$namespace][$tag];
2234                                 }
2235                         }
2236                 }
2237                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2238                 {
2239                         if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2240                         {
2241                                 if (isset($channel[0]['child'][$namespace][$tag]))
2242                                 {
2243                                         return $channel[0]['child'][$namespace][$tag];
2244                                 }
2245                         }
2246                 }
2247                 return null;
2248         }
2249
2250         function get_image_tags($namespace, $tag)
2251         {
2252                 $type = $this->get_type();
2253                 if ($type & SIMPLEPIE_TYPE_RSS_10)
2254                 {
2255                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2256                         {
2257                                 if (isset($image[0]['child'][$namespace][$tag]))
2258                                 {
2259                                         return $image[0]['child'][$namespace][$tag];
2260                                 }
2261                         }
2262                 }
2263                 if ($type & SIMPLEPIE_TYPE_RSS_090)
2264                 {
2265                         if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2266                         {
2267                                 if (isset($image[0]['child'][$namespace][$tag]))
2268                                 {
2269                                         return $image[0]['child'][$namespace][$tag];
2270                                 }
2271                         }
2272                 }
2273                 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2274                 {
2275                         if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2276                         {
2277                                 if (isset($image[0]['child'][$namespace][$tag]))
2278                                 {
2279                                         return $image[0]['child'][$namespace][$tag];
2280                                 }
2281                         }
2282                 }
2283                 return null;
2284         }
2285
2286         function get_base($element = array())
2287         {
2288                 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2289                 {
2290                         return $element['xml_base'];
2291                 }
2292                 elseif ($this->get_link() !== null)
2293                 {
2294                         return $this->get_link();
2295                 }
2296                 else
2297                 {
2298                         return $this->subscribe_url();
2299                 }
2300         }
2301
2302         function sanitize($data, $type, $base = '')
2303         {
2304                 return $this->sanitize->sanitize($data, $type, $base);
2305         }
2306
2307         function get_title()
2308         {
2309                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2310                 {
2311                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2312                 }
2313                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2314                 {
2315                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2316                 }
2317                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2318                 {
2319                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2320                 }
2321                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2322                 {
2323                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2324                 }
2325                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2326                 {
2327                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2328                 }
2329                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2330                 {
2331                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2332                 }
2333                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2334                 {
2335                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2336                 }
2337                 else
2338                 {
2339                         return null;
2340                 }
2341         }
2342
2343         function get_category($key = 0)
2344         {
2345                 $categories = $this->get_categories();
2346                 if (isset($categories[$key]))
2347                 {
2348                         return $categories[$key];
2349                 }
2350                 else
2351                 {
2352                         return null;
2353                 }
2354         }
2355
2356         function get_categories()
2357         {
2358                 $categories = array();
2359
2360                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2361                 {
2362                         $term = null;
2363                         $scheme = null;
2364                         $label = null;
2365                         if (isset($category['attribs']['']['term']))
2366                         {
2367                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2368                         }
2369                         if (isset($category['attribs']['']['scheme']))
2370                         {
2371                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2372                         }
2373                         if (isset($category['attribs']['']['label']))
2374                         {
2375                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2376                         }
2377                         $categories[] = new $this->category_class($term, $scheme, $label);
2378                 }
2379                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2380                 {
2381                         // This is really the label, but keep this as the term also for BC.
2382                         // Label will also work on retrieving because that falls back to term.
2383                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384                         if (isset($category['attribs']['']['domain']))
2385                         {
2386                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2387                         }
2388                         else
2389                         {
2390                                 $scheme = null;
2391                         }
2392                         $categories[] = new $this->category_class($term, $scheme, null);
2393                 }
2394                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2395                 {
2396                         $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2397                 }
2398                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2399                 {
2400                         $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2401                 }
2402
2403                 if (!empty($categories))
2404                 {
2405                         return SimplePie_Misc::array_unique($categories);
2406                 }
2407                 else
2408                 {
2409                         return null;
2410                 }
2411         }
2412
2413         function get_author($key = 0)
2414         {
2415                 $authors = $this->get_authors();
2416                 if (isset($authors[$key]))
2417                 {
2418                         return $authors[$key];
2419                 }
2420                 else
2421                 {
2422                         return null;
2423                 }
2424         }
2425
2426         function get_authors()
2427         {
2428                 $authors = array();
2429                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2430                 {
2431                         $name = null;
2432                         $uri = null;
2433                         $email = null;
2434                         $avatar = null;
2435                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2436                         {
2437                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2438                         }
2439                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2440                         {
2441                                 $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]));
2442                         }
2443                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2444                         {
2445                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2446                         }
2447                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
2448                         {
2449                                 $avatar = $this->sanitize($$author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
2450                         }
2451                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null)
2452                         {
2453                                 $authors[] = new $this->author_class($name, $uri, $email, $avatar);
2454                         }
2455                 }
2456                 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2457                 {
2458                         $name = null;
2459                         $url = null;
2460                         $email = null;
2461                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2462                         {
2463                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2464                         }
2465                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2466                         {
2467                                 $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]));
2468                         }
2469                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2470                         {
2471                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2472                         }
2473                         if ($name !== null || $email !== null || $url !== null)
2474                         {
2475                                 $authors[] = new $this->author_class($name, $url, $email);
2476                         }
2477                 }
2478                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2479                 {
2480                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2481                 }
2482                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2483                 {
2484                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2485                 }
2486                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2487                 {
2488                         $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2489                 }
2490
2491                 if (!empty($authors))
2492                 {
2493                         return SimplePie_Misc::array_unique($authors);
2494                 }
2495                 else
2496                 {
2497                         return null;
2498                 }
2499         }
2500
2501         function get_contributor($key = 0)
2502         {
2503                 $contributors = $this->get_contributors();
2504                 if (isset($contributors[$key]))
2505                 {
2506                         return $contributors[$key];
2507                 }
2508                 else
2509                 {
2510                         return null;
2511                 }
2512         }
2513
2514         function get_contributors()
2515         {
2516                 $contributors = array();
2517                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2518                 {
2519                         $name = null;
2520                         $uri = null;
2521                         $email = null;
2522                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2523                         {
2524                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2525                         }
2526                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2527                         {
2528                                 $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]));
2529                         }
2530                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2531                         {
2532                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2533                         }
2534                         if ($name !== null || $email !== null || $uri !== null)
2535                         {
2536                                 $contributors[] = new $this->author_class($name, $uri, $email);
2537                         }
2538                 }
2539                 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2540                 {
2541                         $name = null;
2542                         $url = null;
2543                         $email = null;
2544                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2545                         {
2546                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2547                         }
2548                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2549                         {
2550                                 $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]));
2551                         }
2552                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2553                         {
2554                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2555                         }
2556                         if ($name !== null || $email !== null || $url !== null)
2557                         {
2558                                 $contributors[] = new $this->author_class($name, $url, $email);
2559                         }
2560                 }
2561
2562                 if (!empty($contributors))
2563                 {
2564                         return SimplePie_Misc::array_unique($contributors);
2565                 }
2566                 else
2567                 {
2568                         return null;
2569                 }
2570         }
2571
2572         function get_link($key = 0, $rel = 'alternate')
2573         {
2574                 $links = $this->get_links($rel);
2575                 if (isset($links[$key]))
2576                 {
2577                         return $links[$key];
2578                 }
2579                 else
2580                 {
2581                         return null;
2582                 }
2583         }
2584
2585         /**
2586          * Added for parity between the parent-level and the item/entry-level.
2587          */
2588         function get_permalink()
2589         {
2590                 return $this->get_link(0);
2591         }
2592
2593         function get_links($rel = 'alternate')
2594         {
2595                 if (!isset($this->data['links']))
2596                 {
2597                         $this->data['links'] = array();
2598                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2599                         {
2600                                 foreach ($links as $link)
2601                                 {
2602                                         if (isset($link['attribs']['']['href']))
2603                                         {
2604                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2605                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2606                                         }
2607                                 }
2608                         }
2609                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2610                         {
2611                                 foreach ($links as $link)
2612                                 {
2613                                         if (isset($link['attribs']['']['href']))
2614                                         {
2615                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2616                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2617
2618                                         }
2619                                 }
2620                         }
2621                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2622                         {
2623                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2624                         }
2625                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2626                         {
2627                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2628                         }
2629                         if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2630                         {
2631                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2632                         }
2633
2634                         $keys = array_keys($this->data['links']);
2635                         foreach ($keys as $key)
2636                         {
2637                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2638                                 {
2639                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2640                                         {
2641                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2642                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2643                                         }
2644                                         else
2645                                         {
2646                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2647                                         }
2648                                 }
2649                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2650                                 {
2651                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2652                                 }
2653                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2654                         }
2655                 }
2656
2657                 if (isset($this->data['links'][$rel]))
2658                 {
2659                         return $this->data['links'][$rel];
2660                 }
2661                 else
2662                 {
2663                         return null;
2664                 }
2665         }
2666
2667         function get_all_discovered_feeds()
2668         {
2669                 return $this->all_discovered_feeds;
2670         }
2671
2672         function get_description()
2673         {
2674                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2675                 {
2676                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2677                 }
2678                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2679                 {
2680                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2681                 }
2682                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2683                 {
2684                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2685                 }
2686                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2687                 {
2688                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2689                 }
2690                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2691                 {
2692                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2693                 }
2694                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2695                 {
2696                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2697                 }
2698                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2699                 {
2700                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2701                 }
2702                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2703                 {
2704                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2705                 }
2706                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2707                 {
2708                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2709                 }
2710                 else
2711                 {
2712                         return null;
2713                 }
2714         }
2715
2716         function get_copyright()
2717         {
2718                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2719                 {
2720                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2721                 }
2722                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2723                 {
2724                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2725                 }
2726                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2727                 {
2728                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2729                 }
2730                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2731                 {
2732                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2733                 }
2734                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2735                 {
2736                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2737                 }
2738                 else
2739                 {
2740                         return null;
2741                 }
2742         }
2743
2744         function get_language()
2745         {
2746                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2747                 {
2748                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2749                 }
2750                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2751                 {
2752                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2753                 }
2754                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2755                 {
2756                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2757                 }
2758                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2759                 {
2760                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2761                 }
2762                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2763                 {
2764                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2765                 }
2766                 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2767                 {
2768                         return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2769                 }
2770                 elseif (isset($this->data['headers']['content-language']))
2771                 {
2772                         return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2773                 }
2774                 else
2775                 {
2776                         return null;
2777                 }
2778         }
2779
2780         function get_latitude()
2781         {
2782                 
2783                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2784                 {
2785                         return (float) $return[0]['data'];
2786                 }
2787                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2788                 {
2789                         return (float) $match[1];
2790                 }
2791                 else
2792                 {
2793                         return null;
2794                 }
2795         }
2796
2797         function get_longitude()
2798         {
2799                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2800                 {
2801                         return (float) $return[0]['data'];
2802                 }
2803                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2804                 {
2805                         return (float) $return[0]['data'];
2806                 }
2807                 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2808                 {
2809                         return (float) $match[2];
2810                 }
2811                 else
2812                 {
2813                         return null;
2814                 }
2815         }
2816
2817         function get_image_title()
2818         {
2819                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2820                 {
2821                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2822                 }
2823                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2824                 {
2825                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2826                 }
2827                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2828                 {
2829                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2830                 }
2831                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2832                 {
2833                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2834                 }
2835                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2836                 {
2837                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2838                 }
2839                 else
2840                 {
2841                         return null;
2842                 }
2843         }
2844
2845         function get_image_url()
2846         {
2847                 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2848                 {
2849                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2850                 }
2851                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2852                 {
2853                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2854                 }
2855                 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2856                 {
2857                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2858                 }
2859                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2860                 {
2861                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2862                 }
2863                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2864                 {
2865                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2866                 }
2867                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2868                 {
2869                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2870                 }
2871                 else
2872                 {
2873                         return null;
2874                 }
2875         }
2876
2877         function get_image_link()
2878         {
2879                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2880                 {
2881                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2882                 }
2883                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2884                 {
2885                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2886                 }
2887                 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2888                 {
2889                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2890                 }
2891                 else
2892                 {
2893                         return null;
2894                 }
2895         }
2896
2897         function get_image_width()
2898         {
2899                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2900                 {
2901                         return round($return[0]['data']);
2902                 }
2903                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2904                 {
2905                         return 88.0;
2906                 }
2907                 else
2908                 {
2909                         return null;
2910                 }
2911         }
2912
2913         function get_image_height()
2914         {
2915                 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2916                 {
2917                         return round($return[0]['data']);
2918                 }
2919                 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2920                 {
2921                         return 31.0;
2922                 }
2923                 else
2924                 {
2925                         return null;
2926                 }
2927         }
2928
2929         function get_item_quantity($max = 0)
2930         {
2931                 $max = (int) $max;
2932                 $qty = count($this->get_items());
2933                 if ($max === 0)
2934                 {
2935                         return $qty;
2936                 }
2937                 else
2938                 {
2939                         return ($qty > $max) ? $max : $qty;
2940                 }
2941         }
2942
2943         function get_item($key = 0)
2944         {
2945                 $items = $this->get_items();
2946                 if (isset($items[$key]))
2947                 {
2948                         return $items[$key];
2949                 }
2950                 else
2951                 {
2952                         return null;
2953                 }
2954         }
2955
2956         function get_items($start = 0, $end = 0)
2957         {
2958                 if (!isset($this->data['items']))
2959                 {
2960                         if (!empty($this->multifeed_objects))
2961                         {
2962                                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2963                         }
2964                         else
2965                         {
2966                                 $this->data['items'] = array();
2967                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2968                                 {
2969                                         $keys = array_keys($items);
2970                                         foreach ($keys as $key)
2971                                         {
2972                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2973                                         }
2974                                 }
2975                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2976                                 {
2977                                         $keys = array_keys($items);
2978                                         foreach ($keys as $key)
2979                                         {
2980                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2981                                         }
2982                                 }
2983                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2984                                 {
2985                                         $keys = array_keys($items);
2986                                         foreach ($keys as $key)
2987                                         {
2988                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2989                                         }
2990                                 }
2991                                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2992                                 {
2993                                         $keys = array_keys($items);
2994                                         foreach ($keys as $key)
2995                                         {
2996                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2997                                         }
2998                                 }
2999                                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
3000                                 {
3001                                         $keys = array_keys($items);
3002                                         foreach ($keys as $key)
3003                                         {
3004                                                 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3005                                         }
3006                                 }
3007                         }
3008                 }
3009
3010                 if (!empty($this->data['items']))
3011                 {
3012                         // If we want to order it by date, check if all items have a date, and then sort it
3013                         if ($this->order_by_date && empty($this->multifeed_objects))
3014                         {
3015                                 if (!isset($this->data['ordered_items']))
3016                                 {
3017                                         $do_sort = true;
3018                                         foreach ($this->data['items'] as $item)
3019                                         {
3020                                                 if (!$item->get_date('U'))
3021                                                 {
3022                                                         $do_sort = false;
3023                                                         break;
3024                                                 }
3025                                         }
3026                                         $item = null;
3027                                         $this->data['ordered_items'] = $this->data['items'];
3028                                         if ($do_sort)
3029                                         {
3030                                                 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3031                                         }
3032                                 }
3033                                 $items = $this->data['ordered_items'];
3034                         }
3035                         else
3036                         {
3037                                 $items = $this->data['items'];
3038                         }
3039
3040                         // Slice the data as desired
3041                         if ($end === 0)
3042                         {
3043                                 return array_slice($items, $start);
3044                         }
3045                         else
3046                         {
3047                                 return array_slice($items, $start, $end);
3048                         }
3049                 }
3050                 else
3051                 {
3052                         return array();
3053                 }
3054         }
3055
3056         /**
3057          * @static
3058          */
3059         function sort_items($a, $b)
3060         {
3061                 return $a->get_date('U') <= $b->get_date('U');
3062         }
3063
3064         /**
3065          * @static
3066          */
3067         function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3068         {
3069                 if (is_array($urls) && sizeof($urls) > 0)
3070                 {
3071                         $items = array();
3072                         foreach ($urls as $arg)
3073                         {
3074                                 if (is_a($arg, 'SimplePie'))
3075                                 {
3076                                         $items = array_merge($items, $arg->get_items(0, $limit));
3077                                 }
3078                                 else
3079                                 {
3080                                         trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3081                                 }
3082                         }
3083
3084                         $do_sort = true;
3085                         foreach ($items as $item)
3086                         {
3087                                 if (!$item->get_date('U'))
3088                                 {
3089                                         $do_sort = false;
3090                                         break;
3091                                 }
3092                         }
3093                         $item = null;
3094                         if ($do_sort)
3095                         {
3096                                 usort($items, array('SimplePie', 'sort_items'));
3097                         }
3098
3099                         if ($end === 0)
3100                         {
3101                                 return array_slice($items, $start);
3102                         }
3103                         else
3104                         {
3105                                 return array_slice($items, $start, $end);
3106                         }
3107                 }
3108                 else
3109                 {
3110                         trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3111                         return array();
3112                 }
3113         }
3114 }
3115
3116 class SimplePie_Item
3117 {
3118         var $feed;
3119         var $data = array();
3120
3121         function SimplePie_Item($feed, $data)
3122         {
3123                 $this->feed = $feed;
3124                 $this->data = $data;
3125         }
3126
3127         function __toString()
3128         {
3129                 return md5(serialize($this->data));
3130         }
3131
3132         /**
3133          * Remove items that link back to this before destroying this object
3134          */
3135         function __destruct()
3136         {
3137                 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3138                 {
3139                         unset($this->feed);
3140                 }
3141         }
3142
3143         function get_item_tags($namespace, $tag)
3144         {
3145                 if (isset($this->data['child'][$namespace][$tag]))
3146                 {
3147                         return $this->data['child'][$namespace][$tag];
3148                 }
3149                 else
3150                 {
3151                         return null;
3152                 }
3153         }
3154
3155         function get_base($element = array())
3156         {
3157                 return $this->feed->get_base($element);
3158         }
3159
3160         function sanitize($data, $type, $base = '')
3161         {
3162                 return $this->feed->sanitize($data, $type, $base);
3163         }
3164
3165         function get_feed()
3166         {
3167                 return $this->feed;
3168         }
3169
3170         function get_id($hash = false)
3171         {
3172                 if (!$hash)
3173                 {
3174                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3175                         {
3176                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3177                         }
3178                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3179                         {
3180                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3181                         }
3182                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3183                         {
3184                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3185                         }
3186                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3187                         {
3188                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3189                         }
3190                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3191                         {
3192                                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3193                         }
3194                         elseif (($return = $this->get_permalink()) !== null)
3195                         {
3196                                 return $return;
3197                         }
3198                         elseif (($return = $this->get_title()) !== null)
3199                         {
3200                                 return $return;
3201                         }
3202                 }
3203                 if ($this->get_permalink() !== null || $this->get_title() !== null)
3204                 {
3205                         return md5($this->get_permalink() . $this->get_title());
3206                 }
3207                 else
3208                 {
3209                         return md5(serialize($this->data));
3210                 }
3211         }
3212
3213         function get_title()
3214         {
3215                 if (!isset($this->data['title']))
3216                 {
3217                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3218                         {
3219                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3220                         }
3221                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3222                         {
3223                                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3224                         }
3225                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3226                         {
3227                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3228                         }
3229                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3230                         {
3231                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3232                         }
3233                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3234                         {
3235                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3236                         }
3237                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3238                         {
3239                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3240                         }
3241                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3242                         {
3243                                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3244                         }
3245                         else
3246                         {
3247                                 $this->data['title'] = null;
3248                         }
3249                 }
3250                 return $this->data['title'];
3251         }
3252
3253         function get_description($description_only = false)
3254         {
3255                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3256                 {
3257                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3258                 }
3259                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3260                 {
3261                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3262                 }
3263                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3264                 {
3265                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3266                 }
3267                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3268                 {
3269                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3270                 }
3271                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3272                 {
3273                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3274                 }
3275                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3276                 {
3277                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3278                 }
3279                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3280                 {
3281                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3282                 }
3283                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3284                 {
3285                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3286                 }
3287                 elseif (!$description_only)
3288                 {
3289                         return $this->get_content(true);
3290                 }
3291                 else
3292                 {
3293                         return null;
3294                 }
3295         }
3296
3297         function get_content($content_only = false)
3298         {
3299                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3300                 {
3301                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3302                 }
3303                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3304                 {
3305                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3306                 }
3307                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3308                 {
3309                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3310                 }
3311                 elseif (!$content_only)
3312                 {
3313                         return $this->get_description(true);
3314                 }
3315                 else
3316                 {
3317                         return null;
3318                 }
3319         }
3320
3321         function get_category($key = 0)
3322         {
3323                 $categories = $this->get_categories();
3324                 if (isset($categories[$key]))
3325                 {
3326                         return $categories[$key];
3327                 }
3328                 else
3329                 {
3330                         return null;
3331                 }
3332         }
3333
3334         function get_categories()
3335         {
3336                 $categories = array();
3337
3338                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3339                 {
3340                         $term = null;
3341                         $scheme = null;
3342                         $label = null;
3343                         if (isset($category['attribs']['']['term']))
3344                         {
3345                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3346                         }
3347                         if (isset($category['attribs']['']['scheme']))
3348                         {
3349                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3350                         }
3351                         if (isset($category['attribs']['']['label']))
3352                         {
3353                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3354                         }
3355                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
3356                 }
3357                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3358                 {
3359                         // This is really the label, but keep this as the term also for BC.
3360                         // Label will also work on retrieving because that falls back to term.
3361                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3362                         if (isset($category['attribs']['']['domain']))
3363                         {
3364                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3365                         }
3366                         else
3367                         {
3368                                 $scheme = null;
3369                         }
3370                         $categories[] = new $this->feed->category_class($term, $scheme, null);
3371                 }
3372                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3373                 {
3374                         $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3375                 }
3376                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3377                 {
3378                         $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3379                 }
3380
3381                 if (!empty($categories))
3382                 {
3383                         return SimplePie_Misc::array_unique($categories);
3384                 }
3385                 else
3386                 {
3387                         return null;
3388                 }
3389         }
3390
3391         function get_author($key = 0)
3392         {
3393                 $authors = $this->get_authors();
3394                 if (isset($authors[$key]))
3395                 {
3396                         return $authors[$key];
3397                 }
3398                 else
3399                 {
3400                         return null;
3401                 }
3402         }
3403
3404         function get_contributor($key = 0)
3405         {
3406                 $contributors = $this->get_contributors();
3407                 if (isset($contributors[$key]))
3408                 {
3409                         return $contributors[$key];
3410                 }
3411                 else
3412                 {
3413                         return null;
3414                 }
3415         }
3416
3417         function get_contributors()
3418         {
3419                 $contributors = array();
3420                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3421                 {
3422                         $name = null;
3423                         $uri = null;
3424                         $email = null;
3425                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3426                         {
3427                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3428                         }
3429                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3430                         {
3431                                 $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]));
3432                         }
3433                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3434                         {
3435                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3436                         }
3437                         if ($name !== null || $email !== null || $uri !== null)
3438                         {
3439                                 $contributors[] = new $this->feed->author_class($name, $uri, $email);
3440                         }
3441                 }
3442                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3443                 {
3444                         $name = null;
3445                         $url = null;
3446                         $email = null;
3447                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3448                         {
3449                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3450                         }
3451                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3452                         {
3453                                 $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]));
3454                         }
3455                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3456                         {
3457                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3458                         }
3459                         if ($name !== null || $email !== null || $url !== null)
3460                         {
3461                                 $contributors[] = new $this->feed->author_class($name, $url, $email);
3462                         }
3463                 }
3464
3465                 if (!empty($contributors))
3466                 {
3467                         return SimplePie_Misc::array_unique($contributors);
3468                 }
3469                 else
3470                 {
3471                         return null;
3472                 }
3473         }
3474
3475         function get_authors()
3476         {
3477                 $authors = array();
3478                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3479                 {
3480                         $name = null;
3481                         $uri = null;
3482                         $email = null;
3483                         $avatar = null;
3484                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3485                         {
3486                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3487                         }
3488                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3489                         {
3490                                 $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]));
3491                         }
3492                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3493                         {
3494                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3495                         }
3496                         if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
3497                         {
3498                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
3499                         }
3500                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null)
3501                         {
3502                                 $authors[] = new $this->feed->author_class($name, $uri, $email, $avatar);
3503
3504                         }
3505                 }
3506                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3507                 {
3508                         $name = null;
3509                         $url = null;
3510                         $email = null;
3511                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3512                         {
3513                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3514                         }
3515                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3516                         {
3517                                 $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]));
3518                         }
3519                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3520                         {
3521                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3522                         }
3523                         if ($name !== null || $email !== null || $url !== null)
3524                         {
3525                                 $authors[] = new $this->feed->author_class($name, $url, $email);
3526                         }
3527                 }
3528                 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3529                 {
3530                         $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3531                 }
3532                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3533                 {
3534                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3535                 }
3536                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3537                 {
3538                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3539                 }
3540                 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3541                 {
3542                         $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3543                 }
3544
3545                 if (!empty($authors))
3546                 {
3547                         return SimplePie_Misc::array_unique($authors);
3548                 }
3549                 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3550                 {
3551                         return $authors;
3552                 }
3553                 elseif ($authors = $this->feed->get_authors())
3554                 {
3555                         return $authors;
3556                 }
3557                 else
3558                 {
3559                         return null;
3560                 }
3561         }
3562
3563         function get_copyright()
3564         {
3565                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3566                 {
3567                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3568                 }
3569                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3570                 {
3571                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3572                 }
3573                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3574                 {
3575                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3576                 }
3577                 else
3578                 {
3579                         return null;
3580                 }
3581         }
3582
3583         function get_date($date_format = 'j F Y, g:i a')
3584         {
3585                 if (!isset($this->data['date']))
3586                 {
3587                         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3588                         {
3589                                 $this->data['date']['raw'] = $return[0]['data'];
3590                         }
3591                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3592                         {
3593                                 $this->data['date']['raw'] = $return[0]['data'];
3594                         }
3595                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3596                         {
3597                                 $this->data['date']['raw'] = $return[0]['data'];
3598                         }
3599                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3600                         {
3601                                 $this->data['date']['raw'] = $return[0]['data'];
3602                         }
3603                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3604                         {
3605                                 $this->data['date']['raw'] = $return[0]['data'];
3606                         }
3607                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3608                         {
3609                                 $this->data['date']['raw'] = $return[0]['data'];
3610                         }
3611                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3612                         {
3613                                 $this->data['date']['raw'] = $return[0]['data'];
3614                         }
3615                         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3616                         {
3617                                 $this->data['date']['raw'] = $return[0]['data'];
3618                         }
3619
3620                         if (!empty($this->data['date']['raw']))
3621                         {
3622                                 $parser = SimplePie_Parse_Date::get();
3623                                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3624                         }
3625                         else
3626                         {
3627                                 $this->data['date'] = null;
3628                         }
3629                 }
3630                 if ($this->data['date'])
3631                 {
3632                         $date_format = (string) $date_format;
3633                         switch ($date_format)
3634                         {
3635                                 case '':
3636                                         return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3637
3638                                 case 'U':
3639                                         return $this->data['date']['parsed'];
3640
3641                                 default:
3642                                         return date($date_format, $this->data['date']['parsed']);
3643                         }
3644                 }
3645                 else
3646                 {
3647                         return null;
3648                 }
3649         }
3650
3651         function get_local_date($date_format = '%c')
3652         {
3653                 if (!$date_format)
3654                 {
3655                         return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3656                 }
3657                 elseif (($date = $this->get_date('U')) !== null)
3658                 {
3659                         return strftime($date_format, $date);
3660                 }
3661                 else
3662                 {
3663                         return null;
3664                 }
3665         }
3666
3667         function get_permalink()
3668         {
3669                 $link = $this->get_link();
3670                 $enclosure = $this->get_enclosure(0);
3671                 if ($link !== null)
3672                 {
3673                         return $link;
3674                 }
3675                 elseif ($enclosure !== null)
3676                 {
3677                         return $enclosure->get_link();
3678                 }
3679                 else
3680                 {
3681                         return null;
3682                 }
3683         }
3684
3685         function get_link($key = 0, $rel = 'alternate')
3686         {
3687                 $links = $this->get_links($rel);
3688                 if ($links[$key] !== null)
3689                 {
3690                         return $links[$key];
3691                 }
3692                 else
3693                 {
3694                         return null;
3695                 }
3696         }
3697
3698         function get_links($rel = 'alternate')
3699         {
3700                 if (!isset($this->data['links']))
3701                 {
3702                         $this->data['links'] = array();
3703                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3704                         {
3705                                 if (isset($link['attribs']['']['href']))
3706                                 {
3707                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3708                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3709
3710                                 }
3711                         }
3712                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3713                         {
3714                                 if (isset($link['attribs']['']['href']))
3715                                 {
3716                                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3717                                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3718                                 }
3719                         }
3720                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3721                         {
3722                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3723                         }
3724                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3725                         {
3726                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3727                         }
3728                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3729                         {
3730                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3731                         }
3732                         if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3733                         {
3734                                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3735                                 {
3736                                         $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3737                                 }
3738                         }
3739
3740                         $keys = array_keys($this->data['links']);
3741                         foreach ($keys as $key)
3742                         {
3743                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3744                                 {
3745                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3746                                         {
3747                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3748                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3749                                         }
3750                                         else
3751                                         {
3752                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3753                                         }
3754                                 }
3755                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3756                                 {
3757                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3758                                 }
3759                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3760                         }
3761                 }
3762                 if (isset($this->data['links'][$rel]))
3763                 {
3764                         return $this->data['links'][$rel];
3765                 }
3766                 else
3767                 {
3768                         return null;
3769                 }
3770         }
3771
3772         /**
3773          * @todo Add ability to prefer one type of content over another (in a media group).
3774          */
3775         function get_enclosure($key = 0, $prefer = null)
3776         {
3777                 $enclosures = $this->get_enclosures();
3778                 if (isset($enclosures[$key]))
3779                 {
3780                         return $enclosures[$key];
3781                 }
3782                 else
3783                 {
3784                         return null;
3785                 }
3786         }
3787
3788         /**
3789          * Grabs all available enclosures (podcasts, etc.)
3790          *
3791          * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3792          *
3793          * 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.
3794          *
3795          * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3796          * @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).
3797          */
3798         function get_enclosures()
3799         {
3800                 if (!isset($this->data['enclosures']))
3801                 {
3802                         $this->data['enclosures'] = array();
3803
3804                         // Elements
3805                         $captions_parent = null;
3806                         $categories_parent = null;
3807                         $copyrights_parent = null;
3808                         $credits_parent = null;
3809                         $description_parent = null;
3810                         $duration_parent = null;
3811                         $hashes_parent = null;
3812                         $keywords_parent = null;
3813                         $player_parent = null;
3814                         $ratings_parent = null;
3815                         $restrictions_parent = null;
3816                         $thumbnails_parent = null;
3817                         $title_parent = null;
3818
3819                         // Let's do the channel and item-level ones first, and just re-use them if we need to.
3820                         $parent = $this->get_feed();
3821
3822                         // CAPTIONS
3823                         if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3824                         {
3825                                 foreach ($captions as $caption)
3826                                 {
3827                                         $caption_type = null;
3828                                         $caption_lang = null;
3829                                         $caption_startTime = null;
3830                                         $caption_endTime = null;
3831                                         $caption_text = null;
3832                                         if (isset($caption['attribs']['']['type']))
3833                                         {
3834                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3835                                         }
3836                                         if (isset($caption['attribs']['']['lang']))
3837                                         {
3838                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3839                                         }
3840                                         if (isset($caption['attribs']['']['start']))
3841                                         {
3842                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3843                                         }
3844                                         if (isset($caption['attribs']['']['end']))
3845                                         {
3846                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3847                                         }
3848                                         if (isset($caption['data']))
3849                                         {
3850                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3851                                         }
3852                                         $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3853                                 }
3854                         }
3855                         elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3856                         {
3857                                 foreach ($captions as $caption)
3858                                 {
3859                                         $caption_type = null;
3860                                         $caption_lang = null;
3861                                         $caption_startTime = null;
3862                                         $caption_endTime = null;
3863                                         $caption_text = null;
3864                                         if (isset($caption['attribs']['']['type']))
3865                                         {
3866                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3867                                         }
3868                                         if (isset($caption['attribs']['']['lang']))
3869                                         {
3870                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3871                                         }
3872                                         if (isset($caption['attribs']['']['start']))
3873                                         {
3874                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3875                                         }
3876                                         if (isset($caption['attribs']['']['end']))
3877                                         {
3878                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3879                                         }
3880                                         if (isset($caption['data']))
3881                                         {
3882                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3883                                         }
3884                                         $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3885                                 }
3886                         }
3887                         if (is_array($captions_parent))
3888                         {
3889                                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3890                         }
3891
3892                         // CATEGORIES
3893                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3894                         {
3895                                 $term = null;
3896                                 $scheme = null;
3897                                 $label = null;
3898                                 if (isset($category['data']))
3899                                 {
3900                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3901                                 }
3902                                 if (isset($category['attribs']['']['scheme']))
3903                                 {
3904                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3905                                 }
3906                                 else
3907                                 {
3908                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3909                                 }
3910                                 if (isset($category['attribs']['']['label']))
3911                                 {
3912                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3913                                 }
3914                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3915                         }
3916                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3917                         {
3918                                 $term = null;
3919                                 $scheme = null;
3920                                 $label = null;
3921                                 if (isset($category['data']))
3922                                 {
3923                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3924                                 }
3925                                 if (isset($category['attribs']['']['scheme']))
3926                                 {
3927                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3928                                 }
3929                                 else
3930                                 {
3931                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
3932                                 }
3933                                 if (isset($category['attribs']['']['label']))
3934                                 {
3935                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3936                                 }
3937                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3938                         }
3939                         foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3940                         {
3941                                 $term = null;
3942                                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3943                                 $label = null;
3944                                 if (isset($category['attribs']['']['text']))
3945                                 {
3946                                         $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3947                                 }
3948                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3949
3950                                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3951                                 {
3952                                         foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3953                                         {
3954                                                 if (isset($subcategory['attribs']['']['text']))
3955                                                 {
3956                                                         $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3957                                                 }
3958                                                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3959                                         }
3960                                 }
3961                         }
3962                         if (is_array($categories_parent))
3963                         {
3964                                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3965                         }
3966
3967                         // COPYRIGHT
3968                         if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3969                         {
3970                                 $copyright_url = null;
3971                                 $copyright_label = null;
3972                                 if (isset($copyright[0]['attribs']['']['url']))
3973                                 {
3974                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3975                                 }
3976                                 if (isset($copyright[0]['data']))
3977                                 {
3978                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3979                                 }
3980                                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
3981                         }
3982                         elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3983                         {
3984                                 $copyright_url = null;
3985                                 $copyright_label = null;
3986                                 if (isset($copyright[0]['attribs']['']['url']))
3987                                 {
3988                                         $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3989                                 }
3990                                 if (isset($copyright[0]['data']))
3991                                 {
3992                                         $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3993                                 }
3994                                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
3995                         }
3996
3997                         // CREDITS
3998                         if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3999                         {
4000                                 foreach ($credits as $credit)
4001                                 {
4002                                         $credit_role = null;
4003                                         $credit_scheme = null;
4004                                         $credit_name = null;
4005                                         if (isset($credit['attribs']['']['role']))
4006                                         {
4007                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4008                                         }
4009                                         if (isset($credit['attribs']['']['scheme']))
4010                                         {
4011                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4012                                         }
4013                                         else
4014                                         {
4015                                                 $credit_scheme = 'urn:ebu';
4016                                         }
4017                                         if (isset($credit['data']))
4018                                         {
4019                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4020                                         }
4021                                         $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4022                                 }
4023                         }
4024                         elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4025                         {
4026                                 foreach ($credits as $credit)
4027                                 {
4028                                         $credit_role = null;
4029                                         $credit_scheme = null;
4030                                         $credit_name = null;
4031                                         if (isset($credit['attribs']['']['role']))
4032                                         {
4033                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4034                                         }
4035                                         if (isset($credit['attribs']['']['scheme']))
4036                                         {
4037                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4038                                         }
4039                                         else
4040                                         {
4041                                                 $credit_scheme = 'urn:ebu';
4042                                         }
4043                                         if (isset($credit['data']))
4044                                         {
4045                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4046                                         }
4047                                         $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4048                                 }
4049                         }
4050                         if (is_array($credits_parent))
4051                         {
4052                                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4053                         }
4054
4055                         // DESCRIPTION
4056                         if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4057                         {
4058                                 if (isset($description_parent[0]['data']))
4059                                 {
4060                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4061                                 }
4062                         }
4063                         elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4064                         {
4065                                 if (isset($description_parent[0]['data']))
4066                                 {
4067                                         $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4068                                 }
4069                         }
4070
4071                         // DURATION
4072                         if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4073                         {
4074                                 $seconds = null;
4075                                 $minutes = null;
4076                                 $hours = null;
4077                                 if (isset($duration_parent[0]['data']))
4078                                 {
4079                                         $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4080                                         if (sizeof($temp) > 0)
4081                                         {
4082                                                 (int) $seconds = array_pop($temp);
4083                                         }
4084                                         if (sizeof($temp) > 0)
4085                                         {
4086                                                 (int) $minutes = array_pop($temp);
4087                                                 $seconds += $minutes * 60;
4088                                         }
4089                                         if (sizeof($temp) > 0)
4090                                         {
4091                                                 (int) $hours = array_pop($temp);
4092                                                 $seconds += $hours * 3600;
4093                                         }
4094                                         unset($temp);
4095                                         $duration_parent = $seconds;
4096                                 }
4097                         }
4098
4099                         // HASHES
4100                         if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4101                         {
4102                                 foreach ($hashes_iterator as $hash)
4103                                 {
4104                                         $value = null;
4105                                         $algo = null;
4106                                         if (isset($hash['data']))
4107                                         {
4108                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4109                                         }
4110                                         if (isset($hash['attribs']['']['algo']))
4111                                         {
4112                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4113                                         }
4114                                         else
4115                                         {
4116                                                 $algo = 'md5';
4117                                         }
4118                                         $hashes_parent[] = $algo.':'.$value;
4119                                 }
4120                         }
4121                         elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4122                         {
4123                                 foreach ($hashes_iterator as $hash)
4124                                 {
4125                                         $value = null;
4126                                         $algo = null;
4127                                         if (isset($hash['data']))
4128                                         {
4129                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4130                                         }
4131                                         if (isset($hash['attribs']['']['algo']))
4132                                         {
4133                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4134                                         }
4135                                         else
4136                                         {
4137                                                 $algo = 'md5';
4138                                         }
4139                                         $hashes_parent[] = $algo.':'.$value;
4140                                 }
4141                         }
4142                         if (is_array($hashes_parent))
4143                         {
4144                                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4145                         }
4146
4147                         // KEYWORDS
4148                         if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, '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 = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, '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_MEDIARSS, '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                         elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4185                         {
4186                                 if (isset($keywords[0]['data']))
4187                                 {
4188                                         $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4189                                         foreach ($temp as $word)
4190                                         {
4191                                                 $keywords_parent[] = trim($word);
4192                                         }
4193                                 }
4194                                 unset($temp);
4195                         }
4196                         if (is_array($keywords_parent))
4197                         {
4198                                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4199                         }
4200
4201                         // PLAYER
4202                         if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4203                         {
4204                                 if (isset($player_parent[0]['attribs']['']['url']))
4205                                 {
4206                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4207                                 }
4208                         }
4209                         elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4210                         {
4211                                 if (isset($player_parent[0]['attribs']['']['url']))
4212                                 {
4213                                         $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4214                                 }
4215                         }
4216
4217                         // RATINGS
4218                         if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4219                         {
4220                                 foreach ($ratings as $rating)
4221                                 {
4222                                         $rating_scheme = null;
4223                                         $rating_value = null;
4224                                         if (isset($rating['attribs']['']['scheme']))
4225                                         {
4226                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4227                                         }
4228                                         else
4229                                         {
4230                                                 $rating_scheme = 'urn:simple';
4231                                         }
4232                                         if (isset($rating['data']))
4233                                         {
4234                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4235                                         }
4236                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4237                                 }
4238                         }
4239                         elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4240                         {
4241                                 foreach ($ratings as $rating)
4242                                 {
4243                                         $rating_scheme = 'urn:itunes';
4244                                         $rating_value = null;
4245                                         if (isset($rating['data']))
4246                                         {
4247                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4248                                         }
4249                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4250                                 }
4251                         }
4252                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4253                         {
4254                                 foreach ($ratings as $rating)
4255                                 {
4256                                         $rating_scheme = null;
4257                                         $rating_value = null;
4258                                         if (isset($rating['attribs']['']['scheme']))
4259                                         {
4260                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4261                                         }
4262                                         else
4263                                         {
4264                                                 $rating_scheme = 'urn:simple';
4265                                         }
4266                                         if (isset($rating['data']))
4267                                         {
4268                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4269                                         }
4270                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4271                                 }
4272                         }
4273                         elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4274                         {
4275                                 foreach ($ratings as $rating)
4276                                 {
4277                                         $rating_scheme = 'urn:itunes';
4278                                         $rating_value = null;
4279                                         if (isset($rating['data']))
4280                                         {
4281                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4282                                         }
4283                                         $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4284                                 }
4285                         }
4286                         if (is_array($ratings_parent))
4287                         {
4288                                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4289                         }
4290
4291                         // RESTRICTIONS
4292                         if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4293                         {
4294                                 foreach ($restrictions as $restriction)
4295                                 {
4296                                         $restriction_relationship = null;
4297                                         $restriction_type = null;
4298                                         $restriction_value = null;
4299                                         if (isset($restriction['attribs']['']['relationship']))
4300                                         {
4301                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4302                                         }
4303                                         if (isset($restriction['attribs']['']['type']))
4304                                         {
4305                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4306                                         }
4307                                         if (isset($restriction['data']))
4308                                         {
4309                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4310                                         }
4311                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4312                                 }
4313                         }
4314                         elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4315                         {
4316                                 foreach ($restrictions as $restriction)
4317                                 {
4318                                         $restriction_relationship = 'allow';
4319                                         $restriction_type = null;
4320                                         $restriction_value = 'itunes';
4321                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4322                                         {
4323                                                 $restriction_relationship = 'deny';
4324                                         }
4325                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4326                                 }
4327                         }
4328                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4329                         {
4330                                 foreach ($restrictions as $restriction)
4331                                 {
4332                                         $restriction_relationship = null;
4333                                         $restriction_type = null;
4334                                         $restriction_value = null;
4335                                         if (isset($restriction['attribs']['']['relationship']))
4336                                         {
4337                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4338                                         }
4339                                         if (isset($restriction['attribs']['']['type']))
4340                                         {
4341                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4342                                         }
4343                                         if (isset($restriction['data']))
4344                                         {
4345                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4346                                         }
4347                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4348                                 }
4349                         }
4350                         elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4351                         {
4352                                 foreach ($restrictions as $restriction)
4353                                 {
4354                                         $restriction_relationship = 'allow';
4355                                         $restriction_type = null;
4356                                         $restriction_value = 'itunes';
4357                                         if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4358                                         {
4359                                                 $restriction_relationship = 'deny';
4360                                         }
4361                                         $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4362                                 }
4363                         }
4364                         if (is_array($restrictions_parent))
4365                         {
4366                                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4367                         }
4368
4369                         // THUMBNAILS
4370                         if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4371                         {
4372                                 foreach ($thumbnails as $thumbnail)
4373                                 {
4374                                         if (isset($thumbnail['attribs']['']['url']))
4375                                         {
4376                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4377                                         }
4378                                 }
4379                         }
4380                         elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4381                         {
4382                                 foreach ($thumbnails as $thumbnail)
4383                                 {
4384                                         if (isset($thumbnail['attribs']['']['url']))
4385                                         {
4386                                                 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4387                                         }
4388                                 }
4389                         }
4390
4391                         // TITLES
4392                         if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4393                         {
4394                                 if (isset($title_parent[0]['data']))
4395                                 {
4396                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4397                                 }
4398                         }
4399                         elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4400                         {
4401                                 if (isset($title_parent[0]['data']))
4402                                 {
4403                                         $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4404                                 }
4405                         }
4406
4407                         // Clear the memory
4408                         unset($parent);
4409
4410                         // Attributes
4411                         $bitrate = null;
4412                         $channels = null;
4413                         $duration = null;
4414                         $expression = null;
4415                         $framerate = null;
4416                         $height = null;
4417                         $javascript = null;
4418                         $lang = null;
4419                         $length = null;
4420                         $medium = null;
4421                         $samplingrate = null;
4422                         $type = null;
4423                         $url = null;
4424                         $width = null;
4425
4426                         // Elements
4427                         $captions = null;
4428                         $categories = null;
4429                         $copyrights = null;
4430                         $credits = null;
4431                         $description = null;
4432                         $hashes = null;
4433                         $keywords = null;
4434                         $player = null;
4435                         $ratings = null;
4436                         $restrictions = null;
4437                         $thumbnails = null;
4438                         $title = null;
4439
4440                         // If we have media:group tags, loop through them.
4441                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4442                         {
4443                                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4444                                 {
4445                                         // If we have media:content tags, loop through them.
4446                                         foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4447                                         {
4448                                                 if (isset($content['attribs']['']['url']))
4449                                                 {
4450                                                         // Attributes
4451                                                         $bitrate = null;
4452                                                         $channels = null;
4453                                                         $duration = null;
4454                                                         $expression = null;
4455                                                         $framerate = null;
4456                                                         $height = null;
4457                                                         $javascript = null;
4458                                                         $lang = null;
4459                                                         $length = null;
4460                                                         $medium = null;
4461                                                         $samplingrate = null;
4462                                                         $type = null;
4463                                                         $url = null;
4464                                                         $width = null;
4465
4466                                                         // Elements
4467                                                         $captions = null;
4468                                                         $categories = null;
4469                                                         $copyrights = null;
4470                                                         $credits = null;
4471                                                         $description = null;
4472                                                         $hashes = null;
4473                                                         $keywords = null;
4474                                                         $player = null;
4475                                                         $ratings = null;
4476                                                         $restrictions = null;
4477                                                         $thumbnails = null;
4478                                                         $title = null;
4479
4480                                                         // Start checking the attributes of media:content
4481                                                         if (isset($content['attribs']['']['bitrate']))
4482                                                         {
4483                                                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4484                                                         }
4485                                                         if (isset($content['attribs']['']['channels']))
4486                                                         {
4487                                                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4488                                                         }
4489                                                         if (isset($content['attribs']['']['duration']))
4490                                                         {
4491                                                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4492                                                         }
4493                                                         else
4494                                                         {
4495                                                                 $duration = $duration_parent;
4496                                                         }
4497                                                         if (isset($content['attribs']['']['expression']))
4498                                                         {
4499                                                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4500                                                         }
4501                                                         if (isset($content['attribs']['']['framerate']))
4502                                                         {
4503                                                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4504                                                         }
4505                                                         if (isset($content['attribs']['']['height']))
4506                                                         {
4507                                                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4508                                                         }
4509                                                         if (isset($content['attribs']['']['lang']))
4510                                                         {
4511                                                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4512                                                         }
4513                                                         if (isset($content['attribs']['']['fileSize']))
4514                                                         {
4515                                                                 $length = ceil($content['attribs']['']['fileSize']);
4516                                                         }
4517                                                         if (isset($content['attribs']['']['medium']))
4518                                                         {
4519                                                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4520                                                         }
4521                                                         if (isset($content['attribs']['']['samplingrate']))
4522                                                         {
4523                                                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4524                                                         }
4525                                                         if (isset($content['attribs']['']['type']))
4526                                                         {
4527                                                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4528                                                         }
4529                                                         if (isset($content['attribs']['']['width']))
4530                                                         {
4531                                                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4532                                                         }
4533                                                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4534
4535                                                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4536
4537                                                         // CAPTIONS
4538                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4539                                                         {
4540                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4541                                                                 {
4542                                                                         $caption_type = null;
4543                                                                         $caption_lang = null;
4544                                                                         $caption_startTime = null;
4545                                                                         $caption_endTime = null;
4546                                                                         $caption_text = null;
4547                                                                         if (isset($caption['attribs']['']['type']))
4548                                                                         {
4549                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4550                                                                         }
4551                                                                         if (isset($caption['attribs']['']['lang']))
4552                                                                         {
4553                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4554                                                                         }
4555                                                                         if (isset($caption['attribs']['']['start']))
4556                                                                         {
4557                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4558                                                                         }
4559                                                                         if (isset($caption['attribs']['']['end']))
4560                                                                         {
4561                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4562                                                                         }
4563                                                                         if (isset($caption['data']))
4564                                                                         {
4565                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4566                                                                         }
4567                                                                         $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4568                                                                 }
4569                                                                 if (is_array($captions))
4570                                                                 {
4571                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4572                                                                 }
4573                                                         }
4574                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4575                                                         {
4576                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4577                                                                 {
4578                                                                         $caption_type = null;
4579                                                                         $caption_lang = null;
4580                                                                         $caption_startTime = null;
4581                                                                         $caption_endTime = null;
4582                                                                         $caption_text = null;
4583                                                                         if (isset($caption['attribs']['']['type']))
4584                                                                         {
4585                                                                                 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4586                                                                         }
4587                                                                         if (isset($caption['attribs']['']['lang']))
4588                                                                         {
4589                                                                                 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4590                                                                         }
4591                                                                         if (isset($caption['attribs']['']['start']))
4592                                                                         {
4593                                                                                 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4594                                                                         }
4595                                                                         if (isset($caption['attribs']['']['end']))
4596                                                                         {
4597                                                                                 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4598                                                                         }
4599                                                                         if (isset($caption['data']))
4600                                                                         {
4601                                                                                 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4602                                                                         }
4603                                                                         $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4604                                                                 }
4605                                                                 if (is_array($captions))
4606                                                                 {
4607                                                                         $captions = array_values(SimplePie_Misc::array_unique($captions));
4608                                                                 }
4609                                                         }
4610                                                         else
4611                                                         {
4612                                                                 $captions = $captions_parent;
4613                                                         }
4614
4615                                                         // CATEGORIES
4616                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4617                                                         {
4618                                                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4619                                                                 {
4620                                                                         $term = null;
4621                                                                         $scheme = null;
4622                                                                         $label = null;
4623                                                                         if (isset($category['data']))
4624                                                                         {
4625                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4626                                                                         }
4627                                                                         if (isset($category['attribs']['']['scheme']))
4628                                                                         {
4629                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4630                                                                         }
4631                                                                         else
4632                                                                         {
4633                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4634                                                                         }
4635                                                                         if (isset($category['attribs']['']['label']))
4636                                                                         {
4637                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4638                                                                         }
4639                                                                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
4640                                                                 }
4641                                                         }
4642                                                         if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4643                                                         {
4644                                                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4645                                                                 {
4646                                                                         $term = null;
4647                                                                         $scheme = null;
4648                                                                         $label = null;
4649                                                                         if (isset($category['data']))
4650                                                                         {
4651                                                                                 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4652                                                                         }
4653                                                                         if (isset($category['attribs']['']['scheme']))
4654                                                                         {
4655                                                                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4656                                                                         }
4657                                                                         else
4658                                                                         {
4659                                                                                 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4660                                                                         }
4661                                                                         if (isset($category['attribs']['']['label']))
4662                                                                         {
4663                                                                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4664                                                                         }
4665                                                                         $categories[] = new $this->feed->category_class($term, $scheme, $label);
4666                                                                 }
4667                                                         }
4668                                                         if (is_array($categories) && is_array($categories_parent))
4669                                                         {
4670                                                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4671                                                         }
4672                                                         elseif (is_array($categories))
4673                                                         {
4674                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
4675                                                         }
4676                                                         elseif (is_array($categories_parent))
4677                                                         {
4678                                                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4679                                                         }
4680
4681                                                         // COPYRIGHTS
4682                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4683                                                         {
4684                                                                 $copyright_url = null;
4685                                                                 $copyright_label = null;
4686                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4687                                                                 {
4688                                                                         $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4689                                                                 }
4690                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4691                                                                 {
4692                                                                         $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4693                                                                 }
4694                                                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4695                                                         }
4696                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4697                                                         {
4698                                                                 $copyright_url = null;
4699                                                                 $copyright_label = null;
4700                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4701                                                                 {
4702                                                                         $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4703                                                                 }
4704                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4705                                                                 {
4706                                                                         $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4707                                                                 }
4708                                                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4709                                                         }
4710                                                         else
4711                                                         {
4712                                                                 $copyrights = $copyrights_parent;
4713                                                         }
4714
4715                                                         // CREDITS
4716                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4717                                                         {
4718                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4719                                                                 {
4720                                                                         $credit_role = null;
4721                                                                         $credit_scheme = null;
4722                                                                         $credit_name = null;
4723                                                                         if (isset($credit['attribs']['']['role']))
4724                                                                         {
4725                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4726                                                                         }
4727                                                                         if (isset($credit['attribs']['']['scheme']))
4728                                                                         {
4729                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4730                                                                         }
4731                                                                         else
4732                                                                         {
4733                                                                                 $credit_scheme = 'urn:ebu';
4734                                                                         }
4735                                                                         if (isset($credit['data']))
4736                                                                         {
4737                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4738                                                                         }
4739                                                                         $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4740                                                                 }
4741                                                                 if (is_array($credits))
4742                                                                 {
4743                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4744                                                                 }
4745                                                         }
4746                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4747                                                         {
4748                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4749                                                                 {
4750                                                                         $credit_role = null;
4751                                                                         $credit_scheme = null;
4752                                                                         $credit_name = null;
4753                                                                         if (isset($credit['attribs']['']['role']))
4754                                                                         {
4755                                                                                 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4756                                                                         }
4757                                                                         if (isset($credit['attribs']['']['scheme']))
4758                                                                         {
4759                                                                                 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4760                                                                         }
4761                                                                         else
4762                                                                         {
4763                                                                                 $credit_scheme = 'urn:ebu';
4764                                                                         }
4765                                                                         if (isset($credit['data']))
4766                                                                         {
4767                                                                                 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4768                                                                         }
4769                                                                         $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4770                                                                 }
4771                                                                 if (is_array($credits))
4772                                                                 {
4773                                                                         $credits = array_values(SimplePie_Misc::array_unique($credits));
4774                                                                 }
4775                                                         }
4776                                                         else
4777                                                         {
4778                                                                 $credits = $credits_parent;
4779                                                         }
4780
4781                                                         // DESCRIPTION
4782                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4783                                                         {
4784                                                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4785                                                         }
4786                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4787                                                         {
4788                                                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4789                                                         }
4790                                                         else
4791                                                         {
4792                                                                 $description = $description_parent;
4793                                                         }
4794
4795                                                         // HASHES
4796                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4797                                                         {
4798                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4799                                                                 {
4800                                                                         $value = null;
4801                                                                         $algo = null;
4802                                                                         if (isset($hash['data']))
4803                                                                         {
4804                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4805                                                                         }
4806                                                                         if (isset($hash['attribs']['']['algo']))
4807                                                                         {
4808                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4809                                                                         }
4810                                                                         else
4811                                                                         {
4812                                                                                 $algo = 'md5';
4813                                                                         }
4814                                                                         $hashes[] = $algo.':'.$value;
4815                                                                 }
4816                                                                 if (is_array($hashes))
4817                                                                 {
4818                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4819                                                                 }
4820                                                         }
4821                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4822                                                         {
4823                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4824                                                                 {
4825                                                                         $value = null;
4826                                                                         $algo = null;
4827                                                                         if (isset($hash['data']))
4828                                                                         {
4829                                                                                 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4830                                                                         }
4831                                                                         if (isset($hash['attribs']['']['algo']))
4832                                                                         {
4833                                                                                 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4834                                                                         }
4835                                                                         else
4836                                                                         {
4837                                                                                 $algo = 'md5';
4838                                                                         }
4839                                                                         $hashes[] = $algo.':'.$value;
4840                                                                 }
4841                                                                 if (is_array($hashes))
4842                                                                 {
4843                                                                         $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4844                                                                 }
4845                                                         }
4846                                                         else
4847                                                         {
4848                                                                 $hashes = $hashes_parent;
4849                                                         }
4850
4851                                                         // KEYWORDS
4852                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4853                                                         {
4854                                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4855                                                                 {
4856                                                                         $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4857                                                                         foreach ($temp as $word)
4858                                                                         {
4859                                                                                 $keywords[] = trim($word);
4860                                                                         }
4861                                                                         unset($temp);
4862                                                                 }
4863                                                                 if (is_array($keywords))
4864                                                                 {
4865                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4866                                                                 }
4867                                                         }
4868                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4869                                                         {
4870                                                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4871                                                                 {
4872                                                                         $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4873                                                                         foreach ($temp as $word)
4874                                                                         {
4875                                                                                 $keywords[] = trim($word);
4876                                                                         }
4877                                                                         unset($temp);
4878                                                                 }
4879                                                                 if (is_array($keywords))
4880                                                                 {
4881                                                                         $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4882                                                                 }
4883                                                         }
4884                                                         else
4885                                                         {
4886                                                                 $keywords = $keywords_parent;
4887                                                         }
4888
4889                                                         // PLAYER
4890                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4891                                                         {
4892                                                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4893                                                         }
4894                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4895                                                         {
4896                                                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4897                                                         }
4898                                                         else
4899                                                         {
4900                                                                 $player = $player_parent;
4901                                                         }
4902
4903                                                         // RATINGS
4904                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4905                                                         {
4906                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4907                                                                 {
4908                                                                         $rating_scheme = null;
4909                                                                         $rating_value = null;
4910                                                                         if (isset($rating['attribs']['']['scheme']))
4911                                                                         {
4912                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4913                                                                         }
4914                                                                         else
4915                                                                         {
4916                                                                                 $rating_scheme = 'urn:simple';
4917                                                                         }
4918                                                                         if (isset($rating['data']))
4919                                                                         {
4920                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4921                                                                         }
4922                                                                         $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4923                                                                 }
4924                                                                 if (is_array($ratings))
4925                                                                 {
4926                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4927                                                                 }
4928                                                         }
4929                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4930                                                         {
4931                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4932                                                                 {
4933                                                                         $rating_scheme = null;
4934                                                                         $rating_value = null;
4935                                                                         if (isset($rating['attribs']['']['scheme']))
4936                                                                         {
4937                                                                                 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4938                                                                         }
4939                                                                         else
4940                                                                         {
4941                                                                                 $rating_scheme = 'urn:simple';
4942                                                                         }
4943                                                                         if (isset($rating['data']))
4944                                                                         {
4945                                                                                 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4946                                                                         }
4947                                                                         $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4948                                                                 }
4949                                                                 if (is_array($ratings))
4950                                                                 {
4951                                                                         $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4952                                                                 }
4953                                                         }
4954                                                         else
4955                                                         {
4956                                                                 $ratings = $ratings_parent;
4957                                                         }
4958
4959                                                         // RESTRICTIONS
4960                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4961                                                         {
4962                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4963                                                                 {
4964                                                                         $restriction_relationship = null;
4965                                                                         $restriction_type = null;
4966                                                                         $restriction_value = null;
4967                                                                         if (isset($restriction['attribs']['']['relationship']))
4968                                                                         {
4969                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4970                                                                         }
4971                                                                         if (isset($restriction['attribs']['']['type']))
4972                                                                         {
4973                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4974                                                                         }
4975                                                                         if (isset($restriction['data']))
4976                                                                         {
4977                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4978                                                                         }
4979                                                                         $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4980                                                                 }
4981                                                                 if (is_array($restrictions))
4982                                                                 {
4983                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4984                                                                 }
4985                                                         }
4986                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4987                                                         {
4988                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4989                                                                 {
4990                                                                         $restriction_relationship = null;
4991                                                                         $restriction_type = null;
4992                                                                         $restriction_value = null;
4993                                                                         if (isset($restriction['attribs']['']['relationship']))
4994                                                                         {
4995                                                                                 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4996                                                                         }
4997                                                                         if (isset($restriction['attribs']['']['type']))
4998                                                                         {
4999                                                                                 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5000                                                                         }
5001                                                                         if (isset($restriction['data']))
5002                                                                         {
5003                                                                                 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5004                                                                         }
5005                                                                         $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5006                                                                 }
5007                                                                 if (is_array($restrictions))
5008                                                                 {
5009                                                                         $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5010                                                                 }
5011                                                         }
5012                                                         else
5013                                                         {
5014                                                                 $restrictions = $restrictions_parent;
5015                                                         }
5016
5017                                                         // THUMBNAILS
5018                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5019                                                         {
5020                                                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5021                                                                 {
5022                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5023                                                                 }
5024                                                                 if (is_array($thumbnails))
5025                                                                 {
5026                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5027                                                                 }
5028                                                         }
5029                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5030                                                         {
5031                                                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5032                                                                 {
5033                                                                         $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5034                                                                 }
5035                                                                 if (is_array($thumbnails))
5036                                                                 {
5037                                                                         $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5038                                                                 }
5039                                                         }
5040                                                         else
5041                                                         {
5042                                                                 $thumbnails = $thumbnails_parent;
5043                                                         }
5044
5045                                                         // TITLES
5046                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5047                                                         {
5048                                                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5049                                                         }
5050                                                         elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5051                                                         {
5052                                                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5053                                                         }
5054                                                         else
5055                                                         {
5056                                                                 $title = $title_parent;
5057                                                         }
5058
5059                                                         $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);
5060                                                 }
5061                                         }
5062                                 }
5063                         }
5064
5065                         // If we have standalone media:content tags, loop through them.
5066                         if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5067                         {
5068                                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5069                                 {
5070                                         if (isset($content['attribs']['']['url']))
5071                                         {
5072                                                 // Attributes
5073                                                 $bitrate = null;
5074                                                 $channels = null;
5075                                                 $duration = null;
5076                                                 $expression = null;
5077                                                 $framerate = null;
5078                                                 $height = null;
5079                                                 $javascript = null;
5080                                                 $lang = null;
5081                                                 $length = null;
5082                                                 $medium = null;
5083                                                 $samplingrate = null;
5084                                                 $type = null;
5085                                                 $url = null;
5086                                                 $width = null;
5087
5088                                                 // Elements
5089                                                 $captions = null;
5090                                                 $categories = null;
5091                                                 $copyrights = null;
5092                                                 $credits = null;
5093                                                 $description = null;
5094                                                 $hashes = null;
5095                                                 $keywords = null;
5096                                                 $player = null;
5097                                                 $ratings = null;
5098                                                 $restrictions = null;
5099                                                 $thumbnails = null;
5100                                                 $title = null;
5101
5102                                                 // Start checking the attributes of media:content
5103                                                 if (isset($content['attribs']['']['bitrate']))
5104                                                 {
5105                                                         $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5106                                                 }
5107                                                 if (isset($content['attribs']['']['channels']))
5108                                                 {
5109                                                         $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5110                                                 }
5111                                                 if (isset($content['attribs']['']['duration']))
5112                                                 {
5113                                                         $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5114                                                 }
5115                                                 else
5116                                                 {
5117                                                         $duration = $duration_parent;
5118                                                 }
5119                                                 if (isset($content['attribs']['']['expression']))
5120                                                 {
5121                                                         $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5122                                                 }
5123                                                 if (isset($content['attribs']['']['framerate']))
5124                                                 {
5125                                                         $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5126                                                 }
5127                                                 if (isset($content['attribs']['']['height']))
5128                                                 {
5129                                                         $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5130                                                 }
5131                                                 if (isset($content['attribs']['']['lang']))
5132                                                 {
5133                                                         $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5134                                                 }
5135                                                 if (isset($content['attribs']['']['fileSize']))
5136                                                 {
5137                                                         $length = ceil($content['attribs']['']['fileSize']);
5138                                                 }
5139                                                 if (isset($content['attribs']['']['medium']))
5140                                                 {
5141                                                         $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5142                                                 }
5143                                                 if (isset($content['attribs']['']['samplingrate']))
5144                                                 {
5145                                                         $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5146                                                 }
5147                                                 if (isset($content['attribs']['']['type']))
5148                                                 {
5149                                                         $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5150                                                 }
5151                                                 if (isset($content['attribs']['']['width']))
5152                                                 {
5153                                                         $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5154                                                 }
5155                                                 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5156
5157                                                 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5158
5159                                                 // CAPTIONS
5160                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5161                                                 {
5162                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5163                                                         {
5164                                                                 $caption_type = null;
5165                                                                 $caption_lang = null;
5166                                                                 $caption_startTime = null;
5167                                                                 $caption_endTime = null;
5168                                                                 $caption_text = null;
5169                                                                 if (isset($caption['attribs']['']['type']))
5170                                                                 {
5171                                                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5172                                                                 }
5173                                                                 if (isset($caption['attribs']['']['lang']))
5174                                                                 {
5175                                                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5176                                                                 }
5177                                                                 if (isset($caption['attribs']['']['start']))
5178                                                                 {
5179                                                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5180                                                                 }
5181                                                                 if (isset($caption['attribs']['']['end']))
5182                                                                 {
5183                                                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5184                                                                 }
5185                                                                 if (isset($caption['data']))
5186                                                                 {
5187                                                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5188                                                                 }
5189                                                                 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5190                                                         }
5191                                                         if (is_array($captions))
5192                                                         {
5193                                                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5194                                                         }
5195                                                 }
5196                                                 else
5197                                                 {
5198                                                         $captions = $captions_parent;
5199                                                 }
5200
5201                                                 // CATEGORIES
5202                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5203                                                 {
5204                                                         foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5205                                                         {
5206                                                                 $term = null;
5207                                                                 $scheme = null;
5208                                                                 $label = null;
5209                                                                 if (isset($category['data']))
5210                                                                 {
5211                                                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5212                                                                 }
5213                                                                 if (isset($category['attribs']['']['scheme']))
5214                                                                 {
5215                                                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5216                                                                 }
5217                                                                 else
5218                                                                 {
5219                                                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
5220                                                                 }
5221                                                                 if (isset($category['attribs']['']['label']))
5222                                                                 {
5223                                                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5224                                                                 }
5225                                                                 $categories[] = new $this->feed->category_class($term, $scheme, $label);
5226                                                         }
5227                                                 }
5228                                                 if (is_array($categories) && is_array($categories_parent))
5229                                                 {
5230                                                         $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5231                                                 }
5232                                                 elseif (is_array($categories))
5233                                                 {
5234                                                         $categories = array_values(SimplePie_Misc::array_unique($categories));
5235                                                 }
5236                                                 elseif (is_array($categories_parent))
5237                                                 {
5238                                                         $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5239                                                 }
5240                                                 else
5241                                                 {
5242                                                         $categories = null;
5243                                                 }
5244
5245                                                 // COPYRIGHTS
5246                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5247                                                 {
5248                                                         $copyright_url = null;
5249                                                         $copyright_label = null;
5250                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5251                                                         {
5252                                                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5253                                                         }
5254                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5255                                                         {
5256                                                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5257                                                         }
5258                                                         $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
5259                                                 }
5260                                                 else
5261                                                 {
5262                                                         $copyrights = $copyrights_parent;
5263                                                 }
5264
5265                                                 // CREDITS
5266                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5267                                                 {
5268                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5269                                                         {
5270                                                                 $credit_role = null;
5271                                                                 $credit_scheme = null;
5272                                                                 $credit_name = null;
5273                                                                 if (isset($credit['attribs']['']['role']))
5274                                                                 {
5275                                                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5276                                                                 }
5277                                                                 if (isset($credit['attribs']['']['scheme']))
5278                                                                 {
5279                                                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5280                                                                 }
5281                                                                 else
5282                                                                 {
5283                                                                         $credit_scheme = 'urn:ebu';
5284                                                                 }
5285                                                                 if (isset($credit['data']))
5286                                                                 {
5287                                                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5288                                                                 }
5289                                                                 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5290                                                         }
5291                                                         if (is_array($credits))
5292                                                         {
5293                                                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5294                                                         }
5295                                                 }
5296                                                 else
5297                                                 {
5298                                                         $credits = $credits_parent;
5299                                                 }
5300
5301                                                 // DESCRIPTION
5302                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5303                                                 {
5304                                                         $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5305                                                 }
5306                                                 else
5307                                                 {
5308                                                         $description = $description_parent;
5309                                                 }
5310
5311                                                 // HASHES
5312                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5313                                                 {
5314                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5315                                                         {
5316                                                                 $value = null;
5317                                                                 $algo = null;
5318                                                                 if (isset($hash['data']))
5319                                                                 {
5320                                                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5321                                                                 }
5322                                                                 if (isset($hash['attribs']['']['algo']))
5323                                                                 {
5324                                                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5325                                                                 }
5326                                                                 else
5327                                                                 {
5328                                                                         $algo = 'md5';
5329                                                                 }
5330                                                                 $hashes[] = $algo.':'.$value;
5331                                                         }
5332                                                         if (is_array($hashes))
5333                                                         {
5334                                                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5335                                                         }
5336                                                 }
5337                                                 else
5338                                                 {
5339                                                         $hashes = $hashes_parent;
5340                                                 }
5341
5342                                                 // KEYWORDS
5343                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5344                                                 {
5345                                                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5346                                                         {
5347                                                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5348                                                                 foreach ($temp as $word)
5349                                                                 {
5350                                                                         $keywords[] = trim($word);
5351                                                                 }
5352                                                                 unset($temp);
5353                                                         }
5354                                                         if (is_array($keywords))
5355                                                         {
5356                                                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5357                                                         }
5358                                                 }
5359                                                 else
5360                                                 {
5361                                                         $keywords = $keywords_parent;
5362                                                 }
5363
5364                                                 // PLAYER
5365                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5366                                                 {
5367                                                         $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5368                                                 }
5369                                                 else
5370                                                 {
5371                                                         $player = $player_parent;
5372                                                 }
5373
5374                                                 // RATINGS
5375                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5376                                                 {
5377                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5378                                                         {
5379                                                                 $rating_scheme = null;
5380                                                                 $rating_value = null;
5381                                                                 if (isset($rating['attribs']['']['scheme']))
5382                                                                 {
5383                                                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5384                                                                 }
5385                                                                 else
5386                                                                 {
5387                                                                         $rating_scheme = 'urn:simple';
5388                                                                 }
5389                                                                 if (isset($rating['data']))
5390                                                                 {
5391                                                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5392                                                                 }
5393                                                                 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
5394                                                         }
5395                                                         if (is_array($ratings))
5396                                                         {
5397                                                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5398                                                         }
5399                                                 }
5400                                                 else
5401                                                 {
5402                                                         $ratings = $ratings_parent;
5403                                                 }
5404
5405                                                 // RESTRICTIONS
5406                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5407                                                 {
5408                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5409                                                         {
5410                                                                 $restriction_relationship = null;
5411                                                                 $restriction_type = null;
5412                                                                 $restriction_value = null;
5413                                                                 if (isset($restriction['attribs']['']['relationship']))
5414                                                                 {
5415                                                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5416                                                                 }
5417                                                                 if (isset($restriction['attribs']['']['type']))
5418                                                                 {
5419                                                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5420                                                                 }
5421                                                                 if (isset($restriction['data']))
5422                                                                 {
5423                                                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5424                                                                 }
5425                                                                 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5426                                                         }
5427                                                         if (is_array($restrictions))
5428                                                         {
5429                                                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5430                                                         }
5431                                                 }
5432                                                 else
5433                                                 {
5434                                                         $restrictions = $restrictions_parent;
5435                                                 }
5436
5437                                                 // THUMBNAILS
5438                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5439                                                 {
5440                                                         foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5441                                                         {
5442                                                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5443                                                         }
5444                                                         if (is_array($thumbnails))
5445                                                         {
5446                                                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5447                                                         }
5448                                                 }
5449                                                 else
5450                                                 {
5451                                                         $thumbnails = $thumbnails_parent;
5452                                                 }
5453
5454                                                 // TITLES
5455                                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5456                                                 {
5457                                                         $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5458                                                 }
5459                                                 else
5460                                                 {
5461                                                         $title = $title_parent;
5462                                                 }
5463
5464                                                 $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);
5465                                         }
5466                                 }
5467                         }
5468
5469                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5470                         {
5471                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5472                                 {
5473                                         // Attributes
5474                                         $bitrate = null;
5475                                         $channels = null;
5476                                         $duration = null;
5477                                         $expression = null;
5478                                         $framerate = null;
5479                                         $height = null;
5480                                         $javascript = null;
5481                                         $lang = null;
5482                                         $length = null;
5483                                         $medium = null;
5484                                         $samplingrate = null;
5485                                         $type = null;
5486                                         $url = null;
5487                                         $width = null;
5488
5489                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5490                                         if (isset($link['attribs']['']['type']))
5491                                         {
5492                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5493                                         }
5494                                         if (isset($link['attribs']['']['length']))
5495                                         {
5496                                                 $length = ceil($link['attribs']['']['length']);
5497                                         }
5498
5499                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5500                                         $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);
5501                                 }
5502                         }
5503
5504                         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5505                         {
5506                                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5507                                 {
5508                                         // Attributes
5509                                         $bitrate = null;
5510                                         $channels = null;
5511                                         $duration = null;
5512                                         $expression = null;
5513                                         $framerate = null;
5514                                         $height = null;
5515                                         $javascript = null;
5516                                         $lang = null;
5517                                         $length = null;
5518                                         $medium = null;
5519                                         $samplingrate = null;
5520                                         $type = null;
5521                                         $url = null;
5522                                         $width = null;
5523
5524                                         $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5525                                         if (isset($link['attribs']['']['type']))
5526                                         {
5527                                                 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5528                                         }
5529                                         if (isset($link['attribs']['']['length']))
5530                                         {
5531                                                 $length = ceil($link['attribs']['']['length']);
5532                                         }
5533
5534                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5535                                         $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);
5536                                 }
5537                         }
5538
5539                         if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5540                         {
5541                                 if (isset($enclosure[0]['attribs']['']['url']))
5542                                 {
5543                                         // Attributes
5544                                         $bitrate = null;
5545                                         $channels = null;
5546                                         $duration = null;
5547                                         $expression = null;
5548                                         $framerate = null;
5549                                         $height = null;
5550                                         $javascript = null;
5551                                         $lang = null;
5552                                         $length = null;
5553                                         $medium = null;
5554                                         $samplingrate = null;
5555                                         $type = null;
5556                                         $url = null;
5557                                         $width = null;
5558
5559                                         $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5560                                         if (isset($enclosure[0]['attribs']['']['type']))
5561                                         {
5562                                                 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5563                                         }
5564                                         if (isset($enclosure[0]['attribs']['']['length']))
5565                                         {
5566                                                 $length = ceil($enclosure[0]['attribs']['']['length']);
5567                                         }
5568
5569                                         // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5570                                         $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);
5571                                 }
5572                         }
5573
5574                         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))
5575                         {
5576                                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5577                                 $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);
5578                         }
5579
5580                         $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5581                 }
5582                 if (!empty($this->data['enclosures']))
5583                 {
5584                         return $this->data['enclosures'];
5585                 }
5586                 else
5587                 {
5588                         return null;
5589                 }
5590         }
5591
5592         function get_latitude()
5593         {
5594                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5595                 {
5596                         return (float) $return[0]['data'];
5597                 }
5598                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5599                 {
5600                         return (float) $match[1];
5601                 }
5602                 else
5603                 {
5604                         return null;
5605                 }
5606         }
5607
5608         function get_longitude()
5609         {
5610                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5611                 {
5612                         return (float) $return[0]['data'];
5613                 }
5614                 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5615                 {
5616                         return (float) $return[0]['data'];
5617                 }
5618                 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5619                 {
5620                         return (float) $match[2];
5621                 }
5622                 else
5623                 {
5624                         return null;
5625                 }
5626         }
5627
5628         function get_source()
5629         {
5630                 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5631                 {
5632                         return new $this->feed->source_class($this, $return[0]);
5633                 }
5634                 else
5635                 {
5636                         return null;
5637                 }
5638         }
5639
5640         /**
5641          * Creates the add_to_* methods' return data
5642          *
5643          * @access private
5644          * @param string $item_url String to prefix to the item permalink
5645          * @param string $title_url String to prefix to the item title
5646          * (and suffix to the item permalink)
5647          * @return mixed URL if feed exists, false otherwise
5648          */
5649         function add_to_service($item_url, $title_url = null, $summary_url = null)
5650         {
5651                 if ($this->get_permalink() !== null)
5652                 {
5653                         $return = $item_url . rawurlencode($this->get_permalink());
5654                         if ($title_url !== null && $this->get_title() !== null)
5655                         {
5656                                 $return .= $title_url . rawurlencode($this->get_title());
5657                         }
5658                         if ($summary_url !== null && $this->get_description() !== null)
5659                         {
5660                                 $return .= $summary_url . rawurlencode($this->get_description());
5661                         }
5662                         return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5663                 }
5664                 else
5665                 {
5666                         return null;
5667                 }
5668         }
5669
5670         function add_to_blinklist()
5671         {
5672                 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5673         }
5674
5675         function add_to_blogmarks()
5676         {
5677                 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5678         }
5679
5680         function add_to_delicious()
5681         {
5682                 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5683         }
5684
5685         function add_to_digg()
5686         {
5687                 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5688         }
5689
5690         function add_to_furl()
5691         {
5692                 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5693         }
5694
5695         function add_to_magnolia()
5696         {
5697                 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5698         }
5699
5700         function add_to_myweb20()
5701         {
5702                 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5703         }
5704
5705         function add_to_newsvine()
5706         {
5707                 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5708         }
5709
5710         function add_to_reddit()
5711         {
5712                 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5713         }
5714
5715         function add_to_segnalo()
5716         {
5717                 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5718         }
5719
5720         function add_to_simpy()
5721         {
5722                 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5723         }
5724
5725         function add_to_spurl()
5726         {
5727                 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5728         }
5729
5730         function add_to_wists()
5731         {
5732                 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5733         }
5734
5735         function search_technorati()
5736         {
5737                 return $this->add_to_service('http://www.technorati.com/search/');
5738         }
5739 }
5740
5741 class SimplePie_Source
5742 {
5743         var $item;
5744         var $data = array();
5745
5746         function SimplePie_Source($item, $data)
5747         {
5748                 $this->item = $item;
5749                 $this->data = $data;
5750         }
5751
5752         function __toString()
5753         {
5754                 return md5(serialize($this->data));
5755         }
5756
5757         function get_source_tags($namespace, $tag)
5758         {
5759                 if (isset($this->data['child'][$namespace][$tag]))
5760                 {
5761                         return $this->data['child'][$namespace][$tag];
5762                 }
5763                 else
5764                 {
5765                         return null;
5766                 }
5767         }
5768
5769         function get_base($element = array())
5770         {
5771                 return $this->item->get_base($element);
5772         }
5773
5774         function sanitize($data, $type, $base = '')
5775         {
5776                 return $this->item->sanitize($data, $type, $base);
5777         }
5778
5779         function get_item()
5780         {
5781                 return $this->item;
5782         }
5783
5784         function get_title()
5785         {
5786                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5787                 {
5788                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5789                 }
5790                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5791                 {
5792                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5793                 }
5794                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5795                 {
5796                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5797                 }
5798                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5799                 {
5800                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5801                 }
5802                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5803                 {
5804                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5805                 }
5806                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5807                 {
5808                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5809                 }
5810                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5811                 {
5812                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5813                 }
5814                 else
5815                 {
5816                         return null;
5817                 }
5818         }
5819
5820         function get_category($key = 0)
5821         {
5822                 $categories = $this->get_categories();
5823                 if (isset($categories[$key]))
5824                 {
5825                         return $categories[$key];
5826                 }
5827                 else
5828                 {
5829                         return null;
5830                 }
5831         }
5832
5833         function get_categories()
5834         {
5835                 $categories = array();
5836
5837                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5838                 {
5839                         $term = null;
5840                         $scheme = null;
5841                         $label = null;
5842                         if (isset($category['attribs']['']['term']))
5843                         {
5844                                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5845                         }
5846                         if (isset($category['attribs']['']['scheme']))
5847                         {
5848                                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5849                         }
5850                         if (isset($category['attribs']['']['label']))
5851                         {
5852                                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5853                         }
5854                         $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5855                 }
5856                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5857                 {
5858                         // This is really the label, but keep this as the term also for BC.
5859                         // Label will also work on retrieving because that falls back to term.
5860                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5861                         if (isset($category['attribs']['']['domain']))
5862                         {
5863                                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5864                         }
5865                         else
5866                         {
5867                                 $scheme = null;
5868                         }
5869                         $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5870                 }
5871                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5872                 {
5873                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5874                 }
5875                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5876                 {
5877                         $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5878                 }
5879
5880                 if (!empty($categories))
5881                 {
5882                         return SimplePie_Misc::array_unique($categories);
5883                 }
5884                 else
5885                 {
5886                         return null;
5887                 }
5888         }
5889
5890         function get_author($key = 0)
5891         {
5892                 $authors = $this->get_authors();
5893                 if (isset($authors[$key]))
5894                 {
5895                         return $authors[$key];
5896                 }
5897                 else
5898                 {
5899                         return null;
5900                 }
5901         }
5902
5903         function get_authors()
5904         {
5905                 $authors = array();
5906                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5907                 {
5908                         $name = null;
5909                         $uri = null;
5910                         $email = null;
5911                         $avatar = null;
5912                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5913                         {
5914                                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5915                         }
5916                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5917                         {
5918                                 $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]));
5919                         }
5920                         if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5921                         {
5922                                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5923                         }
5924                         {
5925                                 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
5926                         }
5927                         if ($name !== null || $email !== null || $uri !== null || $avatar !== null)
5928                         {
5929                                 $authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar);
5930
5931                         }
5932                 }
5933                 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5934                 {
5935                         $name = null;
5936                         $url = null;
5937                         $email = null;
5938                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5939                         {
5940                                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5941                         }
5942                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5943                         {
5944                                 $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]));
5945                         }
5946                         if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5947                         {
5948                                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5949                         }
5950                         if ($name !== null || $email !== null || $url !== null)
5951                         {
5952                                 $authors[] = new $this->item->feed->author_class($name, $url, $email);
5953                         }
5954                 }
5955                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5956                 {
5957                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5958                 }
5959                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5960                 {
5961                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5962                 }
5963                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5964                 {
5965                         $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5966                 }
5967
5968                 if (!empty($authors))
5969                 {
5970                         return SimplePie_Misc::array_unique($authors);
5971                 }
5972                 else
5973                 {
5974                         return null;
5975                 }
5976         }
5977
5978         function get_contributor($key = 0)
5979         {
5980                 $contributors = $this->get_contributors();
5981                 if (isset($contributors[$key]))
5982                 {
5983                         return $contributors[$key];
5984                 }
5985                 else
5986                 {
5987                         return null;
5988                 }
5989         }
5990
5991         function get_contributors()
5992         {
5993                 $contributors = array();
5994                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5995                 {
5996                         $name = null;
5997                         $uri = null;
5998                         $email = null;
5999                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6000                         {
6001                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6002                         }
6003                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6004                         {
6005                                 $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]));
6006                         }
6007                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6008                         {
6009                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6010                         }
6011                         if ($name !== null || $email !== null || $uri !== null)
6012                         {
6013                                 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
6014                         }
6015                 }
6016                 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6017                 {
6018                         $name = null;
6019                         $url = null;
6020                         $email = null;
6021                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6022                         {
6023                                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6024                         }
6025                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6026                         {
6027                                 $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]));
6028                         }
6029                         if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6030                         {
6031                                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6032                         }
6033                         if ($name !== null || $email !== null || $url !== null)
6034                         {
6035                                 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
6036                         }
6037                 }
6038
6039                 if (!empty($contributors))
6040                 {
6041                         return SimplePie_Misc::array_unique($contributors);
6042                 }
6043                 else
6044                 {
6045                         return null;
6046                 }
6047         }
6048
6049         function get_link($key = 0, $rel = 'alternate')
6050         {
6051                 $links = $this->get_links($rel);
6052                 if (isset($links[$key]))
6053                 {
6054                         return $links[$key];
6055                 }
6056                 else
6057                 {
6058                         return null;
6059                 }
6060         }
6061
6062         /**
6063          * Added for parity between the parent-level and the item/entry-level.
6064          */
6065         function get_permalink()
6066         {
6067                 return $this->get_link(0);
6068         }
6069
6070         function get_links($rel = 'alternate')
6071         {
6072                 if (!isset($this->data['links']))
6073                 {
6074                         $this->data['links'] = array();
6075                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6076                         {
6077                                 foreach ($links as $link)
6078                                 {
6079                                         if (isset($link['attribs']['']['href']))
6080                                         {
6081                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6082                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6083                                         }
6084                                 }
6085                         }
6086                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6087                         {
6088                                 foreach ($links as $link)
6089                                 {
6090                                         if (isset($link['attribs']['']['href']))
6091                                         {
6092                                                 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6093                                                 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6094
6095                                         }
6096                                 }
6097                         }
6098                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6099                         {
6100                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6101                         }
6102                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6103                         {
6104                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6105                         }
6106                         if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6107                         {
6108                                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6109                         }
6110
6111                         $keys = array_keys($this->data['links']);
6112                         foreach ($keys as $key)
6113                         {
6114                                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6115                                 {
6116                                         if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6117                                         {
6118                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6119                                                 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6120                                         }
6121                                         else
6122                                         {
6123                                                 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6124                                         }
6125                                 }
6126                                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6127                                 {
6128                                         $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6129                                 }
6130                                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6131                         }
6132                 }
6133
6134                 if (isset($this->data['links'][$rel]))
6135                 {
6136                         return $this->data['links'][$rel];
6137                 }
6138                 else
6139                 {
6140                         return null;
6141                 }
6142         }
6143
6144         function get_description()
6145         {
6146                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6147                 {
6148                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6149                 }
6150                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6151                 {
6152                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6153                 }
6154                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6155                 {
6156                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6157                 }
6158                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6159                 {
6160                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6161                 }
6162                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6163                 {
6164                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6165                 }
6166                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6167                 {
6168                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6169                 }
6170                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6171                 {
6172                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6173                 }
6174                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6175                 {
6176                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6177                 }
6178                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6179                 {
6180                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6181                 }
6182                 else
6183                 {
6184                         return null;
6185                 }
6186         }
6187
6188         function get_copyright()
6189         {
6190                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6191                 {
6192                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6193                 }
6194                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6195                 {
6196                         return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6197                 }
6198                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6199                 {
6200                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6201                 }
6202                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6203                 {
6204                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6205                 }
6206                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6207                 {
6208                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6209                 }
6210                 else
6211                 {
6212                         return null;
6213                 }
6214         }
6215
6216         function get_language()
6217         {
6218                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6219                 {
6220                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6221                 }
6222                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6223                 {
6224                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6225                 }
6226                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6227                 {
6228                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6229                 }
6230                 elseif (isset($this->data['xml_lang']))
6231                 {
6232                         return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6233                 }
6234                 else
6235                 {
6236                         return null;
6237                 }
6238         }
6239
6240         function get_latitude()
6241         {
6242                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
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]+))$/', trim($return[0]['data']), $match))
6247                 {
6248                         return (float) $match[1];
6249                 }
6250                 else
6251                 {
6252                         return null;
6253                 }
6254         }
6255
6256         function get_longitude()
6257         {
6258                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6259                 {
6260                         return (float) $return[0]['data'];
6261                 }
6262                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6263                 {
6264                         return (float) $return[0]['data'];
6265                 }
6266                 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6267                 {
6268                         return (float) $match[2];
6269                 }
6270                 else
6271                 {
6272                         return null;
6273                 }
6274         }
6275
6276         function get_image_url()
6277         {
6278                 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6279                 {
6280                         return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6281                 }
6282                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6283                 {
6284                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6285                 }
6286                 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6287                 {
6288                         return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6289                 }
6290                 else
6291                 {
6292                         return null;
6293                 }
6294         }
6295 }
6296
6297 class SimplePie_Author
6298 {
6299         var $name;
6300         var $link;
6301         var $email;
6302         var $avatar;
6303
6304         // Constructor, used to input the data
6305         function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null)
6306         {
6307                 $this->name = $name;
6308                 $this->link = $link;
6309                 $this->email = $email;
6310                 $this->avatar = $avatar;
6311         }
6312
6313         function __toString()
6314         {
6315                 // There is no $this->data here
6316                 return md5(serialize($this));
6317         }
6318
6319         function get_name()
6320         {
6321                 if ($this->name !== null)
6322                 {
6323                         return $this->name;
6324                 }
6325                 else
6326                 {
6327                         return null;
6328                 }
6329         }
6330
6331         function get_link()
6332         {
6333                 if ($this->link !== null)
6334                 {
6335                         return $this->link;
6336                 }
6337                 else
6338                 {
6339                         return null;
6340                 }
6341         }
6342
6343         function get_email()
6344         {
6345                 if ($this->email !== null)
6346                 {
6347                         return $this->email;
6348                 }
6349                 else
6350                 {
6351                         return null;
6352                 }
6353         }
6354
6355         function get_avatar()
6356         {
6357                 if ($this->avatar !== null)
6358                 {
6359                         return $this->avatar;
6360                 }
6361                 else
6362                 {
6363                         return null;
6364                 }
6365         }
6366
6367
6368 }
6369
6370 class SimplePie_Category
6371 {
6372         var $term;
6373         var $scheme;
6374         var $label;
6375
6376         // Constructor, used to input the data
6377         function SimplePie_Category($term = null, $scheme = null, $label = null)
6378         {
6379                 $this->term = $term;
6380                 $this->scheme = $scheme;
6381                 $this->label = $label;
6382         }
6383
6384         function __toString()
6385         {
6386                 // There is no $this->data here
6387                 return md5(serialize($this));
6388         }
6389
6390         function get_term()
6391         {
6392                 if ($this->term !== null)
6393                 {
6394                         return $this->term;
6395                 }
6396                 else
6397                 {
6398                         return null;
6399                 }
6400         }
6401
6402         function get_scheme()
6403         {
6404                 if ($this->scheme !== null)
6405                 {
6406                         return $this->scheme;
6407                 }
6408                 else
6409                 {
6410                         return null;
6411                 }
6412         }
6413
6414         function get_label()
6415         {
6416                 if ($this->label !== null)
6417                 {
6418                         return $this->label;
6419                 }
6420                 else
6421                 {
6422                         return $this->get_term();
6423                 }
6424         }
6425 }
6426
6427 class SimplePie_Enclosure
6428 {
6429         var $bitrate;
6430         var $captions;
6431         var $categories;
6432         var $channels;
6433         var $copyright;
6434         var $credits;
6435         var $description;
6436         var $duration;
6437         var $expression;
6438         var $framerate;
6439         var $handler;
6440         var $hashes;
6441         var $height;
6442         var $javascript;
6443         var $keywords;
6444         var $lang;
6445         var $length;
6446         var $link;
6447         var $medium;
6448         var $player;
6449         var $ratings;
6450         var $restrictions;
6451         var $samplingrate;
6452         var $thumbnails;
6453         var $title;
6454         var $type;
6455         var $width;
6456
6457         // Constructor, used to input the data
6458         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)
6459         {
6460                 $this->bitrate = $bitrate;
6461                 $this->captions = $captions;
6462                 $this->categories = $categories;
6463                 $this->channels = $channels;
6464                 $this->copyright = $copyright;
6465                 $this->credits = $credits;
6466                 $this->description = $description;
6467                 $this->duration = $duration;
6468                 $this->expression = $expression;
6469                 $this->framerate = $framerate;
6470                 $this->hashes = $hashes;
6471                 $this->height = $height;
6472                 $this->javascript = $javascript;
6473                 $this->keywords = $keywords;
6474                 $this->lang = $lang;
6475                 $this->length = $length;
6476                 $this->link = $link;
6477                 $this->medium = $medium;
6478                 $this->player = $player;
6479                 $this->ratings = $ratings;
6480                 $this->restrictions = $restrictions;
6481                 $this->samplingrate = $samplingrate;
6482                 $this->thumbnails = $thumbnails;
6483                 $this->title = $title;
6484                 $this->type = $type;
6485                 $this->width = $width;
6486                 if (class_exists('idna_convert'))
6487                 {
6488                         $idn = new idna_convert;
6489                         $parsed = SimplePie_Misc::parse_url($link);
6490                         $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6491                 }
6492                 $this->handler = $this->get_handler(); // Needs to load last
6493         }
6494
6495         function __toString()
6496         {
6497                 // There is no $this->data here
6498                 return md5(serialize($this));
6499         }
6500
6501         function get_bitrate()
6502         {
6503                 if ($this->bitrate !== null)
6504                 {
6505                         return $this->bitrate;
6506                 }
6507                 else
6508                 {
6509                         return null;
6510                 }
6511         }
6512
6513         function get_caption($key = 0)
6514         {
6515                 $captions = $this->get_captions();
6516                 if (isset($captions[$key]))
6517                 {
6518                         return $captions[$key];
6519                 }
6520                 else
6521                 {
6522                         return null;
6523                 }
6524         }
6525
6526         function get_captions()
6527         {
6528                 if ($this->captions !== null)
6529                 {
6530                         return $this->captions;
6531                 }
6532                 else
6533                 {
6534                         return null;
6535                 }
6536         }
6537
6538         function get_category($key = 0)
6539         {
6540                 $categories = $this->get_categories();
6541                 if (isset($categories[$key]))
6542                 {
6543                         return $categories[$key];
6544                 }
6545                 else
6546                 {
6547                         return null;
6548                 }
6549         }
6550
6551         function get_categories()
6552         {
6553                 if ($this->categories !== null)
6554                 {
6555                         return $this->categories;
6556                 }
6557                 else
6558                 {
6559                         return null;
6560                 }
6561         }
6562
6563         function get_channels()
6564         {
6565                 if ($this->channels !== null)
6566                 {
6567                         return $this->channels;
6568                 }
6569                 else
6570                 {
6571                         return null;
6572                 }
6573         }
6574
6575         function get_copyright()
6576         {
6577                 if ($this->copyright !== null)
6578                 {
6579                         return $this->copyright;
6580                 }
6581                 else
6582                 {
6583                         return null;
6584                 }
6585         }
6586
6587         function get_credit($key = 0)
6588         {
6589                 $credits = $this->get_credits();
6590                 if (isset($credits[$key]))
6591                 {
6592                         return $credits[$key];
6593                 }
6594                 else
6595                 {
6596                         return null;
6597                 }
6598         }
6599
6600         function get_credits()
6601         {
6602                 if ($this->credits !== null)
6603                 {
6604                         return $this->credits;
6605                 }
6606                 else
6607                 {
6608                         return null;
6609                 }
6610         }
6611
6612         function get_description()
6613         {
6614                 if ($this->description !== null)
6615                 {
6616                         return $this->description;
6617                 }
6618                 else
6619                 {
6620                         return null;
6621                 }
6622         }
6623
6624         function get_duration($convert = false)
6625         {
6626                 if ($this->duration !== null)
6627                 {
6628                         if ($convert)
6629                         {
6630                                 $time = SimplePie_Misc::time_hms($this->duration);
6631                                 return $time;
6632                         }
6633                         else
6634                         {
6635                                 return $this->duration;
6636                         }
6637                 }
6638                 else
6639                 {
6640                         return null;
6641                 }
6642         }
6643
6644         function get_expression()
6645         {
6646                 if ($this->expression !== null)
6647                 {
6648                         return $this->expression;
6649                 }
6650                 else
6651                 {
6652                         return 'full';
6653                 }
6654         }
6655
6656         function get_extension()
6657         {
6658                 if ($this->link !== null)
6659                 {
6660                         $url = SimplePie_Misc::parse_url($this->link);
6661                         if ($url['path'] !== '')
6662                         {
6663                                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6664                         }
6665                 }
6666                 return null;
6667         }
6668
6669         function get_framerate()
6670         {
6671                 if ($this->framerate !== null)
6672                 {
6673                         return $this->framerate;
6674                 }
6675                 else
6676                 {
6677                         return null;
6678                 }
6679         }
6680
6681         function get_handler()
6682         {
6683                 return $this->get_real_type(true);
6684         }
6685
6686         function get_hash($key = 0)
6687         {
6688                 $hashes = $this->get_hashes();
6689                 if (isset($hashes[$key]))
6690                 {
6691                         return $hashes[$key];
6692                 }
6693                 else
6694                 {
6695                         return null;
6696                 }
6697         }
6698
6699         function get_hashes()
6700         {
6701                 if ($this->hashes !== null)
6702                 {
6703                         return $this->hashes;
6704                 }
6705                 else
6706                 {
6707                         return null;
6708                 }
6709         }
6710
6711         function get_height()
6712         {
6713                 if ($this->height !== null)
6714                 {
6715                         return $this->height;
6716                 }
6717                 else
6718                 {
6719                         return null;
6720                 }
6721         }
6722
6723         function get_language()
6724         {
6725                 if ($this->lang !== null)
6726                 {
6727                         return $this->lang;
6728                 }
6729                 else
6730                 {
6731                         return null;
6732                 }
6733         }
6734
6735         function get_keyword($key = 0)
6736         {
6737                 $keywords = $this->get_keywords();
6738                 if (isset($keywords[$key]))
6739                 {
6740                         return $keywords[$key];
6741                 }
6742                 else
6743                 {
6744                         return null;
6745                 }
6746         }
6747
6748         function get_keywords()
6749         {
6750                 if ($this->keywords !== null)
6751                 {
6752                         return $this->keywords;
6753                 }
6754                 else
6755                 {
6756                         return null;
6757                 }
6758         }
6759
6760         function get_length()
6761         {
6762                 if ($this->length !== null)
6763                 {
6764                         return $this->length;
6765                 }
6766                 else
6767                 {
6768                         return null;
6769                 }
6770         }
6771
6772         function get_link()
6773         {
6774                 if ($this->link !== null)
6775                 {
6776                         return urldecode($this->link);
6777                 }
6778                 else
6779                 {
6780                         return null;
6781                 }
6782         }
6783
6784         function get_medium()
6785         {
6786                 if ($this->medium !== null)
6787                 {
6788                         return $this->medium;
6789                 }
6790                 else
6791                 {
6792                         return null;
6793                 }
6794         }
6795
6796         function get_player()
6797         {
6798                 if ($this->player !== null)
6799                 {
6800                         return $this->player;
6801                 }
6802                 else
6803                 {
6804                         return null;
6805                 }
6806         }
6807
6808         function get_rating($key = 0)
6809         {
6810                 $ratings = $this->get_ratings();
6811                 if (isset($ratings[$key]))
6812                 {
6813                         return $ratings[$key];
6814                 }
6815                 else
6816                 {
6817                         return null;
6818                 }
6819         }
6820
6821         function get_ratings()
6822         {
6823                 if ($this->ratings !== null)
6824                 {
6825                         return $this->ratings;
6826                 }
6827                 else
6828                 {
6829                         return null;
6830                 }
6831         }
6832
6833         function get_restriction($key = 0)
6834         {
6835                 $restrictions = $this->get_restrictions();
6836                 if (isset($restrictions[$key]))
6837                 {
6838                         return $restrictions[$key];
6839                 }
6840                 else
6841                 {
6842                         return null;
6843                 }
6844         }
6845
6846         function get_restrictions()
6847         {
6848                 if ($this->restrictions !== null)
6849                 {
6850                         return $this->restrictions;
6851                 }
6852                 else
6853                 {
6854                         return null;
6855                 }
6856         }
6857
6858         function get_sampling_rate()
6859         {
6860                 if ($this->samplingrate !== null)
6861                 {
6862                         return $this->samplingrate;
6863                 }
6864                 else
6865                 {
6866                         return null;
6867                 }
6868         }
6869
6870         function get_size()
6871         {
6872                 $length = $this->get_length();
6873                 if ($length !== null)
6874                 {
6875                         return round($length/1048576, 2);
6876                 }
6877                 else
6878                 {
6879                         return null;
6880                 }
6881         }
6882
6883         function get_thumbnail($key = 0)
6884         {
6885                 $thumbnails = $this->get_thumbnails();
6886                 if (isset($thumbnails[$key]))
6887                 {
6888                         return $thumbnails[$key];
6889                 }
6890                 else
6891                 {
6892                         return null;
6893                 }
6894         }
6895
6896         function get_thumbnails()
6897         {
6898                 if ($this->thumbnails !== null)
6899                 {
6900                         return $this->thumbnails;
6901                 }
6902                 else
6903                 {
6904                         return null;
6905                 }
6906         }
6907
6908         function get_title()
6909         {
6910                 if ($this->title !== null)
6911                 {
6912                         return $this->title;
6913                 }
6914                 else
6915                 {
6916                         return null;
6917                 }
6918         }
6919
6920         function get_type()
6921         {
6922                 if ($this->type !== null)
6923                 {
6924                         return $this->type;
6925                 }
6926                 else
6927                 {
6928                         return null;
6929                 }
6930         }
6931
6932         function get_width()
6933         {
6934                 if ($this->width !== null)
6935                 {
6936                         return $this->width;
6937                 }
6938                 else
6939                 {
6940                         return null;
6941                 }
6942         }
6943
6944         function native_embed($options='')
6945         {
6946                 return $this->embed($options, true);
6947         }
6948
6949         /**
6950          * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6951          */
6952         function embed($options = '', $native = false)
6953         {
6954                 // Set up defaults
6955                 $audio = '';
6956                 $video = '';
6957                 $alt = '';
6958                 $altclass = '';
6959                 $loop = 'false';
6960                 $width = 'auto';
6961                 $height = 'auto';
6962                 $bgcolor = '#ffffff';
6963                 $mediaplayer = '';
6964                 $widescreen = false;
6965                 $handler = $this->get_handler();
6966                 $type = $this->get_real_type();
6967
6968                 // Process options and reassign values as necessary
6969                 if (is_array($options))
6970                 {
6971                         extract($options);
6972                 }
6973                 else
6974                 {
6975                         $options = explode(',', $options);
6976                         foreach($options as $option)
6977                         {
6978                                 $opt = explode(':', $option, 2);
6979                                 if (isset($opt[0], $opt[1]))
6980                                 {
6981                                         $opt[0] = trim($opt[0]);
6982                                         $opt[1] = trim($opt[1]);
6983                                         switch ($opt[0])
6984                                         {
6985                                                 case 'audio':
6986                                                         $audio = $opt[1];
6987                                                         break;
6988
6989                                                 case 'video':
6990                                                         $video = $opt[1];
6991                                                         break;
6992
6993                                                 case 'alt':
6994                                                         $alt = $opt[1];
6995                                                         break;
6996
6997                                                 case 'altclass':
6998                                                         $altclass = $opt[1];
6999                                                         break;
7000
7001                                                 case 'loop':
7002                                                         $loop = $opt[1];
7003                                                         break;
7004
7005                                                 case 'width':
7006                                                         $width = $opt[1];
7007                                                         break;
7008
7009                                                 case 'height':
7010                                                         $height = $opt[1];
7011                                                         break;
7012
7013                                                 case 'bgcolor':
7014                                                         $bgcolor = $opt[1];
7015                                                         break;
7016
7017                                                 case 'mediaplayer':
7018                                                         $mediaplayer = $opt[1];
7019                                                         break;
7020
7021                                                 case 'widescreen':
7022                                                         $widescreen = $opt[1];
7023                                                         break;
7024                                         }
7025                                 }
7026                         }
7027                 }
7028
7029                 $mime = explode('/', $type, 2);
7030                 $mime = $mime[0];
7031
7032                 // Process values for 'auto'
7033                 if ($width === 'auto')
7034                 {
7035                         if ($mime === 'video')
7036                         {
7037                                 if ($height === 'auto')
7038                                 {
7039                                         $width = 480;
7040                                 }
7041                                 elseif ($widescreen)
7042                                 {
7043                                         $width = round((intval($height)/9)*16);
7044                                 }
7045                                 else
7046                                 {
7047                                         $width = round((intval($height)/3)*4);
7048                                 }
7049                         }
7050                         else
7051                         {
7052                                 $width = '100%';
7053                         }
7054                 }
7055
7056                 if ($height === 'auto')
7057                 {
7058                         if ($mime === 'audio')
7059                         {
7060                                 $height = 0;
7061                         }
7062                         elseif ($mime === 'video')
7063                         {
7064                                 if ($width === 'auto')
7065                                 {
7066                                         if ($widescreen)
7067                                         {
7068                                                 $height = 270;
7069                                         }
7070                                         else
7071                                         {
7072                                                 $height = 360;
7073                                         }
7074                                 }
7075                                 elseif ($widescreen)
7076                                 {
7077                                         $height = round((intval($width)/16)*9);
7078                                 }
7079                                 else
7080                                 {
7081                                         $height = round((intval($width)/4)*3);
7082                                 }
7083                         }
7084                         else
7085                         {
7086                                 $height = 376;
7087                         }
7088                 }
7089                 elseif ($mime === 'audio')
7090                 {
7091                         $height = 0;
7092                 }
7093
7094                 // Set proper placeholder value
7095                 if ($mime === 'audio')
7096                 {
7097                         $placeholder = $audio;
7098                 }
7099                 elseif ($mime === 'video')
7100                 {
7101                         $placeholder = $video;
7102                 }
7103
7104                 $embed = '';
7105
7106                 // Make sure the JS library is included
7107                 if (!$native)
7108                 {
7109                         static $javascript_outputted = null;
7110                         if (!$javascript_outputted && $this->javascript)
7111                         {
7112                                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7113                                 $javascript_outputted = true;
7114                         }
7115                 }
7116
7117                 // Odeo Feed MP3's
7118                 if ($handler === 'odeo')
7119                 {
7120                         if ($native)
7121                         {
7122                                 $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>';
7123                         }
7124                         else
7125                         {
7126                                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7127                         }
7128                 }
7129
7130                 // Flash
7131                 elseif ($handler === 'flash')
7132                 {
7133                         if ($native)
7134                         {
7135                                 $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>";
7136                         }
7137                         else
7138                         {
7139                                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7140                         }
7141                 }
7142
7143                 // Flash Media Player file types.
7144                 // Preferred handler for MP3 file types.
7145                 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7146                 {
7147                         $height += 20;
7148                         if ($native)
7149                         {
7150                                 $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>";
7151                         }
7152                         else
7153                         {
7154                                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7155                         }
7156                 }
7157
7158                 // QuickTime 7 file types.  Need to test with QuickTime 6.
7159                 // Only handle MP3's if the Flash Media Player is not present.
7160                 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7161                 {
7162                         $height += 16;
7163                         if ($native)
7164                         {
7165                                 if ($placeholder !== '')
7166                                 {
7167                                         $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>";
7168                                 }
7169                                 else
7170                                 {
7171                                         $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>";
7172                                 }
7173                         }
7174                         else
7175                         {
7176                                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7177                         }
7178                 }
7179
7180                 // Windows Media
7181                 elseif ($handler === 'wmedia')
7182                 {
7183                         $height += 45;
7184                         if ($native)
7185                         {
7186                                 $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>";
7187                         }
7188                         else
7189                         {
7190                                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7191                         }
7192                 }
7193
7194                 // Everything else
7195                 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7196
7197                 return $embed;
7198         }
7199
7200         function get_real_type($find_handler = false)
7201         {
7202                 // If it's Odeo, let's get it out of the way.
7203                 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7204                 {
7205                         return 'odeo';
7206                 }
7207
7208                 // Mime-types by handler.
7209                 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7210                 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7211                 $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
7212                 $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
7213                 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7214
7215                 if ($this->get_type() !== null)
7216                 {
7217                         $type = strtolower($this->type);
7218                 }
7219                 else
7220                 {
7221                         $type = null;
7222                 }
7223
7224                 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7225                 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7226                 {
7227                         switch (strtolower($this->get_extension()))
7228                         {
7229                                 // Audio mime-types
7230                                 case 'aac':
7231                                 case 'adts':
7232                                         $type = 'audio/acc';
7233                                         break;
7234
7235                                 case 'aif':
7236                                 case 'aifc':
7237                                 case 'aiff':
7238                                 case 'cdda':
7239                                         $type = 'audio/aiff';
7240                                         break;
7241
7242                                 case 'bwf':
7243                                         $type = 'audio/wav';
7244                                         break;
7245
7246                                 case 'kar':
7247                                 case 'mid':
7248                                 case 'midi':
7249                                 case 'smf':
7250                                         $type = 'audio/midi';
7251                                         break;
7252
7253                                 case 'm4a':
7254                                         $type = 'audio/x-m4a';
7255                                         break;
7256
7257                                 case 'mp3':
7258                                 case 'swa':
7259                                         $type = 'audio/mp3';
7260                                         break;
7261
7262                                 case 'wav':
7263                                         $type = 'audio/wav';
7264                                         break;
7265
7266                                 case 'wax':
7267                                         $type = 'audio/x-ms-wax';
7268                                         break;
7269
7270                                 case 'wma':
7271                                         $type = 'audio/x-ms-wma';
7272                                         break;
7273
7274                                 // Video mime-types
7275                                 case '3gp':
7276                                 case '3gpp':
7277                                         $type = 'video/3gpp';
7278                                         break;
7279
7280                                 case '3g2':
7281                                 case '3gp2':
7282                                         $type = 'video/3gpp2';
7283                                         break;
7284
7285                                 case 'asf':
7286                                         $type = 'video/x-ms-asf';
7287                                         break;
7288
7289                                 case 'flv':
7290                                         $type = 'video/x-flv';
7291                                         break;
7292
7293                                 case 'm1a':
7294                                 case 'm1s':
7295                                 case 'm1v':
7296                                 case 'm15':
7297                                 case 'm75':
7298                                 case 'mp2':
7299                                 case 'mpa':
7300                                 case 'mpeg':
7301                                 case 'mpg':
7302                                 case 'mpm':
7303                                 case 'mpv':
7304                                         $type = 'video/mpeg';
7305                                         break;
7306
7307                                 case 'm4v':
7308                                         $type = 'video/x-m4v';
7309                                         break;
7310
7311                                 case 'mov':
7312                                 case 'qt':
7313                                         $type = 'video/quicktime';
7314                                         break;
7315
7316                                 case 'mp4':
7317                                 case 'mpg4':
7318                                         $type = 'video/mp4';
7319                                         break;
7320
7321                                 case 'sdv':
7322                                         $type = 'video/sd-video';
7323                                         break;
7324
7325                                 case 'wm':
7326                                         $type = 'video/x-ms-wm';
7327                                         break;
7328
7329                                 case 'wmv':
7330                                         $type = 'video/x-ms-wmv';
7331                                         break;
7332
7333                                 case 'wvx':
7334                                         $type = 'video/x-ms-wvx';
7335                                         break;
7336
7337                                 // Flash mime-types
7338                                 case 'spl':
7339                                         $type = 'application/futuresplash';
7340                                         break;
7341
7342                                 case 'swf':
7343                                         $type = 'application/x-shockwave-flash';
7344                                         break;
7345                         }
7346                 }
7347
7348                 if ($find_handler)
7349                 {
7350                         if (in_array($type, $types_flash))
7351                         {
7352                                 return 'flash';
7353                         }
7354                         elseif (in_array($type, $types_fmedia))
7355                         {
7356                                 return 'fmedia';
7357                         }
7358                         elseif (in_array($type, $types_quicktime))
7359                         {
7360                                 return 'quicktime';
7361                         }
7362                         elseif (in_array($type, $types_wmedia))
7363                         {
7364                                 return 'wmedia';
7365                         }
7366                         elseif (in_array($type, $types_mp3))
7367                         {
7368                                 return 'mp3';
7369                         }
7370                         else
7371                         {
7372                                 return null;
7373                         }
7374                 }
7375                 else
7376                 {
7377                         return $type;
7378                 }
7379         }
7380 }
7381
7382 class SimplePie_Caption
7383 {
7384         var $type;
7385         var $lang;
7386         var $startTime;
7387         var $endTime;
7388         var $text;
7389
7390         // Constructor, used to input the data
7391         function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7392         {
7393                 $this->type = $type;
7394                 $this->lang = $lang;
7395                 $this->startTime = $startTime;
7396                 $this->endTime = $endTime;
7397                 $this->text = $text;
7398         }
7399
7400         function __toString()
7401         {
7402                 // There is no $this->data here
7403                 return md5(serialize($this));
7404         }
7405
7406         function get_endtime()
7407         {
7408                 if ($this->endTime !== null)
7409                 {
7410                         return $this->endTime;
7411                 }
7412                 else
7413                 {
7414                         return null;
7415                 }
7416         }
7417
7418         function get_language()
7419         {
7420                 if ($this->lang !== null)
7421                 {
7422                         return $this->lang;
7423                 }
7424                 else
7425                 {
7426                         return null;
7427                 }
7428         }
7429
7430         function get_starttime()
7431         {
7432                 if ($this->startTime !== null)
7433                 {
7434                         return $this->startTime;
7435                 }
7436                 else
7437                 {
7438                         return null;
7439                 }
7440         }
7441
7442         function get_text()
7443         {
7444                 if ($this->text !== null)
7445                 {
7446                         return $this->text;
7447                 }
7448                 else
7449                 {
7450                         return null;
7451                 }
7452         }
7453
7454         function get_type()
7455         {
7456                 if ($this->type !== null)
7457                 {
7458                         return $this->type;
7459                 }
7460                 else
7461                 {
7462                         return null;
7463                 }
7464         }
7465 }
7466
7467 class SimplePie_Credit
7468 {
7469         var $role;
7470         var $scheme;
7471         var $name;
7472
7473         // Constructor, used to input the data
7474         function SimplePie_Credit($role = null, $scheme = null, $name = null)
7475         {
7476                 $this->role = $role;
7477                 $this->scheme = $scheme;
7478                 $this->name = $name;
7479         }
7480
7481         function __toString()
7482         {
7483                 // There is no $this->data here
7484                 return md5(serialize($this));
7485         }
7486
7487         function get_role()
7488         {
7489                 if ($this->role !== null)
7490                 {
7491                         return $this->role;
7492                 }
7493                 else
7494                 {
7495                         return null;
7496                 }
7497         }
7498
7499         function get_scheme()
7500         {
7501                 if ($this->scheme !== null)
7502                 {
7503                         return $this->scheme;
7504                 }
7505                 else
7506                 {
7507                         return null;
7508                 }
7509         }
7510
7511         function get_name()
7512         {
7513                 if ($this->name !== null)
7514                 {
7515                         return $this->name;
7516                 }
7517                 else
7518                 {
7519                         return null;
7520                 }
7521         }
7522 }
7523
7524 class SimplePie_Copyright
7525 {
7526         var $url;
7527         var $label;
7528
7529         // Constructor, used to input the data
7530         function SimplePie_Copyright($url = null, $label = null)
7531         {
7532                 $this->url = $url;
7533                 $this->label = $label;
7534         }
7535
7536         function __toString()
7537         {
7538                 // There is no $this->data here
7539                 return md5(serialize($this));
7540         }
7541
7542         function get_url()
7543         {
7544                 if ($this->url !== null)
7545                 {
7546                         return $this->url;
7547                 }
7548                 else
7549                 {
7550                         return null;
7551                 }
7552         }
7553
7554         function get_attribution()
7555         {
7556                 if ($this->label !== null)
7557                 {
7558                         return $this->label;
7559                 }
7560                 else
7561                 {
7562                         return null;
7563                 }
7564         }
7565 }
7566
7567 class SimplePie_Rating
7568 {
7569         var $scheme;
7570         var $value;
7571
7572         // Constructor, used to input the data
7573         function SimplePie_Rating($scheme = null, $value = null)
7574         {
7575                 $this->scheme = $scheme;
7576                 $this->value = $value;
7577         }
7578
7579         function __toString()
7580         {
7581                 // There is no $this->data here
7582                 return md5(serialize($this));
7583         }
7584
7585         function get_scheme()
7586         {
7587                 if ($this->scheme !== null)
7588                 {
7589                         return $this->scheme;
7590                 }
7591                 else
7592                 {
7593                         return null;
7594                 }
7595         }
7596
7597         function get_value()
7598         {
7599                 if ($this->value !== null)
7600                 {
7601                         return $this->value;
7602                 }
7603                 else
7604                 {
7605                         return null;
7606                 }
7607         }
7608 }
7609
7610 class SimplePie_Restriction
7611 {
7612         var $relationship;
7613         var $type;
7614         var $value;
7615
7616         // Constructor, used to input the data
7617         function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7618         {
7619                 $this->relationship = $relationship;
7620                 $this->type = $type;
7621                 $this->value = $value;
7622         }
7623
7624         function __toString()
7625         {
7626                 // There is no $this->data here
7627                 return md5(serialize($this));
7628         }
7629
7630         function get_relationship()
7631         {
7632                 if ($this->relationship !== null)
7633                 {
7634                         return $this->relationship;
7635                 }
7636                 else
7637                 {
7638                         return null;
7639                 }
7640         }
7641
7642         function get_type()
7643         {
7644                 if ($this->type !== null)
7645                 {
7646                         return $this->type;
7647                 }
7648                 else
7649                 {
7650                         return null;
7651                 }
7652         }
7653
7654         function get_value()
7655         {
7656                 if ($this->value !== null)
7657                 {
7658                         return $this->value;
7659                 }
7660                 else
7661                 {
7662                         return null;
7663                 }
7664         }
7665 }
7666
7667 /**
7668  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7669  */
7670 class SimplePie_File
7671 {
7672         var $url;
7673         var $useragent;
7674         var $success = true;
7675         var $headers = array();
7676         var $body;
7677         var $status_code;
7678         var $redirects = 0;
7679         var $error;
7680         var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7681
7682         function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7683         {
7684                 if (class_exists('idna_convert'))
7685                 {
7686                         $idn = new idna_convert;
7687                         $parsed = SimplePie_Misc::parse_url($url);
7688                         $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7689                 }
7690                 $this->url = $url;
7691                 $this->useragent = $useragent;
7692                 if (preg_match('/^http(s)?:\/\//i', $url))
7693                 {
7694                         if ($useragent === null)
7695                         {
7696                                 $useragent = ini_get('user_agent');
7697                                 $this->useragent = $useragent;
7698                         }
7699                         if (!is_array($headers))
7700                         {
7701                                 $headers = array();
7702                         }
7703                         if (!$force_fsockopen && function_exists('curl_exec'))
7704                         {
7705                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7706                                 $fp = curl_init();
7707                                 $headers2 = array();
7708                                 foreach ($headers as $key => $value)
7709                                 {
7710                                         $headers2[] = "$key: $value";
7711                                 }
7712                                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7713                                 {
7714                                         curl_setopt($fp, CURLOPT_ENCODING, '');
7715                                 }
7716                                 curl_setopt($fp, CURLOPT_URL, $url);
7717                                 curl_setopt($fp, CURLOPT_HEADER, 1);
7718                                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7719                                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7720                                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7721                                 curl_setopt($fp, CURLOPT_REFERER, $url);
7722                                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7723                                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7724                                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7725                                 {
7726                                         curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7727                                         curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7728                                 }
7729
7730                                 $this->headers = curl_exec($fp);
7731                                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7732                                 {
7733                                         curl_setopt($fp, CURLOPT_ENCODING, 'none');
7734                                         $this->headers = curl_exec($fp);
7735                                 }
7736                                 if (curl_errno($fp))
7737                                 {
7738                                         $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7739                                         $this->success = false;
7740                                 }
7741                                 else
7742                                 {
7743                                         $info = curl_getinfo($fp);
7744                                         curl_close($fp);
7745                                         $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7746                                         $this->headers = array_pop($this->headers);
7747                                         $parser = new SimplePie_HTTP_Parser($this->headers);
7748                                         if ($parser->parse())
7749                                         {
7750                                                 $this->headers = $parser->headers;
7751                                                 $this->body = $parser->body;
7752                                                 $this->status_code = $parser->status_code;
7753                                                 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)
7754                                                 {
7755                                                         $this->redirects++;
7756                                                         $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7757                                                         return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7758                                                 }
7759                                         }
7760                                 }
7761                         }
7762                         else
7763                         {
7764                                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7765                                 $url_parts = parse_url($url);
7766                                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7767                                 {
7768                                         $url_parts['host'] = "ssl://$url_parts[host]";
7769                                         $url_parts['port'] = 443;
7770                                 }
7771                                 if (!isset($url_parts['port']))
7772                                 {
7773                                         $url_parts['port'] = 80;
7774                                 }
7775                                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7776                                 if (!$fp)
7777                                 {
7778                                         $this->error = 'fsockopen error: ' . $errstr;
7779                                         $this->success = false;
7780                                 }
7781                                 else
7782                                 {
7783                                         stream_set_timeout($fp, $timeout);
7784                                         if (isset($url_parts['path']))
7785                                         {
7786                                                 if (isset($url_parts['query']))
7787                                                 {
7788                                                         $get = "$url_parts[path]?$url_parts[query]";
7789                                                 }
7790                                                 else
7791                                                 {
7792                                                         $get = $url_parts['path'];
7793                                                 }
7794                                         }
7795                                         else
7796                                         {
7797                                                 $get = '/';
7798                                         }
7799                                         $out = "GET $get HTTP/1.0\r\n";
7800                                         $out .= "Host: $url_parts[host]\r\n";
7801                                         $out .= "User-Agent: $useragent\r\n";
7802                                         if (extension_loaded('zlib'))
7803                                         {
7804                                                 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7805                                         }
7806
7807                                         if (isset($url_parts['user']) && isset($url_parts['pass']))
7808                                         {
7809                                                 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7810                                         }
7811                                         foreach ($headers as $key => $value)
7812                                         {
7813                                                 $out .= "$key: $value\r\n";
7814                                         }
7815                                         $out .= "Connection: Close\r\n\r\n";
7816                                         fwrite($fp, $out);
7817
7818                                         $info = stream_get_meta_data($fp);
7819
7820                                         $this->headers = '';
7821                                         while (!$info['eof'] && !$info['timed_out'])
7822                                         {
7823                                                 $this->headers .= fread($fp, 1160);
7824                                                 $info = stream_get_meta_data($fp);
7825                                         }
7826                                         if (!$info['timed_out'])
7827                                         {
7828                                                 $parser = new SimplePie_HTTP_Parser($this->headers);
7829                                                 if ($parser->parse())
7830                                                 {
7831                                                         $this->headers = $parser->headers;
7832                                                         $this->body = $parser->body;
7833                                                         $this->status_code = $parser->status_code;
7834                                                         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)
7835                                                         {
7836                                                                 $this->redirects++;
7837                                                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7838                                                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7839                                                         }
7840                                                         if (isset($this->headers['content-encoding']))
7841                                                         {
7842                                                                 // Hey, we act dumb elsewhere, so let's do that here too
7843                                                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7844                                                                 {
7845                                                                         case 'gzip':
7846                                                                         case 'x-gzip':
7847                                                                                 $decoder = new SimplePie_gzdecode($this->body);
7848                                                                                 if (!$decoder->parse())
7849                                                                                 {
7850                                                                                         $this->error = 'Unable to decode HTTP "gzip" stream';
7851                                                                                         $this->success = false;
7852                                                                                 }
7853                                                                                 else
7854                                                                                 {
7855                                                                                         $this->body = $decoder->data;
7856                                                                                 }
7857                                                                                 break;
7858
7859                                                                         case 'deflate':
7860                                                                                 if (($body = gzuncompress($this->body)) === false)
7861                                                                                 {
7862                                                                                         if (($body = gzinflate($this->body)) === false)
7863                                                                                         {
7864                                                                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7865                                                                                                 $this->success = false;
7866                                                                                         }
7867                                                                                 }
7868                                                                                 $this->body = $body;
7869                                                                                 break;
7870
7871                                                                         default:
7872                                                                                 $this->error = 'Unknown content coding';
7873                                                                                 $this->success = false;
7874                                                                 }
7875                                                         }
7876                                                 }
7877                                         }
7878                                         else
7879                                         {
7880                                                 $this->error = 'fsocket timed out';
7881                                                 $this->success = false;
7882                                         }
7883                                         fclose($fp);
7884                                 }
7885                         }
7886                 }
7887                 else
7888                 {
7889                         $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7890                         if (!$this->body = file_get_contents($url))
7891                         {
7892                                 $this->error = 'file_get_contents could not read the file';
7893                                 $this->success = false;
7894                         }
7895                 }
7896         }
7897 }
7898
7899 /**
7900  * HTTP Response Parser
7901  *
7902  * @package SimplePie
7903  */
7904 class SimplePie_HTTP_Parser
7905 {
7906         /**
7907          * HTTP Version
7908          *
7909          * @access public
7910          * @var float
7911          */
7912         var $http_version = 0.0;
7913
7914         /**
7915          * Status code
7916          *
7917          * @access public
7918          * @var int
7919          */
7920         var $status_code = 0;
7921
7922         /**
7923          * Reason phrase
7924          *
7925          * @access public
7926          * @var string
7927          */
7928         var $reason = '';
7929
7930         /**
7931          * Key/value pairs of the headers
7932          *
7933          * @access public
7934          * @var array
7935          */
7936         var $headers = array();
7937
7938         /**
7939          * Body of the response
7940          *
7941          * @access public
7942          * @var string
7943          */
7944         var $body = '';
7945
7946         /**
7947          * Current state of the state machine
7948          *
7949          * @access private
7950          * @var string
7951          */
7952         var $state = 'http_version';
7953
7954         /**
7955          * Input data
7956          *
7957          * @access private
7958          * @var string
7959          */
7960         var $data = '';
7961
7962         /**
7963          * Input data length (to avoid calling strlen() everytime this is needed)
7964          *
7965          * @access private
7966          * @var int
7967          */
7968         var $data_length = 0;
7969
7970         /**
7971          * Current position of the pointer
7972          *
7973          * @var int
7974          * @access private
7975          */
7976         var $position = 0;
7977
7978         /**
7979          * Name of the hedaer currently being parsed
7980          *
7981          * @access private
7982          * @var string
7983          */
7984         var $name = '';
7985
7986         /**
7987          * Value of the hedaer currently being parsed
7988          *
7989          * @access private
7990          * @var string
7991          */
7992         var $value = '';
7993
7994         /**
7995          * Create an instance of the class with the input data
7996          *
7997          * @access public
7998          * @param string $data Input data
7999          */
8000         function SimplePie_HTTP_Parser($data)
8001         {
8002                 $this->data = $data;
8003                 $this->data_length = strlen($this->data);
8004         }
8005
8006         /**
8007          * Parse the input data
8008          *
8009          * @access public
8010          * @return bool true on success, false on failure
8011          */
8012         function parse()
8013         {
8014                 while ($this->state && $this->state !== 'emit' && $this->has_data())
8015                 {
8016                         $state = $this->state;
8017                         $this->$state();
8018                 }
8019                 $this->data = '';
8020                 if ($this->state === 'emit' || $this->state === 'body')
8021                 {
8022                         return true;
8023                 }
8024                 else
8025                 {
8026                         $this->http_version = '';
8027                         $this->status_code = '';
8028                         $this->reason = '';
8029                         $this->headers = array();
8030                         $this->body = '';
8031                         return false;
8032                 }
8033         }
8034
8035         /**
8036          * Check whether there is data beyond the pointer
8037          *
8038          * @access private
8039          * @return bool true if there is further data, false if not
8040          */
8041         function has_data()
8042         {
8043                 return (bool) ($this->position < $this->data_length);
8044         }
8045
8046         /**
8047          * See if the next character is LWS
8048          *
8049          * @access private
8050          * @return bool true if the next character is LWS, false if not
8051          */
8052         function is_linear_whitespace()
8053         {
8054                 return (bool) ($this->data[$this->position] === "\x09"
8055                         || $this->data[$this->position] === "\x20"
8056                         || ($this->data[$this->position] === "\x0A"
8057                                 && isset($this->data[$this->position + 1])
8058                                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8059         }
8060
8061         /**
8062          * Parse the HTTP version
8063          *
8064          * @access private
8065          */
8066         function http_version()
8067         {
8068                 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8069                 {
8070                         $len = strspn($this->data, '0123456789.', 5);
8071                         $this->http_version = substr($this->data, 5, $len);
8072                         $this->position += 5 + $len;
8073                         if (substr_count($this->http_version, '.') <= 1)
8074                         {
8075                                 $this->http_version = (float) $this->http_version;
8076                                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8077                                 $this->state = 'status';
8078                         }
8079                         else
8080                         {
8081                                 $this->state = false;
8082                         }
8083                 }
8084                 else
8085                 {
8086                         $this->state = false;
8087                 }
8088         }
8089
8090         /**
8091          * Parse the status code
8092          *
8093          * @access private
8094          */
8095         function status()
8096         {
8097                 if ($len = strspn($this->data, '0123456789', $this->position))
8098                 {
8099                         $this->status_code = (int) substr($this->data, $this->position, $len);
8100                         $this->position += $len;
8101                         $this->state = 'reason';
8102                 }
8103                 else
8104                 {
8105                         $this->state = false;
8106                 }
8107         }
8108
8109         /**
8110          * Parse the reason phrase
8111          *
8112          * @access private
8113          */
8114         function reason()
8115         {
8116                 $len = strcspn($this->data, "\x0A", $this->position);
8117                 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8118                 $this->position += $len + 1;
8119                 $this->state = 'new_line';
8120         }
8121
8122         /**
8123          * Deal with a new line, shifting data around as needed
8124          *
8125          * @access private
8126          */
8127         function new_line()
8128         {
8129                 $this->value = trim($this->value, "\x0D\x20");
8130                 if ($this->name !== '' && $this->value !== '')
8131                 {
8132                         $this->name = strtolower($this->name);
8133                         if (isset($this->headers[$this->name]))
8134                         {
8135                                 $this->headers[$this->name] .= ', ' . $this->value;
8136                         }
8137                         else
8138                         {
8139                                 $this->headers[$this->name] = $this->value;
8140                         }
8141                 }
8142                 $this->name = '';
8143                 $this->value = '';
8144                 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8145                 {
8146                         $this->position += 2;
8147                         $this->state = 'body';
8148                 }
8149                 elseif ($this->data[$this->position] === "\x0A")
8150                 {
8151                         $this->position++;
8152                         $this->state = 'body';
8153                 }
8154                 else
8155                 {
8156                         $this->state = 'name';
8157                 }
8158         }
8159
8160         /**
8161          * Parse a header name
8162          *
8163          * @access private
8164          */
8165         function name()
8166         {
8167                 $len = strcspn($this->data, "\x0A:", $this->position);
8168                 if (isset($this->data[$this->position + $len]))
8169                 {
8170                         if ($this->data[$this->position + $len] === "\x0A")
8171                         {
8172                                 $this->position += $len;
8173                                 $this->state = 'new_line';
8174                         }
8175                         else
8176                         {
8177                                 $this->name = substr($this->data, $this->position, $len);
8178                                 $this->position += $len + 1;
8179                                 $this->state = 'value';
8180                         }
8181                 }
8182                 else
8183                 {
8184                         $this->state = false;
8185                 }
8186         }
8187
8188         /**
8189          * Parse LWS, replacing consecutive LWS characters with a single space
8190          *
8191          * @access private
8192          */
8193         function linear_whitespace()
8194         {
8195                 do
8196                 {
8197                         if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8198                         {
8199                                 $this->position += 2;
8200                         }
8201                         elseif ($this->data[$this->position] === "\x0A")
8202                         {
8203                                 $this->position++;
8204                         }
8205                         $this->position += strspn($this->data, "\x09\x20", $this->position);
8206                 } while ($this->has_data() && $this->is_linear_whitespace());
8207                 $this->value .= "\x20";
8208         }
8209
8210         /**
8211          * See what state to move to while within non-quoted header values
8212          *
8213          * @access private
8214          */
8215         function value()
8216         {
8217                 if ($this->is_linear_whitespace())
8218                 {
8219                         $this->linear_whitespace();
8220                 }
8221                 else
8222                 {
8223                         switch ($this->data[$this->position])
8224                         {
8225                                 case '"':
8226                                         $this->position++;
8227                                         $this->state = 'quote';
8228                                         break;
8229
8230                                 case "\x0A":
8231                                         $this->position++;
8232                                         $this->state = 'new_line';
8233                                         break;
8234
8235                                 default:
8236                                         $this->state = 'value_char';
8237                                         break;
8238                         }
8239                 }
8240         }
8241
8242         /**
8243          * Parse a header value while outside quotes
8244          *
8245          * @access private
8246          */
8247         function value_char()
8248         {
8249                 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8250                 $this->value .= substr($this->data, $this->position, $len);
8251                 $this->position += $len;
8252                 $this->state = 'value';
8253         }
8254
8255         /**
8256          * See what state to move to while within quoted header values
8257          *
8258          * @access private
8259          */
8260         function quote()
8261         {
8262                 if ($this->is_linear_whitespace())
8263                 {
8264                         $this->linear_whitespace();
8265                 }
8266                 else
8267                 {
8268                         switch ($this->data[$this->position])
8269                         {
8270                                 case '"':
8271                                         $this->position++;
8272                                         $this->state = 'value';
8273                                         break;
8274
8275                                 case "\x0A":
8276                                         $this->position++;
8277                                         $this->state = 'new_line';
8278                                         break;
8279
8280                                 case '\\':
8281                                         $this->position++;
8282                                         $this->state = 'quote_escaped';
8283                                         break;
8284
8285                                 default:
8286                                         $this->state = 'quote_char';
8287                                         break;
8288                         }
8289                 }
8290         }
8291
8292         /**
8293          * Parse a header value while within quotes
8294          *
8295          * @access private
8296          */
8297         function quote_char()
8298         {
8299                 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8300                 $this->value .= substr($this->data, $this->position, $len);
8301                 $this->position += $len;
8302                 $this->state = 'value';
8303         }
8304
8305         /**
8306          * Parse an escaped character within quotes
8307          *
8308          * @access private
8309          */
8310         function quote_escaped()
8311         {
8312                 $this->value .= $this->data[$this->position];
8313                 $this->position++;
8314                 $this->state = 'quote';
8315         }
8316
8317         /**
8318          * Parse the body
8319          *
8320          * @access private
8321          */
8322         function body()
8323         {
8324                 $this->body = substr($this->data, $this->position);
8325                 $this->state = 'emit';
8326         }
8327 }
8328
8329 /**
8330  * gzdecode
8331  *
8332  * @package SimplePie
8333  */
8334 class SimplePie_gzdecode
8335 {
8336         /**
8337          * Compressed data
8338          *
8339          * @access private
8340          * @see gzdecode::$data
8341          */
8342         var $compressed_data;
8343
8344         /**
8345          * Size of compressed data
8346          *
8347          * @access private
8348          */
8349         var $compressed_size;
8350
8351         /**
8352          * Minimum size of a valid gzip string
8353          *
8354          * @access private
8355          */
8356         var $min_compressed_size = 18;
8357
8358         /**
8359          * Current position of pointer
8360          *
8361          * @access private
8362          */
8363         var $position = 0;
8364
8365         /**
8366          * Flags (FLG)
8367          *
8368          * @access private
8369          */
8370         var $flags;
8371
8372         /**
8373          * Uncompressed data
8374          *
8375          * @access public
8376          * @see gzdecode::$compressed_data
8377          */
8378         var $data;
8379
8380         /**
8381          * Modified time
8382          *
8383          * @access public
8384          */
8385         var $MTIME;
8386
8387         /**
8388          * Extra Flags
8389          *
8390          * @access public
8391          */
8392         var $XFL;
8393
8394         /**
8395          * Operating System
8396          *
8397          * @access public
8398          */
8399         var $OS;
8400
8401         /**
8402          * Subfield ID 1
8403          *
8404          * @access public
8405          * @see gzdecode::$extra_field
8406          * @see gzdecode::$SI2
8407          */
8408         var $SI1;
8409
8410         /**
8411          * Subfield ID 2
8412          *
8413          * @access public
8414          * @see gzdecode::$extra_field
8415          * @see gzdecode::$SI1
8416          */
8417         var $SI2;
8418
8419         /**
8420          * Extra field content
8421          *
8422          * @access public
8423          * @see gzdecode::$SI1
8424          * @see gzdecode::$SI2
8425          */
8426         var $extra_field;
8427
8428         /**
8429          * Original filename
8430          *
8431          * @access public
8432          */
8433         var $filename;
8434
8435         /**
8436          * Human readable comment
8437          *
8438          * @access public
8439          */
8440         var $comment;
8441
8442         /**
8443          * Don't allow anything to be set
8444          *
8445          * @access public
8446          */
8447         function __set($name, $value)
8448         {
8449                 trigger_error("Cannot write property $name", E_USER_ERROR);
8450         }
8451
8452         /**
8453          * Set the compressed string and related properties
8454          *
8455          * @access public
8456          */
8457         function SimplePie_gzdecode($data)
8458         {
8459                 $this->compressed_data = $data;
8460                 $this->compressed_size = strlen($data);
8461         }
8462
8463         /**
8464          * Decode the GZIP stream
8465          *
8466          * @access public
8467          */
8468         function parse()
8469         {
8470                 if ($this->compressed_size >= $this->min_compressed_size)
8471                 {
8472                         // Check ID1, ID2, and CM
8473                         if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8474                         {
8475                                 return false;
8476                         }
8477
8478                         // Get the FLG (FLaGs)
8479                         $this->flags = ord($this->compressed_data[3]);
8480
8481                         // FLG bits above (1 << 4) are reserved
8482                         if ($this->flags > 0x1F)
8483                         {
8484                                 return false;
8485                         }
8486
8487                         // Advance the pointer after the above
8488                         $this->position += 4;
8489
8490                         // MTIME
8491                         $mtime = substr($this->compressed_data, $this->position, 4);
8492                         // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8493                         if (current(unpack('S', "\x00\x01")) === 1)
8494                         {
8495                                 $mtime = strrev($mtime);
8496                         }
8497                         $this->MTIME = current(unpack('l', $mtime));
8498                         $this->position += 4;
8499
8500                         // Get the XFL (eXtra FLags)
8501                         $this->XFL = ord($this->compressed_data[$this->position++]);
8502
8503                         // Get the OS (Operating System)
8504                         $this->OS = ord($this->compressed_data[$this->position++]);
8505
8506                         // Parse the FEXTRA
8507                         if ($this->flags & 4)
8508                         {
8509                                 // Read subfield IDs
8510                                 $this->SI1 = $this->compressed_data[$this->position++];
8511                                 $this->SI2 = $this->compressed_data[$this->position++];
8512
8513                                 // SI2 set to zero is reserved for future use
8514                                 if ($this->SI2 === "\x00")
8515                                 {
8516                                         return false;
8517                                 }
8518
8519                                 // Get the length of the extra field
8520                                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8521                                 $position += 2;
8522
8523                                 // Check the length of the string is still valid
8524                                 $this->min_compressed_size += $len + 4;
8525                                 if ($this->compressed_size >= $this->min_compressed_size)
8526                                 {
8527                                         // Set the extra field to the given data
8528                                         $this->extra_field = substr($this->compressed_data, $this->position, $len);
8529                                         $this->position += $len;
8530                                 }
8531                                 else
8532                                 {
8533                                         return false;
8534                                 }
8535                         }
8536
8537                         // Parse the FNAME
8538                         if ($this->flags & 8)
8539                         {
8540                                 // Get the length of the filename
8541                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8542
8543                                 // Check the length of the string is still valid
8544                                 $this->min_compressed_size += $len + 1;
8545                                 if ($this->compressed_size >= $this->min_compressed_size)
8546                                 {
8547                                         // Set the original filename to the given string
8548                                         $this->filename = substr($this->compressed_data, $this->position, $len);
8549                                         $this->position += $len + 1;
8550                                 }
8551                                 else
8552                                 {
8553                                         return false;
8554                                 }
8555                         }
8556
8557                         // Parse the FCOMMENT
8558                         if ($this->flags & 16)
8559                         {
8560                                 // Get the length of the comment
8561                                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8562
8563                                 // Check the length of the string is still valid
8564                                 $this->min_compressed_size += $len + 1;
8565                                 if ($this->compressed_size >= $this->min_compressed_size)
8566                                 {
8567                                         // Set the original comment to the given string
8568                                         $this->comment = substr($this->compressed_data, $this->position, $len);
8569                                         $this->position += $len + 1;
8570                                 }
8571                                 else
8572                                 {
8573                                         return false;
8574                                 }
8575                         }
8576
8577                         // Parse the FHCRC
8578                         if ($this->flags & 2)
8579                         {
8580                                 // Check the length of the string is still valid
8581                                 $this->min_compressed_size += $len + 2;
8582                                 if ($this->compressed_size >= $this->min_compressed_size)
8583                                 {
8584                                         // Read the CRC
8585                                         $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8586
8587                                         // Check the CRC matches
8588                                         if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8589                                         {
8590                                                 $this->position += 2;
8591                                         }
8592                                         else
8593                                         {
8594                                                 return false;
8595                                         }
8596                                 }
8597                                 else
8598                                 {
8599                                         return false;
8600                                 }
8601                         }
8602
8603                         // Decompress the actual data
8604                         if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8605                         {
8606                                 return false;
8607                         }
8608                         else
8609                         {
8610                                 $this->position = $this->compressed_size - 8;
8611                         }
8612
8613                         // Check CRC of data
8614                         $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8615                         $this->position += 4;
8616                         /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8617                         {
8618                                 return false;
8619                         }*/
8620
8621                         // Check ISIZE of data
8622                         $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8623                         $this->position += 4;
8624                         if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8625                         {
8626                                 return false;
8627                         }
8628
8629                         // Wow, against all odds, we've actually got a valid gzip string
8630                         return true;
8631                 }
8632                 else
8633                 {
8634                         return false;
8635                 }
8636         }
8637 }
8638
8639 class SimplePie_Cache
8640 {
8641         /**
8642          * Don't call the constructor. Please.
8643          *
8644          * @access private
8645          */
8646         function SimplePie_Cache()
8647         {
8648                 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8649         }
8650
8651         /**
8652          * Create a new SimplePie_Cache object
8653          *
8654          * @static
8655          * @access public
8656          */
8657         function create($location, $filename, $extension)
8658         {
8659                 $location_iri = new SimplePie_IRI($location);
8660                 switch ($location_iri->get_scheme())
8661                 {
8662                         case 'mysql':
8663                                 if (extension_loaded('mysql'))
8664                                 {
8665                                         return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8666                                 }
8667                                 break;
8668
8669                         default:
8670                                 return new SimplePie_Cache_File($location, $filename, $extension);
8671                 }
8672         }
8673 }
8674
8675 class SimplePie_Cache_File
8676 {
8677         var $location;
8678         var $filename;
8679         var $extension;
8680         var $name;
8681
8682         function SimplePie_Cache_File($location, $filename, $extension)
8683         {
8684                 $this->location = $location;
8685                 $this->filename = $filename;
8686                 $this->extension = $extension;
8687                 $this->name = "$this->location/$this->filename.$this->extension";
8688         }
8689
8690         function save($data)
8691         {
8692                 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8693                 {
8694                         if (is_a($data, 'SimplePie'))
8695                         {
8696                                 $data = $data->data;
8697                         }
8698
8699                         $data = serialize($data);
8700
8701                         if (function_exists('file_put_contents'))
8702                         {
8703                                 return (bool) file_put_contents($this->name, $data);
8704                         }
8705                         else
8706                         {
8707                                 $fp = fopen($this->name, 'wb');
8708                                 if ($fp)
8709                                 {
8710                                         fwrite($fp, $data);
8711                                         fclose($fp);
8712                                         return true;
8713                                 }
8714                         }
8715                 }
8716                 return false;
8717         }
8718
8719         function load()
8720         {
8721                 if (file_exists($this->name) && is_readable($this->name))
8722                 {
8723                         return unserialize(file_get_contents($this->name));
8724                 }
8725                 return false;
8726         }
8727
8728         function mtime()
8729         {
8730                 if (file_exists($this->name))
8731                 {
8732                         return filemtime($this->name);
8733                 }
8734                 return false;
8735         }
8736
8737         function touch()
8738         {
8739                 if (file_exists($this->name))
8740                 {
8741                         return touch($this->name);
8742                 }
8743                 return false;
8744         }
8745
8746         function unlink()
8747         {
8748                 if (file_exists($this->name))
8749                 {
8750                         return unlink($this->name);
8751                 }
8752                 return false;
8753         }
8754 }
8755
8756 class SimplePie_Cache_DB
8757 {
8758         function prepare_simplepie_object_for_cache($data)
8759         {
8760                 $items = $data->get_items();
8761                 $items_by_id = array();
8762
8763                 if (!empty($items))
8764                 {
8765                         foreach ($items as $item)
8766                         {
8767                                 $items_by_id[$item->get_id()] = $item;
8768                         }
8769
8770                         if (count($items_by_id) !== count($items))
8771                         {
8772                                 $items_by_id = array();
8773                                 foreach ($items as $item)
8774                                 {
8775                                         $items_by_id[$item->get_id(true)] = $item;
8776                                 }
8777                         }
8778
8779                         if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8780                         {
8781                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8782                         }
8783                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8784                         {
8785                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8786                         }
8787                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8788                         {
8789                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8790                         }
8791                         elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8792                         {
8793                                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8794                         }
8795                         else
8796                         {
8797                                 $channel = null;
8798                         }
8799
8800                         if ($channel !== null)
8801                         {
8802                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8803                                 {
8804                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8805                                 }
8806                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8807                                 {
8808                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8809                                 }
8810                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8811                                 {
8812                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8813                                 }
8814                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8815                                 {
8816                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8817                                 }
8818                                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8819                                 {
8820                                         unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8821                                 }
8822                         }
8823                         if (isset($data->data['items']))
8824                         {
8825                                 unset($data->data['items']);
8826                         }
8827                         if (isset($data->data['ordered_items']))
8828                         {
8829                                 unset($data->data['ordered_items']);
8830                         }
8831                 }
8832                 return array(serialize($data->data), $items_by_id);
8833         }
8834 }
8835
8836 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8837 {
8838         var $mysql;
8839         var $options;
8840         var $id;
8841
8842         function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8843         {
8844                 $host = $mysql_location->get_host();
8845                 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8846                 {
8847                         $server = ':' . substr($host, 5, -1);
8848                 }
8849                 else
8850                 {
8851                         $server = $host;
8852                         if ($mysql_location->get_port() !== null)
8853                         {
8854                                 $server .= ':' . $mysql_location->get_port();
8855                         }
8856                 }
8857
8858                 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8859                 {
8860                         list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8861                 }
8862                 else
8863                 {
8864                         $username = $mysql_location->get_userinfo();
8865                         $password = null;
8866                 }
8867
8868                 if ($this->mysql = mysql_connect($server, $username, $password))
8869                 {
8870                         $this->id = $name . $extension;
8871                         $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8872                         if (!isset($this->options['prefix'][0]))
8873                         {
8874                                 $this->options['prefix'][0] = '';
8875                         }
8876
8877                         if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8878                                 && mysql_query('SET NAMES utf8')
8879                                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8880                         {
8881                                 $db = array();
8882                                 while ($row = mysql_fetch_row($query))
8883                                 {
8884                                         $db[] = $row[0];
8885                                 }
8886
8887                                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8888                                 {
8889                                         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)))'))
8890                                         {
8891                                                 $this->mysql = null;
8892                                         }
8893                                 }
8894
8895                                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8896                                 {
8897                                         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)))'))
8898                                         {
8899                                                 $this->mysql = null;
8900                                         }
8901                                 }
8902                         }
8903                         else
8904                         {
8905                                 $this->mysql = null;
8906                         }
8907                 }
8908         }
8909
8910         function save($data)
8911         {
8912                 if ($this->mysql)
8913                 {
8914                         $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8915
8916                         if (is_a($data, 'SimplePie'))
8917                         {
8918                                 if (SIMPLEPIE_PHP5)
8919                                 {
8920                                         // This keyword needs to defy coding standards for PHP4 compatibility
8921                                         $data = clone($data);
8922                                 }
8923
8924                                 $prepared = $this->prepare_simplepie_object_for_cache($data);
8925
8926                                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8927                                 {
8928                                         if (mysql_num_rows($query))
8929                                         {
8930                                                 $items = count($prepared[1]);
8931                                                 if ($items)
8932                                                 {
8933                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8934                                                 }
8935                                                 else
8936                                                 {
8937                                                         $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8938                                                 }
8939
8940                                                 if (!mysql_query($sql, $this->mysql))
8941                                                 {
8942                                                         return false;
8943                                                 }
8944                                         }
8945                                         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))
8946                                         {
8947                                                 return false;
8948                                         }
8949
8950                                         $ids = array_keys($prepared[1]);
8951                                         if (!empty($ids))
8952                                         {
8953                                                 foreach ($ids as $id)
8954                                                 {
8955                                                         $database_ids[] = mysql_real_escape_string($id);
8956                                                 }
8957
8958                                                 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))
8959                                                 {
8960                                                         $existing_ids = array();
8961                                                         while ($row = mysql_fetch_row($query))
8962                                                         {
8963                                                                 $existing_ids[] = $row[0];
8964                                                         }
8965
8966                                                         $new_ids = array_diff($ids, $existing_ids);
8967
8968                                                         foreach ($new_ids as $new_id)
8969                                                         {
8970                                                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
8971                                                                 {
8972                                                                         $date = time();
8973                                                                 }
8974
8975                                                                 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))
8976                                                                 {
8977                                                                         return false;
8978                                                                 }
8979                                                         }
8980                                                         return true;
8981                                                 }
8982                                         }
8983                                         else
8984                                         {
8985                                                 return true;
8986                                         }
8987                                 }
8988                         }
8989                         elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8990                         {
8991                                 if (mysql_num_rows($query))
8992                                 {
8993                                         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))
8994                                         {
8995                                                 return true;
8996                                         }
8997                                 }
8998                                 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))
8999                                 {
9000                                         return true;
9001                                 }
9002                         }
9003                 }
9004                 return false;
9005         }
9006
9007         function load()
9008         {
9009                 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)))
9010                 {
9011                         $data = unserialize($row[1]);
9012
9013                         if (isset($this->options['items'][0]))
9014                         {
9015                                 $items = (int) $this->options['items'][0];
9016                         }
9017                         else
9018                         {
9019                                 $items = (int) $row[0];
9020                         }
9021
9022                         if ($items !== 0)
9023                         {
9024                                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9025                                 {
9026                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9027                                 }
9028                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9029                                 {
9030                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9031                                 }
9032                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9033                                 {
9034                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9035                                 }
9036                                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9037                                 {
9038                                         $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9039                                 }
9040                                 else
9041                                 {
9042                                         $feed = null;
9043                                 }
9044
9045                                 if ($feed !== null)
9046                                 {
9047                                         $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9048                                         if ($items > 0)
9049                                         {
9050                                                 $sql .= ' LIMIT ' . $items;
9051                                         }
9052
9053                                         if ($query = mysql_unbuffered_query($sql, $this->mysql))
9054                                         {
9055                                                 while ($row = mysql_fetch_row($query))
9056                                                 {
9057                                                         $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9058                                                 }
9059                                         }
9060                                         else
9061                                         {
9062                                                 return false;
9063                                         }
9064                                 }
9065                         }
9066                         return $data;
9067                 }
9068                 return false;
9069         }
9070
9071         function mtime()
9072         {
9073                 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)))
9074                 {
9075                         return $row[0];
9076                 }
9077                 else
9078                 {
9079                         return false;
9080                 }
9081         }
9082
9083         function touch()
9084         {
9085                 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))
9086                 {
9087                         return true;
9088                 }
9089                 else
9090                 {
9091                         return false;
9092                 }
9093         }
9094
9095         function unlink()
9096         {
9097                 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)))
9098                 {
9099                         return true;
9100                 }
9101                 else
9102                 {
9103                         return false;
9104                 }
9105         }
9106 }
9107
9108 class SimplePie_Misc
9109 {
9110         function time_hms($seconds)
9111         {
9112                 $time = '';
9113
9114                 $hours = floor($seconds / 3600);
9115                 $remainder = $seconds % 3600;
9116                 if ($hours > 0)
9117                 {
9118                         $time .= $hours.':';
9119                 }
9120
9121                 $minutes = floor($remainder / 60);
9122                 $seconds = $remainder % 60;
9123                 if ($minutes < 10 && $hours > 0)
9124                 {
9125                         $minutes = '0' . $minutes;
9126                 }
9127                 if ($seconds < 10)
9128                 {
9129                         $seconds = '0' . $seconds;
9130                 }
9131
9132                 $time .= $minutes.':';
9133                 $time .= $seconds;
9134
9135                 return $time;
9136         }
9137
9138         function absolutize_url($relative, $base)
9139         {
9140                 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9141                 return $iri->get_iri();
9142         }
9143
9144         function remove_dot_segments($input)
9145         {
9146                 $output = '';
9147                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9148                 {
9149                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9150                         if (strpos($input, '../') === 0)
9151                         {
9152                                 $input = substr($input, 3);
9153                         }
9154                         elseif (strpos($input, './') === 0)
9155                         {
9156                                 $input = substr($input, 2);
9157                         }
9158                         // 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,
9159                         elseif (strpos($input, '/./') === 0)
9160                         {
9161                                 $input = substr_replace($input, '/', 0, 3);
9162                         }
9163                         elseif ($input === '/.')
9164                         {
9165                                 $input = '/';
9166                         }
9167                         // 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,
9168                         elseif (strpos($input, '/../') === 0)
9169                         {
9170                                 $input = substr_replace($input, '/', 0, 4);
9171                                 $output = substr_replace($output, '', strrpos($output, '/'));
9172                         }
9173                         elseif ($input === '/..')
9174                         {
9175                                 $input = '/';
9176                                 $output = substr_replace($output, '', strrpos($output, '/'));
9177                         }
9178                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9179                         elseif ($input === '.' || $input === '..')
9180                         {
9181                                 $input = '';
9182                         }
9183                         // 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
9184                         elseif (($pos = strpos($input, '/', 1)) !== false)
9185                         {
9186                                 $output .= substr($input, 0, $pos);
9187                                 $input = substr_replace($input, '', 0, $pos);
9188                         }
9189                         else
9190                         {
9191                                 $output .= $input;
9192                                 $input = '';
9193                         }
9194                 }
9195                 return $output . $input;
9196         }
9197
9198         function get_element($realname, $string)
9199         {
9200                 $return = array();
9201                 $name = preg_quote($realname, '/');
9202                 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9203                 {
9204                         for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9205                         {
9206                                 $return[$i]['tag'] = $realname;
9207                                 $return[$i]['full'] = $matches[$i][0][0];
9208                                 $return[$i]['offset'] = $matches[$i][0][1];
9209                                 if (strlen($matches[$i][3][0]) <= 2)
9210                                 {
9211                                         $return[$i]['self_closing'] = true;
9212                                 }
9213                                 else
9214                                 {
9215                                         $return[$i]['self_closing'] = false;
9216                                         $return[$i]['content'] = $matches[$i][4][0];
9217                                 }
9218                                 $return[$i]['attribs'] = array();
9219                                 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))
9220                                 {
9221                                         for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9222                                         {
9223                                                 if (count($attribs[$j]) === 2)
9224                                                 {
9225                                                         $attribs[$j][2] = $attribs[$j][1];
9226                                                 }
9227                                                 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9228                                         }
9229                                 }
9230                         }
9231                 }
9232                 return $return;
9233         }
9234
9235         function element_implode($element)
9236         {
9237                 $full = "<$element[tag]";
9238                 foreach ($element['attribs'] as $key => $value)
9239                 {
9240                         $key = strtolower($key);
9241                         $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9242                 }
9243                 if ($element['self_closing'])
9244                 {
9245                         $full .= ' />';
9246                 }
9247                 else
9248                 {
9249                         $full .= ">$element[content]</$element[tag]>";
9250                 }
9251                 return $full;
9252         }
9253
9254         function error($message, $level, $file, $line)
9255         {
9256                 if ((ini_get('error_reporting') & $level) > 0)
9257                 {
9258                         switch ($level)
9259                         {
9260                                 case E_USER_ERROR:
9261                                         $note = 'PHP Error';
9262                                         break;
9263                                 case E_USER_WARNING:
9264                                         $note = 'PHP Warning';
9265                                         break;
9266                                 case E_USER_NOTICE:
9267                                         $note = 'PHP Notice';
9268                                         break;
9269                                 default:
9270                                         $note = 'Unknown Error';
9271                                         break;
9272                         }
9273
9274                         $log_error = true;
9275                         if (!function_exists('error_log'))
9276                         {
9277                                 $log_error = false;
9278                         }
9279
9280                         $log_file = @ini_get('error_log');
9281                         if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9282                         {
9283                                 $log_error = false;
9284                         }
9285
9286                         if ($log_error)
9287                         {
9288                                 @error_log("$note: $message in $file on line $line", 0);
9289                         }
9290                 }
9291
9292                 return $message;
9293         }
9294
9295         /**
9296          * If a file has been cached, retrieve and display it.
9297          *
9298          * This is most useful for caching images (get_favicon(), etc.),
9299          * however it works for all cached files.  This WILL NOT display ANY
9300          * file/image/page/whatever, but rather only display what has already
9301          * been cached by SimplePie.
9302          *
9303          * @access public
9304          * @see SimplePie::get_favicon()
9305          * @param str $identifier_url URL that is used to identify the content.
9306          * This may or may not be the actual URL of the live content.
9307          * @param str $cache_location Location of SimplePie's cache.  Defaults
9308          * to './cache'.
9309          * @param str $cache_extension The file extension that the file was
9310          * cached with.  Defaults to 'spc'.
9311          * @param str $cache_class Name of the cache-handling class being used
9312          * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9313          * as-is unless you've overloaded the class.
9314          * @param str $cache_name_function Obsolete. Exists for backwards
9315          * compatibility reasons only.
9316          */
9317         function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9318         {
9319                 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9320
9321                 if ($file = $cache->load())
9322                 {
9323                         if (isset($file['headers']['content-type']))
9324                         {
9325                                 header('Content-type:' . $file['headers']['content-type']);
9326                         }
9327                         else
9328                         {
9329                                 header('Content-type: application/octet-stream');
9330                         }
9331                         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9332                         echo $file['body'];
9333                         exit;
9334                 }
9335
9336                 die('Cached file for ' . $identifier_url . ' cannot be found.');
9337         }
9338
9339         function fix_protocol($url, $http = 1)
9340         {
9341                 $url = SimplePie_Misc::normalize_url($url);
9342                 $parsed = SimplePie_Misc::parse_url($url);
9343                 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9344                 {
9345                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9346                 }
9347
9348                 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9349                 {
9350                         return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9351                 }
9352
9353                 if ($http === 2 && $parsed['scheme'] !== '')
9354                 {
9355                         return "feed:$url";
9356                 }
9357                 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9358                 {
9359                         return substr_replace($url, 'podcast', 0, 4);
9360                 }
9361                 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9362                 {
9363                         return substr_replace($url, 'itpc', 0, 4);
9364                 }
9365                 else
9366                 {
9367                         return $url;
9368                 }
9369         }
9370
9371         function parse_url($url)
9372         {
9373                 $iri = new SimplePie_IRI($url);
9374                 return array(
9375                         'scheme' => (string) $iri->get_scheme(),
9376                         'authority' => (string) $iri->get_authority(),
9377                         'path' => (string) $iri->get_path(),
9378                         'query' => (string) $iri->get_query(),
9379                         'fragment' => (string) $iri->get_fragment()
9380                 );
9381         }
9382
9383         function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9384         {
9385                 $iri = new SimplePie_IRI('');
9386                 $iri->set_scheme($scheme);
9387                 $iri->set_authority($authority);
9388                 $iri->set_path($path);
9389                 $iri->set_query($query);
9390                 $iri->set_fragment($fragment);
9391                 return $iri->get_iri();
9392         }
9393
9394         function normalize_url($url)
9395         {
9396                 $iri = new SimplePie_IRI($url);
9397                 return $iri->get_iri();
9398         }
9399
9400         function percent_encoding_normalization($match)
9401         {
9402                 $integer = hexdec($match[1]);
9403                 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9404                 {
9405                         return chr($integer);
9406                 }
9407                 else
9408                 {
9409                         return strtoupper($match[0]);
9410                 }
9411         }
9412
9413         /**
9414          * Remove bad UTF-8 bytes
9415          *
9416          * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9417          * FAQ: Multilingual Forms (modified to include full ASCII range)
9418          *
9419          * @author Geoffrey Sneddon
9420          * @see http://www.w3.org/International/questions/qa-forms-utf-8
9421          * @param string $str String to remove bad UTF-8 bytes from
9422          * @return string UTF-8 string
9423          */
9424         function utf8_bad_replace($str)
9425         {
9426                 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9427                 {
9428                         return $return;
9429                 }
9430                 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9431                 {
9432                         return $return;
9433                 }
9434                 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))
9435                 {
9436                         return implode("\xEF\xBF\xBD", $matches[0]);
9437                 }
9438                 elseif ($str !== '')
9439                 {
9440                         return "\xEF\xBF\xBD";
9441                 }
9442                 else
9443                 {
9444                         return '';
9445                 }
9446         }
9447
9448         /**
9449          * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9450          *
9451          * @static
9452          * @access public
9453          * @param string $string Windows-1252 encoded string
9454          * @return string UTF-8 encoded string
9455          */
9456         function windows_1252_to_utf8($string)
9457         {
9458                 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");
9459
9460                 return strtr($string, $convert_table);
9461         }
9462
9463         function change_encoding($data, $input, $output)
9464         {
9465                 $input = SimplePie_Misc::encoding($input);
9466                 $output = SimplePie_Misc::encoding($output);
9467
9468                 // We fail to fail on non US-ASCII bytes
9469                 if ($input === 'US-ASCII')
9470                 {
9471                         static $non_ascii_octects = '';
9472                         if (!$non_ascii_octects)
9473                         {
9474                                 for ($i = 0x80; $i <= 0xFF; $i++)
9475                                 {
9476                                         $non_ascii_octects .= chr($i);
9477                                 }
9478                         }
9479                         $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9480                 }
9481
9482                 // This is first, as behaviour of this is completely predictable
9483                 if ($input === 'Windows-1252' && $output === 'UTF-8')
9484                 {
9485                         return SimplePie_Misc::windows_1252_to_utf8($data);
9486                 }
9487                 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9488                 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9489                 {
9490                         return $return;
9491                 }
9492                 // This is last, as behaviour of this varies with OS userland and PHP version
9493                 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9494                 {
9495                         return $return;
9496                 }
9497                 // If we can't do anything, just fail
9498                 else
9499                 {
9500                         return false;
9501                 }
9502         }
9503
9504         function encoding($charset)
9505         {
9506                 // Normalization from UTS #22
9507                 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9508                 {
9509                         case 'adobestandardencoding':
9510                         case 'csadobestandardencoding':
9511                                 return 'Adobe-Standard-Encoding';
9512
9513                         case 'adobesymbolencoding':
9514                         case 'cshppsmath':
9515                                 return 'Adobe-Symbol-Encoding';
9516
9517                         case 'ami1251':
9518                         case 'amiga1251':
9519                                 return 'Amiga-1251';
9520
9521                         case 'ansix31101983':
9522                         case 'csat5001983':
9523                         case 'csiso99naplps':
9524                         case 'isoir99':
9525                         case 'naplps':
9526                                 return 'ANSI_X3.110-1983';
9527
9528                         case 'arabic7':
9529                         case 'asmo449':
9530                         case 'csiso89asmo449':
9531                         case 'iso9036':
9532                         case 'isoir89':
9533                                 return 'ASMO_449';
9534
9535                         case 'big5':
9536                         case 'csbig5':
9537                         case 'xxbig5':
9538                                 return 'Big5';
9539
9540                         case 'big5hkscs':
9541                                 return 'Big5-HKSCS';
9542
9543                         case 'bocu1':
9544                         case 'csbocu1':
9545                                 return 'BOCU-1';
9546
9547                         case 'brf':
9548                         case 'csbrf':
9549                                 return 'BRF';
9550
9551                         case 'bs4730':
9552                         case 'csiso4unitedkingdom':
9553                         case 'gb':
9554                         case 'iso646gb':
9555                         case 'isoir4':
9556                         case 'uk':
9557                                 return 'BS_4730';
9558
9559                         case 'bsviewdata':
9560                         case 'csiso47bsviewdata':
9561                         case 'isoir47':
9562                                 return 'BS_viewdata';
9563
9564                         case 'cesu8':
9565                         case 'cscesu8':
9566                                 return 'CESU-8';
9567
9568                         case 'ca':
9569                         case 'csa71':
9570                         case 'csaz243419851':
9571                         case 'csiso121canadian1':
9572                         case 'iso646ca':
9573                         case 'isoir121':
9574                                 return 'CSA_Z243.4-1985-1';
9575
9576                         case 'csa72':
9577                         case 'csaz243419852':
9578                         case 'csiso122canadian2':
9579                         case 'iso646ca2':
9580                         case 'isoir122':
9581                                 return 'CSA_Z243.4-1985-2';
9582
9583                         case 'csaz24341985gr':
9584                         case 'csiso123csaz24341985gr':
9585                         case 'isoir123':
9586                                 return 'CSA_Z243.4-1985-gr';
9587
9588                         case 'csiso139csn369103':
9589                         case 'csn369103':
9590                         case 'isoir139':
9591                                 return 'CSN_369103';
9592
9593                         case 'csdecmcs':
9594                         case 'dec':
9595                         case 'decmcs':
9596                                 return 'DEC-MCS';
9597
9598                         case 'csiso21german':
9599                         case 'de':
9600                         case 'din66003':
9601                         case 'iso646de':
9602                         case 'isoir21':
9603                                 return 'DIN_66003';
9604
9605                         case 'csdkus':
9606                         case 'dkus':
9607                                 return 'dk-us';
9608
9609                         case 'csiso646danish':
9610                         case 'dk':
9611                         case 'ds2089':
9612                         case 'iso646dk':
9613                                 return 'DS_2089';
9614
9615                         case 'csibmebcdicatde':
9616                         case 'ebcdicatde':
9617                                 return 'EBCDIC-AT-DE';
9618
9619                         case 'csebcdicatdea':
9620                         case 'ebcdicatdea':
9621                                 return 'EBCDIC-AT-DE-A';
9622
9623                         case 'csebcdiccafr':
9624                         case 'ebcdiccafr':
9625                                 return 'EBCDIC-CA-FR';
9626
9627                         case 'csebcdicdkno':
9628                         case 'ebcdicdkno':
9629                                 return 'EBCDIC-DK-NO';
9630
9631                         case 'csebcdicdknoa':
9632                         case 'ebcdicdknoa':
9633                                 return 'EBCDIC-DK-NO-A';
9634
9635                         case 'csebcdices':
9636                         case 'ebcdices':
9637                                 return 'EBCDIC-ES';
9638
9639                         case 'csebcdicesa':
9640                         case 'ebcdicesa':
9641                                 return 'EBCDIC-ES-A';
9642
9643                         case 'csebcdicess':
9644                         case 'ebcdicess':
9645                                 return 'EBCDIC-ES-S';
9646
9647                         case 'csebcdicfise':
9648                         case 'ebcdicfise':
9649                                 return 'EBCDIC-FI-SE';
9650
9651                         case 'csebcdicfisea':
9652                         case 'ebcdicfisea':
9653                                 return 'EBCDIC-FI-SE-A';
9654
9655                         case 'csebcdicfr':
9656                         case 'ebcdicfr':
9657                                 return 'EBCDIC-FR';
9658
9659                         case 'csebcdicit':
9660                         case 'ebcdicit':
9661                                 return 'EBCDIC-IT';
9662
9663                         case 'csebcdicpt':
9664                         case 'ebcdicpt':
9665                                 return 'EBCDIC-PT';
9666
9667                         case 'csebcdicuk':
9668                         case 'ebcdicuk':
9669                                 return 'EBCDIC-UK';
9670
9671                         case 'csebcdicus':
9672                         case 'ebcdicus':
9673                                 return 'EBCDIC-US';
9674
9675                         case 'csiso111ecmacyrillic':
9676                         case 'ecmacyrillic':
9677                         case 'isoir111':
9678                         case 'koi8e':
9679                                 return 'ECMA-cyrillic';
9680
9681                         case 'csiso17spanish':
9682                         case 'es':
9683                         case 'iso646es':
9684                         case 'isoir17':
9685                                 return 'ES';
9686
9687                         case 'csiso85spanish2':
9688                         case 'es2':
9689                         case 'iso646es2':
9690                         case 'isoir85':
9691                                 return 'ES2';
9692
9693                         case 'cseucfixwidjapanese':
9694                         case 'extendedunixcodefixedwidthforjapanese':
9695                                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9696
9697                         case 'cseucpkdfmtjapanese':
9698                         case 'eucjp':
9699                         case 'extendedunixcodepackedformatforjapanese':
9700                                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9701
9702                         case 'gb18030':
9703                                 return 'GB18030';
9704
9705                         case 'chinese':
9706                         case 'cp936':
9707                         case 'csgb2312':
9708                         case 'csiso58gb231280':
9709                         case 'gb2312':
9710                         case 'gb231280':
9711                         case 'gbk':
9712                         case 'isoir58':
9713                         case 'ms936':
9714                         case 'windows936':
9715                                 return 'GBK';
9716
9717                         case 'cn':
9718                         case 'csiso57gb1988':
9719                         case 'gb198880':
9720                         case 'iso646cn':
9721                         case 'isoir57':
9722                                 return 'GB_1988-80';
9723
9724                         case 'csiso153gost1976874':
9725                         case 'gost1976874':
9726                         case 'isoir153':
9727                         case 'stsev35888':
9728                                 return 'GOST_19768-74';
9729
9730                         case 'csiso150':
9731                         case 'csiso150greekccitt':
9732                         case 'greekccitt':
9733                         case 'isoir150':
9734                                 return 'greek-ccitt';
9735
9736                         case 'csiso88greek7':
9737                         case 'greek7':
9738                         case 'isoir88':
9739                                 return 'greek7';
9740
9741                         case 'csiso18greek7old':
9742                         case 'greek7old':
9743                         case 'isoir18':
9744                                 return 'greek7-old';
9745
9746                         case 'cshpdesktop':
9747                         case 'hpdesktop':
9748                                 return 'HP-DeskTop';
9749
9750                         case 'cshplegal':
9751                         case 'hplegal':
9752                                 return 'HP-Legal';
9753
9754                         case 'cshpmath8':
9755                         case 'hpmath8':
9756                                 return 'HP-Math8';
9757
9758                         case 'cshppifont':
9759                         case 'hppifont':
9760                                 return 'HP-Pi-font';
9761
9762                         case 'cshproman8':
9763                         case 'hproman8':
9764                         case 'r8':
9765                         case 'roman8':
9766                                 return 'hp-roman8';
9767
9768                         case 'hzgb2312':
9769                                 return 'HZ-GB-2312';
9770
9771                         case 'csibmsymbols':
9772                         case 'ibmsymbols':
9773                                 return 'IBM-Symbols';
9774
9775                         case 'csibmthai':
9776                         case 'ibmthai':
9777                                 return 'IBM-Thai';
9778
9779                         case 'ccsid858':
9780                         case 'cp858':
9781                         case 'ibm858':
9782                         case 'pcmultilingual850euro':
9783                                 return 'IBM00858';
9784
9785                         case 'ccsid924':
9786                         case 'cp924':
9787                         case 'ebcdiclatin9euro':
9788                         case 'ibm924':
9789                                 return 'IBM00924';
9790
9791                         case 'ccsid1140':
9792                         case 'cp1140':
9793                         case 'ebcdicus37euro':
9794                         case 'ibm1140':
9795                                 return 'IBM01140';
9796
9797                         case 'ccsid1141':
9798                         case 'cp1141':
9799                         case 'ebcdicde273euro':
9800                         case 'ibm1141':
9801                                 return 'IBM01141';
9802
9803                         case 'ccsid1142':
9804                         case 'cp1142':
9805                         case 'ebcdicdk277euro':
9806                         case 'ebcdicno277euro':
9807                         case 'ibm1142':
9808                                 return 'IBM01142';
9809
9810                         case 'ccsid1143':
9811                         case 'cp1143':
9812                         case 'ebcdicfi278euro':
9813                         case 'ebcdicse278euro':
9814                         case 'ibm1143':
9815                                 return 'IBM01143';
9816
9817                         case 'ccsid1144':
9818                         case 'cp1144':
9819                         case 'ebcdicit280euro':
9820                         case 'ibm1144':
9821                                 return 'IBM01144';
9822
9823                         case 'ccsid1145':
9824                         case 'cp1145':
9825                         case 'ebcdices284euro':
9826                         case 'ibm1145':
9827                                 return 'IBM01145';
9828
9829                         case 'ccsid1146':
9830                         case 'cp1146':
9831                         case 'ebcdicgb285euro':
9832                         case 'ibm1146':
9833                                 return 'IBM01146';
9834
9835                         case 'ccsid1147':
9836                         case 'cp1147':
9837                         case 'ebcdicfr297euro':
9838                         case 'ibm1147':
9839                                 return 'IBM01147';
9840
9841                         case 'ccsid1148':
9842                         case 'cp1148':
9843                         case 'ebcdicinternational500euro':
9844                         case 'ibm1148':
9845                                 return 'IBM01148';
9846
9847                         case 'ccsid1149':
9848                         case 'cp1149':
9849                         case 'ebcdicis871euro':
9850                         case 'ibm1149':
9851                                 return 'IBM01149';
9852
9853                         case 'cp37':
9854                         case 'csibm37':
9855                         case 'ebcdiccpca':
9856                         case 'ebcdiccpnl':
9857                         case 'ebcdiccpus':
9858                         case 'ebcdiccpwt':
9859                         case 'ibm37':
9860                                 return 'IBM037';
9861
9862                         case 'cp38':
9863                         case 'csibm38':
9864                         case 'ebcdicint':
9865                         case 'ibm38':
9866                                 return 'IBM038';
9867
9868                         case 'cp273':
9869                         case 'csibm273':
9870                         case 'ibm273':
9871                                 return 'IBM273';
9872
9873                         case 'cp274':
9874                         case 'csibm274':
9875                         case 'ebcdicbe':
9876                         case 'ibm274':
9877                                 return 'IBM274';
9878
9879                         case 'cp275':
9880                         case 'csibm275':
9881                         case 'ebcdicbr':
9882                         case 'ibm275':
9883                                 return 'IBM275';
9884
9885                         case 'csibm277':
9886                         case 'ebcdiccpdk':
9887                         case 'ebcdiccpno':
9888                         case 'ibm277':
9889                                 return 'IBM277';
9890
9891                         case 'cp278':
9892                         case 'csibm278':
9893                         case 'ebcdiccpfi':
9894                         case 'ebcdiccpse':
9895                         case 'ibm278':
9896                                 return 'IBM278';
9897
9898                         case 'cp280':
9899                         case 'csibm280':
9900                         case 'ebcdiccpit':
9901                         case 'ibm280':
9902                                 return 'IBM280';
9903
9904                         case 'cp281':
9905                         case 'csibm281':
9906                         case 'ebcdicjpe':
9907                         case 'ibm281':
9908                                 return 'IBM281';
9909
9910                         case 'cp284':
9911                         case 'csibm284':
9912                         case 'ebcdiccpes':
9913                         case 'ibm284':
9914                                 return 'IBM284';
9915
9916                         case 'cp285':
9917                         case 'csibm285':
9918                         case 'ebcdiccpgb':
9919                         case 'ibm285':
9920                                 return 'IBM285';
9921
9922                         case 'cp290':
9923                         case 'csibm290':
9924                         case 'ebcdicjpkana':
9925                         case 'ibm290':
9926                                 return 'IBM290';
9927
9928                         case 'cp297':
9929                         case 'csibm297':
9930                         case 'ebcdiccpfr':
9931                         case 'ibm297':
9932                                 return 'IBM297';
9933
9934                         case 'cp420':
9935                         case 'csibm420':
9936                         case 'ebcdiccpar1':
9937                         case 'ibm420':
9938                                 return 'IBM420';
9939
9940                         case 'cp423':
9941                         case 'csibm423':
9942                         case 'ebcdiccpgr':
9943                         case 'ibm423':
9944                                 return 'IBM423';
9945
9946                         case 'cp424':
9947                         case 'csibm424':
9948                         case 'ebcdiccphe':
9949                         case 'ibm424':
9950                                 return 'IBM424';
9951
9952                         case '437':
9953                         case 'cp437':
9954                         case 'cspc8codepage437':
9955                         case 'ibm437':
9956                                 return 'IBM437';
9957
9958                         case 'cp500':
9959                         case 'csibm500':
9960                         case 'ebcdiccpbe':
9961                         case 'ebcdiccpch':
9962                         case 'ibm500':
9963                                 return 'IBM500';
9964
9965                         case 'cp775':
9966                         case 'cspc775baltic':
9967                         case 'ibm775':
9968                                 return 'IBM775';
9969
9970                         case '850':
9971                         case 'cp850':
9972                         case 'cspc850multilingual':
9973                         case 'ibm850':
9974                                 return 'IBM850';
9975
9976                         case '851':
9977                         case 'cp851':
9978                         case 'csibm851':
9979                         case 'ibm851':
9980                                 return 'IBM851';
9981
9982                         case '852':
9983                         case 'cp852':
9984                         case 'cspcp852':
9985                         case 'ibm852':
9986                                 return 'IBM852';
9987
9988                         case '855':
9989                         case 'cp855':
9990                         case 'csibm855':
9991                         case 'ibm855':
9992                                 return 'IBM855';
9993
9994                         case '857':
9995                         case 'cp857':
9996                         case 'csibm857':
9997                         case 'ibm857':
9998                                 return 'IBM857';
9999
10000                         case '860':
10001                         case 'cp860':
10002                         case 'csibm860':
10003                         case 'ibm860':
10004                                 return 'IBM860';
10005
10006                         case '861':
10007                         case 'cp861':
10008                         case 'cpis':
10009                         case 'csibm861':
10010                         case 'ibm861':
10011                                 return 'IBM861';
10012
10013                         case '862':
10014                         case 'cp862':
10015                         case 'cspc862latinhebrew':
10016                         case 'ibm862':
10017                                 return 'IBM862';
10018
10019                         case '863':
10020                         case 'cp863':
10021                         case 'csibm863':
10022                         case 'ibm863':
10023                                 return 'IBM863';
10024
10025                         case 'cp864':
10026                         case 'csibm864':
10027                         case 'ibm864':
10028                                 return 'IBM864';
10029
10030                         case '865':
10031                         case 'cp865':
10032                         case 'csibm865':
10033                         case 'ibm865':
10034                                 return 'IBM865';
10035
10036                         case '866':
10037                         case 'cp866':
10038                         case 'csibm866':
10039                         case 'ibm866':
10040                                 return 'IBM866';
10041
10042                         case 'cp868':
10043                         case 'cpar':
10044                         case 'csibm868':
10045                         case 'ibm868':
10046                                 return 'IBM868';
10047
10048                         case '869':
10049                         case 'cp869':
10050                         case 'cpgr':
10051                         case 'csibm869':
10052                         case 'ibm869':
10053                                 return 'IBM869';
10054
10055                         case 'cp870':
10056                         case 'csibm870':
10057                         case 'ebcdiccproece':
10058                         case 'ebcdiccpyu':
10059                         case 'ibm870':
10060                                 return 'IBM870';
10061
10062                         case 'cp871':
10063                         case 'csibm871':
10064                         case 'ebcdiccpis':
10065                         case 'ibm871':
10066                                 return 'IBM871';
10067
10068                         case 'cp880':
10069                         case 'csibm880':
10070                         case 'ebcdiccyrillic':
10071                         case 'ibm880':
10072                                 return 'IBM880';
10073
10074                         case 'cp891':
10075                         case 'csibm891':
10076                         case 'ibm891':
10077                                 return 'IBM891';
10078
10079                         case 'cp903':
10080                         case 'csibm903':
10081                         case 'ibm903':
10082                                 return 'IBM903';
10083
10084                         case '904':
10085                         case 'cp904':
10086                         case 'csibbm904':
10087                         case 'ibm904':
10088                                 return 'IBM904';
10089
10090                         case 'cp905':
10091                         case 'csibm905':
10092                         case 'ebcdiccptr':
10093                         case 'ibm905':
10094                                 return 'IBM905';
10095
10096                         case 'cp918':
10097                         case 'csibm918':
10098                         case 'ebcdiccpar2':
10099                         case 'ibm918':
10100                                 return 'IBM918';
10101
10102                         case 'cp1026':
10103                         case 'csibm1026':
10104                         case 'ibm1026':
10105                                 return 'IBM1026';
10106
10107                         case 'ibm1047':
10108                                 return 'IBM1047';
10109
10110                         case 'csiso143iecp271':
10111                         case 'iecp271':
10112                         case 'isoir143':
10113                                 return 'IEC_P27-1';
10114
10115                         case 'csiso49inis':
10116                         case 'inis':
10117                         case 'isoir49':
10118                                 return 'INIS';
10119
10120                         case 'csiso50inis8':
10121                         case 'inis8':
10122                         case 'isoir50':
10123                                 return 'INIS-8';
10124
10125                         case 'csiso51iniscyrillic':
10126                         case 'iniscyrillic':
10127                         case 'isoir51':
10128                                 return 'INIS-cyrillic';
10129
10130                         case 'csinvariant':
10131                         case 'invariant':
10132                                 return 'INVARIANT';
10133
10134                         case 'iso2022cn':
10135                                 return 'ISO-2022-CN';
10136
10137                         case 'iso2022cnext':
10138                                 return 'ISO-2022-CN-EXT';
10139
10140                         case 'csiso2022jp':
10141                         case 'iso2022jp':
10142                                 return 'ISO-2022-JP';
10143
10144                         case 'csiso2022jp2':
10145                         case 'iso2022jp2':
10146                                 return 'ISO-2022-JP-2';
10147
10148                         case 'csiso2022kr':
10149                         case 'iso2022kr':
10150                                 return 'ISO-2022-KR';
10151
10152                         case 'cswindows30latin1':
10153                         case 'iso88591windows30latin1':
10154                                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10155
10156                         case 'cswindows31latin1':
10157                         case 'iso88591windows31latin1':
10158                                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10159
10160                         case 'csisolatin2':
10161                         case 'iso88592':
10162                         case 'iso885921987':
10163                         case 'isoir101':
10164                         case 'l2':
10165                         case 'latin2':
10166                                 return 'ISO-8859-2';
10167
10168                         case 'cswindows31latin2':
10169                         case 'iso88592windowslatin2':
10170                                 return 'ISO-8859-2-Windows-Latin-2';
10171
10172                         case 'csisolatin3':
10173                         case 'iso88593':
10174                         case 'iso885931988':
10175                         case 'isoir109':
10176                         case 'l3':
10177                         case 'latin3':
10178                                 return 'ISO-8859-3';
10179
10180                         case 'csisolatin4':
10181                         case 'iso88594':
10182                         case 'iso885941988':
10183                         case 'isoir110':
10184                         case 'l4':
10185                         case 'latin4':
10186                                 return 'ISO-8859-4';
10187
10188                         case 'csisolatincyrillic':
10189                         case 'cyrillic':
10190                         case 'iso88595':
10191                         case 'iso885951988':
10192                         case 'isoir144':
10193                                 return 'ISO-8859-5';
10194
10195                         case 'arabic':
10196                         case 'asmo708':
10197                         case 'csisolatinarabic':
10198                         case 'ecma114':
10199                         case 'iso88596':
10200                         case 'iso885961987':
10201                         case 'isoir127':
10202                                 return 'ISO-8859-6';
10203
10204                         case 'csiso88596e':
10205                         case 'iso88596e':
10206                                 return 'ISO-8859-6-E';
10207
10208                         case 'csiso88596i':
10209                         case 'iso88596i':
10210                                 return 'ISO-8859-6-I';
10211
10212                         case 'csisolatingreek':
10213                         case 'ecma118':
10214                         case 'elot928':
10215                         case 'greek':
10216                         case 'greek8':
10217                         case 'iso88597':
10218                         case 'iso885971987':
10219                         case 'isoir126':
10220                                 return 'ISO-8859-7';
10221
10222                         case 'csisolatinhebrew':
10223                         case 'hebrew':
10224                         case 'iso88598':
10225                         case 'iso885981988':
10226                         case 'isoir138':
10227                                 return 'ISO-8859-8';
10228
10229                         case 'csiso88598e':
10230                         case 'iso88598e':
10231                                 return 'ISO-8859-8-E';
10232
10233                         case 'csiso88598i':
10234                         case 'iso88598i':
10235                                 return 'ISO-8859-8-I';
10236
10237                         case 'cswindows31latin5':
10238                         case 'iso88599windowslatin5':
10239                                 return 'ISO-8859-9-Windows-Latin-5';
10240
10241                         case 'csisolatin6':
10242                         case 'iso885910':
10243                         case 'iso8859101992':
10244                         case 'isoir157':
10245                         case 'l6':
10246                         case 'latin6':
10247                                 return 'ISO-8859-10';
10248
10249                         case 'iso885913':
10250                                 return 'ISO-8859-13';
10251
10252                         case 'iso885914':
10253                         case 'iso8859141998':
10254                         case 'isoceltic':
10255                         case 'isoir199':
10256                         case 'l8':
10257                         case 'latin8':
10258                                 return 'ISO-8859-14';
10259
10260                         case 'iso885915':
10261                         case 'latin9':
10262                                 return 'ISO-8859-15';
10263
10264                         case 'iso885916':
10265                         case 'iso8859162001':
10266                         case 'isoir226':
10267                         case 'l10':
10268                         case 'latin10':
10269                                 return 'ISO-8859-16';
10270
10271                         case 'iso10646j1':
10272                                 return 'ISO-10646-J-1';
10273
10274                         case 'csunicode':
10275                         case 'iso10646ucs2':
10276                                 return 'ISO-10646-UCS-2';
10277
10278                         case 'csucs4':
10279                         case 'iso10646ucs4':
10280                                 return 'ISO-10646-UCS-4';
10281
10282                         case 'csunicodeascii':
10283                         case 'iso10646ucsbasic':
10284                                 return 'ISO-10646-UCS-Basic';
10285
10286                         case 'csunicodelatin1':
10287                         case 'iso10646':
10288                         case 'iso10646unicodelatin1':
10289                                 return 'ISO-10646-Unicode-Latin1';
10290
10291                         case 'csiso10646utf1':
10292                         case 'iso10646utf1':
10293                                 return 'ISO-10646-UTF-1';
10294
10295                         case 'csiso115481':
10296                         case 'iso115481':
10297                         case 'isotr115481':
10298                                 return 'ISO-11548-1';
10299
10300                         case 'csiso90':
10301                         case 'isoir90':
10302                                 return 'iso-ir-90';
10303
10304                         case 'csunicodeibm1261':
10305                         case 'isounicodeibm1261':
10306                                 return 'ISO-Unicode-IBM-1261';
10307
10308                         case 'csunicodeibm1264':
10309                         case 'isounicodeibm1264':
10310                                 return 'ISO-Unicode-IBM-1264';
10311
10312                         case 'csunicodeibm1265':
10313                         case 'isounicodeibm1265':
10314                                 return 'ISO-Unicode-IBM-1265';
10315
10316                         case 'csunicodeibm1268':
10317                         case 'isounicodeibm1268':
10318                                 return 'ISO-Unicode-IBM-1268';
10319
10320                         case 'csunicodeibm1276':
10321                         case 'isounicodeibm1276':
10322                                 return 'ISO-Unicode-IBM-1276';
10323
10324                         case 'csiso646basic1983':
10325                         case 'iso646basic1983':
10326                         case 'ref':
10327                                 return 'ISO_646.basic:1983';
10328
10329                         case 'csiso2intlrefversion':
10330                         case 'irv':
10331                         case 'iso646irv1983':
10332                         case 'isoir2':
10333                                 return 'ISO_646.irv:1983';
10334
10335                         case 'csiso2033':
10336                         case 'e13b':
10337                         case 'iso20331983':
10338                         case 'isoir98':
10339                                 return 'ISO_2033-1983';
10340
10341                         case 'csiso5427cyrillic':
10342                         case 'iso5427':
10343                         case 'isoir37':
10344                                 return 'ISO_5427';
10345
10346                         case 'iso5427cyrillic1981':
10347                         case 'iso54271981':
10348                         case 'isoir54':
10349                                 return 'ISO_5427:1981';
10350
10351                         case 'csiso5428greek':
10352                         case 'iso54281980':
10353                         case 'isoir55':
10354                                 return 'ISO_5428:1980';
10355
10356                         case 'csiso6937add':
10357                         case 'iso6937225':
10358                         case 'isoir152':
10359                                 return 'ISO_6937-2-25';
10360
10361                         case 'csisotextcomm':
10362                         case 'iso69372add':
10363                         case 'isoir142':
10364                                 return 'ISO_6937-2-add';
10365
10366                         case 'csiso8859supp':
10367                         case 'iso8859supp':
10368                         case 'isoir154':
10369                         case 'latin125':
10370                                 return 'ISO_8859-supp';
10371
10372                         case 'csiso10367box':
10373                         case 'iso10367box':
10374                         case 'isoir155':
10375                                 return 'ISO_10367-box';
10376
10377                         case 'csiso15italian':
10378                         case 'iso646it':
10379                         case 'isoir15':
10380                         case 'it':
10381                                 return 'IT';
10382
10383                         case 'csiso13jisc6220jp':
10384                         case 'isoir13':
10385                         case 'jisc62201969':
10386                         case 'jisc62201969jp':
10387                         case 'katakana':
10388                         case 'x2017':
10389                                 return 'JIS_C6220-1969-jp';
10390
10391                         case 'csiso14jisc6220ro':
10392                         case 'iso646jp':
10393                         case 'isoir14':
10394                         case 'jisc62201969ro':
10395                         case 'jp':
10396                                 return 'JIS_C6220-1969-ro';
10397
10398                         case 'csiso42jisc62261978':
10399                         case 'isoir42':
10400                         case 'jisc62261978':
10401                                 return 'JIS_C6226-1978';
10402
10403                         case 'csiso87jisx208':
10404                         case 'isoir87':
10405                         case 'jisc62261983':
10406                         case 'jisx2081983':
10407                         case 'x208':
10408                                 return 'JIS_C6226-1983';
10409
10410                         case 'csiso91jisc62291984a':
10411                         case 'isoir91':
10412                         case 'jisc62291984a':
10413                         case 'jpocra':
10414                                 return 'JIS_C6229-1984-a';
10415
10416                         case 'csiso92jisc62991984b':
10417                         case 'iso646jpocrb':
10418                         case 'isoir92':
10419                         case 'jisc62291984b':
10420                         case 'jpocrb':
10421                                 return 'JIS_C6229-1984-b';
10422
10423                         case 'csiso93jis62291984badd':
10424                         case 'isoir93':
10425                         case 'jisc62291984badd':
10426                         case 'jpocrbadd':
10427                                 return 'JIS_C6229-1984-b-add';
10428
10429                         case 'csiso94jis62291984hand':
10430                         case 'isoir94':
10431                         case 'jisc62291984hand':
10432                         case 'jpocrhand':
10433                                 return 'JIS_C6229-1984-hand';
10434
10435                         case 'csiso95jis62291984handadd':
10436                         case 'isoir95':
10437                         case 'jisc62291984handadd':
10438                         case 'jpocrhandadd':
10439                                 return 'JIS_C6229-1984-hand-add';
10440
10441                         case 'csiso96jisc62291984kana':
10442                         case 'isoir96':
10443                         case 'jisc62291984kana':
10444                                 return 'JIS_C6229-1984-kana';
10445
10446                         case 'csjisencoding':
10447                         case 'jisencoding':
10448                                 return 'JIS_Encoding';
10449
10450                         case 'cshalfwidthkatakana':
10451                         case 'jisx201':
10452                         case 'x201':
10453                                 return 'JIS_X0201';
10454
10455                         case 'csiso159jisx2121990':
10456                         case 'isoir159':
10457                         case 'jisx2121990':
10458                         case 'x212':
10459                                 return 'JIS_X0212-1990';
10460
10461                         case 'csiso141jusib1002':
10462                         case 'iso646yu':
10463                         case 'isoir141':
10464                         case 'js':
10465                         case 'jusib1002':
10466                         case 'yu':
10467                                 return 'JUS_I.B1.002';
10468
10469                         case 'csiso147macedonian':
10470                         case 'isoir147':
10471                         case 'jusib1003mac':
10472                         case 'macedonian':
10473                                 return 'JUS_I.B1.003-mac';
10474
10475                         case 'csiso146serbian':
10476                         case 'isoir146':
10477                         case 'jusib1003serb':
10478                         case 'serbian':
10479                                 return 'JUS_I.B1.003-serb';
10480
10481                         case 'koi7switched':
10482                                 return 'KOI7-switched';
10483
10484                         case 'cskoi8r':
10485                         case 'koi8r':
10486                                 return 'KOI8-R';
10487
10488                         case 'koi8u':
10489                                 return 'KOI8-U';
10490
10491                         case 'csksc5636':
10492                         case 'iso646kr':
10493                         case 'ksc5636':
10494                                 return 'KSC5636';
10495
10496                         case 'cskz1048':
10497                         case 'kz1048':
10498                         case 'rk1048':
10499                         case 'strk10482002':
10500                                 return 'KZ-1048';
10501
10502                         case 'csiso19latingreek':
10503                         case 'isoir19':
10504                         case 'latingreek':
10505                                 return 'latin-greek';
10506
10507                         case 'csiso27latingreek1':
10508                         case 'isoir27':
10509                         case 'latingreek1':
10510                                 return 'Latin-greek-1';
10511
10512                         case 'csiso158lap':
10513                         case 'isoir158':
10514                         case 'lap':
10515                         case 'latinlap':
10516                                 return 'latin-lap';
10517
10518                         case 'csmacintosh':
10519                         case 'mac':
10520                         case 'macintosh':
10521                                 return 'macintosh';
10522
10523                         case 'csmicrosoftpublishing':
10524                         case 'microsoftpublishing':
10525                                 return 'Microsoft-Publishing';
10526
10527                         case 'csmnem':
10528                         case 'mnem':
10529                                 return 'MNEM';
10530
10531                         case 'csmnemonic':
10532                         case 'mnemonic':
10533                                 return 'MNEMONIC';
10534
10535                         case 'csiso86hungarian':
10536                         case 'hu':
10537                         case 'iso646hu':
10538                         case 'isoir86':
10539                         case 'msz77953':
10540                                 return 'MSZ_7795.3';
10541
10542                         case 'csnatsdano':
10543                         case 'isoir91':
10544                         case 'natsdano':
10545                                 return 'NATS-DANO';
10546
10547                         case 'csnatsdanoadd':
10548                         case 'isoir92':
10549                         case 'natsdanoadd':
10550                                 return 'NATS-DANO-ADD';
10551
10552                         case 'csnatssefi':
10553                         case 'isoir81':
10554                         case 'natssefi':
10555                                 return 'NATS-SEFI';
10556
10557                         case 'csnatssefiadd':
10558                         case 'isoir82':
10559                         case 'natssefiadd':
10560                                 return 'NATS-SEFI-ADD';
10561
10562                         case 'csiso151cuba':
10563                         case 'cuba':
10564                         case 'iso646cu':
10565                         case 'isoir151':
10566                         case 'ncnc1081':
10567                                 return 'NC_NC00-10:81';
10568
10569                         case 'csiso69french':
10570                         case 'fr':
10571                         case 'iso646fr':
10572                         case 'isoir69':
10573                         case 'nfz62010':
10574                                 return 'NF_Z_62-010';
10575
10576                         case 'csiso25french':
10577                         case 'iso646fr1':
10578                         case 'isoir25':
10579                         case 'nfz620101973':
10580                                 return 'NF_Z_62-010_(1973)';
10581
10582                         case 'csiso60danishnorwegian':
10583                         case 'csiso60norwegian1':
10584                         case 'iso646no':
10585                         case 'isoir60':
10586                         case 'no':
10587                         case 'ns45511':
10588                                 return 'NS_4551-1';
10589
10590                         case 'csiso61norwegian2':
10591                         case 'iso646no2':
10592                         case 'isoir61':
10593                         case 'no2':
10594                         case 'ns45512':
10595                                 return 'NS_4551-2';
10596
10597                         case 'osdebcdicdf3irv':
10598                                 return 'OSD_EBCDIC_DF03_IRV';
10599
10600                         case 'osdebcdicdf41':
10601                                 return 'OSD_EBCDIC_DF04_1';
10602
10603                         case 'osdebcdicdf415':
10604                                 return 'OSD_EBCDIC_DF04_15';
10605
10606                         case 'cspc8danishnorwegian':
10607                         case 'pc8danishnorwegian':
10608                                 return 'PC8-Danish-Norwegian';
10609
10610                         case 'cspc8turkish':
10611                         case 'pc8turkish':
10612                                 return 'PC8-Turkish';
10613
10614                         case 'csiso16portuguese':
10615                         case 'iso646pt':
10616                         case 'isoir16':
10617                         case 'pt':
10618                                 return 'PT';
10619
10620                         case 'csiso84portuguese2':
10621                         case 'iso646pt2':
10622                         case 'isoir84':
10623                         case 'pt2':
10624                                 return 'PT2';
10625
10626                         case 'cp154':
10627                         case 'csptcp154':
10628                         case 'cyrillicasian':
10629                         case 'pt154':
10630                         case 'ptcp154':
10631                                 return 'PTCP154';
10632
10633                         case 'scsu':
10634                                 return 'SCSU';
10635
10636                         case 'csiso10swedish':
10637                         case 'fi':
10638                         case 'iso646fi':
10639                         case 'iso646se':
10640                         case 'isoir10':
10641                         case 'se':
10642                         case 'sen850200b':
10643                                 return 'SEN_850200_B';
10644
10645                         case 'csiso11swedishfornames':
10646                         case 'iso646se2':
10647                         case 'isoir11':
10648                         case 'se2':
10649                         case 'sen850200c':
10650                                 return 'SEN_850200_C';
10651
10652                         case 'csshiftjis':
10653                         case 'mskanji':
10654                         case 'shiftjis':
10655                                 return 'Shift_JIS';
10656
10657                         case 'csiso102t617bit':
10658                         case 'isoir102':
10659                         case 't617bit':
10660                                 return 'T.61-7bit';
10661
10662                         case 'csiso103t618bit':
10663                         case 'isoir103':
10664                         case 't61':
10665                         case 't618bit':
10666                                 return 'T.61-8bit';
10667
10668                         case 'csiso128t101g2':
10669                         case 'isoir128':
10670                         case 't101g2':
10671                                 return 'T.101-G2';
10672
10673                         case 'cstscii':
10674                         case 'tscii':
10675                                 return 'TSCII';
10676
10677                         case 'csunicode11':
10678                         case 'unicode11':
10679                                 return 'UNICODE-1-1';
10680
10681                         case 'csunicode11utf7':
10682                         case 'unicode11utf7':
10683                                 return 'UNICODE-1-1-UTF-7';
10684
10685                         case 'csunknown8bit':
10686                         case 'unknown8bit':
10687                                 return 'UNKNOWN-8BIT';
10688
10689                         case 'ansix341968':
10690                         case 'ansix341986':
10691                         case 'ascii':
10692                         case 'cp367':
10693                         case 'csascii':
10694                         case 'ibm367':
10695                         case 'iso646irv1991':
10696                         case 'iso646us':
10697                         case 'isoir6':
10698                         case 'us':
10699                         case 'usascii':
10700                                 return 'US-ASCII';
10701
10702                         case 'csusdk':
10703                         case 'usdk':
10704                                 return 'us-dk';
10705
10706                         case 'utf7':
10707                                 return 'UTF-7';
10708
10709                         case 'utf8':
10710                                 return 'UTF-8';
10711
10712                         case 'utf16':
10713                                 return 'UTF-16';
10714
10715                         case 'utf16be':
10716                                 return 'UTF-16BE';
10717
10718                         case 'utf16le':
10719                                 return 'UTF-16LE';
10720
10721                         case 'utf32':
10722                                 return 'UTF-32';
10723
10724                         case 'utf32be':
10725                                 return 'UTF-32BE';
10726
10727                         case 'utf32le':
10728                                 return 'UTF-32LE';
10729
10730                         case 'csventurainternational':
10731                         case 'venturainternational':
10732                                 return 'Ventura-International';
10733
10734                         case 'csventuramath':
10735                         case 'venturamath':
10736                                 return 'Ventura-Math';
10737
10738                         case 'csventuraus':
10739                         case 'venturaus':
10740                                 return 'Ventura-US';
10741
10742                         case 'csiso70videotexsupp1':
10743                         case 'isoir70':
10744                         case 'videotexsuppl':
10745                                 return 'videotex-suppl';
10746
10747                         case 'csviqr':
10748                         case 'viqr':
10749                                 return 'VIQR';
10750
10751                         case 'csviscii':
10752                         case 'viscii':
10753                                 return 'VISCII';
10754
10755                         case 'cswindows31j':
10756                         case 'windows31j':
10757                                 return 'Windows-31J';
10758
10759                         case 'iso885911':
10760                         case 'tis620':
10761                                 return 'windows-874';
10762
10763                         case 'cseuckr':
10764                         case 'csksc56011987':
10765                         case 'euckr':
10766                         case 'isoir149':
10767                         case 'korean':
10768                         case 'ksc5601':
10769                         case 'ksc56011987':
10770                         case 'ksc56011989':
10771                         case 'windows949':
10772                                 return 'windows-949';
10773
10774                         case 'windows1250':
10775                                 return 'windows-1250';
10776
10777                         case 'windows1251':
10778                                 return 'windows-1251';
10779
10780                         case 'cp819':
10781                         case 'csisolatin1':
10782                         case 'ibm819':
10783                         case 'iso88591':
10784                         case 'iso885911987':
10785                         case 'isoir100':
10786                         case 'l1':
10787                         case 'latin1':
10788                         case 'windows1252':
10789                                 return 'windows-1252';
10790
10791                         case 'windows1253':
10792                                 return 'windows-1253';
10793
10794                         case 'csisolatin5':
10795                         case 'iso88599':
10796                         case 'iso885991989':
10797                         case 'isoir148':
10798                         case 'l5':
10799                         case 'latin5':
10800                         case 'windows1254':
10801                                 return 'windows-1254';
10802
10803                         case 'windows1255':
10804                                 return 'windows-1255';
10805
10806                         case 'windows1256':
10807                                 return 'windows-1256';
10808
10809                         case 'windows1257':
10810                                 return 'windows-1257';
10811
10812                         case 'windows1258':
10813                                 return 'windows-1258';
10814
10815                         default:
10816                                 return $charset;
10817                 }
10818         }
10819
10820         function get_curl_version()
10821         {
10822                 if (is_array($curl = curl_version()))
10823                 {
10824                         $curl = $curl['version'];
10825                 }
10826                 elseif (substr($curl, 0, 5) === 'curl/')
10827                 {
10828                         $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10829                 }
10830                 elseif (substr($curl, 0, 8) === 'libcurl/')
10831                 {
10832                         $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10833                 }
10834                 else
10835                 {
10836                         $curl = 0;
10837                 }
10838                 return $curl;
10839         }
10840
10841         function is_subclass_of($class1, $class2)
10842         {
10843                 if (func_num_args() !== 2)
10844                 {
10845                         trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10846                 }
10847                 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10848                 {
10849                         return is_subclass_of($class1, $class2);
10850                 }
10851                 elseif (is_string($class1) && is_string($class2))
10852                 {
10853                         if (class_exists($class1))
10854                         {
10855                                 if (class_exists($class2))
10856                                 {
10857                                         $class2 = strtolower($class2);
10858                                         while ($class1 = strtolower(get_parent_class($class1)))
10859                                         {
10860                                                 if ($class1 === $class2)
10861                                                 {
10862                                                         return true;
10863                                                 }
10864                                         }
10865                                 }
10866                         }
10867                         else
10868                         {
10869                                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10870                         }
10871                 }
10872                 return false;
10873         }
10874
10875         /**
10876          * Strip HTML comments
10877          *
10878          * @access public
10879          * @param string $data Data to strip comments from
10880          * @return string Comment stripped string
10881          */
10882         function strip_comments($data)
10883         {
10884                 $output = '';
10885                 while (($start = strpos($data, '<!--')) !== false)
10886                 {
10887                         $output .= substr($data, 0, $start);
10888                         if (($end = strpos($data, '-->', $start)) !== false)
10889                         {
10890                                 $data = substr_replace($data, '', 0, $end + 3);
10891                         }
10892                         else
10893                         {
10894                                 $data = '';
10895                         }
10896                 }
10897                 return $output . $data;
10898         }
10899
10900         function parse_date($dt)
10901         {
10902                 $parser = SimplePie_Parse_Date::get();
10903                 return $parser->parse($dt);
10904         }
10905
10906         /**
10907          * Decode HTML entities
10908          *
10909          * @static
10910          * @access public
10911          * @param string $data Input data
10912          * @return string Output data
10913          */
10914         function entities_decode($data)
10915         {
10916                 $decoder = new SimplePie_Decode_HTML_Entities($data);
10917                 return $decoder->parse();
10918         }
10919
10920         /**
10921          * Remove RFC822 comments
10922          *
10923          * @access public
10924          * @param string $data Data to strip comments from
10925          * @return string Comment stripped string
10926          */
10927         function uncomment_rfc822($string)
10928         {
10929                 $string = (string) $string;
10930                 $position = 0;
10931                 $length = strlen($string);
10932                 $depth = 0;
10933
10934                 $output = '';
10935
10936                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10937                 {
10938                         $output .= substr($string, $position, $pos - $position);
10939                         $position = $pos + 1;
10940                         if ($string[$pos - 1] !== '\\')
10941                         {
10942                                 $depth++;
10943                                 while ($depth && $position < $length)
10944                                 {
10945                                         $position += strcspn($string, '()', $position);
10946                                         if ($string[$position - 1] === '\\')
10947                                         {
10948                                                 $position++;
10949                                                 continue;
10950                                         }
10951                                         elseif (isset($string[$position]))
10952                                         {
10953                                                 switch ($string[$position])
10954                                                 {
10955                                                         case '(':
10956                                                                 $depth++;
10957                                                                 break;
10958
10959                                                         case ')':
10960                                                                 $depth--;
10961                                                                 break;
10962                                                 }
10963                                                 $position++;
10964                                         }
10965                                         else
10966                                         {
10967                                                 break;
10968                                         }
10969                                 }
10970                         }
10971                         else
10972                         {
10973                                 $output .= '(';
10974                         }
10975                 }
10976                 $output .= substr($string, $position);
10977
10978                 return $output;
10979         }
10980
10981         function parse_mime($mime)
10982         {
10983                 if (($pos = strpos($mime, ';')) === false)
10984                 {
10985                         return trim($mime);
10986                 }
10987                 else
10988                 {
10989                         return trim(substr($mime, 0, $pos));
10990                 }
10991         }
10992
10993         function htmlspecialchars_decode($string, $quote_style)
10994         {
10995                 if (function_exists('htmlspecialchars_decode'))
10996                 {
10997                         return htmlspecialchars_decode($string, $quote_style);
10998                 }
10999                 else
11000                 {
11001                         return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11002                 }
11003         }
11004
11005         function atom_03_construct_type($attribs)
11006         {
11007                 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11008                 {
11009                         $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11010                 }
11011                 else
11012                 {
11013                         $mode = SIMPLEPIE_CONSTRUCT_NONE;
11014                 }
11015                 if (isset($attribs['']['type']))
11016                 {
11017                         switch (strtolower(trim($attribs['']['type'])))
11018                         {
11019                                 case 'text':
11020                                 case 'text/plain':
11021                                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11022
11023                                 case 'html':
11024                                 case 'text/html':
11025                                         return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11026
11027                                 case 'xhtml':
11028                                 case 'application/xhtml+xml':
11029                                         return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11030
11031                                 default:
11032                                         return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11033                         }
11034                 }
11035                 else
11036                 {
11037                         return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11038                 }
11039         }
11040
11041         function atom_10_construct_type($attribs)
11042         {
11043                 if (isset($attribs['']['type']))
11044                 {
11045                         switch (strtolower(trim($attribs['']['type'])))
11046                         {
11047                                 case 'text':
11048                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11049
11050                                 case 'html':
11051                                         return SIMPLEPIE_CONSTRUCT_HTML;
11052
11053                                 case 'xhtml':
11054                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11055
11056                                 default:
11057                                         return SIMPLEPIE_CONSTRUCT_NONE;
11058                         }
11059                 }
11060                 return SIMPLEPIE_CONSTRUCT_TEXT;
11061         }
11062
11063         function atom_10_content_construct_type($attribs)
11064         {
11065                 if (isset($attribs['']['type']))
11066                 {
11067                         $type = strtolower(trim($attribs['']['type']));
11068                         switch ($type)
11069                         {
11070                                 case 'text':
11071                                         return SIMPLEPIE_CONSTRUCT_TEXT;
11072
11073                                 case 'html':
11074                                         return SIMPLEPIE_CONSTRUCT_HTML;
11075
11076                                 case 'xhtml':
11077                                         return SIMPLEPIE_CONSTRUCT_XHTML;
11078                         }
11079                         if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11080                         {
11081                                 return SIMPLEPIE_CONSTRUCT_NONE;
11082                         }
11083                         else
11084                         {
11085                                 return SIMPLEPIE_CONSTRUCT_BASE64;
11086                         }
11087                 }
11088                 else
11089                 {
11090                         return SIMPLEPIE_CONSTRUCT_TEXT;
11091                 }
11092         }
11093
11094         function is_isegment_nz_nc($string)
11095         {
11096                 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);
11097         }
11098
11099         function space_seperated_tokens($string)
11100         {
11101                 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11102                 $string_length = strlen($string);
11103
11104                 $position = strspn($string, $space_characters);
11105                 $tokens = array();
11106
11107                 while ($position < $string_length)
11108                 {
11109                         $len = strcspn($string, $space_characters, $position);
11110                         $tokens[] = substr($string, $position, $len);
11111                         $position += $len;
11112                         $position += strspn($string, $space_characters, $position);
11113                 }
11114
11115                 return $tokens;
11116         }
11117
11118         function array_unique($array)
11119         {
11120                 if (version_compare(PHP_VERSION, '5.2', '>='))
11121                 {
11122                         return array_unique($array);
11123                 }
11124                 else
11125                 {
11126                         $array = (array) $array;
11127                         $new_array = array();
11128                         $new_array_strings = array();
11129                         foreach ($array as $key => $value)
11130                         {
11131                                 if (is_object($value))
11132                                 {
11133                                         if (method_exists($value, '__toString'))
11134                                         {
11135                                                 $cmp = $value->__toString();
11136                                         }
11137                                         else
11138                                         {
11139                                                 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11140                                         }
11141                                 }
11142                                 elseif (is_array($value))
11143                                 {
11144                                         $cmp = (string) reset($value);
11145                                 }
11146                                 else
11147                                 {
11148                                         $cmp = (string) $value;
11149                                 }
11150                                 if (!in_array($cmp, $new_array_strings))
11151                                 {
11152                                         $new_array[$key] = $value;
11153                                         $new_array_strings[] = $cmp;
11154                                 }
11155                         }
11156                         return $new_array;
11157                 }
11158         }
11159
11160         /**
11161          * Converts a unicode codepoint to a UTF-8 character
11162          *
11163          * @static
11164          * @access public
11165          * @param int $codepoint Unicode codepoint
11166          * @return string UTF-8 character
11167          */
11168         function codepoint_to_utf8($codepoint)
11169         {
11170                 $codepoint = (int) $codepoint;
11171                 if ($codepoint < 0)
11172                 {
11173                         return false;
11174                 }
11175                 else if ($codepoint <= 0x7f)
11176                 {
11177                         return chr($codepoint);
11178                 }
11179                 else if ($codepoint <= 0x7ff)
11180                 {
11181                         return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11182                 }
11183                 else if ($codepoint <= 0xffff)
11184                 {
11185                         return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11186                 }
11187                 else if ($codepoint <= 0x10ffff)
11188                 {
11189                         return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11190                 }
11191                 else
11192                 {
11193                         // U+FFFD REPLACEMENT CHARACTER
11194                         return "\xEF\xBF\xBD";
11195                 }
11196         }
11197
11198         /**
11199          * Re-implementation of PHP 5's stripos()
11200          *
11201          * Returns the numeric position of the first occurrence of needle in the
11202          * haystack string.
11203          *
11204          * @static
11205          * @access string
11206          * @param object $haystack
11207          * @param string $needle Note that the needle may be a string of one or more
11208          *     characters. If needle is not a string, it is converted to an integer
11209          *     and applied as the ordinal value of a character.
11210          * @param int $offset The optional offset parameter allows you to specify which
11211          *     character in haystack to start searching. The position returned is still
11212          *     relative to the beginning of haystack.
11213          * @return bool If needle is not found, stripos() will return boolean false.
11214          */
11215         function stripos($haystack, $needle, $offset = 0)
11216         {
11217                 if (function_exists('stripos'))
11218                 {
11219                         return stripos($haystack, $needle, $offset);
11220                 }
11221                 else
11222                 {
11223                         if (is_string($needle))
11224                         {
11225                                 $needle = strtolower($needle);
11226                         }
11227                         elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11228                         {
11229                                 $needle = strtolower(chr($needle));
11230                         }
11231                         else
11232                         {
11233                                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11234                                 return false;
11235                         }
11236
11237                         return strpos(strtolower($haystack), $needle, $offset);
11238                 }
11239         }
11240
11241         /**
11242          * Similar to parse_str()
11243          *
11244          * Returns an associative array of name/value pairs, where the value is an
11245          * array of values that have used the same name
11246          *
11247          * @static
11248          * @access string
11249          * @param string $str The input string.
11250          * @return array
11251          */
11252         function parse_str($str)
11253         {
11254                 $return = array();
11255                 $str = explode('&', $str);
11256
11257                 foreach ($str as $section)
11258                 {
11259                         if (strpos($section, '=') !== false)
11260                         {
11261                                 list($name, $value) = explode('=', $section, 2);
11262                                 $return[urldecode($name)][] = urldecode($value);
11263                         }
11264                         else
11265                         {
11266                                 $return[urldecode($section)][] = null;
11267                         }
11268                 }
11269
11270                 return $return;
11271         }
11272
11273         /**
11274          * Detect XML encoding, as per XML 1.0 Appendix F.1
11275          *
11276          * @todo Add support for EBCDIC
11277          * @param string $data XML data
11278          * @return array Possible encodings
11279          */
11280         function xml_encoding($data)
11281         {
11282                 // UTF-32 Big Endian BOM
11283                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11284                 {
11285                         $encoding[] = 'UTF-32BE';
11286                 }
11287                 // UTF-32 Little Endian BOM
11288                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11289                 {
11290                         $encoding[] = 'UTF-32LE';
11291                 }
11292                 // UTF-16 Big Endian BOM
11293                 elseif (substr($data, 0, 2) === "\xFE\xFF")
11294                 {
11295                         $encoding[] = 'UTF-16BE';
11296                 }
11297                 // UTF-16 Little Endian BOM
11298                 elseif (substr($data, 0, 2) === "\xFF\xFE")
11299                 {
11300                         $encoding[] = 'UTF-16LE';
11301                 }
11302                 // UTF-8 BOM
11303                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11304                 {
11305                         $encoding[] = 'UTF-8';
11306                 }
11307                 // UTF-32 Big Endian Without BOM
11308                 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")
11309                 {
11310                         if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11311                         {
11312                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11313                                 if ($parser->parse())
11314                                 {
11315                                         $encoding[] = $parser->encoding;
11316                                 }
11317                         }
11318                         $encoding[] = 'UTF-32BE';
11319                 }
11320                 // UTF-32 Little Endian Without BOM
11321                 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")
11322                 {
11323                         if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11324                         {
11325                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11326                                 if ($parser->parse())
11327                                 {
11328                                         $encoding[] = $parser->encoding;
11329                                 }
11330                         }
11331                         $encoding[] = 'UTF-32LE';
11332                 }
11333                 // UTF-16 Big Endian Without BOM
11334                 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11335                 {
11336                         if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11337                         {
11338                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11339                                 if ($parser->parse())
11340                                 {
11341                                         $encoding[] = $parser->encoding;
11342                                 }
11343                         }
11344                         $encoding[] = 'UTF-16BE';
11345                 }
11346                 // UTF-16 Little Endian Without BOM
11347                 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11348                 {
11349                         if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11350                         {
11351                                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11352                                 if ($parser->parse())
11353                                 {
11354                                         $encoding[] = $parser->encoding;
11355                                 }
11356                         }
11357                         $encoding[] = 'UTF-16LE';
11358                 }
11359                 // US-ASCII (or superset)
11360                 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11361                 {
11362                         if ($pos = strpos($data, "\x3F\x3E"))
11363                         {
11364                                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11365                                 if ($parser->parse())
11366                                 {
11367                                         $encoding[] = $parser->encoding;
11368                                 }
11369                         }
11370                         $encoding[] = 'UTF-8';
11371                 }
11372                 // Fallback to UTF-8
11373                 else
11374                 {
11375                         $encoding[] = 'UTF-8';
11376                 }
11377                 return $encoding;
11378         }
11379
11380         function output_javascript()
11381         {
11382                 if (function_exists('ob_gzhandler'))
11383                 {
11384                         ob_start('ob_gzhandler');
11385                 }
11386                 header('Content-type: text/javascript; charset: UTF-8');
11387                 header('Cache-Control: must-revalidate');
11388                 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11389                 ?>
11390 function embed_odeo(link) {
11391         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>');
11392 }
11393
11394 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11395         if (placeholder != '') {
11396                 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>');
11397         }
11398         else {
11399                 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>');
11400         }
11401 }
11402
11403 function embed_flash(bgcolor, width, height, link, loop, type) {
11404         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>');
11405 }
11406
11407 function embed_flv(width, height, link, placeholder, loop, player) {
11408         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>');
11409 }
11410
11411 function embed_wmedia(width, height, link) {
11412         document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11413 }
11414                 <?php
11415         }
11416 }
11417
11418 /**
11419  * Decode HTML Entities
11420  *
11421  * This implements HTML5 as of revision 967 (2007-06-28)
11422  *
11423  * @package SimplePie
11424  */
11425 class SimplePie_Decode_HTML_Entities
11426 {
11427         /**
11428          * Data to be parsed
11429          *
11430          * @access private
11431          * @var string
11432          */
11433         var $data = '';
11434
11435         /**
11436          * Currently consumed bytes
11437          *
11438          * @access private
11439          * @var string
11440          */
11441         var $consumed = '';
11442
11443         /**
11444          * Position of the current byte being parsed
11445          *
11446          * @access private
11447          * @var int
11448          */
11449         var $position = 0;
11450
11451         /**
11452          * Create an instance of the class with the input data
11453          *
11454          * @access public
11455          * @param string $data Input data
11456          */
11457         function SimplePie_Decode_HTML_Entities($data)
11458         {
11459                 $this->data = $data;
11460         }
11461
11462         /**
11463          * Parse the input data
11464          *
11465          * @access public
11466          * @return string Output data
11467          */
11468         function parse()
11469         {
11470                 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11471                 {
11472                         $this->consume();
11473                         $this->entity();
11474                         $this->consumed = '';
11475                 }
11476                 return $this->data;
11477         }
11478
11479         /**
11480          * Consume the next byte
11481          *
11482          * @access private
11483          * @return mixed The next byte, or false, if there is no more data
11484          */
11485         function consume()
11486         {
11487                 if (isset($this->data[$this->position]))
11488                 {
11489                         $this->consumed .= $this->data[$this->position];
11490                         return $this->data[$this->position++];
11491                 }
11492                 else
11493                 {
11494                         return false;
11495                 }
11496         }
11497
11498         /**
11499          * Consume a range of characters
11500          *
11501          * @access private
11502          * @param string $chars Characters to consume
11503          * @return mixed A series of characters that match the range, or false
11504          */
11505         function consume_range($chars)
11506         {
11507                 if ($len = strspn($this->data, $chars, $this->position))
11508                 {
11509                         $data = substr($this->data, $this->position, $len);
11510                         $this->consumed .= $data;
11511                         $this->position += $len;
11512                         return $data;
11513                 }
11514                 else
11515                 {
11516                         return false;
11517                 }
11518         }
11519
11520         /**
11521          * Unconsume one byte
11522          *
11523          * @access private
11524          */
11525         function unconsume()
11526         {
11527                 $this->consumed = substr($this->consumed, 0, -1);
11528                 $this->position--;
11529         }
11530
11531         /**
11532          * Decode an entity
11533          *
11534          * @access private
11535          */
11536         function entity()
11537         {
11538                 switch ($this->consume())
11539                 {
11540                         case "\x09":
11541                         case "\x0A":
11542                         case "\x0B":
11543                         case "\x0B":
11544                         case "\x0C":
11545                         case "\x20":
11546                         case "\x3C":
11547                         case "\x26":
11548                         case false:
11549                                 break;
11550
11551                         case "\x23":
11552                                 switch ($this->consume())
11553                                 {
11554                                         case "\x78":
11555                                         case "\x58":
11556                                                 $range = '0123456789ABCDEFabcdef';
11557                                                 $hex = true;
11558                                                 break;
11559
11560                                         default:
11561                                                 $range = '0123456789';
11562                                                 $hex = false;
11563                                                 $this->unconsume();
11564                                                 break;
11565                                 }
11566
11567                                 if ($codepoint = $this->consume_range($range))
11568                                 {
11569                                         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");
11570
11571                                         if ($hex)
11572                                         {
11573                                                 $codepoint = hexdec($codepoint);
11574                                         }
11575                                         else
11576                                         {
11577                                                 $codepoint = intval($codepoint);
11578                                         }
11579
11580                                         if (isset($windows_1252_specials[$codepoint]))
11581                                         {
11582                                                 $replacement = $windows_1252_specials[$codepoint];
11583                                         }
11584                                         else
11585                                         {
11586                                                 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11587                                         }
11588
11589                                         if (!in_array($this->consume(), array(';', false), true))
11590                                         {
11591                                                 $this->unconsume();
11592                                         }
11593
11594                                         $consumed_length = strlen($this->consumed);
11595                                         $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11596                                         $this->position += strlen($replacement) - $consumed_length;
11597                                 }
11598                                 break;
11599
11600                         default:
11601                                 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");
11602
11603                                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11604                                 {
11605                                         $consumed = substr($this->consumed, 1);
11606                                         if (isset($entities[$consumed]))
11607                                         {
11608                                                 $match = $consumed;
11609                                         }
11610                                 }
11611
11612                                 if ($match !== null)
11613                                 {
11614                                         $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11615                                         $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11616                                 }
11617                                 break;
11618                 }
11619         }
11620 }
11621
11622 /**
11623  * IRI parser/serialiser
11624  *
11625  * @package SimplePie
11626  */
11627 class SimplePie_IRI
11628 {
11629         /**
11630          * Scheme
11631          *
11632          * @access private
11633          * @var string
11634          */
11635         var $scheme;
11636
11637         /**
11638          * User Information
11639          *
11640          * @access private
11641          * @var string
11642          */
11643         var $userinfo;
11644
11645         /**
11646          * Host
11647          *
11648          * @access private
11649          * @var string
11650          */
11651         var $host;
11652
11653         /**
11654          * Port
11655          *
11656          * @access private
11657          * @var string
11658          */
11659         var $port;
11660
11661         /**
11662          * Path
11663          *
11664          * @access private
11665          * @var string
11666          */
11667         var $path;
11668
11669         /**
11670          * Query
11671          *
11672          * @access private
11673          * @var string
11674          */
11675         var $query;
11676
11677         /**
11678          * Fragment
11679          *
11680          * @access private
11681          * @var string
11682          */
11683         var $fragment;
11684
11685         /**
11686          * Whether the object represents a valid IRI
11687          *
11688          * @access private
11689          * @var array
11690          */
11691         var $valid = array();
11692
11693         /**
11694          * Return the entire IRI when you try and read the object as a string
11695          *
11696          * @access public
11697          * @return string
11698          */
11699         function __toString()
11700         {
11701                 return $this->get_iri();
11702         }
11703
11704         /**
11705          * Create a new IRI object, from a specified string
11706          *
11707          * @access public
11708          * @param string $iri
11709          * @return SimplePie_IRI
11710          */
11711         function SimplePie_IRI($iri)
11712         {
11713                 $iri = (string) $iri;
11714                 if ($iri !== '')
11715                 {
11716                         $parsed = $this->parse_iri($iri);
11717                         $this->set_scheme($parsed['scheme']);
11718                         $this->set_authority($parsed['authority']);
11719                         $this->set_path($parsed['path']);
11720                         $this->set_query($parsed['query']);
11721                         $this->set_fragment($parsed['fragment']);
11722                 }
11723         }
11724
11725         /**
11726          * Create a new IRI object by resolving a relative IRI
11727          *
11728          * @static
11729          * @access public
11730          * @param SimplePie_IRI $base Base IRI
11731          * @param string $relative Relative IRI
11732          * @return SimplePie_IRI
11733          */
11734         function absolutize($base, $relative)
11735         {
11736                 $relative = (string) $relative;
11737                 if ($relative !== '')
11738                 {
11739                         $relative = new SimplePie_IRI($relative);
11740                         if ($relative->get_scheme() !== null)
11741                         {
11742                                 $target = $relative;
11743                         }
11744                         elseif ($base->get_iri() !== null)
11745                         {
11746                                 if ($relative->get_authority() !== null)
11747                                 {
11748                                         $target = $relative;
11749                                         $target->set_scheme($base->get_scheme());
11750                                 }
11751                                 else
11752                                 {
11753                                         $target = new SimplePie_IRI('');
11754                                         $target->set_scheme($base->get_scheme());
11755                                         $target->set_userinfo($base->get_userinfo());
11756                                         $target->set_host($base->get_host());
11757                                         $target->set_port($base->get_port());
11758                                         if ($relative->get_path() !== null)
11759                                         {
11760                                                 if (strpos($relative->get_path(), '/') === 0)
11761                                                 {
11762                                                         $target->set_path($relative->get_path());
11763                                                 }
11764                                                 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11765                                                 {
11766                                                         $target->set_path('/' . $relative->get_path());
11767                                                 }
11768                                                 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11769                                                 {
11770                                                         $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11771                                                 }
11772                                                 else
11773                                                 {
11774                                                         $target->set_path($relative->get_path());
11775                                                 }
11776                                                 $target->set_query($relative->get_query());
11777                                         }
11778                                         else
11779                                         {
11780                                                 $target->set_path($base->get_path());
11781                                                 if ($relative->get_query() !== null)
11782                                                 {
11783                                                         $target->set_query($relative->get_query());
11784                                                 }
11785                                                 elseif ($base->get_query() !== null)
11786                                                 {
11787                                                         $target->set_query($base->get_query());
11788                                                 }
11789                                         }
11790                                 }
11791                                 $target->set_fragment($relative->get_fragment());
11792                         }
11793                         else
11794                         {
11795                                 // No base URL, just return the relative URL
11796                                 $target = $relative;
11797                         }
11798                 }
11799                 else
11800                 {
11801                         $target = $base;
11802                 }
11803                 return $target;
11804         }
11805
11806         /**
11807          * Parse an IRI into scheme/authority/path/query/fragment segments
11808          *
11809          * @access private
11810          * @param string $iri
11811          * @return array
11812          */
11813         function parse_iri($iri)
11814         {
11815                 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11816                 for ($i = count($match); $i <= 9; $i++)
11817                 {
11818                         $match[$i] = '';
11819                 }
11820                 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11821         }
11822
11823         /**
11824          * Remove dot segments from a path
11825          *
11826          * @access private
11827          * @param string $input
11828          * @return string
11829          */
11830         function remove_dot_segments($input)
11831         {
11832                 $output = '';
11833                 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11834                 {
11835                         // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11836                         if (strpos($input, '../') === 0)
11837                         {
11838                                 $input = substr($input, 3);
11839                         }
11840                         elseif (strpos($input, './') === 0)
11841                         {
11842                                 $input = substr($input, 2);
11843                         }
11844                         // 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,
11845                         elseif (strpos($input, '/./') === 0)
11846                         {
11847                                 $input = substr_replace($input, '/', 0, 3);
11848                         }
11849                         elseif ($input === '/.')
11850                         {
11851                                 $input = '/';
11852                         }
11853                         // 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,
11854                         elseif (strpos($input, '/../') === 0)
11855                         {
11856                                 $input = substr_replace($input, '/', 0, 4);
11857                                 $output = substr_replace($output, '', strrpos($output, '/'));
11858                         }
11859                         elseif ($input === '/..')
11860                         {
11861                                 $input = '/';
11862                                 $output = substr_replace($output, '', strrpos($output, '/'));
11863                         }
11864                         // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11865                         elseif ($input === '.' || $input === '..')
11866                         {
11867                                 $input = '';
11868                         }
11869                         // 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
11870                         elseif (($pos = strpos($input, '/', 1)) !== false)
11871                         {
11872                                 $output .= substr($input, 0, $pos);
11873                                 $input = substr_replace($input, '', 0, $pos);
11874                         }
11875                         else
11876                         {
11877                                 $output .= $input;
11878                                 $input = '';
11879                         }
11880                 }
11881                 return $output . $input;
11882         }
11883
11884         /**
11885          * Replace invalid character with percent encoding
11886          *
11887          * @access private
11888          * @param string $string Input string
11889          * @param string $valid_chars Valid characters
11890          * @param int $case Normalise case
11891          * @return string
11892          */
11893         function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11894         {
11895                 // Normalise case
11896                 if ($case & SIMPLEPIE_LOWERCASE)
11897                 {
11898                         $string = strtolower($string);
11899                 }
11900                 elseif ($case & SIMPLEPIE_UPPERCASE)
11901                 {
11902                         $string = strtoupper($string);
11903                 }
11904
11905                 // Store position and string length (to avoid constantly recalculating this)
11906                 $position = 0;
11907                 $strlen = strlen($string);
11908
11909                 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11910                 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11911                 {
11912                         // If we have a % character
11913                         if ($string[$position] === '%')
11914                         {
11915                                 // If we have a pct-encoded section
11916                                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11917                                 {
11918                                         // Get the the represented character
11919                                         $chr = chr(hexdec(substr($string, $position + 1, 2)));
11920
11921                                         // If the character is valid, replace the pct-encoded with the actual character while normalising case
11922                                         if (strpos($valid_chars, $chr) !== false)
11923                                         {
11924                                                 if ($case & SIMPLEPIE_LOWERCASE)
11925                                                 {
11926                                                         $chr = strtolower($chr);
11927                                                 }
11928                                                 elseif ($case & SIMPLEPIE_UPPERCASE)
11929                                                 {
11930                                                         $chr = strtoupper($chr);
11931                                                 }
11932                                                 $string = substr_replace($string, $chr, $position, 3);
11933                                                 $strlen -= 2;
11934                                                 $position++;
11935                                         }
11936
11937                                         // Otherwise just normalise the pct-encoded to uppercase
11938                                         else
11939                                         {
11940                                                 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11941                                                 $position += 3;
11942                                         }
11943                                 }
11944                                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11945                                 else
11946                                 {
11947                                         $string = substr_replace($string, '%25', $position, 1);
11948                                         $strlen += 2;
11949                                         $position += 3;
11950                                 }
11951                         }
11952                         // If we have an invalid character, change into its pct-encoded form
11953                         else
11954                         {
11955                                 $replacement = sprintf("%%%02X", ord($string[$position]));
11956                                 $string = str_replace($string[$position], $replacement, $string);
11957                                 $strlen = strlen($string);
11958                         }
11959                 }
11960                 return $string;
11961         }
11962
11963         /**
11964          * Check if the object represents a valid IRI
11965          *
11966          * @access public
11967          * @return bool
11968          */
11969         function is_valid()
11970         {
11971                 return array_sum($this->valid) === count($this->valid);
11972         }
11973
11974         /**
11975          * Set the scheme. Returns true on success, false on failure (if there are
11976          * any invalid characters).
11977          *
11978          * @access public
11979          * @param string $scheme
11980          * @return bool
11981          */
11982         function set_scheme($scheme)
11983         {
11984                 if ($scheme === null || $scheme === '')
11985                 {
11986                         $this->scheme = null;
11987                 }
11988                 else
11989                 {
11990                         $len = strlen($scheme);
11991                         switch (true)
11992                         {
11993                                 case $len > 1:
11994                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11995                                         {
11996                                                 $this->scheme = null;
11997                                                 $this->valid[__FUNCTION__] = false;
11998                                                 return false;
11999                                         }
12000
12001                                 case $len > 0:
12002                                         if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12003                                         {
12004                                                 $this->scheme = null;
12005                                                 $this->valid[__FUNCTION__] = false;
12006                                                 return false;
12007                                         }
12008                         }
12009                         $this->scheme = strtolower($scheme);
12010                 }
12011                 $this->valid[__FUNCTION__] = true;
12012                 return true;
12013         }
12014
12015         /**
12016          * Set the authority. Returns true on success, false on failure (if there are
12017          * any invalid characters).
12018          *
12019          * @access public
12020          * @param string $authority
12021          * @return bool
12022          */
12023         function set_authority($authority)
12024         {
12025                 if (($userinfo_end = strrpos($authority, '@')) !== false)
12026                 {
12027                         $userinfo = substr($authority, 0, $userinfo_end);
12028                         $authority = substr($authority, $userinfo_end + 1);
12029                 }
12030                 else
12031                 {
12032                         $userinfo = null;
12033                 }
12034
12035                 if (($port_start = strpos($authority, ':')) !== false)
12036                 {
12037                         $port = substr($authority, $port_start + 1);
12038                         $authority = substr($authority, 0, $port_start);
12039                 }
12040                 else
12041                 {
12042                         $port = null;
12043                 }
12044
12045                 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12046         }
12047
12048         /**
12049          * Set the userinfo.
12050          *
12051          * @access public
12052          * @param string $userinfo
12053          * @return bool
12054          */
12055         function set_userinfo($userinfo)
12056         {
12057                 if ($userinfo === null || $userinfo === '')
12058                 {
12059                         $this->userinfo = null;
12060                 }
12061                 else
12062                 {
12063                         $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12064                 }
12065                 $this->valid[__FUNCTION__] = true;
12066                 return true;
12067         }
12068
12069         /**
12070          * Set the host. Returns true on success, false on failure (if there are
12071          * any invalid characters).
12072          *
12073          * @access public
12074          * @param string $host
12075          * @return bool
12076          */
12077         function set_host($host)
12078         {
12079                 if ($host === null || $host === '')
12080                 {
12081                         $this->host = null;
12082                         $this->valid[__FUNCTION__] = true;
12083                         return true;
12084                 }
12085                 elseif ($host[0] === '[' && substr($host, -1) === ']')
12086                 {
12087                         if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12088                         {
12089                                 $this->host = $host;
12090                                 $this->valid[__FUNCTION__] = true;
12091                                 return true;
12092                         }
12093                         else
12094                         {
12095                                 $this->host = null;
12096                                 $this->valid[__FUNCTION__] = false;
12097                                 return false;
12098                         }
12099                 }
12100                 else
12101                 {
12102                         $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12103                         $this->valid[__FUNCTION__] = true;
12104                         return true;
12105                 }
12106         }
12107
12108         /**
12109          * Set the port. Returns true on success, false on failure (if there are
12110          * any invalid characters).
12111          *
12112          * @access public
12113          * @param string $port
12114          * @return bool
12115          */
12116         function set_port($port)
12117         {
12118                 if ($port === null || $port === '')
12119                 {
12120                         $this->port = null;
12121                         $this->valid[__FUNCTION__] = true;
12122                         return true;
12123                 }
12124                 elseif (strspn($port, '0123456789') === strlen($port))
12125                 {
12126                         $this->port = (int) $port;
12127                         $this->valid[__FUNCTION__] = true;
12128                         return true;
12129                 }
12130                 else
12131                 {
12132                         $this->port = null;
12133                         $this->valid[__FUNCTION__] = false;
12134                         return false;
12135                 }
12136         }
12137
12138         /**
12139          * Set the path.
12140          *
12141          * @access public
12142          * @param string $path
12143          * @return bool
12144          */
12145         function set_path($path)
12146         {
12147                 if ($path === null || $path === '')
12148                 {
12149                         $this->path = null;
12150                         $this->valid[__FUNCTION__] = true;
12151                         return true;
12152                 }
12153                 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12154                 {
12155                         $this->path = null;
12156                         $this->valid[__FUNCTION__] = false;
12157                         return false;
12158                 }
12159                 else
12160                 {
12161                         $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12162                         if ($this->scheme !== null)
12163                         {
12164                                 $this->path = $this->remove_dot_segments($this->path);
12165                         }
12166                         $this->valid[__FUNCTION__] = true;
12167                         return true;
12168                 }
12169         }
12170
12171         /**
12172          * Set the query.
12173          *
12174          * @access public
12175          * @param string $query
12176          * @return bool
12177          */
12178         function set_query($query)
12179         {
12180                 if ($query === null || $query === '')
12181                 {
12182                         $this->query = null;
12183                 }
12184                 else
12185                 {
12186                         $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
12187                 }
12188                 $this->valid[__FUNCTION__] = true;
12189                 return true;
12190         }
12191
12192         /**
12193          * Set the fragment.
12194          *
12195          * @access public
12196          * @param string $fragment
12197          * @return bool
12198          */
12199         function set_fragment($fragment)
12200         {
12201                 if ($fragment === null || $fragment === '')
12202                 {
12203                         $this->fragment = null;
12204                 }
12205                 else
12206                 {
12207                         $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12208                 }
12209                 $this->valid[__FUNCTION__] = true;
12210                 return true;
12211         }
12212
12213         /**
12214          * Get the complete IRI
12215          *
12216          * @access public
12217          * @return string
12218          */
12219         function get_iri()
12220         {
12221                 $iri = '';
12222                 if ($this->scheme !== null)
12223                 {
12224                         $iri .= $this->scheme . ':';
12225                 }
12226                 if (($authority = $this->get_authority()) !== null)
12227                 {
12228                         $iri .= '//' . $authority;
12229                 }
12230                 if ($this->path !== null)
12231                 {
12232                         $iri .= $this->path;
12233                 }
12234                 if ($this->query !== null)
12235                 {
12236                         $iri .= '?' . $this->query;
12237                 }
12238                 if ($this->fragment !== null)
12239                 {
12240                         $iri .= '#' . $this->fragment;
12241                 }
12242
12243                 if ($iri !== '')
12244                 {
12245                         return $iri;
12246                 }
12247                 else
12248                 {
12249                         return null;
12250                 }
12251         }
12252
12253         /**
12254          * Get the scheme
12255          *
12256          * @access public
12257          * @return string
12258          */
12259         function get_scheme()
12260         {
12261                 return $this->scheme;
12262         }
12263
12264         /**
12265          * Get the complete authority
12266          *
12267          * @access public
12268          * @return string
12269          */
12270         function get_authority()
12271         {
12272                 $authority = '';
12273                 if ($this->userinfo !== null)
12274                 {
12275                         $authority .= $this->userinfo . '@';
12276                 }
12277                 if ($this->host !== null)
12278                 {
12279                         $authority .= $this->host;
12280                 }
12281                 if ($this->port !== null)
12282                 {
12283                         $authority .= ':' . $this->port;
12284                 }
12285
12286                 if ($authority !== '')
12287                 {
12288                         return $authority;
12289                 }
12290                 else
12291                 {
12292                         return null;
12293                 }
12294         }
12295
12296         /**
12297          * Get the user information
12298          *
12299          * @access public
12300          * @return string
12301          */
12302         function get_userinfo()
12303         {
12304                 return $this->userinfo;
12305         }
12306
12307         /**
12308          * Get the host
12309          *
12310          * @access public
12311          * @return string
12312          */
12313         function get_host()
12314         {
12315                 return $this->host;
12316         }
12317
12318         /**
12319          * Get the port
12320          *
12321          * @access public
12322          * @return string
12323          */
12324         function get_port()
12325         {
12326                 return $this->port;
12327         }
12328
12329         /**
12330          * Get the path
12331          *
12332          * @access public
12333          * @return string
12334          */
12335         function get_path()
12336         {
12337                 return $this->path;
12338         }
12339
12340         /**
12341          * Get the query
12342          *
12343          * @access public
12344          * @return string
12345          */
12346         function get_query()
12347         {
12348                 return $this->query;
12349         }
12350
12351         /**
12352          * Get the fragment
12353          *
12354          * @access public
12355          * @return string
12356          */
12357         function get_fragment()
12358         {
12359                 return $this->fragment;
12360         }
12361 }
12362
12363 /**
12364  * Class to validate and to work with IPv6 addresses.
12365  *
12366  * @package SimplePie
12367  * @copyright 2003-2005 The PHP Group
12368  * @license http://www.opensource.org/licenses/bsd-license.php
12369  * @link http://pear.php.net/package/Net_IPv6
12370  * @author Alexander Merz <alexander.merz@web.de>
12371  * @author elfrink at introweb dot nl
12372  * @author Josh Peck <jmp at joshpeck dot org>
12373  * @author Geoffrey Sneddon <geoffers@gmail.com>
12374  */
12375 class SimplePie_Net_IPv6
12376 {
12377         /**
12378          * Removes a possible existing netmask specification of an IP address.
12379          *
12380          * @param string $ip the (compressed) IP as Hex representation
12381          * @return string the IP the without netmask
12382          * @since 1.1.0
12383          * @access public
12384          * @static
12385          */
12386         function removeNetmaskSpec($ip)
12387         {
12388                 if (strpos($ip, '/') !== false)
12389                 {
12390                         list($addr, $nm) = explode('/', $ip);
12391                 }
12392                 else
12393                 {
12394                         $addr = $ip;
12395                 }
12396                 return $addr;
12397         }
12398
12399         /**
12400          * Uncompresses an IPv6 address
12401          *
12402          * RFC 2373 allows you to compress zeros in an address to '::'. This
12403          * function expects an valid IPv6 address and expands the '::' to
12404          * the required zeros.
12405          *
12406          * Example:      FF01::101      ->      FF01:0:0:0:0:0:0:101
12407          *                       ::1            ->      0:0:0:0:0:0:0:1
12408          *
12409          * @access public
12410          * @static
12411          * @param string $ip a valid IPv6-address (hex format)
12412          * @return string the uncompressed IPv6-address (hex format)
12413          */
12414         function Uncompress($ip)
12415         {
12416                 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12417                 $c1 = -1;
12418                 $c2 = -1;
12419                 if (strpos($ip, '::') !== false)
12420                 {
12421                         list($ip1, $ip2) = explode('::', $ip);
12422                         if ($ip1 === '')
12423                         {
12424                                 $c1 = -1;
12425                         }
12426                         else
12427                         {
12428                                 $pos = 0;
12429                                 if (($pos = substr_count($ip1, ':')) > 0)
12430                                 {
12431                                         $c1 = $pos;
12432                                 }
12433                                 else
12434                                 {
12435                                         $c1 = 0;
12436                                 }
12437                         }
12438                         if ($ip2 === '')
12439                         {
12440                                 $c2 = -1;
12441                         }
12442                         else
12443                         {
12444                                 $pos = 0;
12445                                 if (($pos = substr_count($ip2, ':')) > 0)
12446                                 {
12447                                         $c2 = $pos;
12448                                 }
12449                                 else
12450                                 {
12451                                         $c2 = 0;
12452                                 }
12453                         }
12454                         if (strstr($ip2, '.'))
12455                         {
12456                                 $c2++;
12457                         }
12458                         // ::
12459                         if ($c1 === -1 && $c2 === -1)
12460                         {
12461                                 $uip = '0:0:0:0:0:0:0:0';
12462                         }
12463                         // ::xxx
12464                         else if ($c1 === -1)
12465                         {
12466                                 $fill = str_repeat('0:', 7 - $c2);
12467                                 $uip =  str_replace('::', $fill, $uip);
12468                         }
12469                         // xxx::
12470                         else if ($c2 === -1)
12471                         {
12472                                 $fill = str_repeat(':0', 7 - $c1);
12473                                 $uip =  str_replace('::', $fill, $uip);
12474                         }
12475                         // xxx::xxx
12476                         else
12477                         {
12478                                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12479                                 $uip =  str_replace('::', $fill, $uip);
12480                                 $uip =  str_replace('::', ':', $uip);
12481                         }
12482                 }
12483                 return $uip;
12484         }
12485
12486         /**
12487          * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12488          *
12489          * RFC 2373 allows you to note the last two parts of an IPv6 address as
12490          * an IPv4 compatible address
12491          *
12492          * Example:      0:0:0:0:0:0:13.1.68.3
12493          *                       0:0:0:0:0:FFFF:129.144.52.38
12494          *
12495          * @access public
12496          * @static
12497          * @param string $ip a valid IPv6-address (hex format)
12498          * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12499          */
12500         function SplitV64($ip)
12501         {
12502                 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12503                 if (strstr($ip, '.'))
12504                 {
12505                         $pos = strrpos($ip, ':');
12506                         $ip[$pos] = '_';
12507                         $ipPart = explode('_', $ip);
12508                         return $ipPart;
12509                 }
12510                 else
12511                 {
12512                         return array($ip, '');
12513                 }
12514         }
12515
12516         /**
12517          * Checks an IPv6 address
12518          *
12519          * Checks if the given IP is IPv6-compatible
12520          *
12521          * @access public
12522          * @static
12523          * @param string $ip a valid IPv6-address
12524          * @return bool true if $ip is an IPv6 address
12525          */
12526         function checkIPv6($ip)
12527         {
12528                 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12529                 $count = 0;
12530                 if (!empty($ipPart[0]))
12531                 {
12532                         $ipv6 = explode(':', $ipPart[0]);
12533                         for ($i = 0; $i < count($ipv6); $i++)
12534                         {
12535                                 $dec = hexdec($ipv6[$i]);
12536                                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12537                                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12538                                 {
12539                                         $count++;
12540                                 }
12541                         }
12542                         if ($count === 8)
12543                         {
12544                                 return true;
12545                         }
12546                         elseif ($count === 6 && !empty($ipPart[1]))
12547                         {
12548                                 $ipv4 = explode('.', $ipPart[1]);
12549                                 $count = 0;
12550                                 foreach ($ipv4 as $ipv4_part)
12551                                 {
12552                                         if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12553                                         {
12554                                                 $count++;
12555                                         }
12556                                 }
12557                                 if ($count === 4)
12558                                 {
12559                                         return true;
12560                                 }
12561                         }
12562                         else
12563                         {
12564                                 return false;
12565                         }
12566
12567                 }
12568                 else
12569                 {
12570                         return false;
12571                 }
12572         }
12573 }
12574
12575 /**
12576  * Date Parser
12577  *
12578  * @package SimplePie
12579  */
12580 class SimplePie_Parse_Date
12581 {
12582         /**
12583          * Input data
12584          *
12585          * @access protected
12586          * @var string
12587          */
12588         var $date;
12589
12590         /**
12591          * List of days, calendar day name => ordinal day number in the week
12592          *
12593          * @access protected
12594          * @var array
12595          */
12596         var $day = array(
12597                 // English
12598                 'mon' => 1,
12599                 'monday' => 1,
12600                 'tue' => 2,
12601                 'tuesday' => 2,
12602                 'wed' => 3,
12603                 'wednesday' => 3,
12604                 'thu' => 4,
12605                 'thursday' => 4,
12606                 'fri' => 5,
12607                 'friday' => 5,
12608                 'sat' => 6,
12609                 'saturday' => 6,
12610                 'sun' => 7,
12611                 'sunday' => 7,
12612                 // Dutch
12613                 'maandag' => 1,
12614                 'dinsdag' => 2,
12615                 'woensdag' => 3,
12616                 'donderdag' => 4,
12617                 'vrijdag' => 5,
12618                 'zaterdag' => 6,
12619                 'zondag' => 7,
12620                 // French
12621                 'lundi' => 1,
12622                 'mardi' => 2,
12623                 'mercredi' => 3,
12624                 'jeudi' => 4,
12625                 'vendredi' => 5,
12626                 'samedi' => 6,
12627                 'dimanche' => 7,
12628                 // German
12629                 'montag' => 1,
12630                 'dienstag' => 2,
12631                 'mittwoch' => 3,
12632                 'donnerstag' => 4,
12633                 'freitag' => 5,
12634                 'samstag' => 6,
12635                 'sonnabend' => 6,
12636                 'sonntag' => 7,
12637                 // Italian
12638                 'lunedì' => 1,
12639                 'martedì' => 2,
12640                 'mercoledì' => 3,
12641                 'giovedì' => 4,
12642                 'venerdì' => 5,
12643                 'sabato' => 6,
12644                 'domenica' => 7,
12645                 // Spanish
12646                 'lunes' => 1,
12647                 'martes' => 2,
12648                 'miércoles' => 3,
12649                 'jueves' => 4,
12650                 'viernes' => 5,
12651                 'sábado' => 6,
12652                 'domingo' => 7,
12653                 // Finnish
12654                 'maanantai' => 1,
12655                 'tiistai' => 2,
12656                 'keskiviikko' => 3,
12657                 'torstai' => 4,
12658                 'perjantai' => 5,
12659                 'lauantai' => 6,
12660                 'sunnuntai' => 7,
12661                 // Hungarian
12662                 'hétfő' => 1,
12663                 'kedd' => 2,
12664                 'szerda' => 3,
12665                 'csütörtok' => 4,
12666                 'péntek' => 5,
12667                 'szombat' => 6,
12668                 'vasárnap' => 7,
12669                 // Greek
12670                 'Δευ' => 1,
12671                 'Τρι' => 2,
12672                 'Τετ' => 3,
12673                 'Πεμ' => 4,
12674                 'Παρ' => 5,
12675                 'Σαβ' => 6,
12676                 'Κυρ' => 7,
12677         );
12678
12679         /**
12680          * List of months, calendar month name => calendar month number
12681          *
12682          * @access protected
12683          * @var array
12684          */
12685         var $month = array(
12686                 // English
12687                 'jan' => 1,
12688                 'january' => 1,
12689                 'feb' => 2,
12690                 'february' => 2,
12691                 'mar' => 3,
12692                 'march' => 3,
12693                 'apr' => 4,
12694                 'april' => 4,
12695                 'may' => 5,
12696                 // No long form of May
12697                 'jun' => 6,
12698                 'june' => 6,
12699                 'jul' => 7,
12700                 'july' => 7,
12701                 'aug' => 8,
12702                 'august' => 8,
12703                 'sep' => 9,
12704                 'september' => 8,
12705                 'oct' => 10,
12706                 'october' => 10,
12707                 'nov' => 11,
12708                 'november' => 11,
12709                 'dec' => 12,
12710                 'december' => 12,
12711                 // Dutch
12712                 'januari' => 1,
12713                 'februari' => 2,
12714                 'maart' => 3,
12715                 'april' => 4,
12716                 'mei' => 5,
12717                 'juni' => 6,
12718                 'juli' => 7,
12719                 'augustus' => 8,
12720                 'september' => 9,
12721                 'oktober' => 10,
12722                 'november' => 11,
12723                 'december' => 12,
12724                 // French
12725                 'janvier' => 1,
12726                 'février' => 2,
12727                 'mars' => 3,
12728                 'avril' => 4,
12729                 'mai' => 5,
12730                 'juin' => 6,
12731                 'juillet' => 7,
12732                 'août' => 8,
12733                 'septembre' => 9,
12734                 'octobre' => 10,
12735                 'novembre' => 11,
12736                 'décembre' => 12,
12737                 // German
12738                 'januar' => 1,
12739                 'februar' => 2,
12740                 'märz' => 3,
12741                 'april' => 4,
12742                 'mai' => 5,
12743                 'juni' => 6,
12744                 'juli' => 7,
12745                 'august' => 8,
12746                 'september' => 9,
12747                 'oktober' => 10,
12748                 'november' => 11,
12749                 'dezember' => 12,
12750                 // Italian
12751                 'gennaio' => 1,
12752                 'febbraio' => 2,
12753                 'marzo' => 3,
12754                 'aprile' => 4,
12755                 'maggio' => 5,
12756                 'giugno' => 6,
12757                 'luglio' => 7,
12758                 'agosto' => 8,
12759                 'settembre' => 9,
12760                 'ottobre' => 10,
12761                 'novembre' => 11,
12762                 'dicembre' => 12,
12763                 // Spanish
12764                 'enero' => 1,
12765                 'febrero' => 2,
12766                 'marzo' => 3,
12767                 'abril' => 4,
12768                 'mayo' => 5,
12769                 'junio' => 6,
12770                 'julio' => 7,
12771                 'agosto' => 8,
12772                 'septiembre' => 9,
12773                 'setiembre' => 9,
12774                 'octubre' => 10,
12775                 'noviembre' => 11,
12776                 'diciembre' => 12,
12777                 // Finnish
12778                 'tammikuu' => 1,
12779                 'helmikuu' => 2,
12780                 'maaliskuu' => 3,
12781                 'huhtikuu' => 4,
12782                 'toukokuu' => 5,
12783                 'kesäkuu' => 6,
12784                 'heinäkuu' => 7,
12785                 'elokuu' => 8,
12786                 'suuskuu' => 9,
12787                 'lokakuu' => 10,
12788                 'marras' => 11,
12789                 'joulukuu' => 12,
12790                 // Hungarian
12791                 'január' => 1,
12792                 'február' => 2,
12793                 'március' => 3,
12794                 'április' => 4,
12795                 'május' => 5,
12796                 'június' => 6,
12797                 'július' => 7,
12798                 'augusztus' => 8,
12799                 'szeptember' => 9,
12800                 'október' => 10,
12801                 'november' => 11,
12802                 'december' => 12,
12803                 // Greek
12804                 'Ιαν' => 1,
12805                 'Φεβ' => 2,
12806                 'Μάώ' => 3,
12807                 'Μαώ' => 3,
12808                 'Απρ' => 4,
12809                 'Μάι' => 5,
12810                 'Μαϊ' => 5,
12811                 'Μαι' => 5,
12812                 'Ιούν' => 6,
12813                 'Ιον' => 6,
12814                 'Ιούλ' => 7,
12815                 'Ιολ' => 7,
12816                 'Αύγ' => 8,
12817                 'Αυγ' => 8,
12818                 'Σεπ' => 9,
12819                 'Οκτ' => 10,
12820                 'Νοέ' => 11,
12821                 'Δεκ' => 12,
12822         );
12823
12824         /**
12825          * List of timezones, abbreviation => offset from UTC
12826          *
12827          * @access protected
12828          * @var array
12829          */
12830         var $timezone = array(
12831                 'ACDT' => 37800,
12832                 'ACIT' => 28800,
12833                 'ACST' => 34200,
12834                 'ACT' => -18000,
12835                 'ACWDT' => 35100,
12836                 'ACWST' => 31500,
12837                 'AEDT' => 39600,
12838                 'AEST' => 36000,
12839                 'AFT' => 16200,
12840                 'AKDT' => -28800,
12841                 'AKST' => -32400,
12842                 'AMDT' => 18000,
12843                 'AMT' => -14400,
12844                 'ANAST' => 46800,
12845                 'ANAT' => 43200,
12846                 'ART' => -10800,
12847                 'AZOST' => -3600,
12848                 'AZST' => 18000,
12849                 'AZT' => 14400,
12850                 'BIOT' => 21600,
12851                 'BIT' => -43200,
12852                 'BOT' => -14400,
12853                 'BRST' => -7200,
12854                 'BRT' => -10800,
12855                 'BST' => 3600,
12856                 'BTT' => 21600,
12857                 'CAST' => 18000,
12858                 'CAT' => 7200,
12859                 'CCT' => 23400,
12860                 'CDT' => -18000,
12861                 'CEDT' => 7200,
12862                 'CET' => 3600,
12863                 'CGST' => -7200,
12864                 'CGT' => -10800,
12865                 'CHADT' => 49500,
12866                 'CHAST' => 45900,
12867                 'CIST' => -28800,
12868                 'CKT' => -36000,
12869                 'CLDT' => -10800,
12870                 'CLST' => -14400,
12871                 'COT' => -18000,
12872                 'CST' => -21600,
12873                 'CVT' => -3600,
12874                 'CXT' => 25200,
12875                 'DAVT' => 25200,
12876                 'DTAT' => 36000,
12877                 'EADT' => -18000,
12878                 'EAST' => -21600,
12879                 'EAT' => 10800,
12880                 'ECT' => -18000,
12881                 'EDT' => -14400,
12882                 'EEST' => 10800,
12883                 'EET' => 7200,
12884                 'EGT' => -3600,
12885                 'EKST' => 21600,
12886                 'EST' => -18000,
12887                 'FJT' => 43200,
12888                 'FKDT' => -10800,
12889                 'FKST' => -14400,
12890                 'FNT' => -7200,
12891                 'GALT' => -21600,
12892                 'GEDT' => 14400,
12893                 'GEST' => 10800,
12894                 'GFT' => -10800,
12895                 'GILT' => 43200,
12896                 'GIT' => -32400,
12897                 'GST' => 14400,
12898                 'GST' => -7200,
12899                 'GYT' => -14400,
12900                 'HAA' => -10800,
12901                 'HAC' => -18000,
12902                 'HADT' => -32400,
12903                 'HAE' => -14400,
12904                 'HAP' => -25200,
12905                 'HAR' => -21600,
12906                 'HAST' => -36000,
12907                 'HAT' => -9000,
12908                 'HAY' => -28800,
12909                 'HKST' => 28800,
12910                 'HMT' => 18000,
12911                 'HNA' => -14400,
12912                 'HNC' => -21600,
12913                 'HNE' => -18000,
12914                 'HNP' => -28800,
12915                 'HNR' => -25200,
12916                 'HNT' => -12600,
12917                 'HNY' => -32400,
12918                 'IRDT' => 16200,
12919                 'IRKST' => 32400,
12920                 'IRKT' => 28800,
12921                 'IRST' => 12600,
12922                 'JFDT' => -10800,
12923                 'JFST' => -14400,
12924                 'JST' => 32400,
12925                 'KGST' => 21600,
12926                 'KGT' => 18000,
12927                 'KOST' => 39600,
12928                 'KOVST' => 28800,
12929                 'KOVT' => 25200,
12930                 'KRAST' => 28800,
12931                 'KRAT' => 25200,
12932                 'KST' => 32400,
12933                 'LHDT' => 39600,
12934                 'LHST' => 37800,
12935                 'LINT' => 50400,
12936                 'LKT' => 21600,
12937                 'MAGST' => 43200,
12938                 'MAGT' => 39600,
12939                 'MAWT' => 21600,
12940                 'MDT' => -21600,
12941                 'MESZ' => 7200,
12942                 'MEZ' => 3600,
12943                 'MHT' => 43200,
12944                 'MIT' => -34200,
12945                 'MNST' => 32400,
12946                 'MSDT' => 14400,
12947                 'MSST' => 10800,
12948                 'MST' => -25200,
12949                 'MUT' => 14400,
12950                 'MVT' => 18000,
12951                 'MYT' => 28800,
12952                 'NCT' => 39600,
12953                 'NDT' => -9000,
12954                 'NFT' => 41400,
12955                 'NMIT' => 36000,
12956                 'NOVST' => 25200,
12957                 'NOVT' => 21600,
12958                 'NPT' => 20700,
12959                 'NRT' => 43200,
12960                 'NST' => -12600,
12961                 'NUT' => -39600,
12962                 'NZDT' => 46800,
12963                 'NZST' => 43200,
12964                 'OMSST' => 25200,
12965                 'OMST' => 21600,
12966                 'PDT' => -25200,
12967                 'PET' => -18000,
12968                 'PETST' => 46800,
12969                 'PETT' => 43200,
12970                 'PGT' => 36000,
12971                 'PHOT' => 46800,
12972                 'PHT' => 28800,
12973                 'PKT' => 18000,
12974                 'PMDT' => -7200,
12975                 'PMST' => -10800,
12976                 'PONT' => 39600,
12977                 'PST' => -28800,
12978                 'PWT' => 32400,
12979                 'PYST' => -10800,
12980                 'PYT' => -14400,
12981                 'RET' => 14400,
12982                 'ROTT' => -10800,
12983                 'SAMST' => 18000,
12984                 'SAMT' => 14400,
12985                 'SAST' => 7200,
12986                 'SBT' => 39600,
12987                 'SCDT' => 46800,
12988                 'SCST' => 43200,
12989                 'SCT' => 14400,
12990                 'SEST' => 3600,
12991                 'SGT' => 28800,
12992                 'SIT' => 28800,
12993                 'SRT' => -10800,
12994                 'SST' => -39600,
12995                 'SYST' => 10800,
12996                 'SYT' => 7200,
12997                 'TFT' => 18000,
12998                 'THAT' => -36000,
12999                 'TJT' => 18000,
13000                 'TKT' => -36000,
13001                 'TMT' => 18000,
13002                 'TOT' => 46800,
13003                 'TPT' => 32400,
13004                 'TRUT' => 36000,
13005                 'TVT' => 43200,
13006                 'TWT' => 28800,
13007                 'UYST' => -7200,
13008                 'UYT' => -10800,
13009                 'UZT' => 18000,
13010                 'VET' => -14400,
13011                 'VLAST' => 39600,
13012                 'VLAT' => 36000,
13013                 'VOST' => 21600,
13014                 'VUT' => 39600,
13015                 'WAST' => 7200,
13016                 'WAT' => 3600,
13017                 'WDT' => 32400,
13018                 'WEST' => 3600,
13019                 'WFT' => 43200,
13020                 'WIB' => 25200,
13021                 'WIT' => 32400,
13022                 'WITA' => 28800,
13023                 'WKST' => 18000,
13024                 'WST' => 28800,
13025                 'YAKST' => 36000,
13026                 'YAKT' => 32400,
13027                 'YAPT' => 36000,
13028                 'YEKST' => 21600,
13029                 'YEKT' => 18000,
13030         );
13031
13032         /**
13033          * Cached PCRE for SimplePie_Parse_Date::$day
13034          *
13035          * @access protected
13036          * @var string
13037          */
13038         var $day_pcre;
13039
13040         /**
13041          * Cached PCRE for SimplePie_Parse_Date::$month
13042          *
13043          * @access protected
13044          * @var string
13045          */
13046         var $month_pcre;
13047
13048         /**
13049          * Array of user-added callback methods
13050          *
13051          * @access private
13052          * @var array
13053          */
13054         var $built_in = array();
13055
13056         /**
13057          * Array of user-added callback methods
13058          *
13059          * @access private
13060          * @var array
13061          */
13062         var $user = array();
13063
13064         /**
13065          * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13066          * self::month_pcre, and self::built_in
13067          *
13068          * @access private
13069          */
13070         function SimplePie_Parse_Date()
13071         {
13072                 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13073                 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13074
13075                 static $cache;
13076                 if (!isset($cache[get_class($this)]))
13077                 {
13078                         $all_methods = get_class_methods($this);
13079
13080                         foreach ($all_methods as $method)
13081                         {
13082                                 if (strtolower(substr($method, 0, 5)) === 'date_')
13083                                 {
13084                                         $cache[get_class($this)][] = $method;
13085                                 }
13086                         }
13087                 }
13088
13089                 foreach ($cache[get_class($this)] as $method)
13090                 {
13091                         $this->built_in[] = $method;
13092                 }
13093         }
13094
13095         /**
13096          * Get the object
13097          *
13098          * @access public
13099          */
13100         function get()
13101         {
13102                 static $object;
13103                 if (!$object)
13104                 {
13105                         $object = new SimplePie_Parse_Date;
13106                 }
13107                 return $object;
13108         }
13109
13110         /**
13111          * Parse a date
13112          *
13113          * @final
13114          * @access public
13115          * @param string $date Date to parse
13116          * @return int Timestamp corresponding to date string, or false on failure
13117          */
13118         function parse($date)
13119         {
13120                 foreach ($this->user as $method)
13121                 {
13122                         if (($returned = call_user_func($method, $date)) !== false)
13123                         {
13124                                 return $returned;
13125                         }
13126                 }
13127
13128                 foreach ($this->built_in as $method)
13129                 {
13130                         if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13131                         {
13132                                 return $returned;
13133                         }
13134                 }
13135
13136                 return false;
13137         }
13138
13139         /**
13140          * Add a callback method to parse a date
13141          *
13142          * @final
13143          * @access public
13144          * @param callback $callback
13145          */
13146         function add_callback($callback)
13147         {
13148                 if (is_callable($callback))
13149                 {
13150                         $this->user[] = $callback;
13151                 }
13152                 else
13153                 {
13154                         trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13155                 }
13156         }
13157
13158         /**
13159          * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13160          * well as allowing any of upper or lower case "T", horizontal tabs, or
13161          * spaces to be used as the time seperator (including more than one))
13162          *
13163          * @access protected
13164          * @return int Timestamp
13165          */
13166         function date_w3cdtf($date)
13167         {
13168                 static $pcre;
13169                 if (!$pcre)
13170                 {
13171                         $year = '([0-9]{4})';
13172                         $month = $day = $hour = $minute = $second = '([0-9]{2})';
13173                         $decimal = '([0-9]*)';
13174                         $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13175                         $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13176                 }
13177                 if (preg_match($pcre, $date, $match))
13178                 {
13179                         /*
13180                         Capturing subpatterns:
13181                         1: Year
13182                         2: Month
13183                         3: Day
13184                         4: Hour
13185                         5: Minute
13186                         6: Second
13187                         7: Decimal fraction of a second
13188                         8: Zulu
13189                         9: Timezone ±
13190                         10: Timezone hours
13191                         11: Timezone minutes
13192                         */
13193
13194                         // Fill in empty matches
13195                         for ($i = count($match); $i <= 3; $i++)
13196                         {
13197                                 $match[$i] = '1';
13198                         }
13199
13200                         for ($i = count($match); $i <= 7; $i++)
13201                         {
13202                                 $match[$i] = '0';
13203                         }
13204
13205                         // Numeric timezone
13206                         if (isset($match[9]) && $match[9] !== '')
13207                         {
13208                                 $timezone = $match[10] * 3600;
13209                                 $timezone += $match[11] * 60;
13210                                 if ($match[9] === '-')
13211                                 {
13212                                         $timezone = 0 - $timezone;
13213                                 }
13214                         }
13215                         else
13216                         {
13217                                 $timezone = 0;
13218                         }
13219
13220                         // Convert the number of seconds to an integer, taking decimals into account
13221                         $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13222
13223                         return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13224                 }
13225                 else
13226                 {
13227                         return false;
13228                 }
13229         }
13230
13231         /**
13232          * Remove RFC822 comments
13233          *
13234          * @access protected
13235          * @param string $data Data to strip comments from
13236          * @return string Comment stripped string
13237          */
13238         function remove_rfc2822_comments($string)
13239         {
13240                 $string = (string) $string;
13241                 $position = 0;
13242                 $length = strlen($string);
13243                 $depth = 0;
13244
13245                 $output = '';
13246
13247                 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13248                 {
13249                         $output .= substr($string, $position, $pos - $position);
13250                         $position = $pos + 1;
13251                         if ($string[$pos - 1] !== '\\')
13252                         {
13253                                 $depth++;
13254                                 while ($depth && $position < $length)
13255                                 {
13256                                         $position += strcspn($string, '()', $position);
13257                                         if ($string[$position - 1] === '\\')
13258                                         {
13259                                                 $position++;
13260                                                 continue;
13261                                         }
13262                                         elseif (isset($string[$position]))
13263                                         {
13264                                                 switch ($string[$position])
13265                                                 {
13266                                                         case '(':
13267                                                                 $depth++;
13268                                                                 break;
13269
13270                                                         case ')':
13271                                                                 $depth--;
13272                                                                 break;
13273                                                 }
13274                                                 $position++;
13275                                         }
13276                                         else
13277                                         {
13278                                                 break;
13279                                         }
13280                                 }
13281                         }
13282                         else
13283                         {
13284                                 $output .= '(';
13285                         }
13286                 }
13287                 $output .= substr($string, $position);
13288
13289                 return $output;
13290         }
13291
13292         /**
13293          * Parse RFC2822's date format
13294          *
13295          * @access protected
13296          * @return int Timestamp
13297          */
13298         function date_rfc2822($date)
13299         {
13300                 static $pcre;
13301                 if (!$pcre)
13302                 {
13303                         $wsp = '[\x09\x20]';
13304                         $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13305                         $optional_fws = $fws . '?';
13306                         $day_name = $this->day_pcre;
13307                         $month = $this->month_pcre;
13308                         $day = '([0-9]{1,2})';
13309                         $hour = $minute = $second = '([0-9]{2})';
13310                         $year = '([0-9]{2,4})';
13311                         $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13312                         $character_zone = '([A-Z]{1,5})';
13313                         $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13314                         $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';
13315                 }
13316                 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13317                 {
13318                         /*
13319                         Capturing subpatterns:
13320                         1: Day name
13321                         2: Day
13322                         3: Month
13323                         4: Year
13324                         5: Hour
13325                         6: Minute
13326                         7: Second
13327                         8: Timezone ±
13328                         9: Timezone hours
13329                         10: Timezone minutes
13330                         11: Alphabetic timezone
13331                         */
13332
13333                         // Find the month number
13334                         $month = $this->month[strtolower($match[3])];
13335
13336                         // Numeric timezone
13337                         if ($match[8] !== '')
13338                         {
13339                                 $timezone = $match[9] * 3600;
13340                                 $timezone += $match[10] * 60;
13341                                 if ($match[8] === '-')
13342                                 {
13343                                         $timezone = 0 - $timezone;
13344                                 }
13345                         }
13346                         // Character timezone
13347                         elseif (isset($this->timezone[strtoupper($match[11])]))
13348                         {
13349                                 $timezone = $this->timezone[strtoupper($match[11])];
13350                         }
13351                         // Assume everything else to be -0000
13352                         else
13353                         {
13354                                 $timezone = 0;
13355                         }
13356
13357                         // Deal with 2/3 digit years
13358                         if ($match[4] < 50)
13359                         {
13360                                 $match[4] += 2000;
13361                         }
13362                         elseif ($match[4] < 1000)
13363                         {
13364                                 $match[4] += 1900;
13365                         }
13366
13367                         // Second is optional, if it is empty set it to zero
13368                         if ($match[7] !== '')
13369                         {
13370                                 $second = $match[7];
13371                         }
13372                         else
13373                         {
13374                                 $second = 0;
13375                         }
13376
13377                         return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13378                 }
13379                 else
13380                 {
13381                         return false;
13382                 }
13383         }
13384
13385         /**
13386          * Parse RFC850's date format
13387          *
13388          * @access protected
13389          * @return int Timestamp
13390          */
13391         function date_rfc850($date)
13392         {
13393                 static $pcre;
13394                 if (!$pcre)
13395                 {
13396                         $space = '[\x09\x20]+';
13397                         $day_name = $this->day_pcre;
13398                         $month = $this->month_pcre;
13399                         $day = '([0-9]{1,2})';
13400                         $year = $hour = $minute = $second = '([0-9]{2})';
13401                         $zone = '([A-Z]{1,5})';
13402                         $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13403                 }
13404                 if (preg_match($pcre, $date, $match))
13405                 {
13406                         /*
13407                         Capturing subpatterns:
13408                         1: Day name
13409                         2: Day
13410                         3: Month
13411                         4: Year
13412                         5: Hour
13413                         6: Minute
13414                         7: Second
13415                         8: Timezone
13416                         */
13417
13418                         // Month
13419                         $month = $this->month[strtolower($match[3])];
13420
13421                         // Character timezone
13422                         if (isset($this->timezone[strtoupper($match[8])]))
13423                         {
13424                                 $timezone = $this->timezone[strtoupper($match[8])];
13425                         }
13426                         // Assume everything else to be -0000
13427                         else
13428                         {
13429                                 $timezone = 0;
13430                         }
13431
13432                         // Deal with 2 digit year
13433                         if ($match[4] < 50)
13434                         {
13435                                 $match[4] += 2000;
13436                         }
13437                         else
13438                         {
13439                                 $match[4] += 1900;
13440                         }
13441
13442                         return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13443                 }
13444                 else
13445                 {
13446                         return false;
13447                 }
13448         }
13449
13450         /**
13451          * Parse C99's asctime()'s date format
13452          *
13453          * @access protected
13454          * @return int Timestamp
13455          */
13456         function date_asctime($date)
13457         {
13458                 static $pcre;
13459                 if (!$pcre)
13460                 {
13461                         $space = '[\x09\x20]+';
13462                         $wday_name = $this->day_pcre;
13463                         $mon_name = $this->month_pcre;
13464                         $day = '([0-9]{1,2})';
13465                         $hour = $sec = $min = '([0-9]{2})';
13466                         $year = '([0-9]{4})';
13467                         $terminator = '\x0A?\x00?';
13468                         $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13469                 }
13470                 if (preg_match($pcre, $date, $match))
13471                 {
13472                         /*
13473                         Capturing subpatterns:
13474                         1: Day name
13475                         2: Month
13476                         3: Day
13477                         4: Hour
13478                         5: Minute
13479                         6: Second
13480                         7: Year
13481                         */
13482
13483                         $month = $this->month[strtolower($match[2])];
13484                         return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13485                 }
13486                 else
13487                 {
13488                         return false;
13489                 }
13490         }
13491
13492         /**
13493          * Parse dates using strtotime()
13494          *
13495          * @access protected
13496          * @return int Timestamp
13497          */
13498         function date_strtotime($date)
13499         {
13500                 $strtotime = strtotime($date);
13501                 if ($strtotime === -1 || $strtotime === false)
13502                 {
13503                         return false;
13504                 }
13505                 else
13506                 {
13507                         return $strtotime;
13508                 }
13509         }
13510 }
13511
13512 /**
13513  * Content-type sniffing
13514  *
13515  * @package SimplePie
13516  */
13517 class SimplePie_Content_Type_Sniffer
13518 {
13519         /**
13520          * File object
13521          *
13522          * @var SimplePie_File
13523          * @access private
13524          */
13525         var $file;
13526
13527         /**
13528          * Create an instance of the class with the input file
13529          *
13530          * @access public
13531          * @param SimplePie_Content_Type_Sniffer $file Input file
13532          */
13533         function SimplePie_Content_Type_Sniffer($file)
13534         {
13535                 $this->file = $file;
13536         }
13537
13538         /**
13539          * Get the Content-Type of the specified file
13540          *
13541          * @access public
13542          * @return string Actual Content-Type
13543          */
13544         function get_type()
13545         {
13546                 if (isset($this->file->headers['content-type']))
13547                 {
13548                         if (!isset($this->file->headers['content-encoding'])
13549                                 && ($this->file->headers['content-type'] === 'text/plain'
13550                                         || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13551                                         || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13552                         {
13553                                 return $this->text_or_binary();
13554                         }
13555
13556                         if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13557                         {
13558                                 $official = substr($this->file->headers['content-type'], 0, $pos);
13559                         }
13560                         else
13561                         {
13562                                 $official = $this->file->headers['content-type'];
13563                         }
13564                         $official = strtolower($official);
13565
13566                         if ($official === 'unknown/unknown'
13567                                 || $official === 'application/unknown')
13568                         {
13569                                 return $this->unknown();
13570                         }
13571                         elseif (substr($official, -4) === '+xml'
13572                                 || $official === 'text/xml'
13573                                 || $official === 'application/xml')
13574                         {
13575                                 return $official;
13576                         }
13577                         elseif (substr($official, 0, 6) === 'image/')
13578                         {
13579                                 if ($return = $this->image())
13580                                 {
13581                                         return $return;
13582                                 }
13583                                 else
13584                                 {
13585                                         return $official;
13586                                 }
13587                         }
13588                         elseif ($official === 'text/html')
13589                         {
13590                                 return $this->feed_or_html();
13591                         }
13592                         else
13593                         {
13594                                 return $official;
13595                         }
13596                 }
13597                 else
13598                 {
13599                         return $this->unknown();
13600                 }
13601         }
13602
13603         /**
13604          * Sniff text or binary
13605          *
13606          * @access private
13607          * @return string Actual Content-Type
13608          */
13609         function text_or_binary()
13610         {
13611                 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13612                         || substr($this->file->body, 0, 2) === "\xFF\xFE"
13613                         || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13614                         || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13615                 {
13616                         return 'text/plain';
13617                 }
13618                 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13619                 {
13620                         return 'application/octect-stream';
13621                 }
13622                 else
13623                 {
13624                         return 'text/plain';
13625                 }
13626         }
13627
13628         /**
13629          * Sniff unknown
13630          *
13631          * @access private
13632          * @return string Actual Content-Type
13633          */
13634         function unknown()
13635         {
13636                 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13637                 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13638                         || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13639                         || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13640                 {
13641                         return 'text/html';
13642                 }
13643                 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13644                 {
13645                         return 'application/pdf';
13646                 }
13647                 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13648                 {
13649                         return 'application/postscript';
13650                 }
13651                 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13652                         || substr($this->file->body, 0, 6) === 'GIF89a')
13653                 {
13654                         return 'image/gif';
13655                 }
13656                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13657                 {
13658                         return 'image/png';
13659                 }
13660                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13661                 {
13662                         return 'image/jpeg';
13663                 }
13664                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13665                 {
13666                         return 'image/bmp';
13667                 }
13668                 else
13669                 {
13670                         return $this->text_or_binary();
13671                 }
13672         }
13673
13674         /**
13675          * Sniff images
13676          *
13677          * @access private
13678          * @return string Actual Content-Type
13679          */
13680         function image()
13681         {
13682                 if (substr($this->file->body, 0, 6) === 'GIF87a'
13683                         || substr($this->file->body, 0, 6) === 'GIF89a')
13684                 {
13685                         return 'image/gif';
13686                 }
13687                 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13688                 {
13689                         return 'image/png';
13690                 }
13691                 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13692                 {
13693                         return 'image/jpeg';
13694                 }
13695                 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13696                 {
13697                         return 'image/bmp';
13698                 }
13699                 else
13700                 {
13701                         return false;
13702                 }
13703         }
13704
13705         /**
13706          * Sniff HTML
13707          *
13708          * @access private
13709          * @return string Actual Content-Type
13710          */
13711         function feed_or_html()
13712         {
13713                 $len = strlen($this->file->body);
13714                 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13715
13716                 while ($pos < $len)
13717                 {
13718                         switch ($this->file->body[$pos])
13719                         {
13720                                 case "\x09":
13721                                 case "\x0A":
13722                                 case "\x0D":
13723                                 case "\x20":
13724                                         $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13725                                         continue 2;
13726
13727                                 case '<':
13728                                         $pos++;
13729                                         break;
13730
13731                                 default:
13732                                         return 'text/html';
13733                         }
13734
13735                         if (substr($this->file->body, $pos, 3) === '!--')
13736                         {
13737                                 $pos += 3;
13738                                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13739                                 {
13740                                         $pos += 3;
13741                                 }
13742                                 else
13743                                 {
13744                                         return 'text/html';
13745                                 }
13746                         }
13747                         elseif (substr($this->file->body, $pos, 1) === '!')
13748                         {
13749                                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13750                                 {
13751                                         $pos++;
13752                                 }
13753                                 else
13754                                 {
13755                                         return 'text/html';
13756                                 }
13757                         }
13758                         elseif (substr($this->file->body, $pos, 1) === '?')
13759                         {
13760                                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13761                                 {
13762                                         $pos += 2;
13763                                 }
13764                                 else
13765                                 {
13766                                         return 'text/html';
13767                                 }
13768                         }
13769                         elseif (substr($this->file->body, $pos, 3) === 'rss'
13770                                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13771                         {
13772                                 return 'application/rss+xml';
13773                         }
13774                         elseif (substr($this->file->body, $pos, 4) === 'feed')
13775                         {
13776                                 return 'application/atom+xml';
13777                         }
13778                         else
13779                         {
13780                                 return 'text/html';
13781                         }
13782                 }
13783
13784                 return 'text/html';
13785         }
13786 }
13787
13788 /**
13789  * Parses the XML Declaration
13790  *
13791  * @package SimplePie
13792  */
13793 class SimplePie_XML_Declaration_Parser
13794 {
13795         /**
13796          * XML Version
13797          *
13798          * @access public
13799          * @var string
13800          */
13801         var $version = '1.0';
13802
13803         /**
13804          * Encoding
13805          *
13806          * @access public
13807          * @var string
13808          */
13809         var $encoding = 'UTF-8';
13810
13811         /**
13812          * Standalone
13813          *
13814          * @access public
13815          * @var bool
13816          */
13817         var $standalone = false;
13818
13819         /**
13820          * Current state of the state machine
13821          *
13822          * @access private
13823          * @var string
13824          */
13825         var $state = 'before_version_name';
13826
13827         /**
13828          * Input data
13829          *
13830          * @access private
13831          * @var string
13832          */
13833         var $data = '';
13834
13835         /**
13836          * Input data length (to avoid calling strlen() everytime this is needed)
13837          *
13838          * @access private
13839          * @var int
13840          */
13841         var $data_length = 0;
13842
13843         /**
13844          * Current position of the pointer
13845          *
13846          * @var int
13847          * @access private
13848          */
13849         var $position = 0;
13850
13851         /**
13852          * Create an instance of the class with the input data
13853          *
13854          * @access public
13855          * @param string $data Input data
13856          */
13857         function SimplePie_XML_Declaration_Parser($data)
13858         {
13859                 $this->data = $data;
13860                 $this->data_length = strlen($this->data);
13861         }
13862
13863         /**
13864          * Parse the input data
13865          *
13866          * @access public
13867          * @return bool true on success, false on failure
13868          */
13869         function parse()
13870         {
13871                 while ($this->state && $this->state !== 'emit' && $this->has_data())
13872                 {
13873                         $state = $this->state;
13874                         $this->$state();
13875                 }
13876                 $this->data = '';
13877                 if ($this->state === 'emit')
13878                 {
13879                         return true;
13880                 }
13881                 else
13882                 {
13883                         $this->version = '';
13884                         $this->encoding = '';
13885                         $this->standalone = '';
13886                         return false;
13887                 }
13888         }
13889
13890         /**
13891          * Check whether there is data beyond the pointer
13892          *
13893          * @access private
13894          * @return bool true if there is further data, false if not
13895          */
13896         function has_data()
13897         {
13898                 return (bool) ($this->position < $this->data_length);
13899         }
13900
13901         /**
13902          * Advance past any whitespace
13903          *
13904          * @return int Number of whitespace characters passed
13905          */
13906         function skip_whitespace()
13907         {
13908                 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13909                 $this->position += $whitespace;
13910                 return $whitespace;
13911         }
13912
13913         /**
13914          * Read value
13915          */
13916         function get_value()
13917         {
13918                 $quote = substr($this->data, $this->position, 1);
13919                 if ($quote === '"' || $quote === "'")
13920                 {
13921                         $this->position++;
13922                         $len = strcspn($this->data, $quote, $this->position);
13923                         if ($this->has_data())
13924                         {
13925                                 $value = substr($this->data, $this->position, $len);
13926                                 $this->position += $len + 1;
13927                                 return $value;
13928                         }
13929                 }
13930                 return false;
13931         }
13932
13933         function before_version_name()
13934         {
13935                 if ($this->skip_whitespace())
13936                 {
13937                         $this->state = 'version_name';
13938                 }
13939                 else
13940                 {
13941                         $this->state = false;
13942                 }
13943         }
13944
13945         function version_name()
13946         {
13947                 if (substr($this->data, $this->position, 7) === 'version')
13948                 {
13949                         $this->position += 7;
13950                         $this->skip_whitespace();
13951                         $this->state = 'version_equals';
13952                 }
13953                 else
13954                 {
13955                         $this->state = false;
13956                 }
13957         }
13958
13959         function version_equals()
13960         {
13961                 if (substr($this->data, $this->position, 1) === '=')
13962                 {
13963                         $this->position++;
13964                         $this->skip_whitespace();
13965                         $this->state = 'version_value';
13966                 }
13967                 else
13968                 {
13969                         $this->state = false;
13970                 }
13971         }
13972
13973         function version_value()
13974         {
13975                 if ($this->version = $this->get_value())
13976                 {
13977                         $this->skip_whitespace();
13978                         if ($this->has_data())
13979                         {
13980                                 $this->state = 'encoding_name';
13981                         }
13982                         else
13983                         {
13984                                 $this->state = 'emit';
13985                         }
13986                 }
13987                 else
13988                 {
13989                         $this->state = false;
13990                 }
13991         }
13992
13993         function encoding_name()
13994         {
13995                 if (substr($this->data, $this->position, 8) === 'encoding')
13996                 {
13997                         $this->position += 8;
13998                         $this->skip_whitespace();
13999                         $this->state = 'encoding_equals';
14000                 }
14001                 else
14002                 {
14003                         $this->state = 'standalone_name';
14004                 }
14005         }
14006
14007         function encoding_equals()
14008         {
14009                 if (substr($this->data, $this->position, 1) === '=')
14010                 {
14011                         $this->position++;
14012                         $this->skip_whitespace();
14013                         $this->state = 'encoding_value';
14014                 }
14015                 else
14016                 {
14017                         $this->state = false;
14018                 }
14019         }
14020
14021         function encoding_value()
14022         {
14023                 if ($this->encoding = $this->get_value())
14024                 {
14025                         $this->skip_whitespace();
14026                         if ($this->has_data())
14027                         {
14028                                 $this->state = 'standalone_name';
14029                         }
14030                         else
14031                         {
14032                                 $this->state = 'emit';
14033                         }
14034                 }
14035                 else
14036                 {
14037                         $this->state = false;
14038                 }
14039         }
14040
14041         function standalone_name()
14042         {
14043                 if (substr($this->data, $this->position, 10) === 'standalone')
14044                 {
14045                         $this->position += 10;
14046                         $this->skip_whitespace();
14047                         $this->state = 'standalone_equals';
14048                 }
14049                 else
14050                 {
14051                         $this->state = false;
14052                 }
14053         }
14054
14055         function standalone_equals()
14056         {
14057                 if (substr($this->data, $this->position, 1) === '=')
14058                 {
14059                         $this->position++;
14060                         $this->skip_whitespace();
14061                         $this->state = 'standalone_value';
14062                 }
14063                 else
14064                 {
14065                         $this->state = false;
14066                 }
14067         }
14068
14069         function standalone_value()
14070         {
14071                 if ($standalone = $this->get_value())
14072                 {
14073                         switch ($standalone)
14074                         {
14075                                 case 'yes':
14076                                         $this->standalone = true;
14077                                         break;
14078
14079                                 case 'no':
14080                                         $this->standalone = false;
14081                                         break;
14082
14083                                 default:
14084                                         $this->state = false;
14085                                         return;
14086                         }
14087
14088                         $this->skip_whitespace();
14089                         if ($this->has_data())
14090                         {
14091                                 $this->state = false;
14092                         }
14093                         else
14094                         {
14095                                 $this->state = 'emit';
14096                         }
14097                 }
14098                 else
14099                 {
14100                         $this->state = false;
14101                 }
14102         }
14103 }
14104
14105 class SimplePie_Locator
14106 {
14107         var $useragent;
14108         var $timeout;
14109         var $file;
14110         var $local = array();
14111         var $elsewhere = array();
14112         var $file_class = 'SimplePie_File';
14113         var $cached_entities = array();
14114         var $http_base;
14115         var $base;
14116         var $base_location = 0;
14117         var $checked_feeds = 0;
14118         var $max_checked_feeds = 10;
14119         var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14120
14121         function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14122         {
14123                 $this->file =& $file;
14124                 $this->file_class = $file_class;
14125                 $this->useragent = $useragent;
14126                 $this->timeout = $timeout;
14127                 $this->max_checked_feeds = $max_checked_feeds;
14128                 $this->content_type_sniffer_class = $content_type_sniffer_class;
14129         }
14130
14131         function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14132         {
14133                 if ($this->is_feed($this->file))
14134                 {
14135                         return $this->file;
14136                 }
14137
14138                 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14139                 {
14140                         $sniffer = new $this->content_type_sniffer_class($this->file);
14141                         if ($sniffer->get_type() !== 'text/html')
14142                         {
14143                                 return null;
14144                         }
14145                 }
14146
14147                 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14148                 {
14149                         $this->get_base();
14150                 }
14151
14152                 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14153                 {
14154                         return $working[0];
14155                 }
14156
14157                 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14158                 {
14159                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14160                         {
14161                                 return $working;
14162                         }
14163
14164                         if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14165                         {
14166                                 return $working;
14167                         }
14168
14169                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14170                         {
14171                                 return $working;
14172                         }
14173
14174                         if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14175                         {
14176                                 return $working;
14177                         }
14178                 }
14179                 return null;
14180         }
14181
14182         function is_feed(&$file)
14183         {
14184                 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14185                 {
14186                         $sniffer = new $this->content_type_sniffer_class($file);
14187                         $sniffed = $sniffer->get_type();
14188                         if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14189                         {
14190                                 return true;
14191                         }
14192                         else
14193                         {
14194                                 return false;
14195                         }
14196                 }
14197                 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14198                 {
14199                         return true;
14200                 }
14201                 else
14202                 {
14203                         return false;
14204                 }
14205         }
14206
14207         function get_base()
14208         {
14209                 $this->http_base = $this->file->url;
14210                 $this->base = $this->http_base;
14211                 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14212                 foreach ($elements as $element)
14213                 {
14214                         if ($element['attribs']['href']['data'] !== '')
14215                         {
14216                                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14217                                 $this->base_location = $element['offset'];
14218                                 break;
14219                         }
14220                 }
14221         }
14222
14223         function autodiscovery()
14224         {
14225                 $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));
14226                 $done = array();
14227                 $feeds = array();
14228                 foreach ($links as $link)
14229                 {
14230                         if ($this->checked_feeds === $this->max_checked_feeds)
14231                         {
14232                                 break;
14233                         }
14234                         if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14235                         {
14236                                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14237
14238                                 if ($this->base_location < $link['offset'])
14239                                 {
14240                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14241                                 }
14242                                 else
14243                                 {
14244                                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14245                                 }
14246
14247                                 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]))
14248                                 {
14249                                         $this->checked_feeds++;
14250                                         $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14251                                         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))
14252                                         {
14253                                                 $feeds[$href] = $feed;
14254                                         }
14255                                 }
14256                                 $done[] = $href;
14257                         }
14258                 }
14259
14260                 if (!empty($feeds))
14261                 {
14262                         return array_values($feeds);
14263                 }
14264                 else {
14265                         return null;
14266                 }
14267         }
14268
14269         function get_links()
14270         {
14271                 $links = SimplePie_Misc::get_element('a', $this->file->body);
14272                 foreach ($links as $link)
14273                 {
14274                         if (isset($link['attribs']['href']['data']))
14275                         {
14276                                 $href = trim($link['attribs']['href']['data']);
14277                                 $parsed = SimplePie_Misc::parse_url($href);
14278                                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14279                                 {
14280                                         if ($this->base_location < $link['offset'])
14281                                         {
14282                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14283                                         }
14284                                         else
14285                                         {
14286                                                 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14287                                         }
14288
14289                                         $current = SimplePie_Misc::parse_url($this->file->url);
14290
14291                                         if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14292                                         {
14293                                                 $this->local[] = $href;
14294                                         }
14295                                         else
14296                                         {
14297                                                 $this->elsewhere[] = $href;
14298                                         }
14299                                 }
14300                         }
14301                 }
14302                 $this->local = array_unique($this->local);
14303                 $this->elsewhere = array_unique($this->elsewhere);
14304                 if (!empty($this->local) || !empty($this->elsewhere))
14305                 {
14306                         return true;
14307                 }
14308                 return null;
14309         }
14310
14311         function extension(&$array)
14312         {
14313                 foreach ($array as $key => $value)
14314                 {
14315                         if ($this->checked_feeds === $this->max_checked_feeds)
14316                         {
14317                                 break;
14318                         }
14319                         if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14320                         {
14321                                 $this->checked_feeds++;
14322                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14323                                 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))
14324                                 {
14325                                         return $feed;
14326                                 }
14327                                 else
14328                                 {
14329                                         unset($array[$key]);
14330                                 }
14331                         }
14332                 }
14333                 return null;
14334         }
14335
14336         function body(&$array)
14337         {
14338                 foreach ($array as $key => $value)
14339                 {
14340                         if ($this->checked_feeds === $this->max_checked_feeds)
14341                         {
14342                                 break;
14343                         }
14344                         if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14345                         {
14346                                 $this->checked_feeds++;
14347                                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14348                                 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))
14349                                 {
14350                                         return $feed;
14351                                 }
14352                                 else
14353                                 {
14354                                         unset($array[$key]);
14355                                 }
14356                         }
14357                 }
14358                 return null;
14359         }
14360 }
14361
14362 class SimplePie_Parser
14363 {
14364         var $error_code;
14365         var $error_string;
14366         var $current_line;
14367         var $current_column;
14368         var $current_byte;
14369         var $separator = ' ';
14370         var $namespace = array('');
14371         var $element = array('');
14372         var $xml_base = array('');
14373         var $xml_base_explicit = array(false);
14374         var $xml_lang = array('');
14375         var $data = array();
14376         var $datas = array(array());
14377         var $current_xhtml_construct = -1;
14378         var $encoding;
14379
14380         function parse(&$data, $encoding)
14381         {
14382                 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14383                 if (strtoupper($encoding) === 'US-ASCII')
14384                 {
14385                         $this->encoding = 'UTF-8';
14386                 }
14387                 else
14388                 {
14389                         $this->encoding = $encoding;
14390                 }
14391
14392                 // Strip BOM:
14393                 // UTF-32 Big Endian BOM
14394                 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14395                 {
14396                         $data = substr($data, 4);
14397                 }
14398                 // UTF-32 Little Endian BOM
14399                 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14400                 {
14401                         $data = substr($data, 4);
14402                 }
14403                 // UTF-16 Big Endian BOM
14404                 elseif (substr($data, 0, 2) === "\xFE\xFF")
14405                 {
14406                         $data = substr($data, 2);
14407                 }
14408                 // UTF-16 Little Endian BOM
14409                 elseif (substr($data, 0, 2) === "\xFF\xFE")
14410                 {
14411                         $data = substr($data, 2);
14412                 }
14413                 // UTF-8 BOM
14414                 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14415                 {
14416                         $data = substr($data, 3);
14417                 }
14418
14419                 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14420                 {
14421                         $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14422                         if ($declaration->parse())
14423                         {
14424                                 $data = substr($data, $pos + 2);
14425                                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14426                         }
14427                         else
14428                         {
14429                                 $this->error_string = 'SimplePie bug! Please report this!';
14430                                 return false;
14431                         }
14432                 }
14433
14434                 $return = true;
14435
14436                 static $xml_is_sane = null;
14437                 if ($xml_is_sane === null)
14438                 {
14439                         $parser_check = xml_parser_create();
14440                         xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14441                         xml_parser_free($parser_check);
14442                         $xml_is_sane = isset($values[0]['value']);
14443                 }
14444
14445                 // Create the parser
14446                 if ($xml_is_sane)
14447                 {
14448                         $xml = xml_parser_create_ns($this->encoding, $this->separator);
14449                         xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14450                         xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14451                         xml_set_object($xml, $this);
14452                         xml_set_character_data_handler($xml, 'cdata');
14453                         xml_set_element_handler($xml, 'tag_open', 'tag_close');
14454
14455                         // Parse!
14456                         if (!xml_parse($xml, $data, true))
14457                         {
14458                                 $this->error_code = xml_get_error_code($xml);
14459                                 $this->error_string = xml_error_string($this->error_code);
14460                                 $return = false;
14461                         }
14462                         $this->current_line = xml_get_current_line_number($xml);
14463                         $this->current_column = xml_get_current_column_number($xml);
14464                         $this->current_byte = xml_get_current_byte_index($xml);
14465                         xml_parser_free($xml);
14466                         return $return;
14467                 }
14468                 else
14469                 {
14470                         libxml_clear_errors();
14471                         $xml = new XMLReader();
14472                         $xml->xml($data);
14473                         while (@$xml->read())
14474                         {
14475                                 switch ($xml->nodeType)
14476                                 {
14477
14478                                         case constant('XMLReader::END_ELEMENT'):
14479                                                 if ($xml->namespaceURI !== '')
14480                                                 {
14481                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14482                                                 }
14483                                                 else
14484                                                 {
14485                                                         $tagName = $xml->localName;
14486                                                 }
14487                                                 $this->tag_close(null, $tagName);
14488                                                 break;
14489                                         case constant('XMLReader::ELEMENT'):
14490                                                 $empty = $xml->isEmptyElement;
14491                                                 if ($xml->namespaceURI !== '')
14492                                                 {
14493                                                         $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14494                                                 }
14495                                                 else
14496                                                 {
14497                                                         $tagName = $xml->localName;
14498                                                 }
14499                                                 $attributes = array();
14500                                                 while ($xml->moveToNextAttribute())
14501                                                 {
14502                                                         if ($xml->namespaceURI !== '')
14503                                                         {
14504                                                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14505                                                         }
14506                                                         else
14507                                                         {
14508                                                                 $attrName = $xml->localName;
14509                                                         }
14510                                                         $attributes[$attrName] = $xml->value;
14511                                                 }
14512                                                 $this->tag_open(null, $tagName, $attributes);
14513                                                 if ($empty)
14514                                                 {
14515                                                         $this->tag_close(null, $tagName);
14516                                                 }
14517                                                 break;
14518                                         case constant('XMLReader::TEXT'):
14519
14520                                         case constant('XMLReader::CDATA'):
14521                                                 $this->cdata(null, $xml->value);
14522                                                 break;
14523                                 }
14524                         }
14525                         if ($error = libxml_get_last_error())
14526                         {
14527                                 $this->error_code = $error->code;
14528                                 $this->error_string = $error->message;
14529                                 $this->current_line = $error->line;
14530                                 $this->current_column = $error->column;
14531                                 return false;
14532                         }
14533                         else
14534                         {
14535                                 return true;
14536                         }
14537                 }
14538         }
14539
14540         function get_error_code()
14541         {
14542                 return $this->error_code;
14543         }
14544
14545         function get_error_string()
14546         {
14547                 return $this->error_string;
14548         }
14549
14550         function get_current_line()
14551         {
14552                 return $this->current_line;
14553         }
14554
14555         function get_current_column()
14556         {
14557                 return $this->current_column;
14558         }
14559
14560         function get_current_byte()
14561         {
14562                 return $this->current_byte;
14563         }
14564
14565         function get_data()
14566         {
14567                 return $this->data;
14568         }
14569
14570         function tag_open($parser, $tag, $attributes)
14571         {
14572                 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14573
14574                 $attribs = array();
14575                 foreach ($attributes as $name => $value)
14576                 {
14577                         list($attrib_namespace, $attribute) = $this->split_ns($name);
14578                         $attribs[$attrib_namespace][$attribute] = $value;
14579                 }
14580
14581                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14582                 {
14583                         $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14584                         $this->xml_base_explicit[] = true;
14585                 }
14586                 else
14587                 {
14588                         $this->xml_base[] = end($this->xml_base);
14589                         $this->xml_base_explicit[] = end($this->xml_base_explicit);
14590                 }
14591
14592                 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14593                 {
14594                         $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14595                 }
14596                 else
14597                 {
14598                         $this->xml_lang[] = end($this->xml_lang);
14599                 }
14600
14601                 if ($this->current_xhtml_construct >= 0)
14602                 {
14603                         $this->current_xhtml_construct++;
14604                         if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14605                         {
14606                                 $this->data['data'] .= '<' . end($this->element);
14607                                 if (isset($attribs['']))
14608                                 {
14609                                         foreach ($attribs[''] as $name => $value)
14610                                         {
14611                                                 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14612                                         }
14613                                 }
14614                                 $this->data['data'] .= '>';
14615                         }
14616                 }
14617                 else
14618                 {
14619                         $this->datas[] =& $this->data;
14620                         $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14621                         $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));
14622                         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')
14623                         || (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'))
14624                         {
14625                                 $this->current_xhtml_construct = 0;
14626                         }
14627                 }
14628         }
14629
14630         function cdata($parser, $cdata)
14631         {
14632                 if ($this->current_xhtml_construct >= 0)
14633                 {
14634                         $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14635                 }
14636                 else
14637                 {
14638                         $this->data['data'] .= $cdata;
14639                 }
14640         }
14641
14642         function tag_close($parser, $tag)
14643         {
14644                 if ($this->current_xhtml_construct >= 0)
14645                 {
14646                         $this->current_xhtml_construct--;
14647                         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')))
14648                         {
14649                                 $this->data['data'] .= '</' . end($this->element) . '>';
14650                         }
14651                 }
14652                 if ($this->current_xhtml_construct === -1)
14653                 {
14654                         $this->data =& $this->datas[count($this->datas) - 1];
14655                         array_pop($this->datas);
14656                 }
14657
14658                 array_pop($this->element);
14659                 array_pop($this->namespace);
14660                 array_pop($this->xml_base);
14661                 array_pop($this->xml_base_explicit);
14662                 array_pop($this->xml_lang);
14663         }
14664
14665         function split_ns($string)
14666         {
14667                 static $cache = array();
14668                 if (!isset($cache[$string]))
14669                 {
14670                         if ($pos = strpos($string, $this->separator))
14671                         {
14672                                 static $separator_length;
14673                                 if (!$separator_length)
14674                                 {
14675                                         $separator_length = strlen($this->separator);
14676                                 }
14677                                 $namespace = substr($string, 0, $pos);
14678                                 $local_name = substr($string, $pos + $separator_length);
14679                                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14680                                 {
14681                                         $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14682                                 }
14683
14684                                 // Normalize the Media RSS namespaces
14685                                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14686                                 {
14687                                         $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14688                                 }
14689                                 $cache[$string] = array($namespace, $local_name);
14690                         }
14691                         else
14692                         {
14693                                 $cache[$string] = array('', $string);
14694                         }
14695                 }
14696                 return $cache[$string];
14697         }
14698 }
14699
14700 /**
14701  * @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
14702  */
14703 class SimplePie_Sanitize
14704 {
14705         // Private vars
14706         var $base;
14707
14708         // Options
14709         var $remove_div = true;
14710         var $image_handler = '';
14711         var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14712         var $encode_instead_of_strip = false;
14713         var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14714         var $strip_comments = false;
14715         var $output_encoding = 'UTF-8';
14716         var $enable_cache = true;
14717         var $cache_location = './cache';
14718         var $cache_name_function = 'md5';
14719         var $cache_class = 'SimplePie_Cache';
14720         var $file_class = 'SimplePie_File';
14721         var $timeout = 10;
14722         var $useragent = '';
14723         var $force_fsockopen = false;
14724
14725         var $replace_url_attributes = array(
14726                 'a' => 'href',
14727                 'area' => 'href',
14728                 'blockquote' => 'cite',
14729                 'del' => 'cite',
14730                 'form' => 'action',
14731                 'img' => array('longdesc', 'src'),
14732                 'input' => 'src',
14733                 'ins' => 'cite',
14734                 'q' => 'cite'
14735         );
14736
14737         function remove_div($enable = true)
14738         {
14739                 $this->remove_div = (bool) $enable;
14740         }
14741
14742         function set_image_handler($page = false)
14743         {
14744                 if ($page)
14745                 {
14746                         $this->image_handler = (string) $page;
14747                 }
14748                 else
14749                 {
14750                         $this->image_handler = false;
14751                 }
14752         }
14753
14754         function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14755         {
14756                 if (isset($enable_cache))
14757                 {
14758                         $this->enable_cache = (bool) $enable_cache;
14759                 }
14760
14761                 if ($cache_location)
14762                 {
14763                         $this->cache_location = (string) $cache_location;
14764                 }
14765
14766                 if ($cache_name_function)
14767                 {
14768                         $this->cache_name_function = (string) $cache_name_function;
14769                 }
14770
14771                 if ($cache_class)
14772                 {
14773                         $this->cache_class = (string) $cache_class;
14774                 }
14775         }
14776
14777         function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14778         {
14779                 if ($file_class)
14780                 {
14781                         $this->file_class = (string) $file_class;
14782                 }
14783
14784                 if ($timeout)
14785                 {
14786                         $this->timeout = (string) $timeout;
14787                 }
14788
14789                 if ($useragent)
14790                 {
14791                         $this->useragent = (string) $useragent;
14792                 }
14793
14794                 if ($force_fsockopen)
14795                 {
14796                         $this->force_fsockopen = (string) $force_fsockopen;
14797                 }
14798         }
14799
14800         function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14801         {
14802                 if ($tags)
14803                 {
14804                         if (is_array($tags))
14805                         {
14806                                 $this->strip_htmltags = $tags;
14807                         }
14808                         else
14809                         {
14810                                 $this->strip_htmltags = explode(',', $tags);
14811                         }
14812                 }
14813                 else
14814                 {
14815                         $this->strip_htmltags = false;
14816                 }
14817         }
14818
14819         function encode_instead_of_strip($encode = false)
14820         {
14821                 $this->encode_instead_of_strip = (bool) $encode;
14822         }
14823
14824         function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14825         {
14826                 if ($attribs)
14827                 {
14828                         if (is_array($attribs))
14829                         {
14830                                 $this->strip_attributes = $attribs;
14831                         }
14832                         else
14833                         {
14834                                 $this->strip_attributes = explode(',', $attribs);
14835                         }
14836                 }
14837                 else
14838                 {
14839                         $this->strip_attributes = false;
14840                 }
14841         }
14842
14843         function strip_comments($strip = false)
14844         {
14845                 $this->strip_comments = (bool) $strip;
14846         }
14847
14848         function set_output_encoding($encoding = 'UTF-8')
14849         {
14850                 $this->output_encoding = (string) $encoding;
14851         }
14852
14853         /**
14854          * Set element/attribute key/value pairs of HTML attributes
14855          * containing URLs that need to be resolved relative to the feed
14856          *
14857          * @access public
14858          * @since 1.0
14859          * @param array $element_attribute Element/attribute key/value pairs
14860          */
14861         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'))
14862         {
14863                 $this->replace_url_attributes = (array) $element_attribute;
14864         }
14865
14866         function sanitize($data, $type, $base = '')
14867         {
14868                 $data = trim($data);
14869                 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14870                 {
14871                         if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14872                         {
14873                                 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))
14874                                 {
14875                                         $type |= SIMPLEPIE_CONSTRUCT_HTML;
14876                                 }
14877                                 else
14878                                 {
14879                                         $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14880                                 }
14881                         }
14882
14883                         if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14884                         {
14885                                 $data = base64_decode($data);
14886                         }
14887
14888                         if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14889                         {
14890                                 if ($this->remove_div)
14891                                 {
14892                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14893                                         $data = preg_replace('/<\/div>$/', '', $data);
14894                                 }
14895                                 else
14896                                 {
14897                                         $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14898                                 }
14899                         }
14900
14901                         if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14902                         {
14903                                 // Strip comments
14904                                 if ($this->strip_comments)
14905                                 {
14906                                         $data = SimplePie_Misc::strip_comments($data);
14907                                 }
14908
14909                                 // Strip out HTML tags and attributes that might cause various security problems.
14910                                 // Based on recommendations by Mark Pilgrim at:
14911                                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14912                                 if ($this->strip_htmltags)
14913                                 {
14914                                         foreach ($this->strip_htmltags as $tag)
14915                                         {
14916                                                 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14917                                                 while (preg_match($pcre, $data))
14918                                                 {
14919                                                         $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14920                                                 }
14921                                         }
14922                                 }
14923
14924                                 if ($this->strip_attributes)
14925                                 {
14926                                         foreach ($this->strip_attributes as $attrib)
14927                                         {
14928                                                 $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);
14929                                         }
14930                                 }
14931
14932                                 // Replace relative URLs
14933                                 $this->base = $base;
14934                                 foreach ($this->replace_url_attributes as $element => $attributes)
14935                                 {
14936                                         $data = $this->replace_urls($data, $element, $attributes);
14937                                 }
14938
14939                                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14940                                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14941                                 {
14942                                         $images = SimplePie_Misc::get_element('img', $data);
14943                                         foreach ($images as $img)
14944                                         {
14945                                                 if (isset($img['attribs']['src']['data']))
14946                                                 {
14947                                                         $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14948                                                         $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14949
14950                                                         if ($cache->load())
14951                                                         {
14952                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14953                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14954                                                         }
14955                                                         else
14956                                                         {
14957                                                                 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14958                                                                 $headers = $file->headers;
14959
14960                                                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14961                                                                 {
14962                                                                         if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14963                                                                         {
14964                                                                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14965                                                                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14966                                                                         }
14967                                                                         else
14968                                                                         {
14969                                                                                 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
14970                                                                         }
14971                                                                 }
14972                                                         }
14973                                                 }
14974                                         }
14975                                 }
14976
14977                                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14978                                 $data = trim($data);
14979                         }
14980
14981                         if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14982                         {
14983                                 $data = SimplePie_Misc::absolutize_url($data, $base);
14984                         }
14985
14986                         if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14987                         {
14988                                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14989                         }
14990
14991                         if ($this->output_encoding !== 'UTF-8')
14992                         {
14993                                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14994                         }
14995                 }
14996                 return $data;
14997         }
14998
14999         function replace_urls($data, $tag, $attributes)
15000         {
15001                 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15002                 {
15003                         $elements = SimplePie_Misc::get_element($tag, $data);
15004                         foreach ($elements as $element)
15005                         {
15006                                 if (is_array($attributes))
15007                                 {
15008                                         foreach ($attributes as $attribute)
15009                                         {
15010                                                 if (isset($element['attribs'][$attribute]['data']))
15011                                                 {
15012                                                         $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15013                                                         $new_element = SimplePie_Misc::element_implode($element);
15014                                                         $data = str_replace($element['full'], $new_element, $data);
15015                                                         $element['full'] = $new_element;
15016                                                 }
15017                                         }
15018                                 }
15019                                 elseif (isset($element['attribs'][$attributes]['data']))
15020                                 {
15021                                         $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15022                                         $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15023                                 }
15024                         }
15025                 }
15026                 return $data;
15027         }
15028
15029         function do_strip_htmltags($match)
15030         {
15031                 if ($this->encode_instead_of_strip)
15032                 {
15033                         if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15034                         {
15035                                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15036                                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15037                                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15038                         }
15039                         else
15040                         {
15041                                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15042                         }
15043                 }
15044                 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15045                 {
15046                         return $match[4];
15047                 }
15048                 else
15049                 {
15050                         return '';
15051                 }
15052         }
15053 }
15054
15055 ?>