tbrehm
2013-02-22 526b997c9891a796b152cdbab8e329b356b1f596
commit | author | age
fd9ef2 1 <?php
T 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
f64c86 738         $this->sanitize = new SimplePie_Sanitize;
fd9ef2 739
T 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         {
f64c86 1108             $this->sanitize = new $class;
fd9ef2 1109             return true;
T 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                                 }
f64c86 1602                                 $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
fd9ef2 1603                                 if ($file->success)
T 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                     {
f64c86 1643                         $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
fd9ef2 1644                     }
T 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.
f64c86 1663                     $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
fd9ef2 1664                     if (!$locate->is_feed($file))
T 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;
f64c86 1693                 $sniffer = new $this->content_type_sniffer_class($file);
fd9ef2 1694                 $sniffed = $sniffer->get_type();
T 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
f64c86 1763                     $parser = new $this->parser_class();
fd9ef2 1764
T 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                 {
f64c86 1974                     $file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
fd9ef2 1975
T 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                     {
f64c86 1978                         $sniffer = new $this->content_type_sniffer_class($file);
fd9ef2 1979                         if (substr($sniffer->get_type(), 0, 6) === 'image/')
T 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             }
f64c86 2377             $categories[] = new $this->category_class($term, $scheme, $label);
fd9ef2 2378         }
T 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             }
f64c86 2392             $categories[] = new $this->category_class($term, $scheme, null);
fd9ef2 2393         }
T 2394         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2395         {
f64c86 2396             $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2397         }
T 2398         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2399         {
f64c86 2400             $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2401         }
T 2402
2403         if (!empty($categories))
2404         {
2405             return SimplePie_Misc::array_unique($categories);
2406         }
2407         else
2408         {
2409             return null;
2410         }
2411     }
2412
2413     function get_author($key = 0)
2414     {
2415         $authors = $this->get_authors();
2416         if (isset($authors[$key]))
2417         {
2418             return $authors[$key];
2419         }
2420         else
2421         {
2422             return null;
2423         }
2424     }
2425
2426     function get_authors()
2427     {
2428         $authors = array();
2429         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2430         {
2431             $name = null;
2432             $uri = null;
2433             $email = null;
2434             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2435             {
2436                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2437             }
2438             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2439             {
2440                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2441             }
2442             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2443             {
2444                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2445             }
2446             if ($name !== null || $email !== null || $uri !== null)
2447             {
f64c86 2448                 $authors[] = new $this->author_class($name, $uri, $email);
fd9ef2 2449             }
T 2450         }
2451         if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2452         {
2453             $name = null;
2454             $url = null;
2455             $email = null;
2456             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2457             {
2458                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2459             }
2460             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2461             {
2462                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2463             }
2464             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2465             {
2466                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2467             }
2468             if ($name !== null || $email !== null || $url !== null)
2469             {
f64c86 2470                 $authors[] = new $this->author_class($name, $url, $email);
fd9ef2 2471             }
T 2472         }
2473         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2474         {
f64c86 2475             $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2476         }
T 2477         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2478         {
f64c86 2479             $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2480         }
T 2481         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2482         {
f64c86 2483             $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 2484         }
T 2485
2486         if (!empty($authors))
2487         {
2488             return SimplePie_Misc::array_unique($authors);
2489         }
2490         else
2491         {
2492             return null;
2493         }
2494     }
2495
2496     function get_contributor($key = 0)
2497     {
2498         $contributors = $this->get_contributors();
2499         if (isset($contributors[$key]))
2500         {
2501             return $contributors[$key];
2502         }
2503         else
2504         {
2505             return null;
2506         }
2507     }
2508
2509     function get_contributors()
2510     {
2511         $contributors = array();
2512         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2513         {
2514             $name = null;
2515             $uri = null;
2516             $email = null;
2517             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2518             {
2519                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2520             }
2521             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2522             {
2523                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2524             }
2525             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2526             {
2527                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2528             }
2529             if ($name !== null || $email !== null || $uri !== null)
2530             {
f64c86 2531                 $contributors[] = new $this->author_class($name, $uri, $email);
fd9ef2 2532             }
T 2533         }
2534         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2535         {
2536             $name = null;
2537             $url = null;
2538             $email = null;
2539             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2540             {
2541                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2542             }
2543             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2544             {
2545                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2546             }
2547             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2548             {
2549                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2550             }
2551             if ($name !== null || $email !== null || $url !== null)
2552             {
f64c86 2553                 $contributors[] = new $this->author_class($name, $url, $email);
fd9ef2 2554             }
T 2555         }
2556
2557         if (!empty($contributors))
2558         {
2559             return SimplePie_Misc::array_unique($contributors);
2560         }
2561         else
2562         {
2563             return null;
2564         }
2565     }
2566
2567     function get_link($key = 0, $rel = 'alternate')
2568     {
2569         $links = $this->get_links($rel);
2570         if (isset($links[$key]))
2571         {
2572             return $links[$key];
2573         }
2574         else
2575         {
2576             return null;
2577         }
2578     }
2579
2580     /**
2581      * Added for parity between the parent-level and the item/entry-level.
2582      */
2583     function get_permalink()
2584     {
2585         return $this->get_link(0);
2586     }
2587
2588     function get_links($rel = 'alternate')
2589     {
2590         if (!isset($this->data['links']))
2591         {
2592             $this->data['links'] = array();
2593             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2594             {
2595                 foreach ($links as $link)
2596                 {
2597                     if (isset($link['attribs']['']['href']))
2598                     {
2599                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2600                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2601                     }
2602                 }
2603             }
2604             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2605             {
2606                 foreach ($links as $link)
2607                 {
2608                     if (isset($link['attribs']['']['href']))
2609                     {
2610                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2611                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2612
2613                     }
2614                 }
2615             }
2616             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2617             {
2618                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2619             }
2620             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2621             {
2622                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2623             }
2624             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2625             {
2626                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2627             }
2628
2629             $keys = array_keys($this->data['links']);
2630             foreach ($keys as $key)
2631             {
2632                 if (SimplePie_Misc::is_isegment_nz_nc($key))
2633                 {
2634                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2635                     {
2636                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2637                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2638                     }
2639                     else
2640                     {
2641                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2642                     }
2643                 }
2644                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2645                 {
2646                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2647                 }
2648                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2649             }
2650         }
2651
2652         if (isset($this->data['links'][$rel]))
2653         {
2654             return $this->data['links'][$rel];
2655         }
2656         else
2657         {
2658             return null;
2659         }
2660     }
2661
2662     function get_all_discovered_feeds()
2663     {
2664         return $this->all_discovered_feeds;
2665     }
2666
2667     function get_description()
2668     {
2669         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2670         {
2671             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2672         }
2673         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2674         {
2675             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2676         }
2677         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2678         {
2679             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2680         }
2681         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2682         {
2683             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2684         }
2685         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2686         {
2687             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2688         }
2689         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2690         {
2691             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2692         }
2693         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2694         {
2695             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2696         }
2697         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2698         {
2699             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2700         }
2701         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2702         {
2703             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2704         }
2705         else
2706         {
2707             return null;
2708         }
2709     }
2710
2711     function get_copyright()
2712     {
2713         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2714         {
2715             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2716         }
2717         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2718         {
2719             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2720         }
2721         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2722         {
2723             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2724         }
2725         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2726         {
2727             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2728         }
2729         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2730         {
2731             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2732         }
2733         else
2734         {
2735             return null;
2736         }
2737     }
2738
2739     function get_language()
2740     {
2741         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2742         {
2743             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2744         }
2745         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2746         {
2747             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2748         }
2749         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2750         {
2751             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2752         }
2753         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2754         {
2755             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2756         }
2757         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2758         {
2759             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2760         }
2761         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2762         {
2763             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2764         }
2765         elseif (isset($this->data['headers']['content-language']))
2766         {
2767             return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2768         }
2769         else
2770         {
2771             return null;
2772         }
2773     }
2774
2775     function get_latitude()
2776     {
2777         
2778         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2779         {
2780             return (float) $return[0]['data'];
2781         }
2782         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))
2783         {
2784             return (float) $match[1];
2785         }
2786         else
2787         {
2788             return null;
2789         }
2790     }
2791
2792     function get_longitude()
2793     {
2794         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2795         {
2796             return (float) $return[0]['data'];
2797         }
2798         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2799         {
2800             return (float) $return[0]['data'];
2801         }
2802         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))
2803         {
2804             return (float) $match[2];
2805         }
2806         else
2807         {
2808             return null;
2809         }
2810     }
2811
2812     function get_image_title()
2813     {
2814         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2815         {
2816             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2817         }
2818         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2819         {
2820             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2821         }
2822         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2823         {
2824             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2825         }
2826         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2827         {
2828             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2829         }
2830         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2831         {
2832             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2833         }
2834         else
2835         {
2836             return null;
2837         }
2838     }
2839
2840     function get_image_url()
2841     {
2842         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2843         {
2844             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2845         }
2846         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2847         {
2848             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2849         }
2850         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2851         {
2852             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2853         }
2854         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2855         {
2856             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2857         }
2858         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2859         {
2860             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2861         }
2862         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2863         {
2864             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2865         }
2866         else
2867         {
2868             return null;
2869         }
2870     }
2871
2872     function get_image_link()
2873     {
2874         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2875         {
2876             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2877         }
2878         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2879         {
2880             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2881         }
2882         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2883         {
2884             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2885         }
2886         else
2887         {
2888             return null;
2889         }
2890     }
2891
2892     function get_image_width()
2893     {
2894         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2895         {
2896             return round($return[0]['data']);
2897         }
2898         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2899         {
2900             return 88.0;
2901         }
2902         else
2903         {
2904             return null;
2905         }
2906     }
2907
2908     function get_image_height()
2909     {
2910         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2911         {
2912             return round($return[0]['data']);
2913         }
2914         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2915         {
2916             return 31.0;
2917         }
2918         else
2919         {
2920             return null;
2921         }
2922     }
2923
2924     function get_item_quantity($max = 0)
2925     {
2926         $max = (int) $max;
2927         $qty = count($this->get_items());
2928         if ($max === 0)
2929         {
2930             return $qty;
2931         }
2932         else
2933         {
2934             return ($qty > $max) ? $max : $qty;
2935         }
2936     }
2937
2938     function get_item($key = 0)
2939     {
2940         $items = $this->get_items();
2941         if (isset($items[$key]))
2942         {
2943             return $items[$key];
2944         }
2945         else
2946         {
2947             return null;
2948         }
2949     }
2950
2951     function get_items($start = 0, $end = 0)
2952     {
2953         if (!isset($this->data['items']))
2954         {
2955             if (!empty($this->multifeed_objects))
2956             {
2957                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2958             }
2959             else
2960             {
2961                 $this->data['items'] = array();
2962                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2963                 {
2964                     $keys = array_keys($items);
2965                     foreach ($keys as $key)
2966                     {
f64c86 2967                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 2968                     }
T 2969                 }
2970                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2971                 {
2972                     $keys = array_keys($items);
2973                     foreach ($keys as $key)
2974                     {
f64c86 2975                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 2976                     }
T 2977                 }
2978                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2979                 {
2980                     $keys = array_keys($items);
2981                     foreach ($keys as $key)
2982                     {
f64c86 2983                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 2984                     }
T 2985                 }
2986                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2987                 {
2988                     $keys = array_keys($items);
2989                     foreach ($keys as $key)
2990                     {
f64c86 2991                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 2992                     }
T 2993                 }
2994                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2995                 {
2996                     $keys = array_keys($items);
2997                     foreach ($keys as $key)
2998                     {
f64c86 2999                         $this->data['items'][] = new $this->item_class($this, $items[$key]);
fd9ef2 3000                     }
T 3001                 }
3002             }
3003         }
3004
3005         if (!empty($this->data['items']))
3006         {
3007             // If we want to order it by date, check if all items have a date, and then sort it
3008             if ($this->order_by_date && empty($this->multifeed_objects))
3009             {
3010                 if (!isset($this->data['ordered_items']))
3011                 {
3012                     $do_sort = true;
3013                     foreach ($this->data['items'] as $item)
3014                     {
3015                         if (!$item->get_date('U'))
3016                         {
3017                             $do_sort = false;
3018                             break;
3019                         }
3020                     }
3021                     $item = null;
3022                     $this->data['ordered_items'] = $this->data['items'];
3023                     if ($do_sort)
3024                     {
3025                         usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3026                     }
3027                 }
3028                 $items = $this->data['ordered_items'];
3029             }
3030             else
3031             {
3032                 $items = $this->data['items'];
3033             }
3034
3035             // Slice the data as desired
3036             if ($end === 0)
3037             {
3038                 return array_slice($items, $start);
3039             }
3040             else
3041             {
3042                 return array_slice($items, $start, $end);
3043             }
3044         }
3045         else
3046         {
3047             return array();
3048         }
3049     }
3050
3051     /**
3052      * @static
3053      */
3054     function sort_items($a, $b)
3055     {
3056         return $a->get_date('U') <= $b->get_date('U');
3057     }
3058
3059     /**
3060      * @static
3061      */
3062     function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3063     {
3064         if (is_array($urls) && sizeof($urls) > 0)
3065         {
3066             $items = array();
3067             foreach ($urls as $arg)
3068             {
3069                 if (is_a($arg, 'SimplePie'))
3070                 {
3071                     $items = array_merge($items, $arg->get_items(0, $limit));
3072                 }
3073                 else
3074                 {
3075                     trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3076                 }
3077             }
3078
3079             $do_sort = true;
3080             foreach ($items as $item)
3081             {
3082                 if (!$item->get_date('U'))
3083                 {
3084                     $do_sort = false;
3085                     break;
3086                 }
3087             }
3088             $item = null;
3089             if ($do_sort)
3090             {
3091                 usort($items, array('SimplePie', 'sort_items'));
3092             }
3093
3094             if ($end === 0)
3095             {
3096                 return array_slice($items, $start);
3097             }
3098             else
3099             {
3100                 return array_slice($items, $start, $end);
3101             }
3102         }
3103         else
3104         {
3105             trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3106             return array();
3107         }
3108     }
3109 }
3110
3111 class SimplePie_Item
3112 {
3113     var $feed;
3114     var $data = array();
3115
3116     function SimplePie_Item($feed, $data)
3117     {
3118         $this->feed = $feed;
3119         $this->data = $data;
3120     }
3121
3122     function __toString()
3123     {
3124         return md5(serialize($this->data));
3125     }
3126
3127     /**
3128      * Remove items that link back to this before destroying this object
3129      */
3130     function __destruct()
3131     {
3132         if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3133         {
3134             unset($this->feed);
3135         }
3136     }
3137
3138     function get_item_tags($namespace, $tag)
3139     {
3140         if (isset($this->data['child'][$namespace][$tag]))
3141         {
3142             return $this->data['child'][$namespace][$tag];
3143         }
3144         else
3145         {
3146             return null;
3147         }
3148     }
3149
3150     function get_base($element = array())
3151     {
3152         return $this->feed->get_base($element);
3153     }
3154
3155     function sanitize($data, $type, $base = '')
3156     {
3157         return $this->feed->sanitize($data, $type, $base);
3158     }
3159
3160     function get_feed()
3161     {
3162         return $this->feed;
3163     }
3164
3165     function get_id($hash = false)
3166     {
3167         if (!$hash)
3168         {
3169             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3170             {
3171                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3172             }
3173             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3174             {
3175                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3176             }
3177             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3178             {
3179                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3180             }
3181             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3182             {
3183                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3184             }
3185             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3186             {
3187                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3188             }
3189             elseif (($return = $this->get_permalink()) !== null)
3190             {
3191                 return $return;
3192             }
3193             elseif (($return = $this->get_title()) !== null)
3194             {
3195                 return $return;
3196             }
3197         }
3198         if ($this->get_permalink() !== null || $this->get_title() !== null)
3199         {
3200             return md5($this->get_permalink() . $this->get_title());
3201         }
3202         else
3203         {
3204             return md5(serialize($this->data));
3205         }
3206     }
3207
3208     function get_title()
3209     {
3210         if (!isset($this->data['title']))
3211         {
3212             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3213             {
3214                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3215             }
3216             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3217             {
3218                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3219             }
3220             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3221             {
3222                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3223             }
3224             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3225             {
3226                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3227             }
3228             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3229             {
3230                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3231             }
3232             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3233             {
3234                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3235             }
3236             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3237             {
3238                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3239             }
3240             else
3241             {
3242                 $this->data['title'] = null;
3243             }
3244         }
3245         return $this->data['title'];
3246     }
3247
3248     function get_description($description_only = false)
3249     {
3250         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3251         {
3252             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3253         }
3254         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3255         {
3256             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3257         }
3258         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3259         {
3260             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3261         }
3262         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3263         {
3264             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3265         }
3266         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3267         {
3268             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3269         }
3270         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3271         {
3272             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3273         }
3274         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3275         {
3276             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3277         }
3278         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3279         {
3280             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3281         }
3282         elseif (!$description_only)
3283         {
3284             return $this->get_content(true);
3285         }
3286         else
3287         {
3288             return null;
3289         }
3290     }
3291
3292     function get_content($content_only = false)
3293     {
3294         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3295         {
3296             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3297         }
3298         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3299         {
3300             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3301         }
3302         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3303         {
3304             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3305         }
3306         elseif (!$content_only)
3307         {
3308             return $this->get_description(true);
3309         }
3310         else
3311         {
3312             return null;
3313         }
3314     }
3315
3316     function get_category($key = 0)
3317     {
3318         $categories = $this->get_categories();
3319         if (isset($categories[$key]))
3320         {
3321             return $categories[$key];
3322         }
3323         else
3324         {
3325             return null;
3326         }
3327     }
3328
3329     function get_categories()
3330     {
3331         $categories = array();
3332
3333         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3334         {
3335             $term = null;
3336             $scheme = null;
3337             $label = null;
3338             if (isset($category['attribs']['']['term']))
3339             {
3340                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3341             }
3342             if (isset($category['attribs']['']['scheme']))
3343             {
3344                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3345             }
3346             if (isset($category['attribs']['']['label']))
3347             {
3348                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3349             }
f64c86 3350             $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3351         }
T 3352         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3353         {
3354             // This is really the label, but keep this as the term also for BC.
3355             // Label will also work on retrieving because that falls back to term.
3356             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3357             if (isset($category['attribs']['']['domain']))
3358             {
3359                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3360             }
3361             else
3362             {
3363                 $scheme = null;
3364             }
f64c86 3365             $categories[] = new $this->feed->category_class($term, $scheme, null);
fd9ef2 3366         }
T 3367         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3368         {
f64c86 3369             $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3370         }
T 3371         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3372         {
f64c86 3373             $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3374         }
T 3375
3376         if (!empty($categories))
3377         {
3378             return SimplePie_Misc::array_unique($categories);
3379         }
3380         else
3381         {
3382             return null;
3383         }
3384     }
3385
3386     function get_author($key = 0)
3387     {
3388         $authors = $this->get_authors();
3389         if (isset($authors[$key]))
3390         {
3391             return $authors[$key];
3392         }
3393         else
3394         {
3395             return null;
3396         }
3397     }
3398
3399     function get_contributor($key = 0)
3400     {
3401         $contributors = $this->get_contributors();
3402         if (isset($contributors[$key]))
3403         {
3404             return $contributors[$key];
3405         }
3406         else
3407         {
3408             return null;
3409         }
3410     }
3411
3412     function get_contributors()
3413     {
3414         $contributors = array();
3415         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3416         {
3417             $name = null;
3418             $uri = null;
3419             $email = null;
3420             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3421             {
3422                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3423             }
3424             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3425             {
3426                 $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]));
3427             }
3428             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3429             {
3430                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3431             }
3432             if ($name !== null || $email !== null || $uri !== null)
3433             {
f64c86 3434                 $contributors[] = new $this->feed->author_class($name, $uri, $email);
fd9ef2 3435             }
T 3436         }
3437         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3438         {
3439             $name = null;
3440             $url = null;
3441             $email = null;
3442             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3443             {
3444                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3445             }
3446             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3447             {
3448                 $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]));
3449             }
3450             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3451             {
3452                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3453             }
3454             if ($name !== null || $email !== null || $url !== null)
3455             {
f64c86 3456                 $contributors[] = new $this->feed->author_class($name, $url, $email);
fd9ef2 3457             }
T 3458         }
3459
3460         if (!empty($contributors))
3461         {
3462             return SimplePie_Misc::array_unique($contributors);
3463         }
3464         else
3465         {
3466             return null;
3467         }
3468     }
3469
3470     function get_authors()
3471     {
3472         $authors = array();
3473         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3474         {
3475             $name = null;
3476             $uri = null;
3477             $email = null;
3478             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3479             {
3480                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3481             }
3482             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3483             {
3484                 $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]));
3485             }
3486             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3487             {
3488                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3489             }
3490             if ($name !== null || $email !== null || $uri !== null)
3491             {
f64c86 3492                 $authors[] = new $this->feed->author_class($name, $uri, $email);
fd9ef2 3493             }
T 3494         }
3495         if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3496         {
3497             $name = null;
3498             $url = null;
3499             $email = null;
3500             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3501             {
3502                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3503             }
3504             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3505             {
3506                 $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]));
3507             }
3508             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3509             {
3510                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3511             }
3512             if ($name !== null || $email !== null || $url !== null)
3513             {
f64c86 3514                 $authors[] = new $this->feed->author_class($name, $url, $email);
fd9ef2 3515             }
T 3516         }
3517         if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3518         {
f64c86 3519             $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
fd9ef2 3520         }
T 3521         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3522         {
f64c86 3523             $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3524         }
T 3525         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3526         {
f64c86 3527             $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3528         }
T 3529         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3530         {
f64c86 3531             $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 3532         }
T 3533
3534         if (!empty($authors))
3535         {
3536             return SimplePie_Misc::array_unique($authors);
3537         }
3538         elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3539         {
3540             return $authors;
3541         }
3542         elseif ($authors = $this->feed->get_authors())
3543         {
3544             return $authors;
3545         }
3546         else
3547         {
3548             return null;
3549         }
3550     }
3551
3552     function get_copyright()
3553     {
3554         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3555         {
3556             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3557         }
3558         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3559         {
3560             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3561         }
3562         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3563         {
3564             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3565         }
3566         else
3567         {
3568             return null;
3569         }
3570     }
3571
3572     function get_date($date_format = 'j F Y, g:i a')
3573     {
3574         if (!isset($this->data['date']))
3575         {
3576             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3577             {
3578                 $this->data['date']['raw'] = $return[0]['data'];
3579             }
3580             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3581             {
3582                 $this->data['date']['raw'] = $return[0]['data'];
3583             }
3584             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3585             {
3586                 $this->data['date']['raw'] = $return[0]['data'];
3587             }
3588             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3589             {
3590                 $this->data['date']['raw'] = $return[0]['data'];
3591             }
3592             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3593             {
3594                 $this->data['date']['raw'] = $return[0]['data'];
3595             }
3596             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3597             {
3598                 $this->data['date']['raw'] = $return[0]['data'];
3599             }
3600             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3601             {
3602                 $this->data['date']['raw'] = $return[0]['data'];
3603             }
3604             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3605             {
3606                 $this->data['date']['raw'] = $return[0]['data'];
3607             }
3608
3609             if (!empty($this->data['date']['raw']))
3610             {
3611                 $parser = SimplePie_Parse_Date::get();
3612                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3613             }
3614             else
3615             {
3616                 $this->data['date'] = null;
3617             }
3618         }
3619         if ($this->data['date'])
3620         {
3621             $date_format = (string) $date_format;
3622             switch ($date_format)
3623             {
3624                 case '':
3625                     return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3626
3627                 case 'U':
3628                     return $this->data['date']['parsed'];
3629
3630                 default:
3631                     return date($date_format, $this->data['date']['parsed']);
3632             }
3633         }
3634         else
3635         {
3636             return null;
3637         }
3638     }
3639
3640     function get_local_date($date_format = '%c')
3641     {
3642         if (!$date_format)
3643         {
3644             return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3645         }
3646         elseif (($date = $this->get_date('U')) !== null)
3647         {
3648             return strftime($date_format, $date);
3649         }
3650         else
3651         {
3652             return null;
3653         }
3654     }
3655
3656     function get_permalink()
3657     {
3658         $link = $this->get_link();
3659         $enclosure = $this->get_enclosure(0);
3660         if ($link !== null)
3661         {
3662             return $link;
3663         }
3664         elseif ($enclosure !== null)
3665         {
3666             return $enclosure->get_link();
3667         }
3668         else
3669         {
3670             return null;
3671         }
3672     }
3673
3674     function get_link($key = 0, $rel = 'alternate')
3675     {
3676         $links = $this->get_links($rel);
3677         if ($links[$key] !== null)
3678         {
3679             return $links[$key];
3680         }
3681         else
3682         {
3683             return null;
3684         }
3685     }
3686
3687     function get_links($rel = 'alternate')
3688     {
3689         if (!isset($this->data['links']))
3690         {
3691             $this->data['links'] = array();
3692             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3693             {
3694                 if (isset($link['attribs']['']['href']))
3695                 {
3696                     $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3697                     $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3698
3699                 }
3700             }
3701             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3702             {
3703                 if (isset($link['attribs']['']['href']))
3704                 {
3705                     $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3706                     $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3707                 }
3708             }
3709             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3710             {
3711                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3712             }
3713             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3714             {
3715                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3716             }
3717             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3718             {
3719                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3720             }
3721             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3722             {
3723                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3724                 {
3725                     $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3726                 }
3727             }
3728
3729             $keys = array_keys($this->data['links']);
3730             foreach ($keys as $key)
3731             {
3732                 if (SimplePie_Misc::is_isegment_nz_nc($key))
3733                 {
3734                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3735                     {
3736                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3737                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3738                     }
3739                     else
3740                     {
3741                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3742                     }
3743                 }
3744                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3745                 {
3746                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3747                 }
3748                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3749             }
3750         }
3751         if (isset($this->data['links'][$rel]))
3752         {
3753             return $this->data['links'][$rel];
3754         }
3755         else
3756         {
3757             return null;
3758         }
3759     }
3760
3761     /**
3762      * @todo Add ability to prefer one type of content over another (in a media group).
3763      */
3764     function get_enclosure($key = 0, $prefer = null)
3765     {
3766         $enclosures = $this->get_enclosures();
3767         if (isset($enclosures[$key]))
3768         {
3769             return $enclosures[$key];
3770         }
3771         else
3772         {
3773             return null;
3774         }
3775     }
3776
3777     /**
3778      * Grabs all available enclosures (podcasts, etc.)
3779      *
3780      * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3781      *
3782      * 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.
3783      *
3784      * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3785      * @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).
3786      */
3787     function get_enclosures()
3788     {
3789         if (!isset($this->data['enclosures']))
3790         {
3791             $this->data['enclosures'] = array();
3792
3793             // Elements
3794             $captions_parent = null;
3795             $categories_parent = null;
3796             $copyrights_parent = null;
3797             $credits_parent = null;
3798             $description_parent = null;
3799             $duration_parent = null;
3800             $hashes_parent = null;
3801             $keywords_parent = null;
3802             $player_parent = null;
3803             $ratings_parent = null;
3804             $restrictions_parent = null;
3805             $thumbnails_parent = null;
3806             $title_parent = null;
3807
3808             // Let's do the channel and item-level ones first, and just re-use them if we need to.
3809             $parent = $this->get_feed();
3810
3811             // CAPTIONS
3812             if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3813             {
3814                 foreach ($captions as $caption)
3815                 {
3816                     $caption_type = null;
3817                     $caption_lang = null;
3818                     $caption_startTime = null;
3819                     $caption_endTime = null;
3820                     $caption_text = null;
3821                     if (isset($caption['attribs']['']['type']))
3822                     {
3823                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3824                     }
3825                     if (isset($caption['attribs']['']['lang']))
3826                     {
3827                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3828                     }
3829                     if (isset($caption['attribs']['']['start']))
3830                     {
3831                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3832                     }
3833                     if (isset($caption['attribs']['']['end']))
3834                     {
3835                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3836                     }
3837                     if (isset($caption['data']))
3838                     {
3839                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3840                     }
f64c86 3841                     $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 3842                 }
T 3843             }
3844             elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3845             {
3846                 foreach ($captions as $caption)
3847                 {
3848                     $caption_type = null;
3849                     $caption_lang = null;
3850                     $caption_startTime = null;
3851                     $caption_endTime = null;
3852                     $caption_text = null;
3853                     if (isset($caption['attribs']['']['type']))
3854                     {
3855                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3856                     }
3857                     if (isset($caption['attribs']['']['lang']))
3858                     {
3859                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3860                     }
3861                     if (isset($caption['attribs']['']['start']))
3862                     {
3863                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3864                     }
3865                     if (isset($caption['attribs']['']['end']))
3866                     {
3867                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3868                     }
3869                     if (isset($caption['data']))
3870                     {
3871                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3872                     }
f64c86 3873                     $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 3874                 }
T 3875             }
3876             if (is_array($captions_parent))
3877             {
3878                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3879             }
3880
3881             // CATEGORIES
3882             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3883             {
3884                 $term = null;
3885                 $scheme = null;
3886                 $label = null;
3887                 if (isset($category['data']))
3888                 {
3889                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3890                 }
3891                 if (isset($category['attribs']['']['scheme']))
3892                 {
3893                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3894                 }
3895                 else
3896                 {
3897                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
3898                 }
3899                 if (isset($category['attribs']['']['label']))
3900                 {
3901                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3902                 }
f64c86 3903                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3904             }
T 3905             foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3906             {
3907                 $term = null;
3908                 $scheme = null;
3909                 $label = null;
3910                 if (isset($category['data']))
3911                 {
3912                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3913                 }
3914                 if (isset($category['attribs']['']['scheme']))
3915                 {
3916                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3917                 }
3918                 else
3919                 {
3920                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
3921                 }
3922                 if (isset($category['attribs']['']['label']))
3923                 {
3924                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3925                 }
f64c86 3926                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3927             }
T 3928             foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3929             {
3930                 $term = null;
3931                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3932                 $label = null;
3933                 if (isset($category['attribs']['']['text']))
3934                 {
3935                     $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3936                 }
f64c86 3937                 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3938
T 3939                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3940                 {
3941                     foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3942                     {
3943                         if (isset($subcategory['attribs']['']['text']))
3944                         {
3945                             $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3946                         }
f64c86 3947                         $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 3948                     }
T 3949                 }
3950             }
3951             if (is_array($categories_parent))
3952             {
3953                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3954             }
3955
3956             // COPYRIGHT
3957             if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3958             {
3959                 $copyright_url = null;
3960                 $copyright_label = null;
3961                 if (isset($copyright[0]['attribs']['']['url']))
3962                 {
3963                     $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3964                 }
3965                 if (isset($copyright[0]['data']))
3966                 {
3967                     $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3968                 }
f64c86 3969                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 3970             }
T 3971             elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3972             {
3973                 $copyright_url = null;
3974                 $copyright_label = null;
3975                 if (isset($copyright[0]['attribs']['']['url']))
3976                 {
3977                     $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3978                 }
3979                 if (isset($copyright[0]['data']))
3980                 {
3981                     $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3982                 }
f64c86 3983                 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 3984             }
T 3985
3986             // CREDITS
3987             if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3988             {
3989                 foreach ($credits as $credit)
3990                 {
3991                     $credit_role = null;
3992                     $credit_scheme = null;
3993                     $credit_name = null;
3994                     if (isset($credit['attribs']['']['role']))
3995                     {
3996                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3997                     }
3998                     if (isset($credit['attribs']['']['scheme']))
3999                     {
4000                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4001                     }
4002                     else
4003                     {
4004                         $credit_scheme = 'urn:ebu';
4005                     }
4006                     if (isset($credit['data']))
4007                     {
4008                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4009                     }
f64c86 4010                     $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4011                 }
T 4012             }
4013             elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4014             {
4015                 foreach ($credits as $credit)
4016                 {
4017                     $credit_role = null;
4018                     $credit_scheme = null;
4019                     $credit_name = null;
4020                     if (isset($credit['attribs']['']['role']))
4021                     {
4022                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4023                     }
4024                     if (isset($credit['attribs']['']['scheme']))
4025                     {
4026                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4027                     }
4028                     else
4029                     {
4030                         $credit_scheme = 'urn:ebu';
4031                     }
4032                     if (isset($credit['data']))
4033                     {
4034                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4035                     }
f64c86 4036                     $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4037                 }
T 4038             }
4039             if (is_array($credits_parent))
4040             {
4041                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4042             }
4043
4044             // DESCRIPTION
4045             if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4046             {
4047                 if (isset($description_parent[0]['data']))
4048                 {
4049                     $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4050                 }
4051             }
4052             elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4053             {
4054                 if (isset($description_parent[0]['data']))
4055                 {
4056                     $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4057                 }
4058             }
4059
4060             // DURATION
4061             if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4062             {
4063                 $seconds = null;
4064                 $minutes = null;
4065                 $hours = null;
4066                 if (isset($duration_parent[0]['data']))
4067                 {
4068                     $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4069                     if (sizeof($temp) > 0)
4070                     {
4071                         (int) $seconds = array_pop($temp);
4072                     }
4073                     if (sizeof($temp) > 0)
4074                     {
4075                         (int) $minutes = array_pop($temp);
4076                         $seconds += $minutes * 60;
4077                     }
4078                     if (sizeof($temp) > 0)
4079                     {
4080                         (int) $hours = array_pop($temp);
4081                         $seconds += $hours * 3600;
4082                     }
4083                     unset($temp);
4084                     $duration_parent = $seconds;
4085                 }
4086             }
4087
4088             // HASHES
4089             if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4090             {
4091                 foreach ($hashes_iterator as $hash)
4092                 {
4093                     $value = null;
4094                     $algo = null;
4095                     if (isset($hash['data']))
4096                     {
4097                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4098                     }
4099                     if (isset($hash['attribs']['']['algo']))
4100                     {
4101                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4102                     }
4103                     else
4104                     {
4105                         $algo = 'md5';
4106                     }
4107                     $hashes_parent[] = $algo.':'.$value;
4108                 }
4109             }
4110             elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4111             {
4112                 foreach ($hashes_iterator as $hash)
4113                 {
4114                     $value = null;
4115                     $algo = null;
4116                     if (isset($hash['data']))
4117                     {
4118                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4119                     }
4120                     if (isset($hash['attribs']['']['algo']))
4121                     {
4122                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4123                     }
4124                     else
4125                     {
4126                         $algo = 'md5';
4127                     }
4128                     $hashes_parent[] = $algo.':'.$value;
4129                 }
4130             }
4131             if (is_array($hashes_parent))
4132             {
4133                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4134             }
4135
4136             // KEYWORDS
4137             if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4138             {
4139                 if (isset($keywords[0]['data']))
4140                 {
4141                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4142                     foreach ($temp as $word)
4143                     {
4144                         $keywords_parent[] = trim($word);
4145                     }
4146                 }
4147                 unset($temp);
4148             }
4149             elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4150             {
4151                 if (isset($keywords[0]['data']))
4152                 {
4153                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4154                     foreach ($temp as $word)
4155                     {
4156                         $keywords_parent[] = trim($word);
4157                     }
4158                 }
4159                 unset($temp);
4160             }
4161             elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4162             {
4163                 if (isset($keywords[0]['data']))
4164                 {
4165                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4166                     foreach ($temp as $word)
4167                     {
4168                         $keywords_parent[] = trim($word);
4169                     }
4170                 }
4171                 unset($temp);
4172             }
4173             elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4174             {
4175                 if (isset($keywords[0]['data']))
4176                 {
4177                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4178                     foreach ($temp as $word)
4179                     {
4180                         $keywords_parent[] = trim($word);
4181                     }
4182                 }
4183                 unset($temp);
4184             }
4185             if (is_array($keywords_parent))
4186             {
4187                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4188             }
4189
4190             // PLAYER
4191             if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4192             {
4193                 if (isset($player_parent[0]['attribs']['']['url']))
4194                 {
4195                     $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4196                 }
4197             }
4198             elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4199             {
4200                 if (isset($player_parent[0]['attribs']['']['url']))
4201                 {
4202                     $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4203                 }
4204             }
4205
4206             // RATINGS
4207             if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4208             {
4209                 foreach ($ratings as $rating)
4210                 {
4211                     $rating_scheme = null;
4212                     $rating_value = null;
4213                     if (isset($rating['attribs']['']['scheme']))
4214                     {
4215                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4216                     }
4217                     else
4218                     {
4219                         $rating_scheme = 'urn:simple';
4220                     }
4221                     if (isset($rating['data']))
4222                     {
4223                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4224                     }
f64c86 4225                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4226                 }
T 4227             }
4228             elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4229             {
4230                 foreach ($ratings as $rating)
4231                 {
4232                     $rating_scheme = 'urn:itunes';
4233                     $rating_value = null;
4234                     if (isset($rating['data']))
4235                     {
4236                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4237                     }
f64c86 4238                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4239                 }
T 4240             }
4241             elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4242             {
4243                 foreach ($ratings as $rating)
4244                 {
4245                     $rating_scheme = null;
4246                     $rating_value = null;
4247                     if (isset($rating['attribs']['']['scheme']))
4248                     {
4249                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4250                     }
4251                     else
4252                     {
4253                         $rating_scheme = 'urn:simple';
4254                     }
4255                     if (isset($rating['data']))
4256                     {
4257                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4258                     }
f64c86 4259                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4260                 }
T 4261             }
4262             elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4263             {
4264                 foreach ($ratings as $rating)
4265                 {
4266                     $rating_scheme = 'urn:itunes';
4267                     $rating_value = null;
4268                     if (isset($rating['data']))
4269                     {
4270                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4271                     }
f64c86 4272                     $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4273                 }
T 4274             }
4275             if (is_array($ratings_parent))
4276             {
4277                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4278             }
4279
4280             // RESTRICTIONS
4281             if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4282             {
4283                 foreach ($restrictions as $restriction)
4284                 {
4285                     $restriction_relationship = null;
4286                     $restriction_type = null;
4287                     $restriction_value = null;
4288                     if (isset($restriction['attribs']['']['relationship']))
4289                     {
4290                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4291                     }
4292                     if (isset($restriction['attribs']['']['type']))
4293                     {
4294                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4295                     }
4296                     if (isset($restriction['data']))
4297                     {
4298                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4299                     }
f64c86 4300                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4301                 }
T 4302             }
4303             elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4304             {
4305                 foreach ($restrictions as $restriction)
4306                 {
4307                     $restriction_relationship = 'allow';
4308                     $restriction_type = null;
4309                     $restriction_value = 'itunes';
4310                     if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4311                     {
4312                         $restriction_relationship = 'deny';
4313                     }
f64c86 4314                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4315                 }
T 4316             }
4317             elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4318             {
4319                 foreach ($restrictions as $restriction)
4320                 {
4321                     $restriction_relationship = null;
4322                     $restriction_type = null;
4323                     $restriction_value = null;
4324                     if (isset($restriction['attribs']['']['relationship']))
4325                     {
4326                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4327                     }
4328                     if (isset($restriction['attribs']['']['type']))
4329                     {
4330                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4331                     }
4332                     if (isset($restriction['data']))
4333                     {
4334                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4335                     }
f64c86 4336                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4337                 }
T 4338             }
4339             elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4340             {
4341                 foreach ($restrictions as $restriction)
4342                 {
4343                     $restriction_relationship = 'allow';
4344                     $restriction_type = null;
4345                     $restriction_value = 'itunes';
4346                     if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4347                     {
4348                         $restriction_relationship = 'deny';
4349                     }
f64c86 4350                     $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4351                 }
T 4352             }
4353             if (is_array($restrictions_parent))
4354             {
4355                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4356             }
4357
4358             // THUMBNAILS
4359             if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4360             {
4361                 foreach ($thumbnails as $thumbnail)
4362                 {
4363                     if (isset($thumbnail['attribs']['']['url']))
4364                     {
4365                         $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4366                     }
4367                 }
4368             }
4369             elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4370             {
4371                 foreach ($thumbnails as $thumbnail)
4372                 {
4373                     if (isset($thumbnail['attribs']['']['url']))
4374                     {
4375                         $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4376                     }
4377                 }
4378             }
4379
4380             // TITLES
4381             if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4382             {
4383                 if (isset($title_parent[0]['data']))
4384                 {
4385                     $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4386                 }
4387             }
4388             elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4389             {
4390                 if (isset($title_parent[0]['data']))
4391                 {
4392                     $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4393                 }
4394             }
4395
4396             // Clear the memory
4397             unset($parent);
4398
4399             // Attributes
4400             $bitrate = null;
4401             $channels = null;
4402             $duration = null;
4403             $expression = null;
4404             $framerate = null;
4405             $height = null;
4406             $javascript = null;
4407             $lang = null;
4408             $length = null;
4409             $medium = null;
4410             $samplingrate = null;
4411             $type = null;
4412             $url = null;
4413             $width = null;
4414
4415             // Elements
4416             $captions = null;
4417             $categories = null;
4418             $copyrights = null;
4419             $credits = null;
4420             $description = null;
4421             $hashes = null;
4422             $keywords = null;
4423             $player = null;
4424             $ratings = null;
4425             $restrictions = null;
4426             $thumbnails = null;
4427             $title = null;
4428
4429             // If we have media:group tags, loop through them.
4430             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4431             {
4432                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4433                 {
4434                     // If we have media:content tags, loop through them.
4435                     foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4436                     {
4437                         if (isset($content['attribs']['']['url']))
4438                         {
4439                             // Attributes
4440                             $bitrate = null;
4441                             $channels = null;
4442                             $duration = null;
4443                             $expression = null;
4444                             $framerate = null;
4445                             $height = null;
4446                             $javascript = null;
4447                             $lang = null;
4448                             $length = null;
4449                             $medium = null;
4450                             $samplingrate = null;
4451                             $type = null;
4452                             $url = null;
4453                             $width = null;
4454
4455                             // Elements
4456                             $captions = null;
4457                             $categories = null;
4458                             $copyrights = null;
4459                             $credits = null;
4460                             $description = null;
4461                             $hashes = null;
4462                             $keywords = null;
4463                             $player = null;
4464                             $ratings = null;
4465                             $restrictions = null;
4466                             $thumbnails = null;
4467                             $title = null;
4468
4469                             // Start checking the attributes of media:content
4470                             if (isset($content['attribs']['']['bitrate']))
4471                             {
4472                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4473                             }
4474                             if (isset($content['attribs']['']['channels']))
4475                             {
4476                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4477                             }
4478                             if (isset($content['attribs']['']['duration']))
4479                             {
4480                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4481                             }
4482                             else
4483                             {
4484                                 $duration = $duration_parent;
4485                             }
4486                             if (isset($content['attribs']['']['expression']))
4487                             {
4488                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4489                             }
4490                             if (isset($content['attribs']['']['framerate']))
4491                             {
4492                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4493                             }
4494                             if (isset($content['attribs']['']['height']))
4495                             {
4496                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4497                             }
4498                             if (isset($content['attribs']['']['lang']))
4499                             {
4500                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4501                             }
4502                             if (isset($content['attribs']['']['fileSize']))
4503                             {
4504                                 $length = ceil($content['attribs']['']['fileSize']);
4505                             }
4506                             if (isset($content['attribs']['']['medium']))
4507                             {
4508                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4509                             }
4510                             if (isset($content['attribs']['']['samplingrate']))
4511                             {
4512                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4513                             }
4514                             if (isset($content['attribs']['']['type']))
4515                             {
4516                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4517                             }
4518                             if (isset($content['attribs']['']['width']))
4519                             {
4520                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4521                             }
4522                             $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4523
4524                             // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4525
4526                             // CAPTIONS
4527                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4528                             {
4529                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4530                                 {
4531                                     $caption_type = null;
4532                                     $caption_lang = null;
4533                                     $caption_startTime = null;
4534                                     $caption_endTime = null;
4535                                     $caption_text = null;
4536                                     if (isset($caption['attribs']['']['type']))
4537                                     {
4538                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4539                                     }
4540                                     if (isset($caption['attribs']['']['lang']))
4541                                     {
4542                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4543                                     }
4544                                     if (isset($caption['attribs']['']['start']))
4545                                     {
4546                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4547                                     }
4548                                     if (isset($caption['attribs']['']['end']))
4549                                     {
4550                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4551                                     }
4552                                     if (isset($caption['data']))
4553                                     {
4554                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4555                                     }
f64c86 4556                                     $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 4557                                 }
T 4558                                 if (is_array($captions))
4559                                 {
4560                                     $captions = array_values(SimplePie_Misc::array_unique($captions));
4561                                 }
4562                             }
4563                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4564                             {
4565                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4566                                 {
4567                                     $caption_type = null;
4568                                     $caption_lang = null;
4569                                     $caption_startTime = null;
4570                                     $caption_endTime = null;
4571                                     $caption_text = null;
4572                                     if (isset($caption['attribs']['']['type']))
4573                                     {
4574                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4575                                     }
4576                                     if (isset($caption['attribs']['']['lang']))
4577                                     {
4578                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4579                                     }
4580                                     if (isset($caption['attribs']['']['start']))
4581                                     {
4582                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4583                                     }
4584                                     if (isset($caption['attribs']['']['end']))
4585                                     {
4586                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4587                                     }
4588                                     if (isset($caption['data']))
4589                                     {
4590                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4591                                     }
f64c86 4592                                     $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 4593                                 }
T 4594                                 if (is_array($captions))
4595                                 {
4596                                     $captions = array_values(SimplePie_Misc::array_unique($captions));
4597                                 }
4598                             }
4599                             else
4600                             {
4601                                 $captions = $captions_parent;
4602                             }
4603
4604                             // CATEGORIES
4605                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4606                             {
4607                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4608                                 {
4609                                     $term = null;
4610                                     $scheme = null;
4611                                     $label = null;
4612                                     if (isset($category['data']))
4613                                     {
4614                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4615                                     }
4616                                     if (isset($category['attribs']['']['scheme']))
4617                                     {
4618                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4619                                     }
4620                                     else
4621                                     {
4622                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4623                                     }
4624                                     if (isset($category['attribs']['']['label']))
4625                                     {
4626                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4627                                     }
f64c86 4628                                     $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 4629                                 }
T 4630                             }
4631                             if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4632                             {
4633                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4634                                 {
4635                                     $term = null;
4636                                     $scheme = null;
4637                                     $label = null;
4638                                     if (isset($category['data']))
4639                                     {
4640                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4641                                     }
4642                                     if (isset($category['attribs']['']['scheme']))
4643                                     {
4644                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4645                                     }
4646                                     else
4647                                     {
4648                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
4649                                     }
4650                                     if (isset($category['attribs']['']['label']))
4651                                     {
4652                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4653                                     }
f64c86 4654                                     $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 4655                                 }
T 4656                             }
4657                             if (is_array($categories) && is_array($categories_parent))
4658                             {
4659                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4660                             }
4661                             elseif (is_array($categories))
4662                             {
4663                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
4664                             }
4665                             elseif (is_array($categories_parent))
4666                             {
4667                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4668                             }
4669
4670                             // COPYRIGHTS
4671                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4672                             {
4673                                 $copyright_url = null;
4674                                 $copyright_label = null;
4675                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4676                                 {
4677                                     $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4678                                 }
4679                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4680                                 {
4681                                     $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4682                                 }
f64c86 4683                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 4684                             }
T 4685                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4686                             {
4687                                 $copyright_url = null;
4688                                 $copyright_label = null;
4689                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4690                                 {
4691                                     $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4692                                 }
4693                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4694                                 {
4695                                     $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4696                                 }
f64c86 4697                                 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 4698                             }
T 4699                             else
4700                             {
4701                                 $copyrights = $copyrights_parent;
4702                             }
4703
4704                             // CREDITS
4705                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4706                             {
4707                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4708                                 {
4709                                     $credit_role = null;
4710                                     $credit_scheme = null;
4711                                     $credit_name = null;
4712                                     if (isset($credit['attribs']['']['role']))
4713                                     {
4714                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4715                                     }
4716                                     if (isset($credit['attribs']['']['scheme']))
4717                                     {
4718                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4719                                     }
4720                                     else
4721                                     {
4722                                         $credit_scheme = 'urn:ebu';
4723                                     }
4724                                     if (isset($credit['data']))
4725                                     {
4726                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4727                                     }
f64c86 4728                                     $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4729                                 }
T 4730                                 if (is_array($credits))
4731                                 {
4732                                     $credits = array_values(SimplePie_Misc::array_unique($credits));
4733                                 }
4734                             }
4735                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4736                             {
4737                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4738                                 {
4739                                     $credit_role = null;
4740                                     $credit_scheme = null;
4741                                     $credit_name = null;
4742                                     if (isset($credit['attribs']['']['role']))
4743                                     {
4744                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4745                                     }
4746                                     if (isset($credit['attribs']['']['scheme']))
4747                                     {
4748                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4749                                     }
4750                                     else
4751                                     {
4752                                         $credit_scheme = 'urn:ebu';
4753                                     }
4754                                     if (isset($credit['data']))
4755                                     {
4756                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4757                                     }
f64c86 4758                                     $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 4759                                 }
T 4760                                 if (is_array($credits))
4761                                 {
4762                                     $credits = array_values(SimplePie_Misc::array_unique($credits));
4763                                 }
4764                             }
4765                             else
4766                             {
4767                                 $credits = $credits_parent;
4768                             }
4769
4770                             // DESCRIPTION
4771                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4772                             {
4773                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4774                             }
4775                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4776                             {
4777                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4778                             }
4779                             else
4780                             {
4781                                 $description = $description_parent;
4782                             }
4783
4784                             // HASHES
4785                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4786                             {
4787                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4788                                 {
4789                                     $value = null;
4790                                     $algo = null;
4791                                     if (isset($hash['data']))
4792                                     {
4793                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4794                                     }
4795                                     if (isset($hash['attribs']['']['algo']))
4796                                     {
4797                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4798                                     }
4799                                     else
4800                                     {
4801                                         $algo = 'md5';
4802                                     }
4803                                     $hashes[] = $algo.':'.$value;
4804                                 }
4805                                 if (is_array($hashes))
4806                                 {
4807                                     $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4808                                 }
4809                             }
4810                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4811                             {
4812                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4813                                 {
4814                                     $value = null;
4815                                     $algo = null;
4816                                     if (isset($hash['data']))
4817                                     {
4818                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4819                                     }
4820                                     if (isset($hash['attribs']['']['algo']))
4821                                     {
4822                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4823                                     }
4824                                     else
4825                                     {
4826                                         $algo = 'md5';
4827                                     }
4828                                     $hashes[] = $algo.':'.$value;
4829                                 }
4830                                 if (is_array($hashes))
4831                                 {
4832                                     $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4833                                 }
4834                             }
4835                             else
4836                             {
4837                                 $hashes = $hashes_parent;
4838                             }
4839
4840                             // KEYWORDS
4841                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4842                             {
4843                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4844                                 {
4845                                     $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4846                                     foreach ($temp as $word)
4847                                     {
4848                                         $keywords[] = trim($word);
4849                                     }
4850                                     unset($temp);
4851                                 }
4852                                 if (is_array($keywords))
4853                                 {
4854                                     $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4855                                 }
4856                             }
4857                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4858                             {
4859                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4860                                 {
4861                                     $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4862                                     foreach ($temp as $word)
4863                                     {
4864                                         $keywords[] = trim($word);
4865                                     }
4866                                     unset($temp);
4867                                 }
4868                                 if (is_array($keywords))
4869                                 {
4870                                     $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4871                                 }
4872                             }
4873                             else
4874                             {
4875                                 $keywords = $keywords_parent;
4876                             }
4877
4878                             // PLAYER
4879                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4880                             {
4881                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4882                             }
4883                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4884                             {
4885                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4886                             }
4887                             else
4888                             {
4889                                 $player = $player_parent;
4890                             }
4891
4892                             // RATINGS
4893                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4894                             {
4895                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4896                                 {
4897                                     $rating_scheme = null;
4898                                     $rating_value = null;
4899                                     if (isset($rating['attribs']['']['scheme']))
4900                                     {
4901                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4902                                     }
4903                                     else
4904                                     {
4905                                         $rating_scheme = 'urn:simple';
4906                                     }
4907                                     if (isset($rating['data']))
4908                                     {
4909                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4910                                     }
f64c86 4911                                     $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4912                                 }
T 4913                                 if (is_array($ratings))
4914                                 {
4915                                     $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4916                                 }
4917                             }
4918                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4919                             {
4920                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4921                                 {
4922                                     $rating_scheme = null;
4923                                     $rating_value = null;
4924                                     if (isset($rating['attribs']['']['scheme']))
4925                                     {
4926                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4927                                     }
4928                                     else
4929                                     {
4930                                         $rating_scheme = 'urn:simple';
4931                                     }
4932                                     if (isset($rating['data']))
4933                                     {
4934                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4935                                     }
f64c86 4936                                     $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 4937                                 }
T 4938                                 if (is_array($ratings))
4939                                 {
4940                                     $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4941                                 }
4942                             }
4943                             else
4944                             {
4945                                 $ratings = $ratings_parent;
4946                             }
4947
4948                             // RESTRICTIONS
4949                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4950                             {
4951                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4952                                 {
4953                                     $restriction_relationship = null;
4954                                     $restriction_type = null;
4955                                     $restriction_value = null;
4956                                     if (isset($restriction['attribs']['']['relationship']))
4957                                     {
4958                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4959                                     }
4960                                     if (isset($restriction['attribs']['']['type']))
4961                                     {
4962                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4963                                     }
4964                                     if (isset($restriction['data']))
4965                                     {
4966                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4967                                     }
f64c86 4968                                     $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4969                                 }
T 4970                                 if (is_array($restrictions))
4971                                 {
4972                                     $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4973                                 }
4974                             }
4975                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4976                             {
4977                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4978                                 {
4979                                     $restriction_relationship = null;
4980                                     $restriction_type = null;
4981                                     $restriction_value = null;
4982                                     if (isset($restriction['attribs']['']['relationship']))
4983                                     {
4984                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4985                                     }
4986                                     if (isset($restriction['attribs']['']['type']))
4987                                     {
4988                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4989                                     }
4990                                     if (isset($restriction['data']))
4991                                     {
4992                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4993                                     }
f64c86 4994                                     $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 4995                                 }
T 4996                                 if (is_array($restrictions))
4997                                 {
4998                                     $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4999                                 }
5000                             }
5001                             else
5002                             {
5003                                 $restrictions = $restrictions_parent;
5004                             }
5005
5006                             // THUMBNAILS
5007                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5008                             {
5009                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5010                                 {
5011                                     $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5012                                 }
5013                                 if (is_array($thumbnails))
5014                                 {
5015                                     $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5016                                 }
5017                             }
5018                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5019                             {
5020                                 foreach ($group['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                             else
5030                             {
5031                                 $thumbnails = $thumbnails_parent;
5032                             }
5033
5034                             // TITLES
5035                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5036                             {
5037                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5038                             }
5039                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5040                             {
5041                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5042                             }
5043                             else
5044                             {
5045                                 $title = $title_parent;
5046                             }
5047
f64c86 5048                             $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);
fd9ef2 5049                         }
T 5050                     }
5051                 }
5052             }
5053
5054             // If we have standalone media:content tags, loop through them.
5055             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5056             {
5057                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5058                 {
5059                     if (isset($content['attribs']['']['url']))
5060                     {
5061                         // Attributes
5062                         $bitrate = null;
5063                         $channels = null;
5064                         $duration = null;
5065                         $expression = null;
5066                         $framerate = null;
5067                         $height = null;
5068                         $javascript = null;
5069                         $lang = null;
5070                         $length = null;
5071                         $medium = null;
5072                         $samplingrate = null;
5073                         $type = null;
5074                         $url = null;
5075                         $width = null;
5076
5077                         // Elements
5078                         $captions = null;
5079                         $categories = null;
5080                         $copyrights = null;
5081                         $credits = null;
5082                         $description = null;
5083                         $hashes = null;
5084                         $keywords = null;
5085                         $player = null;
5086                         $ratings = null;
5087                         $restrictions = null;
5088                         $thumbnails = null;
5089                         $title = null;
5090
5091                         // Start checking the attributes of media:content
5092                         if (isset($content['attribs']['']['bitrate']))
5093                         {
5094                             $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5095                         }
5096                         if (isset($content['attribs']['']['channels']))
5097                         {
5098                             $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5099                         }
5100                         if (isset($content['attribs']['']['duration']))
5101                         {
5102                             $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5103                         }
5104                         else
5105                         {
5106                             $duration = $duration_parent;
5107                         }
5108                         if (isset($content['attribs']['']['expression']))
5109                         {
5110                             $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5111                         }
5112                         if (isset($content['attribs']['']['framerate']))
5113                         {
5114                             $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5115                         }
5116                         if (isset($content['attribs']['']['height']))
5117                         {
5118                             $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5119                         }
5120                         if (isset($content['attribs']['']['lang']))
5121                         {
5122                             $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5123                         }
5124                         if (isset($content['attribs']['']['fileSize']))
5125                         {
5126                             $length = ceil($content['attribs']['']['fileSize']);
5127                         }
5128                         if (isset($content['attribs']['']['medium']))
5129                         {
5130                             $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5131                         }
5132                         if (isset($content['attribs']['']['samplingrate']))
5133                         {
5134                             $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5135                         }
5136                         if (isset($content['attribs']['']['type']))
5137                         {
5138                             $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5139                         }
5140                         if (isset($content['attribs']['']['width']))
5141                         {
5142                             $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5143                         }
5144                         $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5145
5146                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5147
5148                         // CAPTIONS
5149                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5150                         {
5151                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5152                             {
5153                                 $caption_type = null;
5154                                 $caption_lang = null;
5155                                 $caption_startTime = null;
5156                                 $caption_endTime = null;
5157                                 $caption_text = null;
5158                                 if (isset($caption['attribs']['']['type']))
5159                                 {
5160                                     $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5161                                 }
5162                                 if (isset($caption['attribs']['']['lang']))
5163                                 {
5164                                     $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5165                                 }
5166                                 if (isset($caption['attribs']['']['start']))
5167                                 {
5168                                     $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5169                                 }
5170                                 if (isset($caption['attribs']['']['end']))
5171                                 {
5172                                     $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5173                                 }
5174                                 if (isset($caption['data']))
5175                                 {
5176                                     $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5177                                 }
f64c86 5178                                 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
fd9ef2 5179                             }
T 5180                             if (is_array($captions))
5181                             {
5182                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
5183                             }
5184                         }
5185                         else
5186                         {
5187                             $captions = $captions_parent;
5188                         }
5189
5190                         // CATEGORIES
5191                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5192                         {
5193                             foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5194                             {
5195                                 $term = null;
5196                                 $scheme = null;
5197                                 $label = null;
5198                                 if (isset($category['data']))
5199                                 {
5200                                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5201                                 }
5202                                 if (isset($category['attribs']['']['scheme']))
5203                                 {
5204                                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5205                                 }
5206                                 else
5207                                 {
5208                                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
5209                                 }
5210                                 if (isset($category['attribs']['']['label']))
5211                                 {
5212                                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5213                                 }
f64c86 5214                                 $categories[] = new $this->feed->category_class($term, $scheme, $label);
fd9ef2 5215                             }
T 5216                         }
5217                         if (is_array($categories) && is_array($categories_parent))
5218                         {
5219                             $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5220                         }
5221                         elseif (is_array($categories))
5222                         {
5223                             $categories = array_values(SimplePie_Misc::array_unique($categories));
5224                         }
5225                         elseif (is_array($categories_parent))
5226                         {
5227                             $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5228                         }
5229                         else
5230                         {
5231                             $categories = null;
5232                         }
5233
5234                         // COPYRIGHTS
5235                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5236                         {
5237                             $copyright_url = null;
5238                             $copyright_label = null;
5239                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5240                             {
5241                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5242                             }
5243                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5244                             {
5245                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5246                             }
f64c86 5247                             $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
fd9ef2 5248                         }
T 5249                         else
5250                         {
5251                             $copyrights = $copyrights_parent;
5252                         }
5253
5254                         // CREDITS
5255                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5256                         {
5257                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5258                             {
5259                                 $credit_role = null;
5260                                 $credit_scheme = null;
5261                                 $credit_name = null;
5262                                 if (isset($credit['attribs']['']['role']))
5263                                 {
5264                                     $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5265                                 }
5266                                 if (isset($credit['attribs']['']['scheme']))
5267                                 {
5268                                     $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5269                                 }
5270                                 else
5271                                 {
5272                                     $credit_scheme = 'urn:ebu';
5273                                 }
5274                                 if (isset($credit['data']))
5275                                 {
5276                                     $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5277                                 }
f64c86 5278                                 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
fd9ef2 5279                             }
T 5280                             if (is_array($credits))
5281                             {
5282                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
5283                             }
5284                         }
5285                         else
5286                         {
5287                             $credits = $credits_parent;
5288                         }
5289
5290                         // DESCRIPTION
5291                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5292                         {
5293                             $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5294                         }
5295                         else
5296                         {
5297                             $description = $description_parent;
5298                         }
5299
5300                         // HASHES
5301                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5302                         {
5303                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5304                             {
5305                                 $value = null;
5306                                 $algo = null;
5307                                 if (isset($hash['data']))
5308                                 {
5309                                     $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5310                                 }
5311                                 if (isset($hash['attribs']['']['algo']))
5312                                 {
5313                                     $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5314                                 }
5315                                 else
5316                                 {
5317                                     $algo = 'md5';
5318                                 }
5319                                 $hashes[] = $algo.':'.$value;
5320                             }
5321                             if (is_array($hashes))
5322                             {
5323                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5324                             }
5325                         }
5326                         else
5327                         {
5328                             $hashes = $hashes_parent;
5329                         }
5330
5331                         // KEYWORDS
5332                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5333                         {
5334                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5335                             {
5336                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5337                                 foreach ($temp as $word)
5338                                 {
5339                                     $keywords[] = trim($word);
5340                                 }
5341                                 unset($temp);
5342                             }
5343                             if (is_array($keywords))
5344                             {
5345                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5346                             }
5347                         }
5348                         else
5349                         {
5350                             $keywords = $keywords_parent;
5351                         }
5352
5353                         // PLAYER
5354                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5355                         {
5356                             $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5357                         }
5358                         else
5359                         {
5360                             $player = $player_parent;
5361                         }
5362
5363                         // RATINGS
5364                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5365                         {
5366                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5367                             {
5368                                 $rating_scheme = null;
5369                                 $rating_value = null;
5370                                 if (isset($rating['attribs']['']['scheme']))
5371                                 {
5372                                     $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5373                                 }
5374                                 else
5375                                 {
5376                                     $rating_scheme = 'urn:simple';
5377                                 }
5378                                 if (isset($rating['data']))
5379                                 {
5380                                     $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5381                                 }
f64c86 5382                                 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
fd9ef2 5383                             }
T 5384                             if (is_array($ratings))
5385                             {
5386                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5387                             }
5388                         }
5389                         else
5390                         {
5391                             $ratings = $ratings_parent;
5392                         }
5393
5394                         // RESTRICTIONS
5395                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5396                         {
5397                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5398                             {
5399                                 $restriction_relationship = null;
5400                                 $restriction_type = null;
5401                                 $restriction_value = null;
5402                                 if (isset($restriction['attribs']['']['relationship']))
5403                                 {
5404                                     $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5405                                 }
5406                                 if (isset($restriction['attribs']['']['type']))
5407                                 {
5408                                     $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5409                                 }
5410                                 if (isset($restriction['data']))
5411                                 {
5412                                     $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5413                                 }
f64c86 5414                                 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
fd9ef2 5415                             }
T 5416                             if (is_array($restrictions))
5417                             {
5418                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5419                             }
5420                         }
5421                         else
5422                         {
5423                             $restrictions = $restrictions_parent;
5424                         }
5425
5426                         // THUMBNAILS
5427                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5428                         {
5429                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5430                             {
5431                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5432                             }
5433                             if (is_array($thumbnails))
5434                             {
5435                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5436                             }
5437                         }
5438                         else
5439                         {
5440                             $thumbnails = $thumbnails_parent;
5441                         }
5442
5443                         // TITLES
5444                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5445                         {
5446                             $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5447                         }
5448                         else
5449                         {
5450                             $title = $title_parent;
5451                         }
5452
f64c86 5453                         $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);
fd9ef2 5454                     }
T 5455                 }
5456             }
5457
5458             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5459             {
5460                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5461                 {
5462                     // Attributes
5463                     $bitrate = null;
5464                     $channels = null;
5465                     $duration = null;
5466                     $expression = null;
5467                     $framerate = null;
5468                     $height = null;
5469                     $javascript = null;
5470                     $lang = null;
5471                     $length = null;
5472                     $medium = null;
5473                     $samplingrate = null;
5474                     $type = null;
5475                     $url = null;
5476                     $width = null;
5477
5478                     $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5479                     if (isset($link['attribs']['']['type']))
5480                     {
5481                         $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5482                     }
5483                     if (isset($link['attribs']['']['length']))
5484                     {
5485                         $length = ceil($link['attribs']['']['length']);
5486                     }
5487
5488                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5489                     $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);
fd9ef2 5490                 }
T 5491             }
5492
5493             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5494             {
5495                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5496                 {
5497                     // Attributes
5498                     $bitrate = null;
5499                     $channels = null;
5500                     $duration = null;
5501                     $expression = null;
5502                     $framerate = null;
5503                     $height = null;
5504                     $javascript = null;
5505                     $lang = null;
5506                     $length = null;
5507                     $medium = null;
5508                     $samplingrate = null;
5509                     $type = null;
5510                     $url = null;
5511                     $width = null;
5512
5513                     $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5514                     if (isset($link['attribs']['']['type']))
5515                     {
5516                         $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5517                     }
5518                     if (isset($link['attribs']['']['length']))
5519                     {
5520                         $length = ceil($link['attribs']['']['length']);
5521                     }
5522
5523                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5524                     $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);
fd9ef2 5525                 }
T 5526             }
5527
5528             if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5529             {
5530                 if (isset($enclosure[0]['attribs']['']['url']))
5531                 {
5532                     // Attributes
5533                     $bitrate = null;
5534                     $channels = null;
5535                     $duration = null;
5536                     $expression = null;
5537                     $framerate = null;
5538                     $height = null;
5539                     $javascript = null;
5540                     $lang = null;
5541                     $length = null;
5542                     $medium = null;
5543                     $samplingrate = null;
5544                     $type = null;
5545                     $url = null;
5546                     $width = null;
5547
5548                     $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5549                     if (isset($enclosure[0]['attribs']['']['type']))
5550                     {
5551                         $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5552                     }
5553                     if (isset($enclosure[0]['attribs']['']['length']))
5554                     {
5555                         $length = ceil($enclosure[0]['attribs']['']['length']);
5556                     }
5557
5558                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5559                     $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);
fd9ef2 5560                 }
T 5561             }
5562
5563             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))
5564             {
5565                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
f64c86 5566                 $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);
fd9ef2 5567             }
T 5568
5569             $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5570         }
5571         if (!empty($this->data['enclosures']))
5572         {
5573             return $this->data['enclosures'];
5574         }
5575         else
5576         {
5577             return null;
5578         }
5579     }
5580
5581     function get_latitude()
5582     {
5583         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5584         {
5585             return (float) $return[0]['data'];
5586         }
5587         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))
5588         {
5589             return (float) $match[1];
5590         }
5591         else
5592         {
5593             return null;
5594         }
5595     }
5596
5597     function get_longitude()
5598     {
5599         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5600         {
5601             return (float) $return[0]['data'];
5602         }
5603         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5604         {
5605             return (float) $return[0]['data'];
5606         }
5607         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))
5608         {
5609             return (float) $match[2];
5610         }
5611         else
5612         {
5613             return null;
5614         }
5615     }
5616
5617     function get_source()
5618     {
5619         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5620         {
5621             return new $this->feed->source_class($this, $return[0]);
5622         }
5623         else
5624         {
5625             return null;
5626         }
5627     }
5628
5629     /**
5630      * Creates the add_to_* methods' return data
5631      *
5632      * @access private
5633      * @param string $item_url String to prefix to the item permalink
5634      * @param string $title_url String to prefix to the item title
5635      * (and suffix to the item permalink)
5636      * @return mixed URL if feed exists, false otherwise
5637      */
5638     function add_to_service($item_url, $title_url = null, $summary_url = null)
5639     {
5640         if ($this->get_permalink() !== null)
5641         {
5642             $return = $item_url . rawurlencode($this->get_permalink());
5643             if ($title_url !== null && $this->get_title() !== null)
5644             {
5645                 $return .= $title_url . rawurlencode($this->get_title());
5646             }
5647             if ($summary_url !== null && $this->get_description() !== null)
5648             {
5649                 $return .= $summary_url . rawurlencode($this->get_description());
5650             }
5651             return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5652         }
5653         else
5654         {
5655             return null;
5656         }
5657     }
5658
5659     function add_to_blinklist()
5660     {
5661         return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5662     }
5663
5664     function add_to_blogmarks()
5665     {
5666         return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5667     }
5668
5669     function add_to_delicious()
5670     {
5671         return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5672     }
5673
5674     function add_to_digg()
5675     {
5676         return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5677     }
5678
5679     function add_to_furl()
5680     {
5681         return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5682     }
5683
5684     function add_to_magnolia()
5685     {
5686         return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5687     }
5688
5689     function add_to_myweb20()
5690     {
5691         return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5692     }
5693
5694     function add_to_newsvine()
5695     {
5696         return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5697     }
5698
5699     function add_to_reddit()
5700     {
5701         return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5702     }
5703
5704     function add_to_segnalo()
5705     {
5706         return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5707     }
5708
5709     function add_to_simpy()
5710     {
5711         return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5712     }
5713
5714     function add_to_spurl()
5715     {
5716         return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5717     }
5718
5719     function add_to_wists()
5720     {
5721         return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5722     }
5723
5724     function search_technorati()
5725     {
5726         return $this->add_to_service('http://www.technorati.com/search/');
5727     }
5728 }
5729
5730 class SimplePie_Source
5731 {
5732     var $item;
5733     var $data = array();
5734
5735     function SimplePie_Source($item, $data)
5736     {
5737         $this->item = $item;
5738         $this->data = $data;
5739     }
5740
5741     function __toString()
5742     {
5743         return md5(serialize($this->data));
5744     }
5745
5746     function get_source_tags($namespace, $tag)
5747     {
5748         if (isset($this->data['child'][$namespace][$tag]))
5749         {
5750             return $this->data['child'][$namespace][$tag];
5751         }
5752         else
5753         {
5754             return null;
5755         }
5756     }
5757
5758     function get_base($element = array())
5759     {
5760         return $this->item->get_base($element);
5761     }
5762
5763     function sanitize($data, $type, $base = '')
5764     {
5765         return $this->item->sanitize($data, $type, $base);
5766     }
5767
5768     function get_item()
5769     {
5770         return $this->item;
5771     }
5772
5773     function get_title()
5774     {
5775         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5776         {
5777             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5778         }
5779         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5780         {
5781             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5782         }
5783         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5784         {
5785             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5786         }
5787         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5788         {
5789             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5790         }
5791         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5792         {
5793             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5794         }
5795         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5796         {
5797             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5798         }
5799         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5800         {
5801             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5802         }
5803         else
5804         {
5805             return null;
5806         }
5807     }
5808
5809     function get_category($key = 0)
5810     {
5811         $categories = $this->get_categories();
5812         if (isset($categories[$key]))
5813         {
5814             return $categories[$key];
5815         }
5816         else
5817         {
5818             return null;
5819         }
5820     }
5821
5822     function get_categories()
5823     {
5824         $categories = array();
5825
5826         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5827         {
5828             $term = null;
5829             $scheme = null;
5830             $label = null;
5831             if (isset($category['attribs']['']['term']))
5832             {
5833                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5834             }
5835             if (isset($category['attribs']['']['scheme']))
5836             {
5837                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5838             }
5839             if (isset($category['attribs']['']['label']))
5840             {
5841                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5842             }
f64c86 5843             $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
fd9ef2 5844         }
T 5845         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5846         {
5847             // This is really the label, but keep this as the term also for BC.
5848             // Label will also work on retrieving because that falls back to term.
5849             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5850             if (isset($category['attribs']['']['domain']))
5851             {
5852                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5853             }
5854             else
5855             {
5856                 $scheme = null;
5857             }
f64c86 5858             $categories[] = new $this->item->feed->category_class($term, $scheme, null);
fd9ef2 5859         }
T 5860         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5861         {
f64c86 5862             $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5863         }
T 5864         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5865         {
f64c86 5866             $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5867         }
T 5868
5869         if (!empty($categories))
5870         {
5871             return SimplePie_Misc::array_unique($categories);
5872         }
5873         else
5874         {
5875             return null;
5876         }
5877     }
5878
5879     function get_author($key = 0)
5880     {
5881         $authors = $this->get_authors();
5882         if (isset($authors[$key]))
5883         {
5884             return $authors[$key];
5885         }
5886         else
5887         {
5888             return null;
5889         }
5890     }
5891
5892     function get_authors()
5893     {
5894         $authors = array();
5895         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5896         {
5897             $name = null;
5898             $uri = null;
5899             $email = null;
5900             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5901             {
5902                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5903             }
5904             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5905             {
5906                 $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]));
5907             }
5908             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5909             {
5910                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5911             }
5912             if ($name !== null || $email !== null || $uri !== null)
5913             {
f64c86 5914                 $authors[] = new $this->item->feed->author_class($name, $uri, $email);
fd9ef2 5915             }
T 5916         }
5917         if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5918         {
5919             $name = null;
5920             $url = null;
5921             $email = null;
5922             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5923             {
5924                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5925             }
5926             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5927             {
5928                 $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]));
5929             }
5930             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5931             {
5932                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5933             }
5934             if ($name !== null || $email !== null || $url !== null)
5935             {
f64c86 5936                 $authors[] = new $this->item->feed->author_class($name, $url, $email);
fd9ef2 5937             }
T 5938         }
5939         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5940         {
f64c86 5941             $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5942         }
T 5943         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5944         {
f64c86 5945             $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5946         }
T 5947         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5948         {
f64c86 5949             $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
fd9ef2 5950         }
T 5951
5952         if (!empty($authors))
5953         {
5954             return SimplePie_Misc::array_unique($authors);
5955         }
5956         else
5957         {
5958             return null;
5959         }
5960     }
5961
5962     function get_contributor($key = 0)
5963     {
5964         $contributors = $this->get_contributors();
5965         if (isset($contributors[$key]))
5966         {
5967             return $contributors[$key];
5968         }
5969         else
5970         {
5971             return null;
5972         }
5973     }
5974
5975     function get_contributors()
5976     {
5977         $contributors = array();
5978         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5979         {
5980             $name = null;
5981             $uri = null;
5982             $email = null;
5983             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5984             {
5985                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5986             }
5987             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5988             {
5989                 $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]));
5990             }
5991             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5992             {
5993                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5994             }
5995             if ($name !== null || $email !== null || $uri !== null)
5996             {
f64c86 5997                 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
fd9ef2 5998             }
T 5999         }
6000         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6001         {
6002             $name = null;
6003             $url = null;
6004             $email = null;
6005             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6006             {
6007                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6008             }
6009             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6010             {
6011                 $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]));
6012             }
6013             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6014             {
6015                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6016             }
6017             if ($name !== null || $email !== null || $url !== null)
6018             {
f64c86 6019                 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
fd9ef2 6020             }
T 6021         }
6022
6023         if (!empty($contributors))
6024         {
6025             return SimplePie_Misc::array_unique($contributors);
6026         }
6027         else
6028         {
6029             return null;
6030         }
6031     }
6032
6033     function get_link($key = 0, $rel = 'alternate')
6034     {
6035         $links = $this->get_links($rel);
6036         if (isset($links[$key]))
6037         {
6038             return $links[$key];
6039         }
6040         else
6041         {
6042             return null;
6043         }
6044     }
6045
6046     /**
6047      * Added for parity between the parent-level and the item/entry-level.
6048      */
6049     function get_permalink()
6050     {
6051         return $this->get_link(0);
6052     }
6053
6054     function get_links($rel = 'alternate')
6055     {
6056         if (!isset($this->data['links']))
6057         {
6058             $this->data['links'] = array();
6059             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6060             {
6061                 foreach ($links as $link)
6062                 {
6063                     if (isset($link['attribs']['']['href']))
6064                     {
6065                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6066                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6067                     }
6068                 }
6069             }
6070             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6071             {
6072                 foreach ($links as $link)
6073                 {
6074                     if (isset($link['attribs']['']['href']))
6075                     {
6076                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6077                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6078
6079                     }
6080                 }
6081             }
6082             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6083             {
6084                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6085             }
6086             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6087             {
6088                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6089             }
6090             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6091             {
6092                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6093             }
6094
6095             $keys = array_keys($this->data['links']);
6096             foreach ($keys as $key)
6097             {
6098                 if (SimplePie_Misc::is_isegment_nz_nc($key))
6099                 {
6100                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6101                     {
6102                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6103                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6104                     }
6105                     else
6106                     {
6107                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6108                     }
6109                 }
6110                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6111                 {
6112                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6113                 }
6114                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6115             }
6116         }
6117
6118         if (isset($this->data['links'][$rel]))
6119         {
6120             return $this->data['links'][$rel];
6121         }
6122         else
6123         {
6124             return null;
6125         }
6126     }
6127
6128     function get_description()
6129     {
6130         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6131         {
6132             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6133         }
6134         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6135         {
6136             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6137         }
6138         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6139         {
6140             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6141         }
6142         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6143         {
6144             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6145         }
6146         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6147         {
6148             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6149         }
6150         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6151         {
6152             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6153         }
6154         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6155         {
6156             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6157         }
6158         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6159         {
6160             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6161         }
6162         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6163         {
6164             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6165         }
6166         else
6167         {
6168             return null;
6169         }
6170     }
6171
6172     function get_copyright()
6173     {
6174         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6175         {
6176             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6177         }
6178         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6179         {
6180             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6181         }
6182         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6183         {
6184             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6185         }
6186         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6187         {
6188             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6189         }
6190         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6191         {
6192             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6193         }
6194         else
6195         {
6196             return null;
6197         }
6198     }
6199
6200     function get_language()
6201     {
6202         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6203         {
6204             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6205         }
6206         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6207         {
6208             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6209         }
6210         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6211         {
6212             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6213         }
6214         elseif (isset($this->data['xml_lang']))
6215         {
6216             return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6217         }
6218         else
6219         {
6220             return null;
6221         }
6222     }
6223
6224     function get_latitude()
6225     {
6226         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6227         {
6228             return (float) $return[0]['data'];
6229         }
6230         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))
6231         {
6232             return (float) $match[1];
6233         }
6234         else
6235         {
6236             return null;
6237         }
6238     }
6239
6240     function get_longitude()
6241     {
6242         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6243         {
6244             return (float) $return[0]['data'];
6245         }
6246         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6247         {
6248             return (float) $return[0]['data'];
6249         }
6250         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))
6251         {
6252             return (float) $match[2];
6253         }
6254         else
6255         {
6256             return null;
6257         }
6258     }
6259
6260     function get_image_url()
6261     {
6262         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6263         {
6264             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6265         }
6266         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6267         {
6268             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6269         }
6270         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6271         {
6272             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6273         }
6274         else
6275         {
6276             return null;
6277         }
6278     }
6279 }
6280
6281 class SimplePie_Author
6282 {
6283     var $name;
6284     var $link;
6285     var $email;
6286
6287     // Constructor, used to input the data
6288     function SimplePie_Author($name = null, $link = null, $email = null)
6289     {
6290         $this->name = $name;
6291         $this->link = $link;
6292         $this->email = $email;
6293     }
6294
6295     function __toString()
6296     {
6297         // There is no $this->data here
6298         return md5(serialize($this));
6299     }
6300
6301     function get_name()
6302     {
6303         if ($this->name !== null)
6304         {
6305             return $this->name;
6306         }
6307         else
6308         {
6309             return null;
6310         }
6311     }
6312
6313     function get_link()
6314     {
6315         if ($this->link !== null)
6316         {
6317             return $this->link;
6318         }
6319         else
6320         {
6321             return null;
6322         }
6323     }
6324
6325     function get_email()
6326     {
6327         if ($this->email !== null)
6328         {
6329             return $this->email;
6330         }
6331         else
6332         {
6333             return null;
6334         }
6335     }
6336 }
6337
6338 class SimplePie_Category
6339 {
6340     var $term;
6341     var $scheme;
6342     var $label;
6343
6344     // Constructor, used to input the data
6345     function SimplePie_Category($term = null, $scheme = null, $label = null)
6346     {
6347         $this->term = $term;
6348         $this->scheme = $scheme;
6349         $this->label = $label;
6350     }
6351
6352     function __toString()
6353     {
6354         // There is no $this->data here
6355         return md5(serialize($this));
6356     }
6357
6358     function get_term()
6359     {
6360         if ($this->term !== null)
6361         {
6362             return $this->term;
6363         }
6364         else
6365         {
6366             return null;
6367         }
6368     }
6369
6370     function get_scheme()
6371     {
6372         if ($this->scheme !== null)
6373         {
6374             return $this->scheme;
6375         }
6376         else
6377         {
6378             return null;
6379         }
6380     }
6381
6382     function get_label()
6383     {
6384         if ($this->label !== null)
6385         {
6386             return $this->label;
6387         }
6388         else
6389         {
6390             return $this->get_term();
6391         }
6392     }
6393 }
6394
6395 class SimplePie_Enclosure
6396 {
6397     var $bitrate;
6398     var $captions;
6399     var $categories;
6400     var $channels;
6401     var $copyright;
6402     var $credits;
6403     var $description;
6404     var $duration;
6405     var $expression;
6406     var $framerate;
6407     var $handler;
6408     var $hashes;
6409     var $height;
6410     var $javascript;
6411     var $keywords;
6412     var $lang;
6413     var $length;
6414     var $link;
6415     var $medium;
6416     var $player;
6417     var $ratings;
6418     var $restrictions;
6419     var $samplingrate;
6420     var $thumbnails;
6421     var $title;
6422     var $type;
6423     var $width;
6424
6425     // Constructor, used to input the data
6426     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)
6427     {
6428         $this->bitrate = $bitrate;
6429         $this->captions = $captions;
6430         $this->categories = $categories;
6431         $this->channels = $channels;
6432         $this->copyright = $copyright;
6433         $this->credits = $credits;
6434         $this->description = $description;
6435         $this->duration = $duration;
6436         $this->expression = $expression;
6437         $this->framerate = $framerate;
6438         $this->hashes = $hashes;
6439         $this->height = $height;
6440         $this->javascript = $javascript;
6441         $this->keywords = $keywords;
6442         $this->lang = $lang;
6443         $this->length = $length;
6444         $this->link = $link;
6445         $this->medium = $medium;
6446         $this->player = $player;
6447         $this->ratings = $ratings;
6448         $this->restrictions = $restrictions;
6449         $this->samplingrate = $samplingrate;
6450         $this->thumbnails = $thumbnails;
6451         $this->title = $title;
6452         $this->type = $type;
6453         $this->width = $width;
6454         if (class_exists('idna_convert'))
6455         {
f64c86 6456             $idn = new idna_convert;
fd9ef2 6457             $parsed = SimplePie_Misc::parse_url($link);
T 6458             $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6459         }
6460         $this->handler = $this->get_handler(); // Needs to load last
6461     }
6462
6463     function __toString()
6464     {
6465         // There is no $this->data here
6466         return md5(serialize($this));
6467     }
6468
6469     function get_bitrate()
6470     {
6471         if ($this->bitrate !== null)
6472         {
6473             return $this->bitrate;
6474         }
6475         else
6476         {
6477             return null;
6478         }
6479     }
6480
6481     function get_caption($key = 0)
6482     {
6483         $captions = $this->get_captions();
6484         if (isset($captions[$key]))
6485         {
6486             return $captions[$key];
6487         }
6488         else
6489         {
6490             return null;
6491         }
6492     }
6493
6494     function get_captions()
6495     {
6496         if ($this->captions !== null)
6497         {
6498             return $this->captions;
6499         }
6500         else
6501         {
6502             return null;
6503         }
6504     }
6505
6506     function get_category($key = 0)
6507     {
6508         $categories = $this->get_categories();
6509         if (isset($categories[$key]))
6510         {
6511             return $categories[$key];
6512         }
6513         else
6514         {
6515             return null;
6516         }
6517     }
6518
6519     function get_categories()
6520     {
6521         if ($this->categories !== null)
6522         {
6523             return $this->categories;
6524         }
6525         else
6526         {
6527             return null;
6528         }
6529     }
6530
6531     function get_channels()
6532     {
6533         if ($this->channels !== null)
6534         {
6535             return $this->channels;
6536         }
6537         else
6538         {
6539             return null;
6540         }
6541     }
6542
6543     function get_copyright()
6544     {
6545         if ($this->copyright !== null)
6546         {
6547             return $this->copyright;
6548         }
6549         else
6550         {
6551             return null;
6552         }
6553     }
6554
6555     function get_credit($key = 0)
6556     {
6557         $credits = $this->get_credits();
6558         if (isset($credits[$key]))
6559         {
6560             return $credits[$key];
6561         }
6562         else
6563         {
6564             return null;
6565         }
6566     }
6567
6568     function get_credits()
6569     {
6570         if ($this->credits !== null)
6571         {
6572             return $this->credits;
6573         }
6574         else
6575         {
6576             return null;
6577         }
6578     }
6579
6580     function get_description()
6581     {
6582         if ($this->description !== null)
6583         {
6584             return $this->description;
6585         }
6586         else
6587         {
6588             return null;
6589         }
6590     }
6591
6592     function get_duration($convert = false)
6593     {
6594         if ($this->duration !== null)
6595         {
6596             if ($convert)
6597             {
6598                 $time = SimplePie_Misc::time_hms($this->duration);
6599                 return $time;
6600             }
6601             else
6602             {
6603                 return $this->duration;
6604             }
6605         }
6606         else
6607         {
6608             return null;
6609         }
6610     }
6611
6612     function get_expression()
6613     {
6614         if ($this->expression !== null)
6615         {
6616             return $this->expression;
6617         }
6618         else
6619         {
6620             return 'full';
6621         }
6622     }
6623
6624     function get_extension()
6625     {
6626         if ($this->link !== null)
6627         {
6628             $url = SimplePie_Misc::parse_url($this->link);
6629             if ($url['path'] !== '')
6630             {
6631                 return pathinfo($url['path'], PATHINFO_EXTENSION);
6632             }
6633         }
6634         return null;
6635     }
6636
6637     function get_framerate()
6638     {
6639         if ($this->framerate !== null)
6640         {
6641             return $this->framerate;
6642         }
6643         else
6644         {
6645             return null;
6646         }
6647     }
6648
6649     function get_handler()
6650     {
6651         return $this->get_real_type(true);
6652     }
6653
6654     function get_hash($key = 0)
6655     {
6656         $hashes = $this->get_hashes();
6657         if (isset($hashes[$key]))
6658         {
6659             return $hashes[$key];
6660         }
6661         else
6662         {
6663             return null;
6664         }
6665     }
6666
6667     function get_hashes()
6668     {
6669         if ($this->hashes !== null)
6670         {
6671             return $this->hashes;
6672         }
6673         else
6674         {
6675             return null;
6676         }
6677     }
6678
6679     function get_height()
6680     {
6681         if ($this->height !== null)
6682         {
6683             return $this->height;
6684         }
6685         else
6686         {
6687             return null;
6688         }
6689     }
6690
6691     function get_language()
6692     {
6693         if ($this->lang !== null)
6694         {
6695             return $this->lang;
6696         }
6697         else
6698         {
6699             return null;
6700         }
6701     }
6702
6703     function get_keyword($key = 0)
6704     {
6705         $keywords = $this->get_keywords();
6706         if (isset($keywords[$key]))
6707         {
6708             return $keywords[$key];
6709         }
6710         else
6711         {
6712             return null;
6713         }
6714     }
6715
6716     function get_keywords()
6717     {
6718         if ($this->keywords !== null)
6719         {
6720             return $this->keywords;
6721         }
6722         else
6723         {
6724             return null;
6725         }
6726     }
6727
6728     function get_length()
6729     {
6730         if ($this->length !== null)
6731         {
6732             return $this->length;
6733         }
6734         else
6735         {
6736             return null;
6737         }
6738     }
6739
6740     function get_link()
6741     {
6742         if ($this->link !== null)
6743         {
6744             return urldecode($this->link);
6745         }
6746         else
6747         {
6748             return null;
6749         }
6750     }
6751
6752     function get_medium()
6753     {
6754         if ($this->medium !== null)
6755         {
6756             return $this->medium;
6757         }
6758         else
6759         {
6760             return null;
6761         }
6762     }
6763
6764     function get_player()
6765     {
6766         if ($this->player !== null)
6767         {
6768             return $this->player;
6769         }
6770         else
6771         {
6772             return null;
6773         }
6774     }
6775
6776     function get_rating($key = 0)
6777     {
6778         $ratings = $this->get_ratings();
6779         if (isset($ratings[$key]))
6780         {
6781             return $ratings[$key];
6782         }
6783         else
6784         {
6785             return null;
6786         }
6787     }
6788
6789     function get_ratings()
6790     {
6791         if ($this->ratings !== null)
6792         {
6793             return $this->ratings;
6794         }
6795         else
6796         {
6797             return null;
6798         }
6799     }
6800
6801     function get_restriction($key = 0)
6802     {
6803         $restrictions = $this->get_restrictions();
6804         if (isset($restrictions[$key]))
6805         {
6806             return $restrictions[$key];
6807         }
6808         else
6809         {
6810             return null;
6811         }
6812     }
6813
6814     function get_restrictions()
6815     {
6816         if ($this->restrictions !== null)
6817         {
6818             return $this->restrictions;
6819         }
6820         else
6821         {
6822             return null;
6823         }
6824     }
6825
6826     function get_sampling_rate()
6827     {
6828         if ($this->samplingrate !== null)
6829         {
6830             return $this->samplingrate;
6831         }
6832         else
6833         {
6834             return null;
6835         }
6836     }
6837
6838     function get_size()
6839     {
6840         $length = $this->get_length();
6841         if ($length !== null)
6842         {
6843             return round($length/1048576, 2);
6844         }
6845         else
6846         {
6847             return null;
6848         }
6849     }
6850
6851     function get_thumbnail($key = 0)
6852     {
6853         $thumbnails = $this->get_thumbnails();
6854         if (isset($thumbnails[$key]))
6855         {
6856             return $thumbnails[$key];
6857         }
6858         else
6859         {
6860             return null;
6861         }
6862     }
6863
6864     function get_thumbnails()
6865     {
6866         if ($this->thumbnails !== null)
6867         {
6868             return $this->thumbnails;
6869         }
6870         else
6871         {
6872             return null;
6873         }
6874     }
6875
6876     function get_title()
6877     {
6878         if ($this->title !== null)
6879         {
6880             return $this->title;
6881         }
6882         else
6883         {
6884             return null;
6885         }
6886     }
6887
6888     function get_type()
6889     {
6890         if ($this->type !== null)
6891         {
6892             return $this->type;
6893         }
6894         else
6895         {
6896             return null;
6897         }
6898     }
6899
6900     function get_width()
6901     {
6902         if ($this->width !== null)
6903         {
6904             return $this->width;
6905         }
6906         else
6907         {
6908             return null;
6909         }
6910     }
6911
6912     function native_embed($options='')
6913     {
6914         return $this->embed($options, true);
6915     }
6916
6917     /**
6918      * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6919      */
6920     function embed($options = '', $native = false)
6921     {
6922         // Set up defaults
6923         $audio = '';
6924         $video = '';
6925         $alt = '';
6926         $altclass = '';
6927         $loop = 'false';
6928         $width = 'auto';
6929         $height = 'auto';
6930         $bgcolor = '#ffffff';
6931         $mediaplayer = '';
6932         $widescreen = false;
6933         $handler = $this->get_handler();
6934         $type = $this->get_real_type();
6935
6936         // Process options and reassign values as necessary
6937         if (is_array($options))
6938         {
6939             extract($options);
6940         }
6941         else
6942         {
6943             $options = explode(',', $options);
6944             foreach($options as $option)
6945             {
6946                 $opt = explode(':', $option, 2);
6947                 if (isset($opt[0], $opt[1]))
6948                 {
6949                     $opt[0] = trim($opt[0]);
6950                     $opt[1] = trim($opt[1]);
6951                     switch ($opt[0])
6952                     {
6953                         case 'audio':
6954                             $audio = $opt[1];
6955                             break;
6956
6957                         case 'video':
6958                             $video = $opt[1];
6959                             break;
6960
6961                         case 'alt':
6962                             $alt = $opt[1];
6963                             break;
6964
6965                         case 'altclass':
6966                             $altclass = $opt[1];
6967                             break;
6968
6969                         case 'loop':
6970                             $loop = $opt[1];
6971                             break;
6972
6973                         case 'width':
6974                             $width = $opt[1];
6975                             break;
6976
6977                         case 'height':
6978                             $height = $opt[1];
6979                             break;
6980
6981                         case 'bgcolor':
6982                             $bgcolor = $opt[1];
6983                             break;
6984
6985                         case 'mediaplayer':
6986                             $mediaplayer = $opt[1];
6987                             break;
6988
6989                         case 'widescreen':
6990                             $widescreen = $opt[1];
6991                             break;
6992                     }
6993                 }
6994             }
6995         }
6996
6997         $mime = explode('/', $type, 2);
6998         $mime = $mime[0];
6999
7000         // Process values for 'auto'
7001         if ($width === 'auto')
7002         {
7003             if ($mime === 'video')
7004             {
7005                 if ($height === 'auto')
7006                 {
7007                     $width = 480;
7008                 }
7009                 elseif ($widescreen)
7010                 {
7011                     $width = round((intval($height)/9)*16);
7012                 }
7013                 else
7014                 {
7015                     $width = round((intval($height)/3)*4);
7016                 }
7017             }
7018             else
7019             {
7020                 $width = '100%';
7021             }
7022         }
7023
7024         if ($height === 'auto')
7025         {
7026             if ($mime === 'audio')
7027             {
7028                 $height = 0;
7029             }
7030             elseif ($mime === 'video')
7031             {
7032                 if ($width === 'auto')
7033                 {
7034                     if ($widescreen)
7035                     {
7036                         $height = 270;
7037                     }
7038                     else
7039                     {
7040                         $height = 360;
7041                     }
7042                 }
7043                 elseif ($widescreen)
7044                 {
7045                     $height = round((intval($width)/16)*9);
7046                 }
7047                 else
7048                 {
7049                     $height = round((intval($width)/4)*3);
7050                 }
7051             }
7052             else
7053             {
7054                 $height = 376;
7055             }
7056         }
7057         elseif ($mime === 'audio')
7058         {
7059             $height = 0;
7060         }
7061
7062         // Set proper placeholder value
7063         if ($mime === 'audio')
7064         {
7065             $placeholder = $audio;
7066         }
7067         elseif ($mime === 'video')
7068         {
7069             $placeholder = $video;
7070         }
7071
7072         $embed = '';
7073
7074         // Make sure the JS library is included
7075         if (!$native)
7076         {
7077             static $javascript_outputted = null;
7078             if (!$javascript_outputted && $this->javascript)
7079             {
7080                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7081                 $javascript_outputted = true;
7082             }
7083         }
7084
7085         // Odeo Feed MP3's
7086         if ($handler === 'odeo')
7087         {
7088             if ($native)
7089             {
7090                 $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>';
7091             }
7092             else
7093             {
7094                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7095             }
7096         }
7097
7098         // Flash
7099         elseif ($handler === 'flash')
7100         {
7101             if ($native)
7102             {
7103                 $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>";
7104             }
7105             else
7106             {
7107                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7108             }
7109         }
7110
7111         // Flash Media Player file types.
7112         // Preferred handler for MP3 file types.
7113         elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7114         {
7115             $height += 20;
7116             if ($native)
7117             {
7118                 $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>";
7119             }
7120             else
7121             {
7122                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7123             }
7124         }
7125
7126         // QuickTime 7 file types.  Need to test with QuickTime 6.
7127         // Only handle MP3's if the Flash Media Player is not present.
7128         elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7129         {
7130             $height += 16;
7131             if ($native)
7132             {
7133                 if ($placeholder !== '')
7134                 {
7135                     $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>";
7136                 }
7137                 else
7138                 {
7139                     $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>";
7140                 }
7141             }
7142             else
7143             {
7144                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7145             }
7146         }
7147
7148         // Windows Media
7149         elseif ($handler === 'wmedia')
7150         {
7151             $height += 45;
7152             if ($native)
7153             {
7154                 $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>";
7155             }
7156             else
7157             {
7158                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7159             }
7160         }
7161
7162         // Everything else
7163         else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7164
7165         return $embed;
7166     }
7167
7168     function get_real_type($find_handler = false)
7169     {
7170         // If it's Odeo, let's get it out of the way.
7171         if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7172         {
7173             return 'odeo';
7174         }
7175
7176         // Mime-types by handler.
7177         $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7178         $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7179         $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
7180         $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
7181         $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7182
7183         if ($this->get_type() !== null)
7184         {
7185             $type = strtolower($this->type);
7186         }
7187         else
7188         {
7189             $type = null;
7190         }
7191
7192         // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7193         if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7194         {
7195             switch (strtolower($this->get_extension()))
7196             {
7197                 // Audio mime-types
7198                 case 'aac':
7199                 case 'adts':
7200                     $type = 'audio/acc';
7201                     break;
7202
7203                 case 'aif':
7204                 case 'aifc':
7205                 case 'aiff':
7206                 case 'cdda':
7207                     $type = 'audio/aiff';
7208                     break;
7209
7210                 case 'bwf':
7211                     $type = 'audio/wav';
7212                     break;
7213
7214                 case 'kar':
7215                 case 'mid':
7216                 case 'midi':
7217                 case 'smf':
7218                     $type = 'audio/midi';
7219                     break;
7220
7221                 case 'm4a':
7222                     $type = 'audio/x-m4a';
7223                     break;
7224
7225                 case 'mp3':
7226                 case 'swa':
7227                     $type = 'audio/mp3';
7228                     break;
7229
7230                 case 'wav':
7231                     $type = 'audio/wav';
7232                     break;
7233
7234                 case 'wax':
7235                     $type = 'audio/x-ms-wax';
7236                     break;
7237
7238                 case 'wma':
7239                     $type = 'audio/x-ms-wma';
7240                     break;
7241
7242                 // Video mime-types
7243                 case '3gp':
7244                 case '3gpp':
7245                     $type = 'video/3gpp';
7246                     break;
7247
7248                 case '3g2':
7249                 case '3gp2':
7250                     $type = 'video/3gpp2';
7251                     break;
7252
7253                 case 'asf':
7254                     $type = 'video/x-ms-asf';
7255                     break;
7256
7257                 case 'flv':
7258                     $type = 'video/x-flv';
7259                     break;
7260
7261                 case 'm1a':
7262                 case 'm1s':
7263                 case 'm1v':
7264                 case 'm15':
7265                 case 'm75':
7266                 case 'mp2':
7267                 case 'mpa':
7268                 case 'mpeg':
7269                 case 'mpg':
7270                 case 'mpm':
7271                 case 'mpv':
7272                     $type = 'video/mpeg';
7273                     break;
7274
7275                 case 'm4v':
7276                     $type = 'video/x-m4v';
7277                     break;
7278
7279                 case 'mov':
7280                 case 'qt':
7281                     $type = 'video/quicktime';
7282                     break;
7283
7284                 case 'mp4':
7285                 case 'mpg4':
7286                     $type = 'video/mp4';
7287                     break;
7288
7289                 case 'sdv':
7290                     $type = 'video/sd-video';
7291                     break;
7292
7293                 case 'wm':
7294                     $type = 'video/x-ms-wm';
7295                     break;
7296
7297                 case 'wmv':
7298                     $type = 'video/x-ms-wmv';
7299                     break;
7300
7301                 case 'wvx':
7302                     $type = 'video/x-ms-wvx';
7303                     break;
7304
7305                 // Flash mime-types
7306                 case 'spl':
7307                     $type = 'application/futuresplash';
7308                     break;
7309
7310                 case 'swf':
7311                     $type = 'application/x-shockwave-flash';
7312                     break;
7313             }
7314         }
7315
7316         if ($find_handler)
7317         {
7318             if (in_array($type, $types_flash))
7319             {
7320                 return 'flash';
7321             }
7322             elseif (in_array($type, $types_fmedia))
7323             {
7324                 return 'fmedia';
7325             }
7326             elseif (in_array($type, $types_quicktime))
7327             {
7328                 return 'quicktime';
7329             }
7330             elseif (in_array($type, $types_wmedia))
7331             {
7332                 return 'wmedia';
7333             }
7334             elseif (in_array($type, $types_mp3))
7335             {
7336                 return 'mp3';
7337             }
7338             else
7339             {
7340                 return null;
7341             }
7342         }
7343         else
7344         {
7345             return $type;
7346         }
7347     }
7348 }
7349
7350 class SimplePie_Caption
7351 {
7352     var $type;
7353     var $lang;
7354     var $startTime;
7355     var $endTime;
7356     var $text;
7357
7358     // Constructor, used to input the data
7359     function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7360     {
7361         $this->type = $type;
7362         $this->lang = $lang;
7363         $this->startTime = $startTime;
7364         $this->endTime = $endTime;
7365         $this->text = $text;
7366     }
7367
7368     function __toString()
7369     {
7370         // There is no $this->data here
7371         return md5(serialize($this));
7372     }
7373
7374     function get_endtime()
7375     {
7376         if ($this->endTime !== null)
7377         {
7378             return $this->endTime;
7379         }
7380         else
7381         {
7382             return null;
7383         }
7384     }
7385
7386     function get_language()
7387     {
7388         if ($this->lang !== null)
7389         {
7390             return $this->lang;
7391         }
7392         else
7393         {
7394             return null;
7395         }
7396     }
7397
7398     function get_starttime()
7399     {
7400         if ($this->startTime !== null)
7401         {
7402             return $this->startTime;
7403         }
7404         else
7405         {
7406             return null;
7407         }
7408     }
7409
7410     function get_text()
7411     {
7412         if ($this->text !== null)
7413         {
7414             return $this->text;
7415         }
7416         else
7417         {
7418             return null;
7419         }
7420     }
7421
7422     function get_type()
7423     {
7424         if ($this->type !== null)
7425         {
7426             return $this->type;
7427         }
7428         else
7429         {
7430             return null;
7431         }
7432     }
7433 }
7434
7435 class SimplePie_Credit
7436 {
7437     var $role;
7438     var $scheme;
7439     var $name;
7440
7441     // Constructor, used to input the data
7442     function SimplePie_Credit($role = null, $scheme = null, $name = null)
7443     {
7444         $this->role = $role;
7445         $this->scheme = $scheme;
7446         $this->name = $name;
7447     }
7448
7449     function __toString()
7450     {
7451         // There is no $this->data here
7452         return md5(serialize($this));
7453     }
7454
7455     function get_role()
7456     {
7457         if ($this->role !== null)
7458         {
7459             return $this->role;
7460         }
7461         else
7462         {
7463             return null;
7464         }
7465     }
7466
7467     function get_scheme()
7468     {
7469         if ($this->scheme !== null)
7470         {
7471             return $this->scheme;
7472         }
7473         else
7474         {
7475             return null;
7476         }
7477     }
7478
7479     function get_name()
7480     {
7481         if ($this->name !== null)
7482         {
7483             return $this->name;
7484         }
7485         else
7486         {
7487             return null;
7488         }
7489     }
7490 }
7491
7492 class SimplePie_Copyright
7493 {
7494     var $url;
7495     var $label;
7496
7497     // Constructor, used to input the data
7498     function SimplePie_Copyright($url = null, $label = null)
7499     {
7500         $this->url = $url;
7501         $this->label = $label;
7502     }
7503
7504     function __toString()
7505     {
7506         // There is no $this->data here
7507         return md5(serialize($this));
7508     }
7509
7510     function get_url()
7511     {
7512         if ($this->url !== null)
7513         {
7514             return $this->url;
7515         }
7516         else
7517         {
7518             return null;
7519         }
7520     }
7521
7522     function get_attribution()
7523     {
7524         if ($this->label !== null)
7525         {
7526             return $this->label;
7527         }
7528         else
7529         {
7530             return null;
7531         }
7532     }
7533 }
7534
7535 class SimplePie_Rating
7536 {
7537     var $scheme;
7538     var $value;
7539
7540     // Constructor, used to input the data
7541     function SimplePie_Rating($scheme = null, $value = null)
7542     {
7543         $this->scheme = $scheme;
7544         $this->value = $value;
7545     }
7546
7547     function __toString()
7548     {
7549         // There is no $this->data here
7550         return md5(serialize($this));
7551     }
7552
7553     function get_scheme()
7554     {
7555         if ($this->scheme !== null)
7556         {
7557             return $this->scheme;
7558         }
7559         else
7560         {
7561             return null;
7562         }
7563     }
7564
7565     function get_value()
7566     {
7567         if ($this->value !== null)
7568         {
7569             return $this->value;
7570         }
7571         else
7572         {
7573             return null;
7574         }
7575     }
7576 }
7577
7578 class SimplePie_Restriction
7579 {
7580     var $relationship;
7581     var $type;
7582     var $value;
7583
7584     // Constructor, used to input the data
7585     function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7586     {
7587         $this->relationship = $relationship;
7588         $this->type = $type;
7589         $this->value = $value;
7590     }
7591
7592     function __toString()
7593     {
7594         // There is no $this->data here
7595         return md5(serialize($this));
7596     }
7597
7598     function get_relationship()
7599     {
7600         if ($this->relationship !== null)
7601         {
7602             return $this->relationship;
7603         }
7604         else
7605         {
7606             return null;
7607         }
7608     }
7609
7610     function get_type()
7611     {
7612         if ($this->type !== null)
7613         {
7614             return $this->type;
7615         }
7616         else
7617         {
7618             return null;
7619         }
7620     }
7621
7622     function get_value()
7623     {
7624         if ($this->value !== null)
7625         {
7626             return $this->value;
7627         }
7628         else
7629         {
7630             return null;
7631         }
7632     }
7633 }
7634
7635 /**
7636  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7637  */
7638 class SimplePie_File
7639 {
7640     var $url;
7641     var $useragent;
7642     var $success = true;
7643     var $headers = array();
7644     var $body;
7645     var $status_code;
7646     var $redirects = 0;
7647     var $error;
7648     var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7649
7650     function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7651     {
7652         if (class_exists('idna_convert'))
7653         {
f64c86 7654             $idn = new idna_convert;
fd9ef2 7655             $parsed = SimplePie_Misc::parse_url($url);
T 7656             $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7657         }
7658         $this->url = $url;
7659         $this->useragent = $useragent;
7660         if (preg_match('/^http(s)?:\/\//i', $url))
7661         {
7662             if ($useragent === null)
7663             {
7664                 $useragent = ini_get('user_agent');
7665                 $this->useragent = $useragent;
7666             }
7667             if (!is_array($headers))
7668             {
7669                 $headers = array();
7670             }
7671             if (!$force_fsockopen && function_exists('curl_exec'))
7672             {
7673                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7674                 $fp = curl_init();
7675                 $headers2 = array();
7676                 foreach ($headers as $key => $value)
7677                 {
7678                     $headers2[] = "$key: $value";
7679                 }
7680                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7681                 {
7682                     curl_setopt($fp, CURLOPT_ENCODING, '');
7683                 }
7684                 curl_setopt($fp, CURLOPT_URL, $url);
7685                 curl_setopt($fp, CURLOPT_HEADER, 1);
7686                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7687                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7688                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7689                 curl_setopt($fp, CURLOPT_REFERER, $url);
7690                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7691                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7692                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7693                 {
7694                     curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7695                     curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7696                 }
7697
7698                 $this->headers = curl_exec($fp);
7699                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7700                 {
7701                     curl_setopt($fp, CURLOPT_ENCODING, 'none');
7702                     $this->headers = curl_exec($fp);
7703                 }
7704                 if (curl_errno($fp))
7705                 {
7706                     $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7707                     $this->success = false;
7708                 }
7709                 else
7710                 {
7711                     $info = curl_getinfo($fp);
7712                     curl_close($fp);
7713                     $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7714                     $this->headers = array_pop($this->headers);
f64c86 7715                     $parser = new SimplePie_HTTP_Parser($this->headers);
fd9ef2 7716                     if ($parser->parse())
T 7717                     {
7718                         $this->headers = $parser->headers;
7719                         $this->body = $parser->body;
7720                         $this->status_code = $parser->status_code;
7721                         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)
7722                         {
7723                             $this->redirects++;
7724                             $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7725                             return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7726                         }
7727                     }
7728                 }
7729             }
7730             else
7731             {
7732                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7733                 $url_parts = parse_url($url);
7734                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7735                 {
7736                     $url_parts['host'] = "ssl://$url_parts[host]";
7737                     $url_parts['port'] = 443;
7738                 }
7739                 if (!isset($url_parts['port']))
7740                 {
7741                     $url_parts['port'] = 80;
7742                 }
7743                 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7744                 if (!$fp)
7745                 {
7746                     $this->error = 'fsockopen error: ' . $errstr;
7747                     $this->success = false;
7748                 }
7749                 else
7750                 {
7751                     stream_set_timeout($fp, $timeout);
7752                     if (isset($url_parts['path']))
7753                     {
7754                         if (isset($url_parts['query']))
7755                         {
7756                             $get = "$url_parts[path]?$url_parts[query]";
7757                         }
7758                         else
7759                         {
7760                             $get = $url_parts['path'];
7761                         }
7762                     }
7763                     else
7764                     {
7765                         $get = '/';
7766                     }
7767                     $out = "GET $get HTTP/1.0\r\n";
7768                     $out .= "Host: $url_parts[host]\r\n";
7769                     $out .= "User-Agent: $useragent\r\n";
7770                     if (extension_loaded('zlib'))
7771                     {
7772                         $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7773                     }
7774
7775                     if (isset($url_parts['user']) && isset($url_parts['pass']))
7776                     {
7777                         $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7778                     }
7779                     foreach ($headers as $key => $value)
7780                     {
7781                         $out .= "$key: $value\r\n";
7782                     }
7783                     $out .= "Connection: Close\r\n\r\n";
7784                     fwrite($fp, $out);
7785
7786                     $info = stream_get_meta_data($fp);
7787
7788                     $this->headers = '';
7789                     while (!$info['eof'] && !$info['timed_out'])
7790                     {
7791                         $this->headers .= fread($fp, 1160);
7792                         $info = stream_get_meta_data($fp);
7793                     }
7794                     if (!$info['timed_out'])
7795                     {
f64c86 7796                         $parser = new SimplePie_HTTP_Parser($this->headers);
fd9ef2 7797                         if ($parser->parse())
T 7798                         {
7799                             $this->headers = $parser->headers;
7800                             $this->body = $parser->body;
7801                             $this->status_code = $parser->status_code;
7802                             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)
7803                             {
7804                                 $this->redirects++;
7805                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7806                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7807                             }
7808                             if (isset($this->headers['content-encoding']))
7809                             {
7810                                 // Hey, we act dumb elsewhere, so let's do that here too
7811                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7812                                 {
7813                                     case 'gzip':
7814                                     case 'x-gzip':
f64c86 7815                                         $decoder = new SimplePie_gzdecode($this->body);
fd9ef2 7816                                         if (!$decoder->parse())
T 7817                                         {
7818                                             $this->error = 'Unable to decode HTTP "gzip" stream';
7819                                             $this->success = false;
7820                                         }
7821                                         else
7822                                         {
7823                                             $this->body = $decoder->data;
7824                                         }
7825                                         break;
7826
7827                                     case 'deflate':
7828                                         if (($body = gzuncompress($this->body)) === false)
7829                                         {
7830                                             if (($body = gzinflate($this->body)) === false)
7831                                             {
7832                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
7833                                                 $this->success = false;
7834                                             }
7835                                         }
7836                                         $this->body = $body;
7837                                         break;
7838
7839                                     default:
7840                                         $this->error = 'Unknown content coding';
7841                                         $this->success = false;
7842                                 }
7843                             }
7844                         }
7845                     }
7846                     else
7847                     {
7848                         $this->error = 'fsocket timed out';
7849                         $this->success = false;
7850                     }
7851                     fclose($fp);
7852                 }
7853             }
7854         }
7855         else
7856         {
7857             $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7858             if (!$this->body = file_get_contents($url))
7859             {
7860                 $this->error = 'file_get_contents could not read the file';
7861                 $this->success = false;
7862             }
7863         }
7864     }
7865 }
7866
7867 /**
7868  * HTTP Response Parser
7869  *
7870  * @package SimplePie
7871  */
7872 class SimplePie_HTTP_Parser
7873 {
7874     /**
7875      * HTTP Version
7876      *
7877      * @access public
7878      * @var float
7879      */
7880     var $http_version = 0.0;
7881
7882     /**
7883      * Status code
7884      *
7885      * @access public
7886      * @var int
7887      */
7888     var $status_code = 0;
7889
7890     /**
7891      * Reason phrase
7892      *
7893      * @access public
7894      * @var string
7895      */
7896     var $reason = '';
7897
7898     /**
7899      * Key/value pairs of the headers
7900      *
7901      * @access public
7902      * @var array
7903      */
7904     var $headers = array();
7905
7906     /**
7907      * Body of the response
7908      *
7909      * @access public
7910      * @var string
7911      */
7912     var $body = '';
7913
7914     /**
7915      * Current state of the state machine
7916      *
7917      * @access private
7918      * @var string
7919      */
7920     var $state = 'http_version';
7921
7922     /**
7923      * Input data
7924      *
7925      * @access private
7926      * @var string
7927      */
7928     var $data = '';
7929
7930     /**
7931      * Input data length (to avoid calling strlen() everytime this is needed)
7932      *
7933      * @access private
7934      * @var int
7935      */
7936     var $data_length = 0;
7937
7938     /**
7939      * Current position of the pointer
7940      *
7941      * @var int
7942      * @access private
7943      */
7944     var $position = 0;
7945
7946     /**
7947      * Name of the hedaer currently being parsed
7948      *
7949      * @access private
7950      * @var string
7951      */
7952     var $name = '';
7953
7954     /**
7955      * Value of the hedaer currently being parsed
7956      *
7957      * @access private
7958      * @var string
7959      */
7960     var $value = '';
7961
7962     /**
7963      * Create an instance of the class with the input data
7964      *
7965      * @access public
7966      * @param string $data Input data
7967      */
7968     function SimplePie_HTTP_Parser($data)
7969     {
7970         $this->data = $data;
7971         $this->data_length = strlen($this->data);
7972     }
7973
7974     /**
7975      * Parse the input data
7976      *
7977      * @access public
7978      * @return bool true on success, false on failure
7979      */
7980     function parse()
7981     {
7982         while ($this->state && $this->state !== 'emit' && $this->has_data())
7983         {
7984             $state = $this->state;
7985             $this->$state();
7986         }
7987         $this->data = '';
7988         if ($this->state === 'emit' || $this->state === 'body')
7989         {
7990             return true;
7991         }
7992         else
7993         {
7994             $this->http_version = '';
7995             $this->status_code = '';
7996             $this->reason = '';
7997             $this->headers = array();
7998             $this->body = '';
7999             return false;
8000         }
8001     }
8002
8003     /**
8004      * Check whether there is data beyond the pointer
8005      *
8006      * @access private
8007      * @return bool true if there is further data, false if not
8008      */
8009     function has_data()
8010     {
8011         return (bool) ($this->position < $this->data_length);
8012     }
8013
8014     /**
8015      * See if the next character is LWS
8016      *
8017      * @access private
8018      * @return bool true if the next character is LWS, false if not
8019      */
8020     function is_linear_whitespace()
8021     {
8022         return (bool) ($this->data[$this->position] === "\x09"
8023             || $this->data[$this->position] === "\x20"
8024             || ($this->data[$this->position] === "\x0A"
8025                 && isset($this->data[$this->position + 1])
8026                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8027     }
8028
8029     /**
8030      * Parse the HTTP version
8031      *
8032      * @access private
8033      */
8034     function http_version()
8035     {
8036         if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8037         {
8038             $len = strspn($this->data, '0123456789.', 5);
8039             $this->http_version = substr($this->data, 5, $len);
8040             $this->position += 5 + $len;
8041             if (substr_count($this->http_version, '.') <= 1)
8042             {
8043                 $this->http_version = (float) $this->http_version;
8044                 $this->position += strspn($this->data, "\x09\x20", $this->position);
8045                 $this->state = 'status';
8046             }
8047             else
8048             {
8049                 $this->state = false;
8050             }
8051         }
8052         else
8053         {
8054             $this->state = false;
8055         }
8056     }
8057
8058     /**
8059      * Parse the status code
8060      *
8061      * @access private
8062      */
8063     function status()
8064     {
8065         if ($len = strspn($this->data, '0123456789', $this->position))
8066         {
8067             $this->status_code = (int) substr($this->data, $this->position, $len);
8068             $this->position += $len;
8069             $this->state = 'reason';
8070         }
8071         else
8072         {
8073             $this->state = false;
8074         }
8075     }
8076
8077     /**
8078      * Parse the reason phrase
8079      *
8080      * @access private
8081      */
8082     function reason()
8083     {
8084         $len = strcspn($this->data, "\x0A", $this->position);
8085         $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8086         $this->position += $len + 1;
8087         $this->state = 'new_line';
8088     }
8089
8090     /**
8091      * Deal with a new line, shifting data around as needed
8092      *
8093      * @access private
8094      */
8095     function new_line()
8096     {
8097         $this->value = trim($this->value, "\x0D\x20");
8098         if ($this->name !== '' && $this->value !== '')
8099         {
8100             $this->name = strtolower($this->name);
8101             if (isset($this->headers[$this->name]))
8102             {
8103                 $this->headers[$this->name] .= ', ' . $this->value;
8104             }
8105             else
8106             {
8107                 $this->headers[$this->name] = $this->value;
8108             }
8109         }
8110         $this->name = '';
8111         $this->value = '';
8112         if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8113         {
8114             $this->position += 2;
8115             $this->state = 'body';
8116         }
8117         elseif ($this->data[$this->position] === "\x0A")
8118         {
8119             $this->position++;
8120             $this->state = 'body';
8121         }
8122         else
8123         {
8124             $this->state = 'name';
8125         }
8126     }
8127
8128     /**
8129      * Parse a header name
8130      *
8131      * @access private
8132      */
8133     function name()
8134     {
8135         $len = strcspn($this->data, "\x0A:", $this->position);
8136         if (isset($this->data[$this->position + $len]))
8137         {
8138             if ($this->data[$this->position + $len] === "\x0A")
8139             {
8140                 $this->position += $len;
8141                 $this->state = 'new_line';
8142             }
8143             else
8144             {
8145                 $this->name = substr($this->data, $this->position, $len);
8146                 $this->position += $len + 1;
8147                 $this->state = 'value';
8148             }
8149         }
8150         else
8151         {
8152             $this->state = false;
8153         }
8154     }
8155
8156     /**
8157      * Parse LWS, replacing consecutive LWS characters with a single space
8158      *
8159      * @access private
8160      */
8161     function linear_whitespace()
8162     {
8163         do
8164         {
8165             if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8166             {
8167                 $this->position += 2;
8168             }
8169             elseif ($this->data[$this->position] === "\x0A")
8170             {
8171                 $this->position++;
8172             }
8173             $this->position += strspn($this->data, "\x09\x20", $this->position);
8174         } while ($this->has_data() && $this->is_linear_whitespace());
8175         $this->value .= "\x20";
8176     }
8177
8178     /**
8179      * See what state to move to while within non-quoted header values
8180      *
8181      * @access private
8182      */
8183     function value()
8184     {
8185         if ($this->is_linear_whitespace())
8186         {
8187             $this->linear_whitespace();
8188         }
8189         else
8190         {
8191             switch ($this->data[$this->position])
8192             {
8193                 case '"':
8194                     $this->position++;
8195                     $this->state = 'quote';
8196                     break;
8197
8198                 case "\x0A":
8199                     $this->position++;
8200                     $this->state = 'new_line';
8201                     break;
8202
8203                 default:
8204                     $this->state = 'value_char';
8205                     break;
8206             }
8207         }
8208     }
8209
8210     /**
8211      * Parse a header value while outside quotes
8212      *
8213      * @access private
8214      */
8215     function value_char()
8216     {
8217         $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8218         $this->value .= substr($this->data, $this->position, $len);
8219         $this->position += $len;
8220         $this->state = 'value';
8221     }
8222
8223     /**
8224      * See what state to move to while within quoted header values
8225      *
8226      * @access private
8227      */
8228     function quote()
8229     {
8230         if ($this->is_linear_whitespace())
8231         {
8232             $this->linear_whitespace();
8233         }
8234         else
8235         {
8236             switch ($this->data[$this->position])
8237             {
8238                 case '"':
8239                     $this->position++;
8240                     $this->state = 'value';
8241                     break;
8242
8243                 case "\x0A":
8244                     $this->position++;
8245                     $this->state = 'new_line';
8246                     break;
8247
8248                 case '\\':
8249                     $this->position++;
8250                     $this->state = 'quote_escaped';
8251                     break;
8252
8253                 default:
8254                     $this->state = 'quote_char';
8255                     break;
8256             }
8257         }
8258     }
8259
8260     /**
8261      * Parse a header value while within quotes
8262      *
8263      * @access private
8264      */
8265     function quote_char()
8266     {
8267         $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8268         $this->value .= substr($this->data, $this->position, $len);
8269         $this->position += $len;
8270         $this->state = 'value';
8271     }
8272
8273     /**
8274      * Parse an escaped character within quotes
8275      *
8276      * @access private
8277      */
8278     function quote_escaped()
8279     {
8280         $this->value .= $this->data[$this->position];
8281         $this->position++;
8282         $this->state = 'quote';
8283     }
8284
8285     /**
8286      * Parse the body
8287      *
8288      * @access private
8289      */
8290     function body()
8291     {
8292         $this->body = substr($this->data, $this->position);
8293         $this->state = 'emit';
8294     }
8295 }
8296
8297 /**
8298  * gzdecode
8299  *
8300  * @package SimplePie
8301  */
8302 class SimplePie_gzdecode
8303 {
8304     /**
8305      * Compressed data
8306      *
8307      * @access private
8308      * @see gzdecode::$data
8309      */
8310     var $compressed_data;
8311
8312     /**
8313      * Size of compressed data
8314      *
8315      * @access private
8316      */
8317     var $compressed_size;
8318
8319     /**
8320      * Minimum size of a valid gzip string
8321      *
8322      * @access private
8323      */
8324     var $min_compressed_size = 18;
8325
8326     /**
8327      * Current position of pointer
8328      *
8329      * @access private
8330      */
8331     var $position = 0;
8332
8333     /**
8334      * Flags (FLG)
8335      *
8336      * @access private
8337      */
8338     var $flags;
8339
8340     /**
8341      * Uncompressed data
8342      *
8343      * @access public
8344      * @see gzdecode::$compressed_data
8345      */
8346     var $data;
8347
8348     /**
8349      * Modified time
8350      *
8351      * @access public
8352      */
8353     var $MTIME;
8354
8355     /**
8356      * Extra Flags
8357      *
8358      * @access public
8359      */
8360     var $XFL;
8361
8362     /**
8363      * Operating System
8364      *
8365      * @access public
8366      */
8367     var $OS;
8368
8369     /**
8370      * Subfield ID 1
8371      *
8372      * @access public
8373      * @see gzdecode::$extra_field
8374      * @see gzdecode::$SI2
8375      */
8376     var $SI1;
8377
8378     /**
8379      * Subfield ID 2
8380      *
8381      * @access public
8382      * @see gzdecode::$extra_field
8383      * @see gzdecode::$SI1
8384      */
8385     var $SI2;
8386
8387     /**
8388      * Extra field content
8389      *
8390      * @access public
8391      * @see gzdecode::$SI1
8392      * @see gzdecode::$SI2
8393      */
8394     var $extra_field;
8395
8396     /**
8397      * Original filename
8398      *
8399      * @access public
8400      */
8401     var $filename;
8402
8403     /**
8404      * Human readable comment
8405      *
8406      * @access public
8407      */
8408     var $comment;
8409
8410     /**
8411      * Don't allow anything to be set
8412      *
8413      * @access public
8414      */
8415     function __set($name, $value)
8416     {
8417         trigger_error("Cannot write property $name", E_USER_ERROR);
8418     }
8419
8420     /**
8421      * Set the compressed string and related properties
8422      *
8423      * @access public
8424      */
8425     function SimplePie_gzdecode($data)
8426     {
8427         $this->compressed_data = $data;
8428         $this->compressed_size = strlen($data);
8429     }
8430
8431     /**
8432      * Decode the GZIP stream
8433      *
8434      * @access public
8435      */
8436     function parse()
8437     {
8438         if ($this->compressed_size >= $this->min_compressed_size)
8439         {
8440             // Check ID1, ID2, and CM
8441             if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8442             {
8443                 return false;
8444             }
8445
8446             // Get the FLG (FLaGs)
8447             $this->flags = ord($this->compressed_data[3]);
8448
8449             // FLG bits above (1 << 4) are reserved
8450             if ($this->flags > 0x1F)
8451             {
8452                 return false;
8453             }
8454
8455             // Advance the pointer after the above
8456             $this->position += 4;
8457
8458             // MTIME
8459             $mtime = substr($this->compressed_data, $this->position, 4);
8460             // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8461             if (current(unpack('S', "\x00\x01")) === 1)
8462             {
8463                 $mtime = strrev($mtime);
8464             }
8465             $this->MTIME = current(unpack('l', $mtime));
8466             $this->position += 4;
8467
8468             // Get the XFL (eXtra FLags)
8469             $this->XFL = ord($this->compressed_data[$this->position++]);
8470
8471             // Get the OS (Operating System)
8472             $this->OS = ord($this->compressed_data[$this->position++]);
8473
8474             // Parse the FEXTRA
8475             if ($this->flags & 4)
8476             {
8477                 // Read subfield IDs
8478                 $this->SI1 = $this->compressed_data[$this->position++];
8479                 $this->SI2 = $this->compressed_data[$this->position++];
8480
8481                 // SI2 set to zero is reserved for future use
8482                 if ($this->SI2 === "\x00")
8483                 {
8484                     return false;
8485                 }
8486
8487                 // Get the length of the extra field
8488                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8489                 $position += 2;
8490
8491                 // Check the length of the string is still valid
8492                 $this->min_compressed_size += $len + 4;
8493                 if ($this->compressed_size >= $this->min_compressed_size)
8494                 {
8495                     // Set the extra field to the given data
8496                     $this->extra_field = substr($this->compressed_data, $this->position, $len);
8497                     $this->position += $len;
8498                 }
8499                 else
8500                 {
8501                     return false;
8502                 }
8503             }
8504
8505             // Parse the FNAME
8506             if ($this->flags & 8)
8507             {
8508                 // Get the length of the filename
8509                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8510
8511                 // Check the length of the string is still valid
8512                 $this->min_compressed_size += $len + 1;
8513                 if ($this->compressed_size >= $this->min_compressed_size)
8514                 {
8515                     // Set the original filename to the given string
8516                     $this->filename = substr($this->compressed_data, $this->position, $len);
8517                     $this->position += $len + 1;
8518                 }
8519                 else
8520                 {
8521                     return false;
8522                 }
8523             }
8524
8525             // Parse the FCOMMENT
8526             if ($this->flags & 16)
8527             {
8528                 // Get the length of the comment
8529                 $len = strcspn($this->compressed_data, "\x00", $this->position);
8530
8531                 // Check the length of the string is still valid
8532                 $this->min_compressed_size += $len + 1;
8533                 if ($this->compressed_size >= $this->min_compressed_size)
8534                 {
8535                     // Set the original comment to the given string
8536                     $this->comment = substr($this->compressed_data, $this->position, $len);
8537                     $this->position += $len + 1;
8538                 }
8539                 else
8540                 {
8541                     return false;
8542                 }
8543             }
8544
8545             // Parse the FHCRC
8546             if ($this->flags & 2)
8547             {
8548                 // Check the length of the string is still valid
8549                 $this->min_compressed_size += $len + 2;
8550                 if ($this->compressed_size >= $this->min_compressed_size)
8551                 {
8552                     // Read the CRC
8553                     $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8554
8555                     // Check the CRC matches
8556                     if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8557                     {
8558                         $this->position += 2;
8559                     }
8560                     else
8561                     {
8562                         return false;
8563                     }
8564                 }
8565                 else
8566                 {
8567                     return false;
8568                 }
8569             }
8570
8571             // Decompress the actual data
8572             if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8573             {
8574                 return false;
8575             }
8576             else
8577             {
8578                 $this->position = $this->compressed_size - 8;
8579             }
8580
8581             // Check CRC of data
8582             $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8583             $this->position += 4;
8584             /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8585             {
8586                 return false;
8587             }*/
8588
8589             // Check ISIZE of data
8590             $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8591             $this->position += 4;
8592             if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8593             {
8594                 return false;
8595             }
8596
8597             // Wow, against all odds, we've actually got a valid gzip string
8598             return true;
8599         }
8600         else
8601         {
8602             return false;
8603         }
8604     }
8605 }
8606
8607 class SimplePie_Cache
8608 {
8609     /**
8610      * Don't call the constructor. Please.
8611      *
8612      * @access private
8613      */
8614     function SimplePie_Cache()
8615     {
8616         trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8617     }
8618
8619     /**
8620      * Create a new SimplePie_Cache object
8621      *
8622      * @static
8623      * @access public
8624      */
8625     function create($location, $filename, $extension)
8626     {
f64c86 8627         $location_iri = new SimplePie_IRI($location);
fd9ef2 8628         switch ($location_iri->get_scheme())
T 8629         {
8630             case 'mysql':
8631                 if (extension_loaded('mysql'))
8632                 {
8633                     return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8634                 }
8635                 break;
8636
8637             default:
8638                 return new SimplePie_Cache_File($location, $filename, $extension);
8639         }
8640     }
8641 }
8642
8643 class SimplePie_Cache_File
8644 {
8645     var $location;
8646     var $filename;
8647     var $extension;
8648     var $name;
8649
8650     function SimplePie_Cache_File($location, $filename, $extension)
8651     {
8652         $this->location = $location;
8653         $this->filename = $filename;
8654         $this->extension = $extension;
8655         $this->name = "$this->location/$this->filename.$this->extension";
8656     }
8657
8658     function save($data)
8659     {
8660         if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8661         {
8662             if (is_a($data, 'SimplePie'))
8663             {
8664                 $data = $data->data;
8665             }
8666
8667             $data = serialize($data);
8668
8669             if (function_exists('file_put_contents'))
8670             {
8671                 return (bool) file_put_contents($this->name, $data);
8672             }
8673             else
8674             {
8675                 $fp = fopen($this->name, 'wb');
8676                 if ($fp)
8677                 {
8678                     fwrite($fp, $data);
8679                     fclose($fp);
8680                     return true;
8681                 }
8682             }
8683         }
8684         return false;
8685     }
8686
8687     function load()
8688     {
8689         if (file_exists($this->name) && is_readable($this->name))
8690         {
8691             return unserialize(file_get_contents($this->name));
8692         }
8693         return false;
8694     }
8695
8696     function mtime()
8697     {
8698         if (file_exists($this->name))
8699         {
8700             return filemtime($this->name);
8701         }
8702         return false;
8703     }
8704
8705     function touch()
8706     {
8707         if (file_exists($this->name))
8708         {
8709             return touch($this->name);
8710         }
8711         return false;
8712     }
8713
8714     function unlink()
8715     {
8716         if (file_exists($this->name))
8717         {
8718             return unlink($this->name);
8719         }
8720         return false;
8721     }
8722 }
8723
8724 class SimplePie_Cache_DB
8725 {
8726     function prepare_simplepie_object_for_cache($data)
8727     {
8728         $items = $data->get_items();
8729         $items_by_id = array();
8730
8731         if (!empty($items))
8732         {
8733             foreach ($items as $item)
8734             {
8735                 $items_by_id[$item->get_id()] = $item;
8736             }
8737
8738             if (count($items_by_id) !== count($items))
8739             {
8740                 $items_by_id = array();
8741                 foreach ($items as $item)
8742                 {
8743                     $items_by_id[$item->get_id(true)] = $item;
8744                 }
8745             }
8746
8747             if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8748             {
8749                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8750             }
8751             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8752             {
8753                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8754             }
8755             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8756             {
8757                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8758             }
8759             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8760             {
8761                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8762             }
8763             else
8764             {
8765                 $channel = null;
8766             }
8767
8768             if ($channel !== null)
8769             {
8770                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8771                 {
8772                     unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8773                 }
8774                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8775                 {
8776                     unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8777                 }
8778                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8779                 {
8780                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8781                 }
8782                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8783                 {
8784                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8785                 }
8786                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8787                 {
8788                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8789                 }
8790             }
8791             if (isset($data->data['items']))
8792             {
8793                 unset($data->data['items']);
8794             }
8795             if (isset($data->data['ordered_items']))
8796             {
8797                 unset($data->data['ordered_items']);
8798             }
8799         }
8800         return array(serialize($data->data), $items_by_id);
8801     }
8802 }
8803
8804 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8805 {
8806     var $mysql;
8807     var $options;
8808     var $id;
8809
8810     function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8811     {
8812         $host = $mysql_location->get_host();
8813         if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8814         {
8815             $server = ':' . substr($host, 5, -1);
8816         }
8817         else
8818         {
8819             $server = $host;
8820             if ($mysql_location->get_port() !== null)
8821             {
8822                 $server .= ':' . $mysql_location->get_port();
8823             }
8824         }
8825
8826         if (strpos($mysql_location->get_userinfo(), ':') !== false)
8827         {
8828             list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8829         }
8830         else
8831         {
8832             $username = $mysql_location->get_userinfo();
8833             $password = null;
8834         }
8835
8836         if ($this->mysql = mysql_connect($server, $username, $password))
8837         {
8838             $this->id = $name . $extension;
8839             $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8840             if (!isset($this->options['prefix'][0]))
8841             {
8842                 $this->options['prefix'][0] = '';
8843             }
8844
8845             if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8846                 && mysql_query('SET NAMES utf8')
8847                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8848             {
8849                 $db = array();
8850                 while ($row = mysql_fetch_row($query))
8851                 {
8852                     $db[] = $row[0];
8853                 }
8854
8855                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8856                 {
8857                     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)))'))
8858                     {
8859                         $this->mysql = null;
8860                     }
8861                 }
8862
8863                 if (!in_array($this->options['prefix'][0] . 'items', $db))
8864                 {
8865                     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)))'))
8866                     {
8867                         $this->mysql = null;
8868                     }
8869                 }
8870             }
8871             else
8872             {
8873                 $this->mysql = null;
8874             }
8875         }
8876     }
8877
8878     function save($data)
8879     {
8880         if ($this->mysql)
8881         {
8882             $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8883
8884             if (is_a($data, 'SimplePie'))
8885             {
8886                 if (SIMPLEPIE_PHP5)
8887                 {
8888                     // This keyword needs to defy coding standards for PHP4 compatibility
8889                     $data = clone($data);
8890                 }
8891
8892                 $prepared = $this->prepare_simplepie_object_for_cache($data);
8893
8894                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8895                 {
8896                     if (mysql_num_rows($query))
8897                     {
8898                         $items = count($prepared[1]);
8899                         if ($items)
8900                         {
8901                             $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8902                         }
8903                         else
8904                         {
8905                             $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8906                         }
8907
8908                         if (!mysql_query($sql, $this->mysql))
8909                         {
8910                             return false;
8911                         }
8912                     }
8913                     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))
8914                     {
8915                         return false;
8916                     }
8917
8918                     $ids = array_keys($prepared[1]);
8919                     if (!empty($ids))
8920                     {
8921                         foreach ($ids as $id)
8922                         {
8923                             $database_ids[] = mysql_real_escape_string($id);
8924                         }
8925
8926                         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))
8927                         {
8928                             $existing_ids = array();
8929                             while ($row = mysql_fetch_row($query))
8930                             {
8931                                 $existing_ids[] = $row[0];
8932                             }
8933
8934                             $new_ids = array_diff($ids, $existing_ids);
8935
8936                             foreach ($new_ids as $new_id)
8937                             {
8938                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
8939                                 {
8940                                     $date = time();
8941                                 }
8942
8943                                 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))
8944                                 {
8945                                     return false;
8946                                 }
8947                             }
8948                             return true;
8949                         }
8950                     }
8951                     else
8952                     {
8953                         return true;
8954                     }
8955                 }
8956             }
8957             elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8958             {
8959                 if (mysql_num_rows($query))
8960                 {
8961                     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))
8962                     {
8963                         return true;
8964                     }
8965                 }
8966                 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))
8967                 {
8968                     return true;
8969                 }
8970             }
8971         }
8972         return false;
8973     }
8974
8975     function load()
8976     {
8977         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)))
8978         {
8979             $data = unserialize($row[1]);
8980
8981             if (isset($this->options['items'][0]))
8982             {
8983                 $items = (int) $this->options['items'][0];
8984             }
8985             else
8986             {
8987                 $items = (int) $row[0];
8988             }
8989
8990             if ($items !== 0)
8991             {
8992                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8993                 {
8994                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8995                 }
8996                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8997                 {
8998                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8999                 }
9000                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9001                 {
9002                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9003                 }
9004                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9005                 {
9006                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9007                 }
9008                 else
9009                 {
9010                     $feed = null;
9011                 }
9012
9013                 if ($feed !== null)
9014                 {
9015                     $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9016                     if ($items > 0)
9017                     {
9018                         $sql .= ' LIMIT ' . $items;
9019                     }
9020
9021                     if ($query = mysql_unbuffered_query($sql, $this->mysql))
9022                     {
9023                         while ($row = mysql_fetch_row($query))
9024                         {
9025                             $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9026                         }
9027                     }
9028                     else
9029                     {
9030                         return false;
9031                     }
9032                 }
9033             }
9034             return $data;
9035         }
9036         return false;
9037     }
9038
9039     function mtime()
9040     {
9041         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)))
9042         {
9043             return $row[0];
9044         }
9045         else
9046         {
9047             return false;
9048         }
9049     }
9050
9051     function touch()
9052     {
9053         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))
9054         {
9055             return true;
9056         }
9057         else
9058         {
9059             return false;
9060         }
9061     }
9062
9063     function unlink()
9064     {
9065         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)))
9066         {
9067             return true;
9068         }
9069         else
9070         {
9071             return false;
9072         }
9073     }
9074 }
9075
9076 class SimplePie_Misc
9077 {
9078     function time_hms($seconds)
9079     {
9080         $time = '';
9081
9082         $hours = floor($seconds / 3600);
9083         $remainder = $seconds % 3600;
9084         if ($hours > 0)
9085         {
9086             $time .= $hours.':';
9087         }
9088
9089         $minutes = floor($remainder / 60);
9090         $seconds = $remainder % 60;
9091         if ($minutes < 10 && $hours > 0)
9092         {
9093             $minutes = '0' . $minutes;
9094         }
9095         if ($seconds < 10)
9096         {
9097             $seconds = '0' . $seconds;
9098         }
9099
9100         $time .= $minutes.':';
9101         $time .= $seconds;
9102
9103         return $time;
9104     }
9105
72695f 9106     static function absolutize_url($relative, $base)
fd9ef2 9107     {
T 9108         $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9109         return $iri->get_iri();
9110     }
9111
9112     function remove_dot_segments($input)
9113     {
9114         $output = '';
9115         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9116         {
9117             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9118             if (strpos($input, '../') === 0)
9119             {
9120                 $input = substr($input, 3);
9121             }
9122             elseif (strpos($input, './') === 0)
9123             {
9124                 $input = substr($input, 2);
9125             }
9126             // 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,
9127             elseif (strpos($input, '/./') === 0)
9128             {
9129                 $input = substr_replace($input, '/', 0, 3);
9130             }
9131             elseif ($input === '/.')
9132             {
9133                 $input = '/';
9134             }
9135             // 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,
9136             elseif (strpos($input, '/../') === 0)
9137             {
9138                 $input = substr_replace($input, '/', 0, 4);
9139                 $output = substr_replace($output, '', strrpos($output, '/'));
9140             }
9141             elseif ($input === '/..')
9142             {
9143                 $input = '/';
9144                 $output = substr_replace($output, '', strrpos($output, '/'));
9145             }
9146             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9147             elseif ($input === '.' || $input === '..')
9148             {
9149                 $input = '';
9150             }
9151             // 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
9152             elseif (($pos = strpos($input, '/', 1)) !== false)
9153             {
9154                 $output .= substr($input, 0, $pos);
9155                 $input = substr_replace($input, '', 0, $pos);
9156             }
9157             else
9158             {
9159                 $output .= $input;
9160                 $input = '';
9161             }
9162         }
9163         return $output . $input;
9164     }
9165
72695f 9166     static function get_element($realname, $string)
fd9ef2 9167     {
T 9168         $return = array();
9169         $name = preg_quote($realname, '/');
9170         if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9171         {
9172             for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9173             {
9174                 $return[$i]['tag'] = $realname;
9175                 $return[$i]['full'] = $matches[$i][0][0];
9176                 $return[$i]['offset'] = $matches[$i][0][1];
9177                 if (strlen($matches[$i][3][0]) <= 2)
9178                 {
9179                     $return[$i]['self_closing'] = true;
9180                 }
9181                 else
9182                 {
9183                     $return[$i]['self_closing'] = false;
9184                     $return[$i]['content'] = $matches[$i][4][0];
9185                 }
9186                 $return[$i]['attribs'] = array();
9187                 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))
9188                 {
9189                     for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9190                     {
9191                         if (count($attribs[$j]) === 2)
9192                         {
9193                             $attribs[$j][2] = $attribs[$j][1];
9194                         }
9195                         $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9196                     }
9197                 }
9198             }
9199         }
9200         return $return;
9201     }
9202
9203     function element_implode($element)
9204     {
9205         $full = "<$element[tag]";
9206         foreach ($element['attribs'] as $key => $value)
9207         {
9208             $key = strtolower($key);
9209             $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9210         }
9211         if ($element['self_closing'])
9212         {
9213             $full .= ' />';
9214         }
9215         else
9216         {
9217             $full .= ">$element[content]</$element[tag]>";
9218         }
9219         return $full;
9220     }
9221
9222     function error($message, $level, $file, $line)
9223     {
9224         if ((ini_get('error_reporting') & $level) > 0)
9225         {
9226             switch ($level)
9227             {
9228                 case E_USER_ERROR:
9229                     $note = 'PHP Error';
9230                     break;
9231                 case E_USER_WARNING:
9232                     $note = 'PHP Warning';
9233                     break;
9234                 case E_USER_NOTICE:
9235                     $note = 'PHP Notice';
9236                     break;
9237                 default:
9238                     $note = 'Unknown Error';
9239                     break;
9240             }
9241
9242             $log_error = true;
9243             if (!function_exists('error_log'))
9244             {
9245                 $log_error = false;
9246             }
9247
9248             $log_file = @ini_get('error_log');
9249             if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9250             {
9251                 $log_error = false;
9252             }
9253
9254             if ($log_error)
9255             {
9256                 @error_log("$note: $message in $file on line $line", 0);
9257             }
9258         }
9259
9260         return $message;
9261     }
9262
9263     /**
9264      * If a file has been cached, retrieve and display it.
9265      *
9266      * This is most useful for caching images (get_favicon(), etc.),
9267      * however it works for all cached files.  This WILL NOT display ANY
9268      * file/image/page/whatever, but rather only display what has already
9269      * been cached by SimplePie.
9270      *
9271      * @access public
9272      * @see SimplePie::get_favicon()
9273      * @param str $identifier_url URL that is used to identify the content.
9274      * This may or may not be the actual URL of the live content.
9275      * @param str $cache_location Location of SimplePie's cache.  Defaults
9276      * to './cache'.
9277      * @param str $cache_extension The file extension that the file was
9278      * cached with.  Defaults to 'spc'.
9279      * @param str $cache_class Name of the cache-handling class being used
9280      * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
9281      * as-is unless you've overloaded the class.
9282      * @param str $cache_name_function Obsolete. Exists for backwards
9283      * compatibility reasons only.
9284      */
9285     function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9286     {
9287         $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9288
9289         if ($file = $cache->load())
9290         {
9291             if (isset($file['headers']['content-type']))
9292             {
9293                 header('Content-type:' . $file['headers']['content-type']);
9294             }
9295             else
9296             {
9297                 header('Content-type: application/octet-stream');
9298             }
9299             header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9300             echo $file['body'];
9301             exit;
9302         }
9303
9304         die('Cached file for ' . $identifier_url . ' cannot be found.');
9305     }
9306
526b99 9307     public static function fix_protocol($url, $http = 1)
fd9ef2 9308     {
T 9309         $url = SimplePie_Misc::normalize_url($url);
9310         $parsed = SimplePie_Misc::parse_url($url);
9311         if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9312         {
9313             return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9314         }
9315
9316         if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9317         {
9318             return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9319         }
9320
9321         if ($http === 2 && $parsed['scheme'] !== '')
9322         {
9323             return "feed:$url";
9324         }
9325         elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9326         {
9327             return substr_replace($url, 'podcast', 0, 4);
9328         }
9329         elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9330         {
9331             return substr_replace($url, 'itpc', 0, 4);
9332         }
9333         else
9334         {
9335             return $url;
9336         }
9337     }
9338
526b99 9339     public static function parse_url($url)
fd9ef2 9340     {
f64c86 9341         $iri = new SimplePie_IRI($url);
fd9ef2 9342         return array(
T 9343             'scheme' => (string) $iri->get_scheme(),
9344             'authority' => (string) $iri->get_authority(),
9345             'path' => (string) $iri->get_path(),
9346             'query' => (string) $iri->get_query(),
9347             'fragment' => (string) $iri->get_fragment()
9348         );
9349     }
9350
9351     function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9352     {
f64c86 9353         $iri = new SimplePie_IRI('');
fd9ef2 9354         $iri->set_scheme($scheme);
T 9355         $iri->set_authority($authority);
9356         $iri->set_path($path);
9357         $iri->set_query($query);
9358         $iri->set_fragment($fragment);
9359         return $iri->get_iri();
9360     }
9361
526b99 9362     public static function normalize_url($url)
fd9ef2 9363     {
f64c86 9364         $iri = new SimplePie_IRI($url);
fd9ef2 9365         return $iri->get_iri();
T 9366     }
9367
9368     function percent_encoding_normalization($match)
9369     {
9370         $integer = hexdec($match[1]);
9371         if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9372         {
9373             return chr($integer);
9374         }
9375         else
9376         {
9377             return strtoupper($match[0]);
9378         }
9379     }
9380
9381     /**
9382      * Remove bad UTF-8 bytes
9383      *
9384      * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9385      * FAQ: Multilingual Forms (modified to include full ASCII range)
9386      *
9387      * @author Geoffrey Sneddon
9388      * @see http://www.w3.org/International/questions/qa-forms-utf-8
9389      * @param string $str String to remove bad UTF-8 bytes from
9390      * @return string UTF-8 string
9391      */
9392     function utf8_bad_replace($str)
9393     {
9394         if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9395         {
9396             return $return;
9397         }
9398         elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9399         {
9400             return $return;
9401         }
9402         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))
9403         {
9404             return implode("\xEF\xBF\xBD", $matches[0]);
9405         }
9406         elseif ($str !== '')
9407         {
9408             return "\xEF\xBF\xBD";
9409         }
9410         else
9411         {
9412             return '';
9413         }
9414     }
9415
9416     /**
9417      * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9418      *
9419      * @static
9420      * @access public
9421      * @param string $string Windows-1252 encoded string
9422      * @return string UTF-8 encoded string
9423      */
9424     function windows_1252_to_utf8($string)
9425     {
9426         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");
9427
9428         return strtr($string, $convert_table);
9429     }
9430
526b99 9431     public static function change_encoding($data, $input, $output)
fd9ef2 9432     {
T 9433         $input = SimplePie_Misc::encoding($input);
9434         $output = SimplePie_Misc::encoding($output);
9435
9436         // We fail to fail on non US-ASCII bytes
9437         if ($input === 'US-ASCII')
9438         {
9439             static $non_ascii_octects = '';
9440             if (!$non_ascii_octects)
9441             {
9442                 for ($i = 0x80; $i <= 0xFF; $i++)
9443                 {
9444                     $non_ascii_octects .= chr($i);
9445                 }
9446             }
9447             $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9448         }
9449
9450         // This is first, as behaviour of this is completely predictable
9451         if ($input === 'Windows-1252' && $output === 'UTF-8')
9452         {
9453             return SimplePie_Misc::windows_1252_to_utf8($data);
9454         }
9455         // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9456         elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9457         {
9458             return $return;
9459         }
9460         // This is last, as behaviour of this varies with OS userland and PHP version
9461         elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9462         {
9463             return $return;
9464         }
9465         // If we can't do anything, just fail
9466         else
9467         {
9468             return false;
9469         }
9470     }
9471
526b99 9472     public static function encoding($charset)
fd9ef2 9473     {
T 9474         // Normalization from UTS #22
9475         switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9476         {
9477             case 'adobestandardencoding':
9478             case 'csadobestandardencoding':
9479                 return 'Adobe-Standard-Encoding';
9480
9481             case 'adobesymbolencoding':
9482             case 'cshppsmath':
9483                 return 'Adobe-Symbol-Encoding';
9484
9485             case 'ami1251':
9486             case 'amiga1251':
9487                 return 'Amiga-1251';
9488
9489             case 'ansix31101983':
9490             case 'csat5001983':
9491             case 'csiso99naplps':
9492             case 'isoir99':
9493             case 'naplps':
9494                 return 'ANSI_X3.110-1983';
9495
9496             case 'arabic7':
9497             case 'asmo449':
9498             case 'csiso89asmo449':
9499             case 'iso9036':
9500             case 'isoir89':
9501                 return 'ASMO_449';
9502
9503             case 'big5':
9504             case 'csbig5':
9505             case 'xxbig5':
9506                 return 'Big5';
9507
9508             case 'big5hkscs':
9509                 return 'Big5-HKSCS';
9510
9511             case 'bocu1':
9512             case 'csbocu1':
9513                 return 'BOCU-1';
9514
9515             case 'brf':
9516             case 'csbrf':
9517                 return 'BRF';
9518
9519             case 'bs4730':
9520             case 'csiso4unitedkingdom':
9521             case 'gb':
9522             case 'iso646gb':
9523             case 'isoir4':
9524             case 'uk':
9525                 return 'BS_4730';
9526
9527             case 'bsviewdata':
9528             case 'csiso47bsviewdata':
9529             case 'isoir47':
9530                 return 'BS_viewdata';
9531
9532             case 'cesu8':
9533             case 'cscesu8':
9534                 return 'CESU-8';
9535
9536             case 'ca':
9537             case 'csa71':
9538             case 'csaz243419851':
9539             case 'csiso121canadian1':
9540             case 'iso646ca':
9541             case 'isoir121':
9542                 return 'CSA_Z243.4-1985-1';
9543
9544             case 'csa72':
9545             case 'csaz243419852':
9546             case 'csiso122canadian2':
9547             case 'iso646ca2':
9548             case 'isoir122':
9549                 return 'CSA_Z243.4-1985-2';
9550
9551             case 'csaz24341985gr':
9552             case 'csiso123csaz24341985gr':
9553             case 'isoir123':
9554                 return 'CSA_Z243.4-1985-gr';
9555
9556             case 'csiso139csn369103':
9557             case 'csn369103':
9558             case 'isoir139':
9559                 return 'CSN_369103';
9560
9561             case 'csdecmcs':
9562             case 'dec':
9563             case 'decmcs':
9564                 return 'DEC-MCS';
9565
9566             case 'csiso21german':
9567             case 'de':
9568             case 'din66003':
9569             case 'iso646de':
9570             case 'isoir21':
9571                 return 'DIN_66003';
9572
9573             case 'csdkus':
9574             case 'dkus':
9575                 return 'dk-us';
9576
9577             case 'csiso646danish':
9578             case 'dk':
9579             case 'ds2089':
9580             case 'iso646dk':
9581                 return 'DS_2089';
9582
9583             case 'csibmebcdicatde':
9584             case 'ebcdicatde':
9585                 return 'EBCDIC-AT-DE';
9586
9587             case 'csebcdicatdea':
9588             case 'ebcdicatdea':
9589                 return 'EBCDIC-AT-DE-A';
9590
9591             case 'csebcdiccafr':
9592             case 'ebcdiccafr':
9593                 return 'EBCDIC-CA-FR';
9594
9595             case 'csebcdicdkno':
9596             case 'ebcdicdkno':
9597                 return 'EBCDIC-DK-NO';
9598
9599             case 'csebcdicdknoa':
9600             case 'ebcdicdknoa':
9601                 return 'EBCDIC-DK-NO-A';
9602
9603             case 'csebcdices':
9604             case 'ebcdices':
9605                 return 'EBCDIC-ES';
9606
9607             case 'csebcdicesa':
9608             case 'ebcdicesa':
9609                 return 'EBCDIC-ES-A';
9610
9611             case 'csebcdicess':
9612             case 'ebcdicess':
9613                 return 'EBCDIC-ES-S';
9614
9615             case 'csebcdicfise':
9616             case 'ebcdicfise':
9617                 return 'EBCDIC-FI-SE';
9618
9619             case 'csebcdicfisea':
9620             case 'ebcdicfisea':
9621                 return 'EBCDIC-FI-SE-A';
9622
9623             case 'csebcdicfr':
9624             case 'ebcdicfr':
9625                 return 'EBCDIC-FR';
9626
9627             case 'csebcdicit':
9628             case 'ebcdicit':
9629                 return 'EBCDIC-IT';
9630
9631             case 'csebcdicpt':
9632             case 'ebcdicpt':
9633                 return 'EBCDIC-PT';
9634
9635             case 'csebcdicuk':
9636             case 'ebcdicuk':
9637                 return 'EBCDIC-UK';
9638
9639             case 'csebcdicus':
9640             case 'ebcdicus':
9641                 return 'EBCDIC-US';
9642
9643             case 'csiso111ecmacyrillic':
9644             case 'ecmacyrillic':
9645             case 'isoir111':
9646             case 'koi8e':
9647                 return 'ECMA-cyrillic';
9648
9649             case 'csiso17spanish':
9650             case 'es':
9651             case 'iso646es':
9652             case 'isoir17':
9653                 return 'ES';
9654
9655             case 'csiso85spanish2':
9656             case 'es2':
9657             case 'iso646es2':
9658             case 'isoir85':
9659                 return 'ES2';
9660
9661             case 'cseucfixwidjapanese':
9662             case 'extendedunixcodefixedwidthforjapanese':
9663                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9664
9665             case 'cseucpkdfmtjapanese':
9666             case 'eucjp':
9667             case 'extendedunixcodepackedformatforjapanese':
9668                 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9669
9670             case 'gb18030':
9671                 return 'GB18030';
9672
9673             case 'chinese':
9674             case 'cp936':
9675             case 'csgb2312':
9676             case 'csiso58gb231280':
9677             case 'gb2312':
9678             case 'gb231280':
9679             case 'gbk':
9680             case 'isoir58':
9681             case 'ms936':
9682             case 'windows936':
9683                 return 'GBK';
9684
9685             case 'cn':
9686             case 'csiso57gb1988':
9687             case 'gb198880':
9688             case 'iso646cn':
9689             case 'isoir57':
9690                 return 'GB_1988-80';
9691
9692             case 'csiso153gost1976874':
9693             case 'gost1976874':
9694             case 'isoir153':
9695             case 'stsev35888':
9696                 return 'GOST_19768-74';
9697
9698             case 'csiso150':
9699             case 'csiso150greekccitt':
9700             case 'greekccitt':
9701             case 'isoir150':
9702                 return 'greek-ccitt';
9703
9704             case 'csiso88greek7':
9705             case 'greek7':
9706             case 'isoir88':
9707                 return 'greek7';
9708
9709             case 'csiso18greek7old':
9710             case 'greek7old':
9711             case 'isoir18':
9712                 return 'greek7-old';
9713
9714             case 'cshpdesktop':
9715             case 'hpdesktop':
9716                 return 'HP-DeskTop';
9717
9718             case 'cshplegal':
9719             case 'hplegal':
9720                 return 'HP-Legal';
9721
9722             case 'cshpmath8':
9723             case 'hpmath8':
9724                 return 'HP-Math8';
9725
9726             case 'cshppifont':
9727             case 'hppifont':
9728                 return 'HP-Pi-font';
9729
9730             case 'cshproman8':
9731             case 'hproman8':
9732             case 'r8':
9733             case 'roman8':
9734                 return 'hp-roman8';
9735
9736             case 'hzgb2312':
9737                 return 'HZ-GB-2312';
9738
9739             case 'csibmsymbols':
9740             case 'ibmsymbols':
9741                 return 'IBM-Symbols';
9742
9743             case 'csibmthai':
9744             case 'ibmthai':
9745                 return 'IBM-Thai';
9746
9747             case 'ccsid858':
9748             case 'cp858':
9749             case 'ibm858':
9750             case 'pcmultilingual850euro':
9751                 return 'IBM00858';
9752
9753             case 'ccsid924':
9754             case 'cp924':
9755             case 'ebcdiclatin9euro':
9756             case 'ibm924':
9757                 return 'IBM00924';
9758
9759             case 'ccsid1140':
9760             case 'cp1140':
9761             case 'ebcdicus37euro':
9762             case 'ibm1140':
9763                 return 'IBM01140';
9764
9765             case 'ccsid1141':
9766             case 'cp1141':
9767             case 'ebcdicde273euro':
9768             case 'ibm1141':
9769                 return 'IBM01141';
9770
9771             case 'ccsid1142':
9772             case 'cp1142':
9773             case 'ebcdicdk277euro':
9774             case 'ebcdicno277euro':
9775             case 'ibm1142':
9776                 return 'IBM01142';
9777
9778             case 'ccsid1143':
9779             case 'cp1143':
9780             case 'ebcdicfi278euro':
9781             case 'ebcdicse278euro':
9782             case 'ibm1143':
9783                 return 'IBM01143';
9784
9785             case 'ccsid1144':
9786             case 'cp1144':
9787             case 'ebcdicit280euro':
9788             case 'ibm1144':
9789                 return 'IBM01144';
9790
9791             case 'ccsid1145':
9792             case 'cp1145':
9793             case 'ebcdices284euro':
9794             case 'ibm1145':
9795                 return 'IBM01145';
9796
9797             case 'ccsid1146':
9798             case 'cp1146':
9799             case 'ebcdicgb285euro':
9800             case 'ibm1146':
9801                 return 'IBM01146';
9802
9803             case 'ccsid1147':
9804             case 'cp1147':
9805             case 'ebcdicfr297euro':
9806             case 'ibm1147':
9807                 return 'IBM01147';
9808
9809             case 'ccsid1148':
9810             case 'cp1148':
9811             case 'ebcdicinternational500euro':
9812             case 'ibm1148':
9813                 return 'IBM01148';
9814
9815             case 'ccsid1149':
9816             case 'cp1149':
9817             case 'ebcdicis871euro':
9818             case 'ibm1149':
9819                 return 'IBM01149';
9820
9821             case 'cp37':
9822             case 'csibm37':
9823             case 'ebcdiccpca':
9824             case 'ebcdiccpnl':
9825             case 'ebcdiccpus':
9826             case 'ebcdiccpwt':
9827             case 'ibm37':
9828                 return 'IBM037';
9829
9830             case 'cp38':
9831             case 'csibm38':
9832             case 'ebcdicint':
9833             case 'ibm38':
9834                 return 'IBM038';
9835
9836             case 'cp273':
9837             case 'csibm273':
9838             case 'ibm273':
9839                 return 'IBM273';
9840
9841             case 'cp274':
9842             case 'csibm274':
9843             case 'ebcdicbe':
9844             case 'ibm274':
9845                 return 'IBM274';
9846
9847             case 'cp275':
9848             case 'csibm275':
9849             case 'ebcdicbr':
9850             case 'ibm275':
9851                 return 'IBM275';
9852
9853             case 'csibm277':
9854             case 'ebcdiccpdk':
9855             case 'ebcdiccpno':
9856             case 'ibm277':
9857                 return 'IBM277';
9858
9859             case 'cp278':
9860             case 'csibm278':
9861             case 'ebcdiccpfi':
9862             case 'ebcdiccpse':
9863             case 'ibm278':
9864                 return 'IBM278';
9865
9866             case 'cp280':
9867             case 'csibm280':
9868             case 'ebcdiccpit':
9869             case 'ibm280':
9870                 return 'IBM280';
9871
9872             case 'cp281':
9873             case 'csibm281':
9874             case 'ebcdicjpe':
9875             case 'ibm281':
9876                 return 'IBM281';
9877
9878             case 'cp284':
9879             case 'csibm284':
9880             case 'ebcdiccpes':
9881             case 'ibm284':
9882                 return 'IBM284';
9883
9884             case 'cp285':
9885             case 'csibm285':
9886             case 'ebcdiccpgb':
9887             case 'ibm285':
9888                 return 'IBM285';
9889
9890             case 'cp290':
9891             case 'csibm290':
9892             case 'ebcdicjpkana':
9893             case 'ibm290':
9894                 return 'IBM290';
9895
9896             case 'cp297':
9897             case 'csibm297':
9898             case 'ebcdiccpfr':
9899             case 'ibm297':
9900                 return 'IBM297';
9901
9902             case 'cp420':
9903             case 'csibm420':
9904             case 'ebcdiccpar1':
9905             case 'ibm420':
9906                 return 'IBM420';
9907
9908             case 'cp423':
9909             case 'csibm423':
9910             case 'ebcdiccpgr':
9911             case 'ibm423':
9912                 return 'IBM423';
9913
9914             case 'cp424':
9915             case 'csibm424':
9916             case 'ebcdiccphe':
9917             case 'ibm424':
9918                 return 'IBM424';
9919
9920             case '437':
9921             case 'cp437':
9922             case 'cspc8codepage437':
9923             case 'ibm437':
9924                 return 'IBM437';
9925
9926             case 'cp500':
9927             case 'csibm500':
9928             case 'ebcdiccpbe':
9929             case 'ebcdiccpch':
9930             case 'ibm500':
9931                 return 'IBM500';
9932
9933             case 'cp775':
9934             case 'cspc775baltic':
9935             case 'ibm775':
9936                 return 'IBM775';
9937
9938             case '850':
9939             case 'cp850':
9940             case 'cspc850multilingual':
9941             case 'ibm850':
9942                 return 'IBM850';
9943
9944             case '851':
9945             case 'cp851':
9946             case 'csibm851':
9947             case 'ibm851':
9948                 return 'IBM851';
9949
9950             case '852':
9951             case 'cp852':
9952             case 'cspcp852':
9953             case 'ibm852':
9954                 return 'IBM852';
9955
9956             case '855':
9957             case 'cp855':
9958             case 'csibm855':
9959             case 'ibm855':
9960                 return 'IBM855';
9961
9962             case '857':
9963             case 'cp857':
9964             case 'csibm857':
9965             case 'ibm857':
9966                 return 'IBM857';
9967
9968             case '860':
9969             case 'cp860':
9970             case 'csibm860':
9971             case 'ibm860':
9972                 return 'IBM860';
9973
9974             case '861':
9975             case 'cp861':
9976             case 'cpis':
9977             case 'csibm861':
9978             case 'ibm861':
9979                 return 'IBM861';
9980
9981             case '862':
9982             case 'cp862':
9983             case 'cspc862latinhebrew':
9984             case 'ibm862':
9985                 return 'IBM862';
9986
9987             case '863':
9988             case 'cp863':
9989             case 'csibm863':
9990             case 'ibm863':
9991                 return 'IBM863';
9992
9993             case 'cp864':
9994             case 'csibm864':
9995             case 'ibm864':
9996                 return 'IBM864';
9997
9998             case '865':
9999             case 'cp865':
10000             case 'csibm865':
10001             case 'ibm865':
10002                 return 'IBM865';
10003
10004             case '866':
10005             case 'cp866':
10006             case 'csibm866':
10007             case 'ibm866':
10008                 return 'IBM866';
10009
10010             case 'cp868':
10011             case 'cpar':
10012             case 'csibm868':
10013             case 'ibm868':
10014                 return 'IBM868';
10015
10016             case '869':
10017             case 'cp869':
10018             case 'cpgr':
10019             case 'csibm869':
10020             case 'ibm869':
10021                 return 'IBM869';
10022
10023             case 'cp870':
10024             case 'csibm870':
10025             case 'ebcdiccproece':
10026             case 'ebcdiccpyu':
10027             case 'ibm870':
10028                 return 'IBM870';
10029
10030             case 'cp871':
10031             case 'csibm871':
10032             case 'ebcdiccpis':
10033             case 'ibm871':
10034                 return 'IBM871';
10035
10036             case 'cp880':
10037             case 'csibm880':
10038             case 'ebcdiccyrillic':
10039             case 'ibm880':
10040                 return 'IBM880';
10041
10042             case 'cp891':
10043             case 'csibm891':
10044             case 'ibm891':
10045                 return 'IBM891';
10046
10047             case 'cp903':
10048             case 'csibm903':
10049             case 'ibm903':
10050                 return 'IBM903';
10051
10052             case '904':
10053             case 'cp904':
10054             case 'csibbm904':
10055             case 'ibm904':
10056                 return 'IBM904';
10057
10058             case 'cp905':
10059             case 'csibm905':
10060             case 'ebcdiccptr':
10061             case 'ibm905':
10062                 return 'IBM905';
10063
10064             case 'cp918':
10065             case 'csibm918':
10066             case 'ebcdiccpar2':
10067             case 'ibm918':
10068                 return 'IBM918';
10069
10070             case 'cp1026':
10071             case 'csibm1026':
10072             case 'ibm1026':
10073                 return 'IBM1026';
10074
10075             case 'ibm1047':
10076                 return 'IBM1047';
10077
10078             case 'csiso143iecp271':
10079             case 'iecp271':
10080             case 'isoir143':
10081                 return 'IEC_P27-1';
10082
10083             case 'csiso49inis':
10084             case 'inis':
10085             case 'isoir49':
10086                 return 'INIS';
10087
10088             case 'csiso50inis8':
10089             case 'inis8':
10090             case 'isoir50':
10091                 return 'INIS-8';
10092
10093             case 'csiso51iniscyrillic':
10094             case 'iniscyrillic':
10095             case 'isoir51':
10096                 return 'INIS-cyrillic';
10097
10098             case 'csinvariant':
10099             case 'invariant':
10100                 return 'INVARIANT';
10101
10102             case 'iso2022cn':
10103                 return 'ISO-2022-CN';
10104
10105             case 'iso2022cnext':
10106                 return 'ISO-2022-CN-EXT';
10107
10108             case 'csiso2022jp':
10109             case 'iso2022jp':
10110                 return 'ISO-2022-JP';
10111
10112             case 'csiso2022jp2':
10113             case 'iso2022jp2':
10114                 return 'ISO-2022-JP-2';
10115
10116             case 'csiso2022kr':
10117             case 'iso2022kr':
10118                 return 'ISO-2022-KR';
10119
10120             case 'cswindows30latin1':
10121             case 'iso88591windows30latin1':
10122                 return 'ISO-8859-1-Windows-3.0-Latin-1';
10123
10124             case 'cswindows31latin1':
10125             case 'iso88591windows31latin1':
10126                 return 'ISO-8859-1-Windows-3.1-Latin-1';
10127
10128             case 'csisolatin2':
10129             case 'iso88592':
10130             case 'iso885921987':
10131             case 'isoir101':
10132             case 'l2':
10133             case 'latin2':
10134                 return 'ISO-8859-2';
10135
10136             case 'cswindows31latin2':
10137             case 'iso88592windowslatin2':
10138                 return 'ISO-8859-2-Windows-Latin-2';
10139
10140             case 'csisolatin3':
10141             case 'iso88593':
10142             case 'iso885931988':
10143             case 'isoir109':
10144             case 'l3':
10145             case 'latin3':
10146                 return 'ISO-8859-3';
10147
10148             case 'csisolatin4':
10149             case 'iso88594':
10150             case 'iso885941988':
10151             case 'isoir110':
10152             case 'l4':
10153             case 'latin4':
10154                 return 'ISO-8859-4';
10155
10156             case 'csisolatincyrillic':
10157             case 'cyrillic':
10158             case 'iso88595':
10159             case 'iso885951988':
10160             case 'isoir144':
10161                 return 'ISO-8859-5';
10162
10163             case 'arabic':
10164             case 'asmo708':
10165             case 'csisolatinarabic':
10166             case 'ecma114':
10167             case 'iso88596':
10168             case 'iso885961987':
10169             case 'isoir127':
10170                 return 'ISO-8859-6';
10171
10172             case 'csiso88596e':
10173             case 'iso88596e':
10174                 return 'ISO-8859-6-E';
10175
10176             case 'csiso88596i':
10177             case 'iso88596i':
10178                 return 'ISO-8859-6-I';
10179
10180             case 'csisolatingreek':
10181             case 'ecma118':
10182             case 'elot928':
10183             case 'greek':
10184             case 'greek8':
10185             case 'iso88597':
10186             case 'iso885971987':
10187             case 'isoir126':
10188                 return 'ISO-8859-7';
10189
10190             case 'csisolatinhebrew':
10191             case 'hebrew':
10192             case 'iso88598':
10193             case 'iso885981988':
10194             case 'isoir138':
10195                 return 'ISO-8859-8';
10196
10197             case 'csiso88598e':
10198             case 'iso88598e':
10199                 return 'ISO-8859-8-E';
10200
10201             case 'csiso88598i':
10202             case 'iso88598i':
10203                 return 'ISO-8859-8-I';
10204
10205             case 'cswindows31latin5':
10206             case 'iso88599windowslatin5':
10207                 return 'ISO-8859-9-Windows-Latin-5';
10208
10209             case 'csisolatin6':
10210             case 'iso885910':
10211             case 'iso8859101992':
10212             case 'isoir157':
10213             case 'l6':
10214             case 'latin6':
10215                 return 'ISO-8859-10';
10216
10217             case 'iso885913':
10218                 return 'ISO-8859-13';
10219
10220             case 'iso885914':
10221             case 'iso8859141998':
10222             case 'isoceltic':
10223             case 'isoir199':
10224             case 'l8':
10225             case 'latin8':
10226                 return 'ISO-8859-14';
10227
10228             case 'iso885915':
10229             case 'latin9':
10230                 return 'ISO-8859-15';
10231
10232             case 'iso885916':
10233             case 'iso8859162001':
10234             case 'isoir226':
10235             case 'l10':
10236             case 'latin10':
10237                 return 'ISO-8859-16';
10238
10239             case 'iso10646j1':
10240                 return 'ISO-10646-J-1';
10241
10242             case 'csunicode':
10243             case 'iso10646ucs2':
10244                 return 'ISO-10646-UCS-2';
10245
10246             case 'csucs4':
10247             case 'iso10646ucs4':
10248                 return 'ISO-10646-UCS-4';
10249
10250             case 'csunicodeascii':
10251             case 'iso10646ucsbasic':
10252                 return 'ISO-10646-UCS-Basic';
10253
10254             case 'csunicodelatin1':
10255             case 'iso10646':
10256             case 'iso10646unicodelatin1':
10257                 return 'ISO-10646-Unicode-Latin1';
10258
10259             case 'csiso10646utf1':
10260             case 'iso10646utf1':
10261                 return 'ISO-10646-UTF-1';
10262
10263             case 'csiso115481':
10264             case 'iso115481':
10265             case 'isotr115481':
10266                 return 'ISO-11548-1';
10267
10268             case 'csiso90':
10269             case 'isoir90':
10270                 return 'iso-ir-90';
10271
10272             case 'csunicodeibm1261':
10273             case 'isounicodeibm1261':
10274                 return 'ISO-Unicode-IBM-1261';
10275
10276             case 'csunicodeibm1264':
10277             case 'isounicodeibm1264':
10278                 return 'ISO-Unicode-IBM-1264';
10279
10280             case 'csunicodeibm1265':
10281             case 'isounicodeibm1265':
10282                 return 'ISO-Unicode-IBM-1265';
10283
10284             case 'csunicodeibm1268':
10285             case 'isounicodeibm1268':
10286                 return 'ISO-Unicode-IBM-1268';
10287
10288             case 'csunicodeibm1276':
10289             case 'isounicodeibm1276':
10290                 return 'ISO-Unicode-IBM-1276';
10291
10292             case 'csiso646basic1983':
10293             case 'iso646basic1983':
10294             case 'ref':
10295                 return 'ISO_646.basic:1983';
10296
10297             case 'csiso2intlrefversion':
10298             case 'irv':
10299             case 'iso646irv1983':
10300             case 'isoir2':
10301                 return 'ISO_646.irv:1983';
10302
10303             case 'csiso2033':
10304             case 'e13b':
10305             case 'iso20331983':
10306             case 'isoir98':
10307                 return 'ISO_2033-1983';
10308
10309             case 'csiso5427cyrillic':
10310             case 'iso5427':
10311             case 'isoir37':
10312                 return 'ISO_5427';
10313
10314             case 'iso5427cyrillic1981':
10315             case 'iso54271981':
10316             case 'isoir54':
10317                 return 'ISO_5427:1981';
10318
10319             case 'csiso5428greek':
10320             case 'iso54281980':
10321             case 'isoir55':
10322                 return 'ISO_5428:1980';
10323
10324             case 'csiso6937add':
10325             case 'iso6937225':
10326             case 'isoir152':
10327                 return 'ISO_6937-2-25';
10328
10329             case 'csisotextcomm':
10330             case 'iso69372add':
10331             case 'isoir142':
10332                 return 'ISO_6937-2-add';
10333
10334             case 'csiso8859supp':
10335             case 'iso8859supp':
10336             case 'isoir154':
10337             case 'latin125':
10338                 return 'ISO_8859-supp';
10339
10340             case 'csiso10367box':
10341             case 'iso10367box':
10342             case 'isoir155':
10343                 return 'ISO_10367-box';
10344
10345             case 'csiso15italian':
10346             case 'iso646it':
10347             case 'isoir15':
10348             case 'it':
10349                 return 'IT';
10350
10351             case 'csiso13jisc6220jp':
10352             case 'isoir13':
10353             case 'jisc62201969':
10354             case 'jisc62201969jp':
10355             case 'katakana':
10356             case 'x2017':
10357                 return 'JIS_C6220-1969-jp';
10358
10359             case 'csiso14jisc6220ro':
10360             case 'iso646jp':
10361             case 'isoir14':
10362             case 'jisc62201969ro':
10363             case 'jp':
10364                 return 'JIS_C6220-1969-ro';
10365
10366             case 'csiso42jisc62261978':
10367             case 'isoir42':
10368             case 'jisc62261978':
10369                 return 'JIS_C6226-1978';
10370
10371             case 'csiso87jisx208':
10372             case 'isoir87':
10373             case 'jisc62261983':
10374             case 'jisx2081983':
10375             case 'x208':
10376                 return 'JIS_C6226-1983';
10377
10378             case 'csiso91jisc62291984a':
10379             case 'isoir91':
10380             case 'jisc62291984a':
10381             case 'jpocra':
10382                 return 'JIS_C6229-1984-a';
10383
10384             case 'csiso92jisc62991984b':
10385             case 'iso646jpocrb':
10386             case 'isoir92':
10387             case 'jisc62291984b':
10388             case 'jpocrb':
10389                 return 'JIS_C6229-1984-b';
10390
10391             case 'csiso93jis62291984badd':
10392             case 'isoir93':
10393             case 'jisc62291984badd':
10394             case 'jpocrbadd':
10395                 return 'JIS_C6229-1984-b-add';
10396
10397             case 'csiso94jis62291984hand':
10398             case 'isoir94':
10399             case 'jisc62291984hand':
10400             case 'jpocrhand':
10401                 return 'JIS_C6229-1984-hand';
10402
10403             case 'csiso95jis62291984handadd':
10404             case 'isoir95':
10405             case 'jisc62291984handadd':
10406             case 'jpocrhandadd':
10407                 return 'JIS_C6229-1984-hand-add';
10408
10409             case 'csiso96jisc62291984kana':
10410             case 'isoir96':
10411             case 'jisc62291984kana':
10412                 return 'JIS_C6229-1984-kana';
10413
10414             case 'csjisencoding':
10415             case 'jisencoding':
10416                 return 'JIS_Encoding';
10417
10418             case 'cshalfwidthkatakana':
10419             case 'jisx201':
10420             case 'x201':
10421                 return 'JIS_X0201';
10422
10423             case 'csiso159jisx2121990':
10424             case 'isoir159':
10425             case 'jisx2121990':
10426             case 'x212':
10427                 return 'JIS_X0212-1990';
10428
10429             case 'csiso141jusib1002':
10430             case 'iso646yu':
10431             case 'isoir141':
10432             case 'js':
10433             case 'jusib1002':
10434             case 'yu':
10435                 return 'JUS_I.B1.002';
10436
10437             case 'csiso147macedonian':
10438             case 'isoir147':
10439             case 'jusib1003mac':
10440             case 'macedonian':
10441                 return 'JUS_I.B1.003-mac';
10442
10443             case 'csiso146serbian':
10444             case 'isoir146':
10445             case 'jusib1003serb':
10446             case 'serbian':
10447                 return 'JUS_I.B1.003-serb';
10448
10449             case 'koi7switched':
10450                 return 'KOI7-switched';
10451
10452             case 'cskoi8r':
10453             case 'koi8r':
10454                 return 'KOI8-R';
10455
10456             case 'koi8u':
10457                 return 'KOI8-U';
10458
10459             case 'csksc5636':
10460             case 'iso646kr':
10461             case 'ksc5636':
10462                 return 'KSC5636';
10463
10464             case 'cskz1048':
10465             case 'kz1048':
10466             case 'rk1048':
10467             case 'strk10482002':
10468                 return 'KZ-1048';
10469
10470             case 'csiso19latingreek':
10471             case 'isoir19':
10472             case 'latingreek':
10473                 return 'latin-greek';
10474
10475             case 'csiso27latingreek1':
10476             case 'isoir27':
10477             case 'latingreek1':
10478                 return 'Latin-greek-1';
10479
10480             case 'csiso158lap':
10481             case 'isoir158':
10482             case 'lap':
10483             case 'latinlap':
10484                 return 'latin-lap';
10485
10486             case 'csmacintosh':
10487             case 'mac':
10488             case 'macintosh':
10489                 return 'macintosh';
10490
10491             case 'csmicrosoftpublishing':
10492             case 'microsoftpublishing':
10493                 return 'Microsoft-Publishing';
10494
10495             case 'csmnem':
10496             case 'mnem':
10497                 return 'MNEM';
10498
10499             case 'csmnemonic':
10500             case 'mnemonic':
10501                 return 'MNEMONIC';
10502
10503             case 'csiso86hungarian':
10504             case 'hu':
10505             case 'iso646hu':
10506             case 'isoir86':
10507             case 'msz77953':
10508                 return 'MSZ_7795.3';
10509
10510             case 'csnatsdano':
10511             case 'isoir91':
10512             case 'natsdano':
10513                 return 'NATS-DANO';
10514
10515             case 'csnatsdanoadd':
10516             case 'isoir92':
10517             case 'natsdanoadd':
10518                 return 'NATS-DANO-ADD';
10519
10520             case 'csnatssefi':
10521             case 'isoir81':
10522             case 'natssefi':
10523                 return 'NATS-SEFI';
10524
10525             case 'csnatssefiadd':
10526             case 'isoir82':
10527             case 'natssefiadd':
10528                 return 'NATS-SEFI-ADD';
10529
10530             case 'csiso151cuba':
10531             case 'cuba':
10532             case 'iso646cu':
10533             case 'isoir151':
10534             case 'ncnc1081':
10535                 return 'NC_NC00-10:81';
10536
10537             case 'csiso69french':
10538             case 'fr':
10539             case 'iso646fr':
10540             case 'isoir69':
10541             case 'nfz62010':
10542                 return 'NF_Z_62-010';
10543
10544             case 'csiso25french':
10545             case 'iso646fr1':
10546             case 'isoir25':
10547             case 'nfz620101973':
10548                 return 'NF_Z_62-010_(1973)';
10549
10550             case 'csiso60danishnorwegian':
10551             case 'csiso60norwegian1':
10552             case 'iso646no':
10553             case 'isoir60':
10554             case 'no':
10555             case 'ns45511':
10556                 return 'NS_4551-1';
10557
10558             case 'csiso61norwegian2':
10559             case 'iso646no2':
10560             case 'isoir61':
10561             case 'no2':
10562             case 'ns45512':
10563                 return 'NS_4551-2';
10564
10565             case 'osdebcdicdf3irv':
10566                 return 'OSD_EBCDIC_DF03_IRV';
10567
10568             case 'osdebcdicdf41':
10569                 return 'OSD_EBCDIC_DF04_1';
10570
10571             case 'osdebcdicdf415':
10572                 return 'OSD_EBCDIC_DF04_15';
10573
10574             case 'cspc8danishnorwegian':
10575             case 'pc8danishnorwegian':
10576                 return 'PC8-Danish-Norwegian';
10577
10578             case 'cspc8turkish':
10579             case 'pc8turkish':
10580                 return 'PC8-Turkish';
10581
10582             case 'csiso16portuguese':
10583             case 'iso646pt':
10584             case 'isoir16':
10585             case 'pt':
10586                 return 'PT';
10587
10588             case 'csiso84portuguese2':
10589             case 'iso646pt2':
10590             case 'isoir84':
10591             case 'pt2':
10592                 return 'PT2';
10593
10594             case 'cp154':
10595             case 'csptcp154':
10596             case 'cyrillicasian':
10597             case 'pt154':
10598             case 'ptcp154':
10599                 return 'PTCP154';
10600
10601             case 'scsu':
10602                 return 'SCSU';
10603
10604             case 'csiso10swedish':
10605             case 'fi':
10606             case 'iso646fi':
10607             case 'iso646se':
10608             case 'isoir10':
10609             case 'se':
10610             case 'sen850200b':
10611                 return 'SEN_850200_B';
10612
10613             case 'csiso11swedishfornames':
10614             case 'iso646se2':
10615             case 'isoir11':
10616             case 'se2':
10617             case 'sen850200c':
10618                 return 'SEN_850200_C';
10619
10620             case 'csshiftjis':
10621             case 'mskanji':
10622             case 'shiftjis':
10623                 return 'Shift_JIS';
10624
10625             case 'csiso102t617bit':
10626             case 'isoir102':
10627             case 't617bit':
10628                 return 'T.61-7bit';
10629
10630             case 'csiso103t618bit':
10631             case 'isoir103':
10632             case 't61':
10633             case 't618bit':
10634                 return 'T.61-8bit';
10635
10636             case 'csiso128t101g2':
10637             case 'isoir128':
10638             case 't101g2':
10639                 return 'T.101-G2';
10640
10641             case 'cstscii':
10642             case 'tscii':
10643                 return 'TSCII';
10644
10645             case 'csunicode11':
10646             case 'unicode11':
10647                 return 'UNICODE-1-1';
10648
10649             case 'csunicode11utf7':
10650             case 'unicode11utf7':
10651                 return 'UNICODE-1-1-UTF-7';
10652
10653             case 'csunknown8bit':
10654             case 'unknown8bit':
10655                 return 'UNKNOWN-8BIT';
10656
10657             case 'ansix341968':
10658             case 'ansix341986':
10659             case 'ascii':
10660             case 'cp367':
10661             case 'csascii':
10662             case 'ibm367':
10663             case 'iso646irv1991':
10664             case 'iso646us':
10665             case 'isoir6':
10666             case 'us':
10667             case 'usascii':
10668                 return 'US-ASCII';
10669
10670             case 'csusdk':
10671             case 'usdk':
10672                 return 'us-dk';
10673
10674             case 'utf7':
10675                 return 'UTF-7';
10676
10677             case 'utf8':
10678                 return 'UTF-8';
10679
10680             case 'utf16':
10681                 return 'UTF-16';
10682
10683             case 'utf16be':
10684                 return 'UTF-16BE';
10685
10686             case 'utf16le':
10687                 return 'UTF-16LE';
10688
10689             case 'utf32':
10690                 return 'UTF-32';
10691
10692             case 'utf32be':
10693                 return 'UTF-32BE';
10694
10695             case 'utf32le':
10696                 return 'UTF-32LE';
10697
10698             case 'csventurainternational':
10699             case 'venturainternational':
10700                 return 'Ventura-International';
10701
10702             case 'csventuramath':
10703             case 'venturamath':
10704                 return 'Ventura-Math';
10705
10706             case 'csventuraus':
10707             case 'venturaus':
10708                 return 'Ventura-US';
10709
10710             case 'csiso70videotexsupp1':
10711             case 'isoir70':
10712             case 'videotexsuppl':
10713                 return 'videotex-suppl';
10714
10715             case 'csviqr':
10716             case 'viqr':
10717                 return 'VIQR';
10718
10719             case 'csviscii':
10720             case 'viscii':
10721                 return 'VISCII';
10722
10723             case 'cswindows31j':
10724             case 'windows31j':
10725                 return 'Windows-31J';
10726
10727             case 'iso885911':
10728             case 'tis620':
10729                 return 'windows-874';
10730
10731             case 'cseuckr':
10732             case 'csksc56011987':
10733             case 'euckr':
10734             case 'isoir149':
10735             case 'korean':
10736             case 'ksc5601':
10737             case 'ksc56011987':
10738             case 'ksc56011989':
10739             case 'windows949':
10740                 return 'windows-949';
10741
10742             case 'windows1250':
10743                 return 'windows-1250';
10744
10745             case 'windows1251':
10746                 return 'windows-1251';
10747
10748             case 'cp819':
10749             case 'csisolatin1':
10750             case 'ibm819':
10751             case 'iso88591':
10752             case 'iso885911987':
10753             case 'isoir100':
10754             case 'l1':
10755             case 'latin1':
10756             case 'windows1252':
10757                 return 'windows-1252';
10758
10759             case 'windows1253':
10760                 return 'windows-1253';
10761
10762             case 'csisolatin5':
10763             case 'iso88599':
10764             case 'iso885991989':
10765             case 'isoir148':
10766             case 'l5':
10767             case 'latin5':
10768             case 'windows1254':
10769                 return 'windows-1254';
10770
10771             case 'windows1255':
10772                 return 'windows-1255';
10773
10774             case 'windows1256':
10775                 return 'windows-1256';
10776
10777             case 'windows1257':
10778                 return 'windows-1257';
10779
10780             case 'windows1258':
10781                 return 'windows-1258';
10782
10783             default:
10784                 return $charset;
10785         }
10786     }
10787
526b99 10788     public static function get_curl_version()
fd9ef2 10789     {
T 10790         if (is_array($curl = curl_version()))
10791         {
10792             $curl = $curl['version'];
10793         }
10794         elseif (substr($curl, 0, 5) === 'curl/')
10795         {
10796             $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10797         }
10798         elseif (substr($curl, 0, 8) === 'libcurl/')
10799         {
10800             $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10801         }
10802         else
10803         {
10804             $curl = 0;
10805         }
10806         return $curl;
10807     }
10808
10809     function is_subclass_of($class1, $class2)
10810     {
10811         if (func_num_args() !== 2)
10812         {
10813             trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10814         }
10815         elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10816         {
10817             return is_subclass_of($class1, $class2);
10818         }
10819         elseif (is_string($class1) && is_string($class2))
10820         {
10821             if (class_exists($class1))
10822             {
10823                 if (class_exists($class2))
10824                 {
10825                     $class2 = strtolower($class2);
10826                     while ($class1 = strtolower(get_parent_class($class1)))
10827                     {
10828                         if ($class1 === $class2)
10829                         {
10830                             return true;
10831                         }
10832                     }
10833                 }
10834             }
10835             else
10836             {
10837                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10838             }
10839         }
10840         return false;
10841     }
10842
10843     /**
10844      * Strip HTML comments
10845      *
10846      * @access public
10847      * @param string $data Data to strip comments from
10848      * @return string Comment stripped string
10849      */
10850     function strip_comments($data)
10851     {
10852         $output = '';
10853         while (($start = strpos($data, '<!--')) !== false)
10854         {
10855             $output .= substr($data, 0, $start);
10856             if (($end = strpos($data, '-->', $start)) !== false)
10857             {
10858                 $data = substr_replace($data, '', 0, $end + 3);
10859             }
10860             else
10861             {
10862                 $data = '';
10863             }
10864         }
10865         return $output . $data;
10866     }
10867
829b76 10868     static function parse_date($dt)
fd9ef2 10869     {
T 10870         $parser = SimplePie_Parse_Date::get();
10871         return $parser->parse($dt);
10872     }
10873
10874     /**
10875      * Decode HTML entities
10876      *
10877      * @static
10878      * @access public
10879      * @param string $data Input data
10880      * @return string Output data
10881      */
10882     function entities_decode($data)
10883     {
f64c86 10884         $decoder = new SimplePie_Decode_HTML_Entities($data);
fd9ef2 10885         return $decoder->parse();
T 10886     }
10887
10888     /**
10889      * Remove RFC822 comments
10890      *
10891      * @access public
10892      * @param string $data Data to strip comments from
10893      * @return string Comment stripped string
10894      */
10895     function uncomment_rfc822($string)
10896     {
10897         $string = (string) $string;
10898         $position = 0;
10899         $length = strlen($string);
10900         $depth = 0;
10901
10902         $output = '';
10903
10904         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10905         {
10906             $output .= substr($string, $position, $pos - $position);
10907             $position = $pos + 1;
10908             if ($string[$pos - 1] !== '\\')
10909             {
10910                 $depth++;
10911                 while ($depth && $position < $length)
10912                 {
10913                     $position += strcspn($string, '()', $position);
10914                     if ($string[$position - 1] === '\\')
10915                     {
10916                         $position++;
10917                         continue;
10918                     }
10919                     elseif (isset($string[$position]))
10920                     {
10921                         switch ($string[$position])
10922                         {
10923                             case '(':
10924                                 $depth++;
10925                                 break;
10926
10927                             case ')':
10928                                 $depth--;
10929                                 break;
10930                         }
10931                         $position++;
10932                     }
10933                     else
10934                     {
10935                         break;
10936                     }
10937                 }
10938             }
10939             else
10940             {
10941                 $output .= '(';
10942             }
10943         }
10944         $output .= substr($string, $position);
10945
10946         return $output;
10947     }
10948
10949     function parse_mime($mime)
10950     {
10951         if (($pos = strpos($mime, ';')) === false)
10952         {
10953             return trim($mime);
10954         }
10955         else
10956         {
10957             return trim(substr($mime, 0, $pos));
10958         }
10959     }
10960
10961     function htmlspecialchars_decode($string, $quote_style)
10962     {
10963         if (function_exists('htmlspecialchars_decode'))
10964         {
10965             return htmlspecialchars_decode($string, $quote_style);
10966         }
10967         else
10968         {
10969             return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10970         }
10971     }
10972
10973     function atom_03_construct_type($attribs)
10974     {
10975         if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10976         {
10977             $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10978         }
10979         else
10980         {
10981             $mode = SIMPLEPIE_CONSTRUCT_NONE;
10982         }
10983         if (isset($attribs['']['type']))
10984         {
10985             switch (strtolower(trim($attribs['']['type'])))
10986             {
10987                 case 'text':
10988                 case 'text/plain':
10989                     return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10990
10991                 case 'html':
10992                 case 'text/html':
10993                     return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10994
10995                 case 'xhtml':
10996                 case 'application/xhtml+xml':
10997                     return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10998
10999                 default:
11000                     return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11001             }
11002         }
11003         else
11004         {
11005             return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11006         }
11007     }
11008
72695f 11009     static function atom_10_construct_type($attribs)
fd9ef2 11010     {
T 11011         if (isset($attribs['']['type']))
11012         {
11013             switch (strtolower(trim($attribs['']['type'])))
11014             {
11015                 case 'text':
11016                     return SIMPLEPIE_CONSTRUCT_TEXT;
11017
11018                 case 'html':
11019                     return SIMPLEPIE_CONSTRUCT_HTML;
11020
11021                 case 'xhtml':
11022                     return SIMPLEPIE_CONSTRUCT_XHTML;
11023
11024                 default:
11025                     return SIMPLEPIE_CONSTRUCT_NONE;
11026             }
11027         }
11028         return SIMPLEPIE_CONSTRUCT_TEXT;
11029     }
11030
11031     function atom_10_content_construct_type($attribs)
11032     {
11033         if (isset($attribs['']['type']))
11034         {
11035             $type = strtolower(trim($attribs['']['type']));
11036             switch ($type)
11037             {
11038                 case 'text':
11039                     return SIMPLEPIE_CONSTRUCT_TEXT;
11040
11041                 case 'html':
11042                     return SIMPLEPIE_CONSTRUCT_HTML;
11043
11044                 case 'xhtml':
11045                     return SIMPLEPIE_CONSTRUCT_XHTML;
11046             }
11047             if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11048             {
11049                 return SIMPLEPIE_CONSTRUCT_NONE;
11050             }
11051             else
11052             {
11053                 return SIMPLEPIE_CONSTRUCT_BASE64;
11054             }
11055         }
11056         else
11057         {
11058             return SIMPLEPIE_CONSTRUCT_TEXT;
11059         }
11060     }
11061
72695f 11062     static function is_isegment_nz_nc($string)
fd9ef2 11063     {
T 11064         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);
11065     }
11066
11067     function space_seperated_tokens($string)
11068     {
11069         $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11070         $string_length = strlen($string);
11071
11072         $position = strspn($string, $space_characters);
11073         $tokens = array();
11074
11075         while ($position < $string_length)
11076         {
11077             $len = strcspn($string, $space_characters, $position);
11078             $tokens[] = substr($string, $position, $len);
11079             $position += $len;
11080             $position += strspn($string, $space_characters, $position);
11081         }
11082
11083         return $tokens;
11084     }
11085
11086     function array_unique($array)
11087     {
11088         if (version_compare(PHP_VERSION, '5.2', '>='))
11089         {
11090             return array_unique($array);
11091         }
11092         else
11093         {
11094             $array = (array) $array;
11095             $new_array = array();
11096             $new_array_strings = array();
11097             foreach ($array as $key => $value)
11098             {
11099                 if (is_object($value))
11100                 {
11101                     if (method_exists($value, '__toString'))
11102                     {
11103                         $cmp = $value->__toString();
11104                     }
11105                     else
11106                     {
11107                         trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11108                     }
11109                 }
11110                 elseif (is_array($value))
11111                 {
11112                     $cmp = (string) reset($value);
11113                 }
11114                 else
11115                 {
11116                     $cmp = (string) $value;
11117                 }
11118                 if (!in_array($cmp, $new_array_strings))
11119                 {
11120                     $new_array[$key] = $value;
11121                     $new_array_strings[] = $cmp;
11122                 }
11123             }
11124             return $new_array;
11125         }
11126     }
11127
11128     /**
11129      * Converts a unicode codepoint to a UTF-8 character
11130      *
11131      * @static
11132      * @access public
11133      * @param int $codepoint Unicode codepoint
11134      * @return string UTF-8 character
11135      */
11136     function codepoint_to_utf8($codepoint)
11137     {
11138         $codepoint = (int) $codepoint;
11139         if ($codepoint < 0)
11140         {
11141             return false;
11142         }
11143         else if ($codepoint <= 0x7f)
11144         {
11145             return chr($codepoint);
11146         }
11147         else if ($codepoint <= 0x7ff)
11148         {
11149             return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11150         }
11151         else if ($codepoint <= 0xffff)
11152         {
11153             return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11154         }
11155         else if ($codepoint <= 0x10ffff)
11156         {
11157             return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11158         }
11159         else
11160         {
11161             // U+FFFD REPLACEMENT CHARACTER
11162             return "\xEF\xBF\xBD";
11163         }
11164     }
11165
11166     /**
11167      * Re-implementation of PHP 5's stripos()
11168      *
11169      * Returns the numeric position of the first occurrence of needle in the
11170      * haystack string.
11171      *
11172      * @static
11173      * @access string
11174      * @param object $haystack
11175      * @param string $needle Note that the needle may be a string of one or more
11176      *     characters. If needle is not a string, it is converted to an integer
11177      *     and applied as the ordinal value of a character.
11178      * @param int $offset The optional offset parameter allows you to specify which
11179      *     character in haystack to start searching. The position returned is still
11180      *     relative to the beginning of haystack.
11181      * @return bool If needle is not found, stripos() will return boolean false.
11182      */
11183     function stripos($haystack, $needle, $offset = 0)
11184     {
11185         if (function_exists('stripos'))
11186         {
11187             return stripos($haystack, $needle, $offset);
11188         }
11189         else
11190         {
11191             if (is_string($needle))
11192             {
11193                 $needle = strtolower($needle);
11194             }
11195             elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11196             {
11197                 $needle = strtolower(chr($needle));
11198             }
11199             else
11200             {
11201                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11202                 return false;
11203             }
11204
11205             return strpos(strtolower($haystack), $needle, $offset);
11206         }
11207     }
11208
11209     /**
11210      * Similar to parse_str()
11211      *
11212      * Returns an associative array of name/value pairs, where the value is an
11213      * array of values that have used the same name
11214      *
11215      * @static
11216      * @access string
11217      * @param string $str The input string.
11218      * @return array
11219      */
11220     function parse_str($str)
11221     {
11222         $return = array();
11223         $str = explode('&', $str);
11224
11225         foreach ($str as $section)
11226         {
11227             if (strpos($section, '=') !== false)
11228             {
11229                 list($name, $value) = explode('=', $section, 2);
11230                 $return[urldecode($name)][] = urldecode($value);
11231             }
11232             else
11233             {
11234                 $return[urldecode($section)][] = null;
11235             }
11236         }
11237
11238         return $return;
11239     }
11240
11241     /**
11242      * Detect XML encoding, as per XML 1.0 Appendix F.1
11243      *
11244      * @todo Add support for EBCDIC
11245      * @param string $data XML data
11246      * @return array Possible encodings
11247      */
526b99 11248     public static function xml_encoding($data)
fd9ef2 11249     {
T 11250         // UTF-32 Big Endian BOM
11251         if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11252         {
11253             $encoding[] = 'UTF-32BE';
11254         }
11255         // UTF-32 Little Endian BOM
11256         elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11257         {
11258             $encoding[] = 'UTF-32LE';
11259         }
11260         // UTF-16 Big Endian BOM
11261         elseif (substr($data, 0, 2) === "\xFE\xFF")
11262         {
11263             $encoding[] = 'UTF-16BE';
11264         }
11265         // UTF-16 Little Endian BOM
11266         elseif (substr($data, 0, 2) === "\xFF\xFE")
11267         {
11268             $encoding[] = 'UTF-16LE';
11269         }
11270         // UTF-8 BOM
11271         elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11272         {
11273             $encoding[] = 'UTF-8';
11274         }
11275         // UTF-32 Big Endian Without BOM
11276         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")
11277         {
11278             if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11279             {
f64c86 11280                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
fd9ef2 11281                 if ($parser->parse())
T 11282                 {
11283                     $encoding[] = $parser->encoding;
11284                 }
11285             }
11286             $encoding[] = 'UTF-32BE';
11287         }
11288         // UTF-32 Little Endian Without BOM
11289         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")
11290         {
11291             if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11292             {
f64c86 11293                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
fd9ef2 11294                 if ($parser->parse())
T 11295                 {
11296                     $encoding[] = $parser->encoding;
11297                 }
11298             }
11299             $encoding[] = 'UTF-32LE';
11300         }
11301         // UTF-16 Big Endian Without BOM
11302         elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11303         {
11304             if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11305             {
f64c86 11306                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
fd9ef2 11307                 if ($parser->parse())
T 11308                 {
11309                     $encoding[] = $parser->encoding;
11310                 }
11311             }
11312             $encoding[] = 'UTF-16BE';
11313         }
11314         // UTF-16 Little Endian Without BOM
11315         elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11316         {
11317             if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11318             {
f64c86 11319                 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
fd9ef2 11320                 if ($parser->parse())
T 11321                 {
11322                     $encoding[] = $parser->encoding;
11323                 }
11324             }
11325             $encoding[] = 'UTF-16LE';
11326         }
11327         // US-ASCII (or superset)
11328         elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11329         {
11330             if ($pos = strpos($data, "\x3F\x3E"))
11331             {
f64c86 11332                 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
fd9ef2 11333                 if ($parser->parse())
T 11334                 {
11335                     $encoding[] = $parser->encoding;
11336                 }
11337             }
11338             $encoding[] = 'UTF-8';
11339         }
11340         // Fallback to UTF-8
11341         else
11342         {
11343             $encoding[] = 'UTF-8';
11344         }
11345         return $encoding;
11346     }
11347
11348     function output_javascript()
11349     {
11350         if (function_exists('ob_gzhandler'))
11351         {
11352             ob_start('ob_gzhandler');
11353         }
11354         header('Content-type: text/javascript; charset: UTF-8');
11355         header('Cache-Control: must-revalidate');
11356         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11357         ?>
11358 function embed_odeo(link) {
11359     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>');
11360 }
11361
11362 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11363     if (placeholder != '') {
11364         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>');
11365     }
11366     else {
11367         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>');
11368     }
11369 }
11370
11371 function embed_flash(bgcolor, width, height, link, loop, type) {
11372     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>');
11373 }
11374
11375 function embed_flv(width, height, link, placeholder, loop, player) {
11376     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>');
11377 }
11378
11379 function embed_wmedia(width, height, link) {
11380     document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11381 }
11382         <?php
11383     }
11384 }
11385
11386 /**
11387  * Decode HTML Entities
11388  *
11389  * This implements HTML5 as of revision 967 (2007-06-28)
11390  *
11391  * @package SimplePie
11392  */
11393 class SimplePie_Decode_HTML_Entities
11394 {
11395     /**
11396      * Data to be parsed
11397      *
11398      * @access private
11399      * @var string
11400      */
11401     var $data = '';
11402
11403     /**
11404      * Currently consumed bytes
11405      *
11406      * @access private
11407      * @var string
11408      */
11409     var $consumed = '';
11410
11411     /**
11412      * Position of the current byte being parsed
11413      *
11414      * @access private
11415      * @var int
11416      */
11417     var $position = 0;
11418
11419     /**
11420      * Create an instance of the class with the input data
11421      *
11422      * @access public
11423      * @param string $data Input data
11424      */
11425     function SimplePie_Decode_HTML_Entities($data)
11426     {
11427         $this->data = $data;
11428     }
11429
11430     /**
11431      * Parse the input data
11432      *
11433      * @access public
11434      * @return string Output data
11435      */
11436     function parse()
11437     {
11438         while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11439         {
11440             $this->consume();
11441             $this->entity();
11442             $this->consumed = '';
11443         }
11444         return $this->data;
11445     }
11446
11447     /**
11448      * Consume the next byte
11449      *
11450      * @access private
11451      * @return mixed The next byte, or false, if there is no more data
11452      */
11453     function consume()
11454     {
11455         if (isset($this->data[$this->position]))
11456         {
11457             $this->consumed .= $this->data[$this->position];
11458             return $this->data[$this->position++];
11459         }
11460         else
11461         {
11462             return false;
11463         }
11464     }
11465
11466     /**
11467      * Consume a range of characters
11468      *
11469      * @access private
11470      * @param string $chars Characters to consume
11471      * @return mixed A series of characters that match the range, or false
11472      */
11473     function consume_range($chars)
11474     {
11475         if ($len = strspn($this->data, $chars, $this->position))
11476         {
11477             $data = substr($this->data, $this->position, $len);
11478             $this->consumed .= $data;
11479             $this->position += $len;
11480             return $data;
11481         }
11482         else
11483         {
11484             return false;
11485         }
11486     }
11487
11488     /**
11489      * Unconsume one byte
11490      *
11491      * @access private
11492      */
11493     function unconsume()
11494     {
11495         $this->consumed = substr($this->consumed, 0, -1);
11496         $this->position--;
11497     }
11498
11499     /**
11500      * Decode an entity
11501      *
11502      * @access private
11503      */
11504     function entity()
11505     {
11506         switch ($this->consume())
11507         {
11508             case "\x09":
11509             case "\x0A":
11510             case "\x0B":
11511             case "\x0B":
11512             case "\x0C":
11513             case "\x20":
11514             case "\x3C":
11515             case "\x26":
11516             case false:
11517                 break;
11518
11519             case "\x23":
11520                 switch ($this->consume())
11521                 {
11522                     case "\x78":
11523                     case "\x58":
11524                         $range = '0123456789ABCDEFabcdef';
11525                         $hex = true;
11526                         break;
11527
11528                     default:
11529                         $range = '0123456789';
11530                         $hex = false;
11531                         $this->unconsume();
11532                         break;
11533                 }
11534
11535                 if ($codepoint = $this->consume_range($range))
11536                 {
11537                     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");
11538
11539                     if ($hex)
11540                     {
11541                         $codepoint = hexdec($codepoint);
11542                     }
11543                     else
11544                     {
11545                         $codepoint = intval($codepoint);
11546                     }
11547
11548                     if (isset($windows_1252_specials[$codepoint]))
11549                     {
11550                         $replacement = $windows_1252_specials[$codepoint];
11551                     }
11552                     else
11553                     {
11554                         $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11555                     }
11556
11557                     if (!in_array($this->consume(), array(';', false), true))
11558                     {
11559                         $this->unconsume();
11560                     }
11561
11562                     $consumed_length = strlen($this->consumed);
11563                     $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11564                     $this->position += strlen($replacement) - $consumed_length;
11565                 }
11566                 break;
11567
11568             default:
11569                 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");
11570
11571                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11572                 {
11573                     $consumed = substr($this->consumed, 1);
11574                     if (isset($entities[$consumed]))
11575                     {
11576                         $match = $consumed;
11577                     }
11578                 }
11579
11580                 if ($match !== null)
11581                 {
11582                      $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11583                     $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11584                 }
11585                 break;
11586         }
11587     }
11588 }
11589
11590 /**
11591  * IRI parser/serialiser
11592  *
11593  * @package SimplePie
11594  */
11595 class SimplePie_IRI
11596 {
11597     /**
11598      * Scheme
11599      *
11600      * @access private
11601      * @var string
11602      */
11603     var $scheme;
11604
11605     /**
11606      * User Information
11607      *
11608      * @access private
11609      * @var string
11610      */
11611     var $userinfo;
11612
11613     /**
11614      * Host
11615      *
11616      * @access private
11617      * @var string
11618      */
11619     var $host;
11620
11621     /**
11622      * Port
11623      *
11624      * @access private
11625      * @var string
11626      */
11627     var $port;
11628
11629     /**
11630      * Path
11631      *
11632      * @access private
11633      * @var string
11634      */
11635     var $path;
11636
11637     /**
11638      * Query
11639      *
11640      * @access private
11641      * @var string
11642      */
11643     var $query;
11644
11645     /**
11646      * Fragment
11647      *
11648      * @access private
11649      * @var string
11650      */
11651     var $fragment;
11652
11653     /**
11654      * Whether the object represents a valid IRI
11655      *
11656      * @access private
11657      * @var array
11658      */
11659     var $valid = array();
11660
11661     /**
11662      * Return the entire IRI when you try and read the object as a string
11663      *
11664      * @access public
11665      * @return string
11666      */
11667     function __toString()
11668     {
11669         return $this->get_iri();
11670     }
11671
11672     /**
11673      * Create a new IRI object, from a specified string
11674      *
11675      * @access public
11676      * @param string $iri
11677      * @return SimplePie_IRI
11678      */
11679     function SimplePie_IRI($iri)
11680     {
11681         $iri = (string) $iri;
11682         if ($iri !== '')
11683         {
11684             $parsed = $this->parse_iri($iri);
11685             $this->set_scheme($parsed['scheme']);
11686             $this->set_authority($parsed['authority']);
11687             $this->set_path($parsed['path']);
11688             $this->set_query($parsed['query']);
11689             $this->set_fragment($parsed['fragment']);
11690         }
11691     }
11692
11693     /**
11694      * Create a new IRI object by resolving a relative IRI
11695      *
11696      * @static
11697      * @access public
11698      * @param SimplePie_IRI $base Base IRI
11699      * @param string $relative Relative IRI
11700      * @return SimplePie_IRI
11701      */
72695f 11702     static function absolutize($base, $relative)
fd9ef2 11703     {
T 11704         $relative = (string) $relative;
11705         if ($relative !== '')
11706         {
f64c86 11707             $relative = new SimplePie_IRI($relative);
fd9ef2 11708             if ($relative->get_scheme() !== null)
T 11709             {
11710                 $target = $relative;
11711             }
11712             elseif ($base->get_iri() !== null)
11713             {
11714                 if ($relative->get_authority() !== null)
11715                 {
11716                     $target = $relative;
11717                     $target->set_scheme($base->get_scheme());
11718                 }
11719                 else
11720                 {
f64c86 11721                     $target = new SimplePie_IRI('');
fd9ef2 11722                     $target->set_scheme($base->get_scheme());
T 11723                     $target->set_userinfo($base->get_userinfo());
11724                     $target->set_host($base->get_host());
11725                     $target->set_port($base->get_port());
11726                     if ($relative->get_path() !== null)
11727                     {
11728                         if (strpos($relative->get_path(), '/') === 0)
11729                         {
11730                             $target->set_path($relative->get_path());
11731                         }
11732                         elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11733                         {
11734                             $target->set_path('/' . $relative->get_path());
11735                         }
11736                         elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11737                         {
11738                             $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11739                         }
11740                         else
11741                         {
11742                             $target->set_path($relative->get_path());
11743                         }
11744                         $target->set_query($relative->get_query());
11745                     }
11746                     else
11747                     {
11748                         $target->set_path($base->get_path());
11749                         if ($relative->get_query() !== null)
11750                         {
11751                             $target->set_query($relative->get_query());
11752                         }
11753                         elseif ($base->get_query() !== null)
11754                         {
11755                             $target->set_query($base->get_query());
11756                         }
11757                     }
11758                 }
11759                 $target->set_fragment($relative->get_fragment());
11760             }
11761             else
11762             {
11763                 // No base URL, just return the relative URL
11764                 $target = $relative;
11765             }
11766         }
11767         else
11768         {
11769             $target = $base;
11770         }
11771         return $target;
11772     }
11773
11774     /**
11775      * Parse an IRI into scheme/authority/path/query/fragment segments
11776      *
11777      * @access private
11778      * @param string $iri
11779      * @return array
11780      */
11781     function parse_iri($iri)
11782     {
11783         preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11784         for ($i = count($match); $i <= 9; $i++)
11785         {
11786             $match[$i] = '';
11787         }
11788         return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11789     }
11790
11791     /**
11792      * Remove dot segments from a path
11793      *
11794      * @access private
11795      * @param string $input
11796      * @return string
11797      */
11798     function remove_dot_segments($input)
11799     {
11800         $output = '';
11801         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11802         {
11803             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11804             if (strpos($input, '../') === 0)
11805             {
11806                 $input = substr($input, 3);
11807             }
11808             elseif (strpos($input, './') === 0)
11809             {
11810                 $input = substr($input, 2);
11811             }
11812             // 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,
11813             elseif (strpos($input, '/./') === 0)
11814             {
11815                 $input = substr_replace($input, '/', 0, 3);
11816             }
11817             elseif ($input === '/.')
11818             {
11819                 $input = '/';
11820             }
11821             // 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,
11822             elseif (strpos($input, '/../') === 0)
11823             {
11824                 $input = substr_replace($input, '/', 0, 4);
11825                 $output = substr_replace($output, '', strrpos($output, '/'));
11826             }
11827             elseif ($input === '/..')
11828             {
11829                 $input = '/';
11830                 $output = substr_replace($output, '', strrpos($output, '/'));
11831             }
11832             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11833             elseif ($input === '.' || $input === '..')
11834             {
11835                 $input = '';
11836             }
11837             // 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
11838             elseif (($pos = strpos($input, '/', 1)) !== false)
11839             {
11840                 $output .= substr($input, 0, $pos);
11841                 $input = substr_replace($input, '', 0, $pos);
11842             }
11843             else
11844             {
11845                 $output .= $input;
11846                 $input = '';
11847             }
11848         }
11849         return $output . $input;
11850     }
11851
11852     /**
11853      * Replace invalid character with percent encoding
11854      *
11855      * @access private
11856      * @param string $string Input string
11857      * @param string $valid_chars Valid characters
11858      * @param int $case Normalise case
11859      * @return string
11860      */
11861     function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11862     {
11863         // Normalise case
11864         if ($case & SIMPLEPIE_LOWERCASE)
11865         {
11866             $string = strtolower($string);
11867         }
11868         elseif ($case & SIMPLEPIE_UPPERCASE)
11869         {
11870             $string = strtoupper($string);
11871         }
11872
11873         // Store position and string length (to avoid constantly recalculating this)
11874         $position = 0;
11875         $strlen = strlen($string);
11876
11877         // Loop as long as we have invalid characters, advancing the position to the next invalid character
11878         while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11879         {
11880             // If we have a % character
11881             if ($string[$position] === '%')
11882             {
11883                 // If we have a pct-encoded section
11884                 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11885                 {
11886                     // Get the the represented character
11887                     $chr = chr(hexdec(substr($string, $position + 1, 2)));
11888
11889                     // If the character is valid, replace the pct-encoded with the actual character while normalising case
11890                     if (strpos($valid_chars, $chr) !== false)
11891                     {
11892                         if ($case & SIMPLEPIE_LOWERCASE)
11893                         {
11894                             $chr = strtolower($chr);
11895                         }
11896                         elseif ($case & SIMPLEPIE_UPPERCASE)
11897                         {
11898                             $chr = strtoupper($chr);
11899                         }
11900                         $string = substr_replace($string, $chr, $position, 3);
11901                         $strlen -= 2;
11902                         $position++;
11903                     }
11904
11905                     // Otherwise just normalise the pct-encoded to uppercase
11906                     else
11907                     {
11908                         $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11909                         $position += 3;
11910                     }
11911                 }
11912                 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11913                 else
11914                 {
11915                     $string = substr_replace($string, '%25', $position, 1);
11916                     $strlen += 2;
11917                     $position += 3;
11918                 }
11919             }
11920             // If we have an invalid character, change into its pct-encoded form
11921             else
11922             {
11923                 $replacement = sprintf("%%%02X", ord($string[$position]));
11924                 $string = str_replace($string[$position], $replacement, $string);
11925                 $strlen = strlen($string);
11926             }
11927         }
11928         return $string;
11929     }
11930
11931     /**
11932      * Check if the object represents a valid IRI
11933      *
11934      * @access public
11935      * @return bool
11936      */
11937     function is_valid()
11938     {
11939         return array_sum($this->valid) === count($this->valid);
11940     }
11941
11942     /**
11943      * Set the scheme. Returns true on success, false on failure (if there are
11944      * any invalid characters).
11945      *
11946      * @access public
11947      * @param string $scheme
11948      * @return bool
11949      */
11950     function set_scheme($scheme)
11951     {
11952         if ($scheme === null || $scheme === '')
11953         {
11954             $this->scheme = null;
11955         }
11956         else
11957         {
11958             $len = strlen($scheme);
11959             switch (true)
11960             {
11961                 case $len > 1:
11962                     if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11963                     {
11964                         $this->scheme = null;
11965                         $this->valid[__FUNCTION__] = false;
11966                         return false;
11967                     }
11968
11969                 case $len > 0:
11970                     if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11971                     {
11972                         $this->scheme = null;
11973                         $this->valid[__FUNCTION__] = false;
11974                         return false;
11975                     }
11976             }
11977             $this->scheme = strtolower($scheme);
11978         }
11979         $this->valid[__FUNCTION__] = true;
11980         return true;
11981     }
11982
11983     /**
11984      * Set the authority. Returns true on success, false on failure (if there are
11985      * any invalid characters).
11986      *
11987      * @access public
11988      * @param string $authority
11989      * @return bool
11990      */
11991     function set_authority($authority)
11992     {
11993         if (($userinfo_end = strrpos($authority, '@')) !== false)
11994         {
11995             $userinfo = substr($authority, 0, $userinfo_end);
11996             $authority = substr($authority, $userinfo_end + 1);
11997         }
11998         else
11999         {
12000             $userinfo = null;
12001         }
12002
12003         if (($port_start = strpos($authority, ':')) !== false)
12004         {
12005             $port = substr($authority, $port_start + 1);
12006             $authority = substr($authority, 0, $port_start);
12007         }
12008         else
12009         {
12010             $port = null;
12011         }
12012
12013         return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12014     }
12015
12016     /**
12017      * Set the userinfo.
12018      *
12019      * @access public
12020      * @param string $userinfo
12021      * @return bool
12022      */
12023     function set_userinfo($userinfo)
12024     {
12025         if ($userinfo === null || $userinfo === '')
12026         {
12027             $this->userinfo = null;
12028         }
12029         else
12030         {
12031             $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12032         }
12033         $this->valid[__FUNCTION__] = true;
12034         return true;
12035     }
12036
12037     /**
12038      * Set the host. Returns true on success, false on failure (if there are
12039      * any invalid characters).
12040      *
12041      * @access public
12042      * @param string $host
12043      * @return bool
12044      */
12045     function set_host($host)
12046     {
12047         if ($host === null || $host === '')
12048         {
12049             $this->host = null;
12050             $this->valid[__FUNCTION__] = true;
12051             return true;
12052         }
12053         elseif ($host[0] === '[' && substr($host, -1) === ']')
12054         {
12055             if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12056             {
12057                 $this->host = $host;
12058                 $this->valid[__FUNCTION__] = true;
12059                 return true;
12060             }
12061             else
12062             {
12063                 $this->host = null;
12064                 $this->valid[__FUNCTION__] = false;
12065                 return false;
12066             }
12067         }
12068         else
12069         {
12070             $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12071             $this->valid[__FUNCTION__] = true;
12072             return true;
12073         }
12074     }
12075
12076     /**
12077      * Set the port. Returns true on success, false on failure (if there are
12078      * any invalid characters).
12079      *
12080      * @access public
12081      * @param string $port
12082      * @return bool
12083      */
12084     function set_port($port)
12085     {
12086         if ($port === null || $port === '')
12087         {
12088             $this->port = null;
12089             $this->valid[__FUNCTION__] = true;
12090             return true;
12091         }
12092         elseif (strspn($port, '0123456789') === strlen($port))
12093         {
12094             $this->port = (int) $port;
12095             $this->valid[__FUNCTION__] = true;
12096             return true;
12097         }
12098         else
12099         {
12100             $this->port = null;
12101             $this->valid[__FUNCTION__] = false;
12102             return false;
12103         }
12104     }
12105
12106     /**
12107      * Set the path.
12108      *
12109      * @access public
12110      * @param string $path
12111      * @return bool
12112      */
12113     function set_path($path)
12114     {
12115         if ($path === null || $path === '')
12116         {
12117             $this->path = null;
12118             $this->valid[__FUNCTION__] = true;
12119             return true;
12120         }
12121         elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12122         {
12123             $this->path = null;
12124             $this->valid[__FUNCTION__] = false;
12125             return false;
12126         }
12127         else
12128         {
12129             $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12130             if ($this->scheme !== null)
12131             {
12132                 $this->path = $this->remove_dot_segments($this->path);
12133             }
12134             $this->valid[__FUNCTION__] = true;
12135             return true;
12136         }
12137     }
12138
12139     /**
12140      * Set the query.
12141      *
12142      * @access public
12143      * @param string $query
12144      * @return bool
12145      */
12146     function set_query($query)
12147     {
12148         if ($query === null || $query === '')
12149         {
12150             $this->query = null;
12151         }
12152         else
12153         {
02bf99 12154             $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
fd9ef2 12155         }
T 12156         $this->valid[__FUNCTION__] = true;
12157         return true;
12158     }
12159
12160     /**
12161      * Set the fragment.
12162      *
12163      * @access public
12164      * @param string $fragment
12165      * @return bool
12166      */
12167     function set_fragment($fragment)
12168     {
12169         if ($fragment === null || $fragment === '')
12170         {
12171             $this->fragment = null;
12172         }
12173         else
12174         {
12175             $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12176         }
12177         $this->valid[__FUNCTION__] = true;
12178         return true;
12179     }
12180
12181     /**
12182      * Get the complete IRI
12183      *
12184      * @access public
12185      * @return string
12186      */
12187     function get_iri()
12188     {
12189         $iri = '';
12190         if ($this->scheme !== null)
12191         {
12192             $iri .= $this->scheme . ':';
12193         }
12194         if (($authority = $this->get_authority()) !== null)
12195         {
12196             $iri .= '//' . $authority;
12197         }
12198         if ($this->path !== null)
12199         {
12200             $iri .= $this->path;
12201         }
12202         if ($this->query !== null)
12203         {
12204             $iri .= '?' . $this->query;
12205         }
12206         if ($this->fragment !== null)
12207         {
12208             $iri .= '#' . $this->fragment;
12209         }
12210
12211         if ($iri !== '')
12212         {
12213             return $iri;
12214         }
12215         else
12216         {
12217             return null;
12218         }
12219     }
12220
12221     /**
12222      * Get the scheme
12223      *
12224      * @access public
12225      * @return string
12226      */
12227     function get_scheme()
12228     {
12229         return $this->scheme;
12230     }
12231
12232     /**
12233      * Get the complete authority
12234      *
12235      * @access public
12236      * @return string
12237      */
12238     function get_authority()
12239     {
12240         $authority = '';
12241         if ($this->userinfo !== null)
12242         {
12243             $authority .= $this->userinfo . '@';
12244         }
12245         if ($this->host !== null)
12246         {
12247             $authority .= $this->host;
12248         }
12249         if ($this->port !== null)
12250         {
12251             $authority .= ':' . $this->port;
12252         }
12253
12254         if ($authority !== '')
12255         {
12256             return $authority;
12257         }
12258         else
12259         {
12260             return null;
12261         }
12262     }
12263
12264     /**
12265      * Get the user information
12266      *
12267      * @access public
12268      * @return string
12269      */
12270     function get_userinfo()
12271     {
12272         return $this->userinfo;
12273     }
12274
12275     /**
12276      * Get the host
12277      *
12278      * @access public
12279      * @return string
12280      */
12281     function get_host()
12282     {
12283         return $this->host;
12284     }
12285
12286     /**
12287      * Get the port
12288      *
12289      * @access public
12290      * @return string
12291      */
12292     function get_port()
12293     {
12294         return $this->port;
12295     }
12296
12297     /**
12298      * Get the path
12299      *
12300      * @access public
12301      * @return string
12302      */
12303     function get_path()
12304     {
12305         return $this->path;
12306     }
12307
12308     /**
12309      * Get the query
12310      *
12311      * @access public
12312      * @return string
12313      */
12314     function get_query()
12315     {
12316         return $this->query;
12317     }
12318
12319     /**
12320      * Get the fragment
12321      *
12322      * @access public
12323      * @return string
12324      */
12325     function get_fragment()
12326     {
12327         return $this->fragment;
12328     }
12329 }
12330
12331 /**
12332  * Class to validate and to work with IPv6 addresses.
12333  *
12334  * @package SimplePie
12335  * @copyright 2003-2005 The PHP Group
12336  * @license http://www.opensource.org/licenses/bsd-license.php
12337  * @link http://pear.php.net/package/Net_IPv6
12338  * @author Alexander Merz <alexander.merz@web.de>
12339  * @author elfrink at introweb dot nl
12340  * @author Josh Peck <jmp at joshpeck dot org>
12341  * @author Geoffrey Sneddon <geoffers@gmail.com>
12342  */
12343 class SimplePie_Net_IPv6
12344 {
12345     /**
12346      * Removes a possible existing netmask specification of an IP address.
12347      *
12348      * @param string $ip the (compressed) IP as Hex representation
12349      * @return string the IP the without netmask
12350      * @since 1.1.0
12351      * @access public
12352      * @static
12353      */
12354     function removeNetmaskSpec($ip)
12355     {
12356         if (strpos($ip, '/') !== false)
12357         {
12358             list($addr, $nm) = explode('/', $ip);
12359         }
12360         else
12361         {
12362             $addr = $ip;
12363         }
12364         return $addr;
12365     }
12366
12367     /**
12368      * Uncompresses an IPv6 address
12369      *
12370      * RFC 2373 allows you to compress zeros in an address to '::'. This
12371      * function expects an valid IPv6 address and expands the '::' to
12372      * the required zeros.
12373      *
12374      * Example:     FF01::101    ->    FF01:0:0:0:0:0:0:101
12375      *             ::1        ->    0:0:0:0:0:0:0:1
12376      *
12377      * @access public
12378      * @static
12379      * @param string $ip a valid IPv6-address (hex format)
12380      * @return string the uncompressed IPv6-address (hex format)
12381      */
12382     function Uncompress($ip)
12383     {
12384         $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12385         $c1 = -1;
12386         $c2 = -1;
12387         if (strpos($ip, '::') !== false)
12388         {
12389             list($ip1, $ip2) = explode('::', $ip);
12390             if ($ip1 === '')
12391             {
12392                 $c1 = -1;
12393             }
12394             else
12395             {
12396                 $pos = 0;
12397                 if (($pos = substr_count($ip1, ':')) > 0)
12398                 {
12399                     $c1 = $pos;
12400                 }
12401                 else
12402                 {
12403                     $c1 = 0;
12404                 }
12405             }
12406             if ($ip2 === '')
12407             {
12408                 $c2 = -1;
12409             }
12410             else
12411             {
12412                 $pos = 0;
12413                 if (($pos = substr_count($ip2, ':')) > 0)
12414                 {
12415                     $c2 = $pos;
12416                 }
12417                 else
12418                 {
12419                     $c2 = 0;
12420                 }
12421             }
12422             if (strstr($ip2, '.'))
12423             {
12424                 $c2++;
12425             }
12426             // ::
12427             if ($c1 === -1 && $c2 === -1)
12428             {
12429                 $uip = '0:0:0:0:0:0:0:0';
12430             }
12431             // ::xxx
12432             else if ($c1 === -1)
12433             {
12434                 $fill = str_repeat('0:', 7 - $c2);
12435                 $uip =    str_replace('::', $fill, $uip);
12436             }
12437             // xxx::
12438             else if ($c2 === -1)
12439             {
12440                 $fill = str_repeat(':0', 7 - $c1);
12441                 $uip =    str_replace('::', $fill, $uip);
12442             }
12443             // xxx::xxx
12444             else
12445             {
12446                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12447                 $uip =    str_replace('::', $fill, $uip);
12448                 $uip =    str_replace('::', ':', $uip);
12449             }
12450         }
12451         return $uip;
12452     }
12453
12454     /**
12455      * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12456      *
12457      * RFC 2373 allows you to note the last two parts of an IPv6 address as
12458      * an IPv4 compatible address
12459      *
12460      * Example:     0:0:0:0:0:0:13.1.68.3
12461      *             0:0:0:0:0:FFFF:129.144.52.38
12462      *
12463      * @access public
12464      * @static
12465      * @param string $ip a valid IPv6-address (hex format)
12466      * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12467      */
12468     function SplitV64($ip)
12469     {
12470         $ip = SimplePie_Net_IPv6::Uncompress($ip);
12471         if (strstr($ip, '.'))
12472         {
12473             $pos = strrpos($ip, ':');
12474             $ip[$pos] = '_';
12475             $ipPart = explode('_', $ip);
12476             return $ipPart;
12477         }
12478         else
12479         {
12480             return array($ip, '');
12481         }
12482     }
12483
12484     /**
12485      * Checks an IPv6 address
12486      *
12487      * Checks if the given IP is IPv6-compatible
12488      *
12489      * @access public
12490      * @static
12491      * @param string $ip a valid IPv6-address
12492      * @return bool true if $ip is an IPv6 address
12493      */
12494     function checkIPv6($ip)
12495     {
12496         $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12497         $count = 0;
12498         if (!empty($ipPart[0]))
12499         {
12500             $ipv6 = explode(':', $ipPart[0]);
12501             for ($i = 0; $i < count($ipv6); $i++)
12502             {
12503                 $dec = hexdec($ipv6[$i]);
12504                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12505                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12506                 {
12507                     $count++;
12508                 }
12509             }
12510             if ($count === 8)
12511             {
12512                 return true;
12513             }
12514             elseif ($count === 6 && !empty($ipPart[1]))
12515             {
12516                 $ipv4 = explode('.', $ipPart[1]);
12517                 $count = 0;
12518                 foreach ($ipv4 as $ipv4_part)
12519                 {
12520                     if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12521                     {
12522                         $count++;
12523                     }
12524                 }
12525                 if ($count === 4)
12526                 {
12527                     return true;
12528                 }
12529             }
12530             else
12531             {
12532                 return false;
12533             }
12534
12535         }
12536         else
12537         {
12538             return false;
12539         }
12540     }
12541 }
12542
12543 /**
12544  * Date Parser
12545  *
12546  * @package SimplePie
12547  */
12548 class SimplePie_Parse_Date
12549 {
12550     /**
12551      * Input data
12552      *
12553      * @access protected
12554      * @var string
12555      */
12556     var $date;
12557
12558     /**
12559      * List of days, calendar day name => ordinal day number in the week
12560      *
12561      * @access protected
12562      * @var array
12563      */
12564     var $day = array(
12565         // English
12566         'mon' => 1,
12567         'monday' => 1,
12568         'tue' => 2,
12569         'tuesday' => 2,
12570         'wed' => 3,
12571         'wednesday' => 3,
12572         'thu' => 4,
12573         'thursday' => 4,
12574         'fri' => 5,
12575         'friday' => 5,
12576         'sat' => 6,
12577         'saturday' => 6,
12578         'sun' => 7,
12579         'sunday' => 7,
12580         // Dutch
12581         'maandag' => 1,
12582         'dinsdag' => 2,
12583         'woensdag' => 3,
12584         'donderdag' => 4,
12585         'vrijdag' => 5,
12586         'zaterdag' => 6,
12587         'zondag' => 7,
12588         // French
12589         'lundi' => 1,
12590         'mardi' => 2,
12591         'mercredi' => 3,
12592         'jeudi' => 4,
12593         'vendredi' => 5,
12594         'samedi' => 6,
12595         'dimanche' => 7,
12596         // German
12597         'montag' => 1,
12598         'dienstag' => 2,
12599         'mittwoch' => 3,
12600         'donnerstag' => 4,
12601         'freitag' => 5,
12602         'samstag' => 6,
12603         'sonnabend' => 6,
12604         'sonntag' => 7,
12605         // Italian
12606         'lunedì' => 1,
12607         'martedì' => 2,
12608         'mercoledì' => 3,
12609         'giovedì' => 4,
12610         'venerdì' => 5,
12611         'sabato' => 6,
12612         'domenica' => 7,
12613         // Spanish
12614         'lunes' => 1,
12615         'martes' => 2,
12616         'miércoles' => 3,
12617         'jueves' => 4,
12618         'viernes' => 5,
12619         'sábado' => 6,
12620         'domingo' => 7,
12621         // Finnish
12622         'maanantai' => 1,
12623         'tiistai' => 2,
12624         'keskiviikko' => 3,
12625         'torstai' => 4,
12626         'perjantai' => 5,
12627         'lauantai' => 6,
12628         'sunnuntai' => 7,
12629         // Hungarian
12630         'hétfő' => 1,
12631         'kedd' => 2,
12632         'szerda' => 3,
12633         'csütörtok' => 4,
12634         'péntek' => 5,
12635         'szombat' => 6,
12636         'vasárnap' => 7,
12637         // Greek
12638         'Δευ' => 1,
12639         'Τρι' => 2,
12640         'Τετ' => 3,
12641         'Πεμ' => 4,
12642         'Παρ' => 5,
12643         'Σαβ' => 6,
12644         'Κυρ' => 7,
12645     );
12646
12647     /**
12648      * List of months, calendar month name => calendar month number
12649      *
12650      * @access protected
12651      * @var array
12652      */
12653     var $month = array(
12654         // English
12655         'jan' => 1,
12656         'january' => 1,
12657         'feb' => 2,
12658         'february' => 2,
12659         'mar' => 3,
12660         'march' => 3,
12661         'apr' => 4,
12662         'april' => 4,
12663         'may' => 5,
12664         // No long form of May
12665         'jun' => 6,
12666         'june' => 6,
12667         'jul' => 7,
12668         'july' => 7,
12669         'aug' => 8,
12670         'august' => 8,
12671         'sep' => 9,
12672         'september' => 8,
12673         'oct' => 10,
12674         'october' => 10,
12675         'nov' => 11,
12676         'november' => 11,
12677         'dec' => 12,
12678         'december' => 12,
12679         // Dutch
12680         'januari' => 1,
12681         'februari' => 2,
12682         'maart' => 3,
12683         'april' => 4,
12684         'mei' => 5,
12685         'juni' => 6,
12686         'juli' => 7,
12687         'augustus' => 8,
12688         'september' => 9,
12689         'oktober' => 10,
12690         'november' => 11,
12691         'december' => 12,
12692         // French
12693         'janvier' => 1,
12694         'février' => 2,
12695         'mars' => 3,
12696         'avril' => 4,
12697         'mai' => 5,
12698         'juin' => 6,
12699         'juillet' => 7,
12700         'août' => 8,
12701         'septembre' => 9,
12702         'octobre' => 10,
12703         'novembre' => 11,
12704         'décembre' => 12,
12705         // German
12706         'januar' => 1,
12707         'februar' => 2,
12708         'märz' => 3,
12709         'april' => 4,
12710         'mai' => 5,
12711         'juni' => 6,
12712         'juli' => 7,
12713         'august' => 8,
12714         'september' => 9,
12715         'oktober' => 10,
12716         'november' => 11,
12717         'dezember' => 12,
12718         // Italian
12719         'gennaio' => 1,
12720         'febbraio' => 2,
12721         'marzo' => 3,
12722         'aprile' => 4,
12723         'maggio' => 5,
12724         'giugno' => 6,
12725         'luglio' => 7,
12726         'agosto' => 8,
12727         'settembre' => 9,
12728         'ottobre' => 10,
12729         'novembre' => 11,
12730         'dicembre' => 12,
12731         // Spanish
12732         'enero' => 1,
12733         'febrero' => 2,
12734         'marzo' => 3,
12735         'abril' => 4,
12736         'mayo' => 5,
12737         'junio' => 6,
12738         'julio' => 7,
12739         'agosto' => 8,
12740         'septiembre' => 9,
12741         'setiembre' => 9,
12742         'octubre' => 10,
12743         'noviembre' => 11,
12744         'diciembre' => 12,
12745         // Finnish
12746         'tammikuu' => 1,
12747         'helmikuu' => 2,
12748         'maaliskuu' => 3,
12749         'huhtikuu' => 4,
12750         'toukokuu' => 5,
12751         'kesäkuu' => 6,
12752         'heinäkuu' => 7,
12753         'elokuu' => 8,
12754         'suuskuu' => 9,
12755         'lokakuu' => 10,
12756         'marras' => 11,
12757         'joulukuu' => 12,
12758         // Hungarian
12759         'január' => 1,
12760         'február' => 2,
12761         'március' => 3,
12762         'április' => 4,
12763         'május' => 5,
12764         'június' => 6,
12765         'július' => 7,
12766         'augusztus' => 8,
12767         'szeptember' => 9,
12768         'október' => 10,
12769         'november' => 11,
12770         'december' => 12,
12771         // Greek
12772         'Ιαν' => 1,
12773         'Φεβ' => 2,
12774         'Μάώ' => 3,
12775         'Μαώ' => 3,
12776         'Απρ' => 4,
12777         'Μάι' => 5,
12778         'Μαϊ' => 5,
12779         'Μαι' => 5,
12780         'Ιούν' => 6,
12781         'Ιον' => 6,
12782         'Ιούλ' => 7,
12783         'Ιολ' => 7,
12784         'Αύγ' => 8,
12785         'Αυγ' => 8,
12786         'Σεπ' => 9,
12787         'Οκτ' => 10,
12788         'Νοέ' => 11,
12789         'Δεκ' => 12,
12790     );
12791
12792     /**
12793      * List of timezones, abbreviation => offset from UTC
12794      *
12795      * @access protected
12796      * @var array
12797      */
12798     var $timezone = array(
12799         'ACDT' => 37800,
12800         'ACIT' => 28800,
12801         'ACST' => 34200,
12802         'ACT' => -18000,
12803         'ACWDT' => 35100,
12804         'ACWST' => 31500,
12805         'AEDT' => 39600,
12806         'AEST' => 36000,
12807         'AFT' => 16200,
12808         'AKDT' => -28800,
12809         'AKST' => -32400,
12810         'AMDT' => 18000,
12811         'AMT' => -14400,
12812         'ANAST' => 46800,
12813         'ANAT' => 43200,
12814         'ART' => -10800,
12815         'AZOST' => -3600,
12816         'AZST' => 18000,
12817         'AZT' => 14400,
12818         'BIOT' => 21600,
12819         'BIT' => -43200,
12820         'BOT' => -14400,
12821         'BRST' => -7200,
12822         'BRT' => -10800,
12823         'BST' => 3600,
12824         'BTT' => 21600,
12825         'CAST' => 18000,
12826         'CAT' => 7200,
12827         'CCT' => 23400,
12828         'CDT' => -18000,
12829         'CEDT' => 7200,
12830         'CET' => 3600,
12831         'CGST' => -7200,
12832         'CGT' => -10800,
12833         'CHADT' => 49500,
12834         'CHAST' => 45900,
12835         'CIST' => -28800,
12836         'CKT' => -36000,
12837         'CLDT' => -10800,
12838         'CLST' => -14400,
12839         'COT' => -18000,
12840         'CST' => -21600,
12841         'CVT' => -3600,
12842         'CXT' => 25200,
12843         'DAVT' => 25200,
12844         'DTAT' => 36000,
12845         'EADT' => -18000,
12846         'EAST' => -21600,
12847         'EAT' => 10800,
12848         'ECT' => -18000,
12849         'EDT' => -14400,
12850         'EEST' => 10800,
12851         'EET' => 7200,
12852         'EGT' => -3600,
12853         'EKST' => 21600,
12854         'EST' => -18000,
12855         'FJT' => 43200,
12856         'FKDT' => -10800,
12857         'FKST' => -14400,
12858         'FNT' => -7200,
12859         'GALT' => -21600,
12860         'GEDT' => 14400,
12861         'GEST' => 10800,
12862         'GFT' => -10800,
12863         'GILT' => 43200,
12864         'GIT' => -32400,
12865         'GST' => 14400,
12866         'GST' => -7200,
12867         'GYT' => -14400,
12868         'HAA' => -10800,
12869         'HAC' => -18000,
12870         'HADT' => -32400,
12871         'HAE' => -14400,
12872         'HAP' => -25200,
12873         'HAR' => -21600,
12874         'HAST' => -36000,
12875         'HAT' => -9000,
12876         'HAY' => -28800,
12877         'HKST' => 28800,
12878         'HMT' => 18000,
12879         'HNA' => -14400,
12880         'HNC' => -21600,
12881         'HNE' => -18000,
12882         'HNP' => -28800,
12883         'HNR' => -25200,
12884         'HNT' => -12600,
12885         'HNY' => -32400,
12886         'IRDT' => 16200,
12887         'IRKST' => 32400,
12888         'IRKT' => 28800,
12889         'IRST' => 12600,
12890         'JFDT' => -10800,
12891         'JFST' => -14400,
12892         'JST' => 32400,
12893         'KGST' => 21600,
12894         'KGT' => 18000,
12895         'KOST' => 39600,
12896         'KOVST' => 28800,
12897         'KOVT' => 25200,
12898         'KRAST' => 28800,
12899         'KRAT' => 25200,
12900         'KST' => 32400,
12901         'LHDT' => 39600,
12902         'LHST' => 37800,
12903         'LINT' => 50400,
12904         'LKT' => 21600,
12905         'MAGST' => 43200,
12906         'MAGT' => 39600,
12907         'MAWT' => 21600,
12908         'MDT' => -21600,
12909         'MESZ' => 7200,
12910         'MEZ' => 3600,
12911         'MHT' => 43200,
12912         'MIT' => -34200,
12913         'MNST' => 32400,
12914         'MSDT' => 14400,
12915         'MSST' => 10800,
12916         'MST' => -25200,
12917         'MUT' => 14400,
12918         'MVT' => 18000,
12919         'MYT' => 28800,
12920         'NCT' => 39600,
12921         'NDT' => -9000,
12922         'NFT' => 41400,
12923         'NMIT' => 36000,
12924         'NOVST' => 25200,
12925         'NOVT' => 21600,
12926         'NPT' => 20700,
12927         'NRT' => 43200,
12928         'NST' => -12600,
12929         'NUT' => -39600,
12930         'NZDT' => 46800,
12931         'NZST' => 43200,
12932         'OMSST' => 25200,
12933         'OMST' => 21600,
12934         'PDT' => -25200,
12935         'PET' => -18000,
12936         'PETST' => 46800,
12937         'PETT' => 43200,
12938         'PGT' => 36000,
12939         'PHOT' => 46800,
12940         'PHT' => 28800,
12941         'PKT' => 18000,
12942         'PMDT' => -7200,
12943         'PMST' => -10800,
12944         'PONT' => 39600,
12945         'PST' => -28800,
12946         'PWT' => 32400,
12947         'PYST' => -10800,
12948         'PYT' => -14400,
12949         'RET' => 14400,
12950         'ROTT' => -10800,
12951         'SAMST' => 18000,
12952         'SAMT' => 14400,
12953         'SAST' => 7200,
12954         'SBT' => 39600,
12955         'SCDT' => 46800,
12956         'SCST' => 43200,
12957         'SCT' => 14400,
12958         'SEST' => 3600,
12959         'SGT' => 28800,
12960         'SIT' => 28800,
12961         'SRT' => -10800,
12962         'SST' => -39600,
12963         'SYST' => 10800,
12964         'SYT' => 7200,
12965         'TFT' => 18000,
12966         'THAT' => -36000,
12967         'TJT' => 18000,
12968         'TKT' => -36000,
12969         'TMT' => 18000,
12970         'TOT' => 46800,
12971         'TPT' => 32400,
12972         'TRUT' => 36000,
12973         'TVT' => 43200,
12974         'TWT' => 28800,
12975         'UYST' => -7200,
12976         'UYT' => -10800,
12977         'UZT' => 18000,
12978         'VET' => -14400,
12979         'VLAST' => 39600,
12980         'VLAT' => 36000,
12981         'VOST' => 21600,
12982         'VUT' => 39600,
12983         'WAST' => 7200,
12984         'WAT' => 3600,
12985         'WDT' => 32400,
12986         'WEST' => 3600,
12987         'WFT' => 43200,
12988         'WIB' => 25200,
12989         'WIT' => 32400,
12990         'WITA' => 28800,
12991         'WKST' => 18000,
12992         'WST' => 28800,
12993         'YAKST' => 36000,
12994         'YAKT' => 32400,
12995         'YAPT' => 36000,
12996         'YEKST' => 21600,
12997         'YEKT' => 18000,
12998     );
12999
13000     /**
13001      * Cached PCRE for SimplePie_Parse_Date::$day
13002      *
13003      * @access protected
13004      * @var string
13005      */
13006     var $day_pcre;
13007
13008     /**
13009      * Cached PCRE for SimplePie_Parse_Date::$month
13010      *
13011      * @access protected
13012      * @var string
13013      */
13014     var $month_pcre;
13015
13016     /**
13017      * Array of user-added callback methods
13018      *
13019      * @access private
13020      * @var array
13021      */
13022     var $built_in = array();
13023
13024     /**
13025      * Array of user-added callback methods
13026      *
13027      * @access private
13028      * @var array
13029      */
13030     var $user = array();
13031
13032     /**
13033      * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13034      * self::month_pcre, and self::built_in
13035      *
13036      * @access private
13037      */
13038     function SimplePie_Parse_Date()
13039     {
13040         $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13041         $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13042
13043         static $cache;
13044         if (!isset($cache[get_class($this)]))
13045         {
13046             $all_methods = get_class_methods($this);
13047
13048             foreach ($all_methods as $method)
13049             {
13050                 if (strtolower(substr($method, 0, 5)) === 'date_')
13051                 {
13052                     $cache[get_class($this)][] = $method;
13053                 }
13054             }
13055         }
13056
13057         foreach ($cache[get_class($this)] as $method)
13058         {
13059             $this->built_in[] = $method;
13060         }
13061     }
13062
13063     /**
13064      * Get the object
13065      *
13066      * @access public
13067      */
829b76 13068     static function get()
fd9ef2 13069     {
T 13070         static $object;
13071         if (!$object)
13072         {
f64c86 13073             $object = new SimplePie_Parse_Date;
fd9ef2 13074         }
T 13075         return $object;
13076     }
13077
13078     /**
13079      * Parse a date
13080      *
13081      * @final
13082      * @access public
13083      * @param string $date Date to parse
13084      * @return int Timestamp corresponding to date string, or false on failure
13085      */
13086     function parse($date)
13087     {
13088         foreach ($this->user as $method)
13089         {
13090             if (($returned = call_user_func($method, $date)) !== false)
13091             {
13092                 return $returned;
13093             }
13094         }
13095
13096         foreach ($this->built_in as $method)
13097         {
13098             if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13099             {
13100                 return $returned;
13101             }
13102         }
13103
13104         return false;
13105     }
13106
13107     /**
13108      * Add a callback method to parse a date
13109      *
13110      * @final
13111      * @access public
13112      * @param callback $callback
13113      */
13114     function add_callback($callback)
13115     {
13116         if (is_callable($callback))
13117         {
13118             $this->user[] = $callback;
13119         }
13120         else
13121         {
13122             trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13123         }
13124     }
13125
13126     /**
13127      * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13128      * well as allowing any of upper or lower case "T", horizontal tabs, or
13129      * spaces to be used as the time seperator (including more than one))
13130      *
13131      * @access protected
13132      * @return int Timestamp
13133      */
13134     function date_w3cdtf($date)
13135     {
13136         static $pcre;
13137         if (!$pcre)
13138         {
13139             $year = '([0-9]{4})';
13140             $month = $day = $hour = $minute = $second = '([0-9]{2})';
13141             $decimal = '([0-9]*)';
13142             $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13143             $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13144         }
13145         if (preg_match($pcre, $date, $match))
13146         {
13147             /*
13148             Capturing subpatterns:
13149             1: Year
13150             2: Month
13151             3: Day
13152             4: Hour
13153             5: Minute
13154             6: Second
13155             7: Decimal fraction of a second
13156             8: Zulu
13157             9: Timezone ±
13158             10: Timezone hours
13159             11: Timezone minutes
13160             */
13161
13162             // Fill in empty matches
13163             for ($i = count($match); $i <= 3; $i++)
13164             {
13165                 $match[$i] = '1';
13166             }
13167
13168             for ($i = count($match); $i <= 7; $i++)
13169             {
13170                 $match[$i] = '0';
13171             }
13172
13173             // Numeric timezone
13174             if (isset($match[9]) && $match[9] !== '')
13175             {
13176                 $timezone = $match[10] * 3600;
13177                 $timezone += $match[11] * 60;
13178                 if ($match[9] === '-')
13179                 {
13180                     $timezone = 0 - $timezone;
13181                 }
13182             }
13183             else
13184             {
13185                 $timezone = 0;
13186             }
13187
13188             // Convert the number of seconds to an integer, taking decimals into account
13189             $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13190
13191             return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13192         }
13193         else
13194         {
13195             return false;
13196         }
13197     }
13198
13199     /**
13200      * Remove RFC822 comments
13201      *
13202      * @access protected
13203      * @param string $data Data to strip comments from
13204      * @return string Comment stripped string
13205      */
13206     function remove_rfc2822_comments($string)
13207     {
13208         $string = (string) $string;
13209         $position = 0;
13210         $length = strlen($string);
13211         $depth = 0;
13212
13213         $output = '';
13214
13215         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13216         {
13217             $output .= substr($string, $position, $pos - $position);
13218             $position = $pos + 1;
13219             if ($string[$pos - 1] !== '\\')
13220             {
13221                 $depth++;
13222                 while ($depth && $position < $length)
13223                 {
13224                     $position += strcspn($string, '()', $position);
13225                     if ($string[$position - 1] === '\\')
13226                     {
13227                         $position++;
13228                         continue;
13229                     }
13230                     elseif (isset($string[$position]))
13231                     {
13232                         switch ($string[$position])
13233                         {
13234                             case '(':
13235                                 $depth++;
13236                                 break;
13237
13238                             case ')':
13239                                 $depth--;
13240                                 break;
13241                         }
13242                         $position++;
13243                     }
13244                     else
13245                     {
13246                         break;
13247                     }
13248                 }
13249             }
13250             else
13251             {
13252                 $output .= '(';
13253             }
13254         }
13255         $output .= substr($string, $position);
13256
13257         return $output;
13258     }
13259
13260     /**
13261      * Parse RFC2822's date format
13262      *
13263      * @access protected
13264      * @return int Timestamp
13265      */
13266     function date_rfc2822($date)
13267     {
13268         static $pcre;
13269         if (!$pcre)
13270         {
13271             $wsp = '[\x09\x20]';
13272             $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13273             $optional_fws = $fws . '?';
13274             $day_name = $this->day_pcre;
13275             $month = $this->month_pcre;
13276             $day = '([0-9]{1,2})';
13277             $hour = $minute = $second = '([0-9]{2})';
13278             $year = '([0-9]{2,4})';
13279             $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13280             $character_zone = '([A-Z]{1,5})';
13281             $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13282             $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';
13283         }
13284         if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13285         {
13286             /*
13287             Capturing subpatterns:
13288             1: Day name
13289             2: Day
13290             3: Month
13291             4: Year
13292             5: Hour
13293             6: Minute
13294             7: Second
13295             8: Timezone ±
13296             9: Timezone hours
13297             10: Timezone minutes
13298             11: Alphabetic timezone
13299             */
13300
13301             // Find the month number
13302             $month = $this->month[strtolower($match[3])];
13303
13304             // Numeric timezone
13305             if ($match[8] !== '')
13306             {
13307                 $timezone = $match[9] * 3600;
13308                 $timezone += $match[10] * 60;
13309                 if ($match[8] === '-')
13310                 {
13311                     $timezone = 0 - $timezone;
13312                 }
13313             }
13314             // Character timezone
13315             elseif (isset($this->timezone[strtoupper($match[11])]))
13316             {
13317                 $timezone = $this->timezone[strtoupper($match[11])];
13318             }
13319             // Assume everything else to be -0000
13320             else
13321             {
13322                 $timezone = 0;
13323             }
13324
13325             // Deal with 2/3 digit years
13326             if ($match[4] < 50)
13327             {
13328                 $match[4] += 2000;
13329             }
13330             elseif ($match[4] < 1000)
13331             {
13332                 $match[4] += 1900;
13333             }
13334
13335             // Second is optional, if it is empty set it to zero
13336             if ($match[7] !== '')
13337             {
13338                 $second = $match[7];
13339             }
13340             else
13341             {
13342                 $second = 0;
13343             }
13344
13345             return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13346         }
13347         else
13348         {
13349             return false;
13350         }
13351     }
13352
13353     /**
13354      * Parse RFC850's date format
13355      *
13356      * @access protected
13357      * @return int Timestamp
13358      */
13359     function date_rfc850($date)
13360     {
13361         static $pcre;
13362         if (!$pcre)
13363         {
13364             $space = '[\x09\x20]+';
13365             $day_name = $this->day_pcre;
13366             $month = $this->month_pcre;
13367             $day = '([0-9]{1,2})';
13368             $year = $hour = $minute = $second = '([0-9]{2})';
13369             $zone = '([A-Z]{1,5})';
13370             $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13371         }
13372         if (preg_match($pcre, $date, $match))
13373         {
13374             /*
13375             Capturing subpatterns:
13376             1: Day name
13377             2: Day
13378             3: Month
13379             4: Year
13380             5: Hour
13381             6: Minute
13382             7: Second
13383             8: Timezone
13384             */
13385
13386             // Month
13387             $month = $this->month[strtolower($match[3])];
13388
13389             // Character timezone
13390             if (isset($this->timezone[strtoupper($match[8])]))
13391             {
13392                 $timezone = $this->timezone[strtoupper($match[8])];
13393             }
13394             // Assume everything else to be -0000
13395             else
13396             {
13397                 $timezone = 0;
13398             }
13399
13400             // Deal with 2 digit year
13401             if ($match[4] < 50)
13402             {
13403                 $match[4] += 2000;
13404             }
13405             else
13406             {
13407                 $match[4] += 1900;
13408             }
13409
13410             return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13411         }
13412         else
13413         {
13414             return false;
13415         }
13416     }
13417
13418     /**
13419      * Parse C99's asctime()'s date format
13420      *
13421      * @access protected
13422      * @return int Timestamp
13423      */
13424     function date_asctime($date)
13425     {
13426         static $pcre;
13427         if (!$pcre)
13428         {
13429             $space = '[\x09\x20]+';
13430             $wday_name = $this->day_pcre;
13431             $mon_name = $this->month_pcre;
13432             $day = '([0-9]{1,2})';
13433             $hour = $sec = $min = '([0-9]{2})';
13434             $year = '([0-9]{4})';
13435             $terminator = '\x0A?\x00?';
13436             $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13437         }
13438         if (preg_match($pcre, $date, $match))
13439         {
13440             /*
13441             Capturing subpatterns:
13442             1: Day name
13443             2: Month
13444             3: Day
13445             4: Hour
13446             5: Minute
13447             6: Second
13448             7: Year
13449             */
13450
13451             $month = $this->month[strtolower($match[2])];
13452             return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13453         }
13454         else
13455         {
13456             return false;
13457         }
13458     }
13459
13460     /**
13461      * Parse dates using strtotime()
13462      *
13463      * @access protected
13464      * @return int Timestamp
13465      */
13466     function date_strtotime($date)
13467     {
13468         $strtotime = strtotime($date);
13469         if ($strtotime === -1 || $strtotime === false)
13470         {
13471             return false;
13472         }
13473         else
13474         {
13475             return $strtotime;
13476         }
13477     }
13478 }
13479
13480 /**
13481  * Content-type sniffing
13482  *
13483  * @package SimplePie
13484  */
13485 class SimplePie_Content_Type_Sniffer
13486 {
13487     /**
13488      * File object
13489      *
13490      * @var SimplePie_File
13491      * @access private
13492      */
13493     var $file;
13494
13495     /**
13496      * Create an instance of the class with the input file
13497      *
13498      * @access public
13499      * @param SimplePie_Content_Type_Sniffer $file Input file
13500      */
13501     function SimplePie_Content_Type_Sniffer($file)
13502     {
13503         $this->file = $file;
13504     }
13505
13506     /**
13507      * Get the Content-Type of the specified file
13508      *
13509      * @access public
13510      * @return string Actual Content-Type
13511      */
13512     function get_type()
13513     {
13514         if (isset($this->file->headers['content-type']))
13515         {
13516             if (!isset($this->file->headers['content-encoding'])
13517                 && ($this->file->headers['content-type'] === 'text/plain'
13518                     || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13519                     || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13520             {
13521                 return $this->text_or_binary();
13522             }
13523
13524             if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13525             {
13526                 $official = substr($this->file->headers['content-type'], 0, $pos);
13527             }
13528             else
13529             {
13530                 $official = $this->file->headers['content-type'];
13531             }
13532             $official = strtolower($official);
13533
13534             if ($official === 'unknown/unknown'
13535                 || $official === 'application/unknown')
13536             {
13537                 return $this->unknown();
13538             }
13539             elseif (substr($official, -4) === '+xml'
13540                 || $official === 'text/xml'
13541                 || $official === 'application/xml')
13542             {
13543                 return $official;
13544             }
13545             elseif (substr($official, 0, 6) === 'image/')
13546             {
13547                 if ($return = $this->image())
13548                 {
13549                     return $return;
13550                 }
13551                 else
13552                 {
13553                     return $official;
13554                 }
13555             }
13556             elseif ($official === 'text/html')
13557             {
13558                 return $this->feed_or_html();
13559             }
13560             else
13561             {
13562                 return $official;
13563             }
13564         }
13565         else
13566         {
13567             return $this->unknown();
13568         }
13569     }
13570
13571     /**
13572      * Sniff text or binary
13573      *
13574      * @access private
13575      * @return string Actual Content-Type
13576      */
13577     function text_or_binary()
13578     {
13579         if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13580             || substr($this->file->body, 0, 2) === "\xFF\xFE"
13581             || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13582             || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13583         {
13584             return 'text/plain';
13585         }
13586         elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13587         {
13588             return 'application/octect-stream';
13589         }
13590         else
13591         {
13592             return 'text/plain';
13593         }
13594     }
13595
13596     /**
13597      * Sniff unknown
13598      *
13599      * @access private
13600      * @return string Actual Content-Type
13601      */
13602     function unknown()
13603     {
13604         $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13605         if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13606             || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13607             || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13608         {
13609             return 'text/html';
13610         }
13611         elseif (substr($this->file->body, 0, 5) === '%PDF-')
13612         {
13613             return 'application/pdf';
13614         }
13615         elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13616         {
13617             return 'application/postscript';
13618         }
13619         elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13620             || substr($this->file->body, 0, 6) === 'GIF89a')
13621         {
13622             return 'image/gif';
13623         }
13624         elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13625         {
13626             return 'image/png';
13627         }
13628         elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13629         {
13630             return 'image/jpeg';
13631         }
13632         elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13633         {
13634             return 'image/bmp';
13635         }
13636         else
13637         {
13638             return $this->text_or_binary();
13639         }
13640     }
13641
13642     /**
13643      * Sniff images
13644      *
13645      * @access private
13646      * @return string Actual Content-Type
13647      */
13648     function image()
13649     {
13650         if (substr($this->file->body, 0, 6) === 'GIF87a'
13651             || substr($this->file->body, 0, 6) === 'GIF89a')
13652         {
13653             return 'image/gif';
13654         }
13655         elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13656         {
13657             return 'image/png';
13658         }
13659         elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13660         {
13661             return 'image/jpeg';
13662         }
13663         elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13664         {
13665             return 'image/bmp';
13666         }
13667         else
13668         {
13669             return false;
13670         }
13671     }
13672
13673     /**
13674      * Sniff HTML
13675      *
13676      * @access private
13677      * @return string Actual Content-Type
13678      */
13679     function feed_or_html()
13680     {
13681         $len = strlen($this->file->body);
13682         $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13683
13684         while ($pos < $len)
13685         {
13686             switch ($this->file->body[$pos])
13687             {
13688                 case "\x09":
13689                 case "\x0A":
13690                 case "\x0D":
13691                 case "\x20":
13692                     $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13693                     continue 2;
13694
13695                 case '<':
13696                     $pos++;
13697                     break;
13698
13699                 default:
13700                     return 'text/html';
13701             }
13702
13703             if (substr($this->file->body, $pos, 3) === '!--')
13704             {
13705                 $pos += 3;
13706                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13707                 {
13708                     $pos += 3;
13709                 }
13710                 else
13711                 {
13712                     return 'text/html';
13713                 }
13714             }
13715             elseif (substr($this->file->body, $pos, 1) === '!')
13716             {
13717                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13718                 {
13719                     $pos++;
13720                 }
13721                 else
13722                 {
13723                     return 'text/html';
13724                 }
13725             }
13726             elseif (substr($this->file->body, $pos, 1) === '?')
13727             {
13728                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13729                 {
13730                     $pos += 2;
13731                 }
13732                 else
13733                 {
13734                     return 'text/html';
13735                 }
13736             }
13737             elseif (substr($this->file->body, $pos, 3) === 'rss'
13738                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13739             {
13740                 return 'application/rss+xml';
13741             }
13742             elseif (substr($this->file->body, $pos, 4) === 'feed')
13743             {
13744                 return 'application/atom+xml';
13745             }
13746             else
13747             {
13748                 return 'text/html';
13749             }
13750         }
13751
13752         return 'text/html';
13753     }
13754 }
13755
13756 /**
13757  * Parses the XML Declaration
13758  *
13759  * @package SimplePie
13760  */
13761 class SimplePie_XML_Declaration_Parser
13762 {
13763     /**
13764      * XML Version
13765      *
13766      * @access public
13767      * @var string
13768      */
13769     var $version = '1.0';
13770
13771     /**
13772      * Encoding
13773      *
13774      * @access public
13775      * @var string
13776      */
13777     var $encoding = 'UTF-8';
13778
13779     /**
13780      * Standalone
13781      *
13782      * @access public
13783      * @var bool
13784      */
13785     var $standalone = false;
13786
13787     /**
13788      * Current state of the state machine
13789      *
13790      * @access private
13791      * @var string
13792      */
13793     var $state = 'before_version_name';
13794
13795     /**
13796      * Input data
13797      *
13798      * @access private
13799      * @var string
13800      */
13801     var $data = '';
13802
13803     /**
13804      * Input data length (to avoid calling strlen() everytime this is needed)
13805      *
13806      * @access private
13807      * @var int
13808      */
13809     var $data_length = 0;
13810
13811     /**
13812      * Current position of the pointer
13813      *
13814      * @var int
13815      * @access private
13816      */
13817     var $position = 0;
13818
13819     /**
13820      * Create an instance of the class with the input data
13821      *
13822      * @access public
13823      * @param string $data Input data
13824      */
13825     function SimplePie_XML_Declaration_Parser($data)
13826     {
13827         $this->data = $data;
13828         $this->data_length = strlen($this->data);
13829     }
13830
13831     /**
13832      * Parse the input data
13833      *
13834      * @access public
13835      * @return bool true on success, false on failure
13836      */
13837     function parse()
13838     {
13839         while ($this->state && $this->state !== 'emit' && $this->has_data())
13840         {
13841             $state = $this->state;
13842             $this->$state();
13843         }
13844         $this->data = '';
13845         if ($this->state === 'emit')
13846         {
13847             return true;
13848         }
13849         else
13850         {
13851             $this->version = '';
13852             $this->encoding = '';
13853             $this->standalone = '';
13854             return false;
13855         }
13856     }
13857
13858     /**
13859      * Check whether there is data beyond the pointer
13860      *
13861      * @access private
13862      * @return bool true if there is further data, false if not
13863      */
13864     function has_data()
13865     {
13866         return (bool) ($this->position < $this->data_length);
13867     }
13868
13869     /**
13870      * Advance past any whitespace
13871      *
13872      * @return int Number of whitespace characters passed
13873      */
13874     function skip_whitespace()
13875     {
13876         $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13877         $this->position += $whitespace;
13878         return $whitespace;
13879     }
13880
13881     /**
13882      * Read value
13883      */
13884     function get_value()
13885     {
13886         $quote = substr($this->data, $this->position, 1);
13887         if ($quote === '"' || $quote === "'")
13888         {
13889             $this->position++;
13890             $len = strcspn($this->data, $quote, $this->position);
13891             if ($this->has_data())
13892             {
13893                 $value = substr($this->data, $this->position, $len);
13894                 $this->position += $len + 1;
13895                 return $value;
13896             }
13897         }
13898         return false;
13899     }
13900
13901     function before_version_name()
13902     {
13903         if ($this->skip_whitespace())
13904         {
13905             $this->state = 'version_name';
13906         }
13907         else
13908         {
13909             $this->state = false;
13910         }
13911     }
13912
13913     function version_name()
13914     {
13915         if (substr($this->data, $this->position, 7) === 'version')
13916         {
13917             $this->position += 7;
13918             $this->skip_whitespace();
13919             $this->state = 'version_equals';
13920         }
13921         else
13922         {
13923             $this->state = false;
13924         }
13925     }
13926
13927     function version_equals()
13928     {
13929         if (substr($this->data, $this->position, 1) === '=')
13930         {
13931             $this->position++;
13932             $this->skip_whitespace();
13933             $this->state = 'version_value';
13934         }
13935         else
13936         {
13937             $this->state = false;
13938         }
13939     }
13940
13941     function version_value()
13942     {
13943         if ($this->version = $this->get_value())
13944         {
13945             $this->skip_whitespace();
13946             if ($this->has_data())
13947             {
13948                 $this->state = 'encoding_name';
13949             }
13950             else
13951             {
13952                 $this->state = 'emit';
13953             }
13954         }
13955         else
13956         {
13957             $this->state = false;
13958         }
13959     }
13960
13961     function encoding_name()
13962     {
13963         if (substr($this->data, $this->position, 8) === 'encoding')
13964         {
13965             $this->position += 8;
13966             $this->skip_whitespace();
13967             $this->state = 'encoding_equals';
13968         }
13969         else
13970         {
13971             $this->state = 'standalone_name';
13972         }
13973     }
13974
13975     function encoding_equals()
13976     {
13977         if (substr($this->data, $this->position, 1) === '=')
13978         {
13979             $this->position++;
13980             $this->skip_whitespace();
13981             $this->state = 'encoding_value';
13982         }
13983         else
13984         {
13985             $this->state = false;
13986         }
13987     }
13988
13989     function encoding_value()
13990     {
13991         if ($this->encoding = $this->get_value())
13992         {
13993             $this->skip_whitespace();
13994             if ($this->has_data())
13995             {
13996                 $this->state = 'standalone_name';
13997             }
13998             else
13999             {
14000                 $this->state = 'emit';
14001             }
14002         }
14003         else
14004         {
14005             $this->state = false;
14006         }
14007     }
14008
14009     function standalone_name()
14010     {
14011         if (substr($this->data, $this->position, 10) === 'standalone')
14012         {
14013             $this->position += 10;
14014             $this->skip_whitespace();
14015             $this->state = 'standalone_equals';
14016         }
14017         else
14018         {
14019             $this->state = false;
14020         }
14021     }
14022
14023     function standalone_equals()
14024     {
14025         if (substr($this->data, $this->position, 1) === '=')
14026         {
14027             $this->position++;
14028             $this->skip_whitespace();
14029             $this->state = 'standalone_value';
14030         }
14031         else
14032         {
14033             $this->state = false;
14034         }
14035     }
14036
14037     function standalone_value()
14038     {
14039         if ($standalone = $this->get_value())
14040         {
14041             switch ($standalone)
14042             {
14043                 case 'yes':
14044                     $this->standalone = true;
14045                     break;
14046
14047                 case 'no':
14048                     $this->standalone = false;
14049                     break;
14050
14051                 default:
14052                     $this->state = false;
14053                     return;
14054             }
14055
14056             $this->skip_whitespace();
14057             if ($this->has_data())
14058             {
14059                 $this->state = false;
14060             }
14061             else
14062             {
14063                 $this->state = 'emit';
14064             }
14065         }
14066         else
14067         {
14068             $this->state = false;
14069         }
14070     }
14071 }
14072
14073 class SimplePie_Locator
14074 {
14075     var $useragent;
14076     var $timeout;
14077     var $file;
14078     var $local = array();
14079     var $elsewhere = array();
14080     var $file_class = 'SimplePie_File';
14081     var $cached_entities = array();
14082     var $http_base;
14083     var $base;
14084     var $base_location = 0;
14085     var $checked_feeds = 0;
14086     var $max_checked_feeds = 10;
14087     var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14088
14089     function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14090     {
14091         $this->file =& $file;
14092         $this->file_class = $file_class;
14093         $this->useragent = $useragent;
14094         $this->timeout = $timeout;
14095         $this->max_checked_feeds = $max_checked_feeds;
14096         $this->content_type_sniffer_class = $content_type_sniffer_class;
14097     }
14098
14099     function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14100     {
14101         if ($this->is_feed($this->file))
14102         {
14103             return $this->file;
14104         }
14105
14106         if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14107         {
f64c86 14108             $sniffer = new $this->content_type_sniffer_class($this->file);
fd9ef2 14109             if ($sniffer->get_type() !== 'text/html')
T 14110             {
14111                 return null;
14112             }
14113         }
14114
14115         if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14116         {
14117             $this->get_base();
14118         }
14119
14120         if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14121         {
14122             return $working[0];
14123         }
14124
14125         if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14126         {
14127             if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14128             {
14129                 return $working;
14130             }
14131
14132             if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14133             {
14134                 return $working;
14135             }
14136
14137             if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14138             {
14139                 return $working;
14140             }
14141
14142             if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14143             {
14144                 return $working;
14145             }
14146         }
14147         return null;
14148     }
14149
14150     function is_feed(&$file)
14151     {
14152         if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14153         {
f64c86 14154             $sniffer = new $this->content_type_sniffer_class($file);
fd9ef2 14155             $sniffed = $sniffer->get_type();
T 14156             if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14157             {
14158                 return true;
14159             }
14160             else
14161             {
14162                 return false;
14163             }
14164         }
14165         elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14166         {
14167             return true;
14168         }
14169         else
14170         {
14171             return false;
14172         }
14173     }
14174
14175     function get_base()
14176     {
14177         $this->http_base = $this->file->url;
14178         $this->base = $this->http_base;
14179         $elements = SimplePie_Misc::get_element('base', $this->file->body);
14180         foreach ($elements as $element)
14181         {
14182             if ($element['attribs']['href']['data'] !== '')
14183             {
14184                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14185                 $this->base_location = $element['offset'];
14186                 break;
14187             }
14188         }
14189     }
14190
14191     function autodiscovery()
14192     {
14193         $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));
14194         $done = array();
14195         $feeds = array();
14196         foreach ($links as $link)
14197         {
14198             if ($this->checked_feeds === $this->max_checked_feeds)
14199             {
14200                 break;
14201             }
14202             if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14203             {
14204                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14205
14206                 if ($this->base_location < $link['offset'])
14207                 {
14208                     $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14209                 }
14210                 else
14211                 {
14212                     $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14213                 }
14214
14215                 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]))
14216                 {
14217                     $this->checked_feeds++;
f64c86 14218                     $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
fd9ef2 14219                     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))
T 14220                     {
14221                         $feeds[$href] = $feed;
14222                     }
14223                 }
14224                 $done[] = $href;
14225             }
14226         }
14227
14228         if (!empty($feeds))
14229         {
14230             return array_values($feeds);
14231         }
14232         else {
14233             return null;
14234         }
14235     }
14236
14237     function get_links()
14238     {
14239         $links = SimplePie_Misc::get_element('a', $this->file->body);
14240         foreach ($links as $link)
14241         {
14242             if (isset($link['attribs']['href']['data']))
14243             {
14244                 $href = trim($link['attribs']['href']['data']);
14245                 $parsed = SimplePie_Misc::parse_url($href);
14246                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14247                 {
14248                     if ($this->base_location < $link['offset'])
14249                     {
14250                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14251                     }
14252                     else
14253                     {
14254                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14255                     }
14256
14257                     $current = SimplePie_Misc::parse_url($this->file->url);
14258
14259                     if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14260                     {
14261                         $this->local[] = $href;
14262                     }
14263                     else
14264                     {
14265                         $this->elsewhere[] = $href;
14266                     }
14267                 }
14268             }
14269         }
14270         $this->local = array_unique($this->local);
14271         $this->elsewhere = array_unique($this->elsewhere);
14272         if (!empty($this->local) || !empty($this->elsewhere))
14273         {
14274             return true;
14275         }
14276         return null;
14277     }
14278
14279     function extension(&$array)
14280     {
14281         foreach ($array as $key => $value)
14282         {
14283             if ($this->checked_feeds === $this->max_checked_feeds)
14284             {
14285                 break;
14286             }
14287             if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14288             {
14289                 $this->checked_feeds++;
f64c86 14290                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
fd9ef2 14291                 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))
T 14292                 {
14293                     return $feed;
14294                 }
14295                 else
14296                 {
14297                     unset($array[$key]);
14298                 }
14299             }
14300         }
14301         return null;
14302     }
14303
14304     function body(&$array)
14305     {
14306         foreach ($array as $key => $value)
14307         {
14308             if ($this->checked_feeds === $this->max_checked_feeds)
14309             {
14310                 break;
14311             }
14312             if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14313             {
14314                 $this->checked_feeds++;
f64c86 14315                 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
fd9ef2 14316                 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))
T 14317                 {
14318                     return $feed;
14319                 }
14320                 else
14321                 {
14322                     unset($array[$key]);
14323                 }
14324             }
14325         }
14326         return null;
14327     }
14328 }
14329
14330 class SimplePie_Parser
14331 {
14332     var $error_code;
14333     var $error_string;
14334     var $current_line;
14335     var $current_column;
14336     var $current_byte;
14337     var $separator = ' ';
14338     var $namespace = array('');
14339     var $element = array('');
14340     var $xml_base = array('');
14341     var $xml_base_explicit = array(false);
14342     var $xml_lang = array('');
14343     var $data = array();
14344     var $datas = array(array());
14345     var $current_xhtml_construct = -1;
14346     var $encoding;
14347
14348     function parse(&$data, $encoding)
14349     {
14350         // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14351         if (strtoupper($encoding) === 'US-ASCII')
14352         {
14353             $this->encoding = 'UTF-8';
14354         }
14355         else
14356         {
14357             $this->encoding = $encoding;
14358         }
14359
14360         // Strip BOM:
14361         // UTF-32 Big Endian BOM
14362         if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14363         {
14364             $data = substr($data, 4);
14365         }
14366         // UTF-32 Little Endian BOM
14367         elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14368         {
14369             $data = substr($data, 4);
14370         }
14371         // UTF-16 Big Endian BOM
14372         elseif (substr($data, 0, 2) === "\xFE\xFF")
14373         {
14374             $data = substr($data, 2);
14375         }
14376         // UTF-16 Little Endian BOM
14377         elseif (substr($data, 0, 2) === "\xFF\xFE")
14378         {
14379             $data = substr($data, 2);
14380         }
14381         // UTF-8 BOM
14382         elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14383         {
14384             $data = substr($data, 3);
14385         }
14386
14387         if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14388         {
f64c86 14389             $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
fd9ef2 14390             if ($declaration->parse())
T 14391             {
14392                 $data = substr($data, $pos + 2);
14393                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14394             }
14395             else
14396             {
14397                 $this->error_string = 'SimplePie bug! Please report this!';
14398                 return false;
14399             }
14400         }
14401
14402         $return = true;
14403
14404         static $xml_is_sane = null;
14405         if ($xml_is_sane === null)
14406         {
14407             $parser_check = xml_parser_create();
14408             xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
14409             xml_parser_free($parser_check);
14410             $xml_is_sane = isset($values[0]['value']);
14411         }
14412
14413         // Create the parser
14414         if ($xml_is_sane)
14415         {
14416             $xml = xml_parser_create_ns($this->encoding, $this->separator);
14417             xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14418             xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14419             xml_set_object($xml, $this);
14420             xml_set_character_data_handler($xml, 'cdata');
14421             xml_set_element_handler($xml, 'tag_open', 'tag_close');
14422
14423             // Parse!
14424             if (!xml_parse($xml, $data, true))
14425             {
14426                 $this->error_code = xml_get_error_code($xml);
14427                 $this->error_string = xml_error_string($this->error_code);
14428                 $return = false;
14429             }
14430             $this->current_line = xml_get_current_line_number($xml);
14431             $this->current_column = xml_get_current_column_number($xml);
14432             $this->current_byte = xml_get_current_byte_index($xml);
14433             xml_parser_free($xml);
14434             return $return;
14435         }
14436         else
14437         {
14438             libxml_clear_errors();
f64c86 14439             $xml = new XMLReader();
fd9ef2 14440             $xml->xml($data);
T 14441             while (@$xml->read())
14442             {
14443                 switch ($xml->nodeType)
14444                 {
14445
14446                     case constant('XMLReader::END_ELEMENT'):
14447                         if ($xml->namespaceURI !== '')
14448                         {
14449                             $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14450                         }
14451                         else
14452                         {
14453                             $tagName = $xml->localName;
14454                         }
14455                         $this->tag_close(null, $tagName);
14456                         break;
14457                     case constant('XMLReader::ELEMENT'):
14458                         $empty = $xml->isEmptyElement;
14459                         if ($xml->namespaceURI !== '')
14460                         {
14461                             $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14462                         }
14463                         else
14464                         {
14465                             $tagName = $xml->localName;
14466                         }
14467                         $attributes = array();
14468                         while ($xml->moveToNextAttribute())
14469                         {
14470                             if ($xml->namespaceURI !== '')
14471                             {
14472                                 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14473                             }
14474                             else
14475                             {
14476                                 $attrName = $xml->localName;
14477                             }
14478                             $attributes[$attrName] = $xml->value;
14479                         }
14480                         $this->tag_open(null, $tagName, $attributes);
14481                         if ($empty)
14482                         {
14483                             $this->tag_close(null, $tagName);
14484                         }
14485                         break;
14486                     case constant('XMLReader::TEXT'):
14487
14488                     case constant('XMLReader::CDATA'):
14489                         $this->cdata(null, $xml->value);
14490                         break;
14491                 }
14492             }
14493             if ($error = libxml_get_last_error())
14494             {
14495                 $this->error_code = $error->code;
14496                 $this->error_string = $error->message;
14497                 $this->current_line = $error->line;
14498                 $this->current_column = $error->column;
14499                 return false;
14500             }
14501             else
14502             {
14503                 return true;
14504             }
14505         }
14506     }
14507
14508     function get_error_code()
14509     {
14510         return $this->error_code;
14511     }
14512
14513     function get_error_string()
14514     {
14515         return $this->error_string;
14516     }
14517
14518     function get_current_line()
14519     {
14520         return $this->current_line;
14521     }
14522
14523     function get_current_column()
14524     {
14525         return $this->current_column;
14526     }
14527
14528     function get_current_byte()
14529     {
14530         return $this->current_byte;
14531     }
14532
14533     function get_data()
14534     {
14535         return $this->data;
14536     }
14537
14538     function tag_open($parser, $tag, $attributes)
14539     {
14540         list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14541
14542         $attribs = array();
14543         foreach ($attributes as $name => $value)
14544         {
14545             list($attrib_namespace, $attribute) = $this->split_ns($name);
14546             $attribs[$attrib_namespace][$attribute] = $value;
14547         }
14548
14549         if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14550         {
14551             $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14552             $this->xml_base_explicit[] = true;
14553         }
14554         else
14555         {
14556             $this->xml_base[] = end($this->xml_base);
14557             $this->xml_base_explicit[] = end($this->xml_base_explicit);
14558         }
14559
14560         if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14561         {
14562             $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14563         }
14564         else
14565         {
14566             $this->xml_lang[] = end($this->xml_lang);
14567         }
14568
14569         if ($this->current_xhtml_construct >= 0)
14570         {
14571             $this->current_xhtml_construct++;
14572             if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14573             {
14574                 $this->data['data'] .= '<' . end($this->element);
14575                 if (isset($attribs['']))
14576                 {
14577                     foreach ($attribs[''] as $name => $value)
14578                     {
14579                         $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14580                     }
14581                 }
14582                 $this->data['data'] .= '>';
14583             }
14584         }
14585         else
14586         {
14587             $this->datas[] =& $this->data;
14588             $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14589             $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));
14590             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')
14591             || (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'))
14592             {
14593                 $this->current_xhtml_construct = 0;
14594             }
14595         }
14596     }
14597
14598     function cdata($parser, $cdata)
14599     {
14600         if ($this->current_xhtml_construct >= 0)
14601         {
14602             $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14603         }
14604         else
14605         {
14606             $this->data['data'] .= $cdata;
14607         }
14608     }
14609
14610     function tag_close($parser, $tag)
14611     {
14612         if ($this->current_xhtml_construct >= 0)
14613         {
14614             $this->current_xhtml_construct--;
14615             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')))
14616             {
14617                 $this->data['data'] .= '</' . end($this->element) . '>';
14618             }
14619         }
14620         if ($this->current_xhtml_construct === -1)
14621         {
14622             $this->data =& $this->datas[count($this->datas) - 1];
14623             array_pop($this->datas);
14624         }
14625
14626         array_pop($this->element);
14627         array_pop($this->namespace);
14628         array_pop($this->xml_base);
14629         array_pop($this->xml_base_explicit);
14630         array_pop($this->xml_lang);
14631     }
14632
14633     function split_ns($string)
14634     {
14635         static $cache = array();
14636         if (!isset($cache[$string]))
14637         {
14638             if ($pos = strpos($string, $this->separator))
14639             {
14640                 static $separator_length;
14641                 if (!$separator_length)
14642                 {
14643                     $separator_length = strlen($this->separator);
14644                 }
14645                 $namespace = substr($string, 0, $pos);
14646                 $local_name = substr($string, $pos + $separator_length);
14647                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14648                 {
14649                     $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14650                 }
14651
14652                 // Normalize the Media RSS namespaces
14653                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14654                 {
14655                     $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14656                 }
14657                 $cache[$string] = array($namespace, $local_name);
14658             }
14659             else
14660             {
14661                 $cache[$string] = array('', $string);
14662             }
14663         }
14664         return $cache[$string];
14665     }
14666 }
14667
14668 /**
14669  * @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
14670  */
14671 class SimplePie_Sanitize
14672 {
14673     // Private vars
14674     var $base;
14675
14676     // Options
14677     var $remove_div = true;
14678     var $image_handler = '';
14679     var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14680     var $encode_instead_of_strip = false;
14681     var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14682     var $strip_comments = false;
14683     var $output_encoding = 'UTF-8';
14684     var $enable_cache = true;
14685     var $cache_location = './cache';
14686     var $cache_name_function = 'md5';
14687     var $cache_class = 'SimplePie_Cache';
14688     var $file_class = 'SimplePie_File';
14689     var $timeout = 10;
14690     var $useragent = '';
14691     var $force_fsockopen = false;
14692
14693     var $replace_url_attributes = array(
14694         'a' => 'href',
14695         'area' => 'href',
14696         'blockquote' => 'cite',
14697         'del' => 'cite',
14698         'form' => 'action',
14699         'img' => array('longdesc', 'src'),
14700         'input' => 'src',
14701         'ins' => 'cite',
14702         'q' => 'cite'
14703     );
14704
14705     function remove_div($enable = true)
14706     {
14707         $this->remove_div = (bool) $enable;
14708     }
14709
14710     function set_image_handler($page = false)
14711     {
14712         if ($page)
14713         {
14714             $this->image_handler = (string) $page;
14715         }
14716         else
14717         {
14718             $this->image_handler = false;
14719         }
14720     }
14721
14722     function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14723     {
14724         if (isset($enable_cache))
14725         {
14726             $this->enable_cache = (bool) $enable_cache;
14727         }
14728
14729         if ($cache_location)
14730         {
14731             $this->cache_location = (string) $cache_location;
14732         }
14733
14734         if ($cache_name_function)
14735         {
14736             $this->cache_name_function = (string) $cache_name_function;
14737         }
14738
14739         if ($cache_class)
14740         {
14741             $this->cache_class = (string) $cache_class;
14742         }
14743     }
14744
14745     function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14746     {
14747         if ($file_class)
14748         {
14749             $this->file_class = (string) $file_class;
14750         }
14751
14752         if ($timeout)
14753         {
14754             $this->timeout = (string) $timeout;
14755         }
14756
14757         if ($useragent)
14758         {
14759             $this->useragent = (string) $useragent;
14760         }
14761
14762         if ($force_fsockopen)
14763         {
14764             $this->force_fsockopen = (string) $force_fsockopen;
14765         }
14766     }
14767
14768     function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14769     {
14770         if ($tags)
14771         {
14772             if (is_array($tags))
14773             {
14774                 $this->strip_htmltags = $tags;
14775             }
14776             else
14777             {
14778                 $this->strip_htmltags = explode(',', $tags);
14779             }
14780         }
14781         else
14782         {
14783             $this->strip_htmltags = false;
14784         }
14785     }
14786
14787     function encode_instead_of_strip($encode = false)
14788     {
14789         $this->encode_instead_of_strip = (bool) $encode;
14790     }
14791
14792     function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14793     {
14794         if ($attribs)
14795         {
14796             if (is_array($attribs))
14797             {
14798                 $this->strip_attributes = $attribs;
14799             }
14800             else
14801             {
14802                 $this->strip_attributes = explode(',', $attribs);
14803             }
14804         }
14805         else
14806         {
14807             $this->strip_attributes = false;
14808         }
14809     }
14810
14811     function strip_comments($strip = false)
14812     {
14813         $this->strip_comments = (bool) $strip;
14814     }
14815
14816     function set_output_encoding($encoding = 'UTF-8')
14817     {
14818         $this->output_encoding = (string) $encoding;
14819     }
14820
14821     /**
14822      * Set element/attribute key/value pairs of HTML attributes
14823      * containing URLs that need to be resolved relative to the feed
14824      *
14825      * @access public
14826      * @since 1.0
14827      * @param array $element_attribute Element/attribute key/value pairs
14828      */
14829     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'))
14830     {
14831         $this->replace_url_attributes = (array) $element_attribute;
14832     }
14833
14834     function sanitize($data, $type, $base = '')
14835     {
14836         $data = trim($data);
14837         if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14838         {
14839             if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14840             {
14841                 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))
14842                 {
14843                     $type |= SIMPLEPIE_CONSTRUCT_HTML;
14844                 }
14845                 else
14846                 {
14847                     $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14848                 }
14849             }
14850
14851             if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14852             {
14853                 $data = base64_decode($data);
14854             }
14855
14856             if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14857             {
14858                 if ($this->remove_div)
14859                 {
14860                     $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14861                     $data = preg_replace('/<\/div>$/', '', $data);
14862                 }
14863                 else
14864                 {
14865                     $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14866                 }
14867             }
14868
14869             if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14870             {
14871                 // Strip comments
14872                 if ($this->strip_comments)
14873                 {
14874                     $data = SimplePie_Misc::strip_comments($data);
14875                 }
14876
14877                 // Strip out HTML tags and attributes that might cause various security problems.
14878                 // Based on recommendations by Mark Pilgrim at:
14879                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14880                 if ($this->strip_htmltags)
14881                 {
14882                     foreach ($this->strip_htmltags as $tag)
14883                     {
14884                         $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14885                         while (preg_match($pcre, $data))
14886                         {
14887                             $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14888                         }
14889                     }
14890                 }
14891
14892                 if ($this->strip_attributes)
14893                 {
14894                     foreach ($this->strip_attributes as $attrib)
14895                     {
14896                         $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);
14897                     }
14898                 }
14899
14900                 // Replace relative URLs
14901                 $this->base = $base;
14902                 foreach ($this->replace_url_attributes as $element => $attributes)
14903                 {
14904                     $data = $this->replace_urls($data, $element, $attributes);
14905                 }
14906
14907                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14908                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14909                 {
14910                     $images = SimplePie_Misc::get_element('img', $data);
14911                     foreach ($images as $img)
14912                     {
14913                         if (isset($img['attribs']['src']['data']))
14914                         {
14915                             $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14916                             $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14917
14918                             if ($cache->load())
14919                             {
14920                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14921                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14922                             }
14923                             else
14924                             {
f64c86 14925                                 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
fd9ef2 14926                                 $headers = $file->headers;
T 14927
14928                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14929                                 {
14930                                     if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14931                                     {
14932                                         $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14933                                         $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14934                                     }
14935                                     else
14936                                     {
14937                                         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);
14938                                     }
14939                                 }
14940                             }
14941                         }
14942                     }
14943                 }
14944
14945                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14946                 $data = trim($data);
14947             }
14948
14949             if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14950             {
14951                 $data = SimplePie_Misc::absolutize_url($data, $base);
14952             }
14953
14954             if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14955             {
14956                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14957             }
14958
14959             if ($this->output_encoding !== 'UTF-8')
14960             {
14961                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14962             }
14963         }
14964         return $data;
14965     }
14966
14967     function replace_urls($data, $tag, $attributes)
14968     {
14969         if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14970         {
14971             $elements = SimplePie_Misc::get_element($tag, $data);
14972             foreach ($elements as $element)
14973             {
14974                 if (is_array($attributes))
14975                 {
14976                     foreach ($attributes as $attribute)
14977                     {
14978                         if (isset($element['attribs'][$attribute]['data']))
14979                         {
14980                             $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14981                             $new_element = SimplePie_Misc::element_implode($element);
14982                             $data = str_replace($element['full'], $new_element, $data);
14983                             $element['full'] = $new_element;
14984                         }
14985                     }
14986                 }
14987                 elseif (isset($element['attribs'][$attributes]['data']))
14988                 {
14989                     $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14990                     $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14991                 }
14992             }
14993         }
14994         return $data;
14995     }
14996
14997     function do_strip_htmltags($match)
14998     {
14999         if ($this->encode_instead_of_strip)
15000         {
15001             if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15002             {
15003                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15004                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15005                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
15006             }
15007             else
15008             {
15009                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15010             }
15011         }
15012         elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15013         {
15014             return $match[4];
15015         }
15016         else
15017         {
15018             return '';
15019         }
15020     }
15021 }
15022
15023 ?>