Make WordPress Core

Changeset 21644


Ignore:
Timestamp:
08/28/2012 05:24:33 PM (13 years ago)
Author:
nacin
Message:

Update to SimplePie 1.3. props rmccue.

Uses individual files for each class. We now conditionally load only the pieces
we need, resulting in less memory usage. Also easier to maintain now that it is
not a single 387KB file.

fixes #21183.

Location:
trunk/wp-includes
Files:
42 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/class-feed.php

    r17928 r21644  
    1111     * @access public
    1212     */
    13     function create($location, $filename, $extension) {
     13    public static function create($location, $filename, $extension) {
    1414        return new WP_Feed_Cache_Transient($location, $filename, $extension);
    1515    }
  • trunk/wp-includes/class-simplepie.php

    r20715 r21644  
    11<?php
    22if ( ! class_exists( 'SimplePie' ) ) :
     3
     4// Load classes we will need.
     5require ABSPATH . WPINC . '/SimplePie/Misc.php';
     6require ABSPATH . WPINC . '/SimplePie/Cache.php';
     7require ABSPATH . WPINC . '/SimplePie/File.php';
     8require ABSPATH . WPINC . '/SimplePie/Sanitize.php';
     9require ABSPATH . WPINC . '/SimplePie/Registry.php';
     10require ABSPATH . WPINC . '/SimplePie/IRI.php';
     11require ABSPATH . WPINC . '/SimplePie/Locator.php';
     12require ABSPATH . WPINC . '/SimplePie/Content/Type/Sniffer.php';
     13require ABSPATH . WPINC . '/SimplePie/XML/Declaration/Parser.php';
     14require ABSPATH . WPINC . '/SimplePie/Parser.php';
     15require ABSPATH . WPINC . '/SimplePie/Item.php';
     16require ABSPATH . WPINC . '/SimplePie/Parse/Date.php';
     17require ABSPATH . WPINC . '/SimplePie/Author.php';
     18
     19/**
     20 * WordPress autoloader for SimplePie.
     21 *
     22 * @since 3.5.0
     23 */
     24function wp_simplepie_autoload( $class ) {
     25    if ( 0 !== strpos( $class, 'SimplePie_' ) )
     26        return;
     27
     28    $file = dirname( __FILE__ ) . '/' . str_replace( '_', '/', $class ) . '.php';
     29    include $file;
     30}
     31
     32if ( function_exists( 'spl_autoload_register' ) ) {
     33    /**
     34     * We autoload classes we may not need.
     35     *
     36     * If SPL is disabled, we load all of SimplePie manually.
     37     *
     38     * Core.php is not loaded manually, because SimplePie_Core (a deprecated class)
     39     * was never included in WordPress core.
     40     */
     41    spl_autoload_register( 'wp_simplepie_autoload' );
     42} else {
     43    require ABSPATH . WPINC . '/SimplePie/Cache/Base.php';
     44    require ABSPATH . WPINC . '/SimplePie/Cache/DB.php';
     45    require ABSPATH . WPINC . '/SimplePie/Cache/File.php';
     46    require ABSPATH . WPINC . '/SimplePie/Cache/Memcache.php';
     47    require ABSPATH . WPINC . '/SimplePie/Cache/MySQL.php';
     48    require ABSPATH . WPINC . '/SimplePie/Caption.php';
     49    require ABSPATH . WPINC . '/SimplePie/Category.php';
     50    require ABSPATH . WPINC . '/SimplePie/Copyright.php';
     51    require ABSPATH . WPINC . '/SimplePie/Credit.php';
     52    require ABSPATH . WPINC . '/SimplePie/Decode/HTML/Entities.php';
     53    require ABSPATH . WPINC . '/SimplePie/Enclosure.php';
     54    require ABSPATH . WPINC . '/SimplePie/gzdecode.php';
     55    require ABSPATH . WPINC . '/SimplePie/HTTP/Parser.php';
     56    require ABSPATH . WPINC . '/SimplePie/Net/IPv6.php';
     57    require ABSPATH . WPINC . '/SimplePie/Rating.php';
     58    require ABSPATH . WPINC . '/SimplePie/Restriction.php';
     59    require ABSPATH . WPINC . '/SimplePie/Source.php';
     60}
     61
    362/**
    463 * SimplePie
     
    766 * Takes the hard work out of managing a complete RSS/Atom solution.
    867 *
    9  * Copyright (c) 2004-2011, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
     68 * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
    1069 * All rights reserved.
    1170 *
     
    3594 *
    3695 * @package SimplePie
    37  * @version 1.2.1
    38  * @copyright 2004-2011 Ryan Parman, Geoffrey Sneddon, Ryan McCue
     96 * @version 1.3
     97 * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
    3998 * @author Ryan Parman
    4099 * @author Geoffrey Sneddon
    41100 * @author Ryan McCue
    42101 * @link http://simplepie.org/ SimplePie
    43  * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
    44102 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
    45  * @todo phpDoc comments
    46103 */
    47104
     
    54111 * SimplePie Version
    55112 */
    56 define('SIMPLEPIE_VERSION', '1.2.1');
     113define('SIMPLEPIE_VERSION', '1.3');
    57114
    58115/**
    59116 * SimplePie Build
    60  */
    61 define('SIMPLEPIE_BUILD', '20111015034325');
     117 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
     118 */
     119define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));
    62120
    63121/**
     
    336394
    337395/**
    338  * Wrong Media RSS Namespace
     396 * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
    339397 */
    340398define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
    341399
    342400/**
     401 * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
     402 */
     403define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
     404
     405/**
     406 * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
     407 */
     408define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
     409
     410/**
     411 * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
     412 */
     413define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
     414
     415/**
     416 * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
     417 */
     418define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
     419
     420/**
    343421 * iTunes RSS Namespace
    344422 */
     
    356434
    357435/**
    358  * Whether we're running on PHP5
    359  */
    360 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
    361 
    362 /**
    363436 * No file source
    364437 */
     
    389462 */
    390463define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
     464
     465
    391466
    392467/**
     
    394469 *
    395470 * @package SimplePie
     471 * @subpackage API
    396472 */
    397473class SimplePie
     
    401477     * @access private
    402478     */
    403     var $data = array();
     479    public $data = array();
    404480
    405481    /**
     
    407483     * @access private
    408484     */
    409     var $error;
     485    public $error;
    410486
    411487    /**
     
    414490     * @access private
    415491     */
    416     var $sanitize;
     492    public $sanitize;
    417493
    418494    /**
     
    421497     * @access private
    422498     */
    423     var $useragent = SIMPLEPIE_USERAGENT;
     499    public $useragent = SIMPLEPIE_USERAGENT;
    424500
    425501    /**
     
    428504     * @access private
    429505     */
    430     var $feed_url;
     506    public $feed_url;
    431507
    432508    /**
     
    435511     * @access private
    436512     */
    437     var $file;
     513    public $file;
    438514
    439515    /**
     
    442518     * @access private
    443519     */
    444     var $raw_data;
     520    public $raw_data;
    445521
    446522    /**
     
    449525     * @access private
    450526     */
    451     var $timeout = 10;
     527    public $timeout = 10;
    452528
    453529    /**
     
    457533     * @access private
    458534     */
    459     var $force_fsockopen = false;
     535    public $force_fsockopen = false;
    460536
    461537    /**
     
    465541     * @access private
    466542     */
    467     var $force_feed = false;
    468 
    469     /**
    470      * @var bool Enable/Disable XML dump
    471      * @see SimplePie::enable_xml_dump()
    472      * @access private
    473      */
    474     var $xml_dump = false;
     543    public $force_feed = false;
    475544
    476545    /**
     
    479548     * @access private
    480549     */
    481     var $cache = true;
     550    public $cache = true;
    482551
    483552    /**
     
    486555     * @access private
    487556     */
    488     var $cache_duration = 3600;
     557    public $cache_duration = 3600;
    489558
    490559    /**
     
    493562     * @access private
    494563     */
    495     var $autodiscovery_cache_duration = 604800; // 7 Days.
     564    public $autodiscovery_cache_duration = 604800; // 7 Days.
    496565
    497566    /**
     
    500569     * @access private
    501570     */
    502     var $cache_location = './cache';
     571    public $cache_location = './cache';
    503572
    504573    /**
     
    507576     * @access private
    508577     */
    509     var $cache_name_function = 'md5';
     578    public $cache_name_function = 'md5';
    510579
    511580    /**
     
    514583     * @access private
    515584     */
    516     var $order_by_date = true;
     585    public $order_by_date = true;
    517586
    518587    /**
     
    522591     * @access private
    523592     */
    524     var $input_encoding = false;
     593    public $input_encoding = false;
    525594
    526595    /**
     
    529598     * @access private
    530599     */
    531     var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
    532 
    533     /**
    534      * @var string Class used for caching feeds
    535      * @see SimplePie::set_cache_class()
    536      * @access private
    537      */
    538     var $cache_class = 'SimplePie_Cache';
    539 
    540     /**
    541      * @var string Class used for locating feeds
    542      * @see SimplePie::set_locator_class()
    543      * @access private
    544      */
    545     var $locator_class = 'SimplePie_Locator';
    546 
    547     /**
    548      * @var string Class used for parsing feeds
    549      * @see SimplePie::set_parser_class()
    550      * @access private
    551      */
    552     var $parser_class = 'SimplePie_Parser';
    553 
    554     /**
    555      * @var string Class used for fetching feeds
    556      * @see SimplePie::set_file_class()
    557      * @access private
    558      */
    559     var $file_class = 'SimplePie_File';
    560 
    561     /**
    562      * @var string Class used for items
    563      * @see SimplePie::set_item_class()
    564      * @access private
    565      */
    566     var $item_class = 'SimplePie_Item';
    567 
    568     /**
    569      * @var string Class used for authors
    570      * @see SimplePie::set_author_class()
    571      * @access private
    572      */
    573     var $author_class = 'SimplePie_Author';
    574 
    575     /**
    576      * @var string Class used for categories
    577      * @see SimplePie::set_category_class()
    578      * @access private
    579      */
    580     var $category_class = 'SimplePie_Category';
    581 
    582     /**
    583      * @var string Class used for enclosures
    584      * @see SimplePie::set_enclosures_class()
    585      * @access private
    586      */
    587     var $enclosure_class = 'SimplePie_Enclosure';
    588 
    589     /**
    590      * @var string Class used for Media RSS <media:text> captions
    591      * @see SimplePie::set_caption_class()
    592      * @access private
    593      */
    594     var $caption_class = 'SimplePie_Caption';
    595 
    596     /**
    597      * @var string Class used for Media RSS <media:copyright>
    598      * @see SimplePie::set_copyright_class()
    599      * @access private
    600      */
    601     var $copyright_class = 'SimplePie_Copyright';
    602 
    603     /**
    604      * @var string Class used for Media RSS <media:credit>
    605      * @see SimplePie::set_credit_class()
    606      * @access private
    607      */
    608     var $credit_class = 'SimplePie_Credit';
    609 
    610     /**
    611      * @var string Class used for Media RSS <media:rating>
    612      * @see SimplePie::set_rating_class()
    613      * @access private
    614      */
    615     var $rating_class = 'SimplePie_Rating';
    616 
    617     /**
    618      * @var string Class used for Media RSS <media:restriction>
    619      * @see SimplePie::set_restriction_class()
    620      * @access private
    621      */
    622     var $restriction_class = 'SimplePie_Restriction';
    623 
    624     /**
    625      * @var string Class used for content-type sniffing
    626      * @see SimplePie::set_content_type_sniffer_class()
    627      * @access private
    628      */
    629     var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
    630 
    631     /**
    632      * @var string Class used for item sources.
    633      * @see SimplePie::set_source_class()
    634      * @access private
    635      */
    636     var $source_class = 'SimplePie_Source';
    637 
    638     /**
    639      * @var mixed Set javascript query string parameter (false, or
    640      * anything type-cast to false, disables this feature)
    641      * @see SimplePie::set_javascript()
    642      * @access private
    643      */
    644     var $javascript = 'js';
     600    public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
     601
     602    /**
     603     * Class registry object
     604     *
     605     * @var SimplePie_Registry
     606     */
     607    public $registry;
    645608
    646609    /**
     
    649612     * @access private
    650613     */
    651     var $max_checked_feeds = 10;
     614    public $max_checked_feeds = 10;
    652615
    653616    /**
     
    656619     * @access private
    657620     */
    658     var $all_discovered_feeds = array();
    659 
    660     /**
    661      * @var string Web-accessible path to the handler_favicon.php file.
    662      * @see SimplePie::set_favicon_handler()
    663      * @access private
    664      */
    665     var $favicon_handler = '';
     621    public $all_discovered_feeds = array();
    666622
    667623    /**
     
    670626     * @access private
    671627     */
    672     var $image_handler = '';
     628    public $image_handler = '';
    673629
    674630    /**
     
    677633     * @access private
    678634     */
    679     var $multifeed_url = array();
     635    public $multifeed_url = array();
    680636
    681637    /**
     
    683639     * @access private
    684640     */
    685     var $multifeed_objects = array();
     641    public $multifeed_objects = array();
    686642
    687643    /**
     
    690646     * @access private
    691647     */
    692     var $config_settings = null;
     648    public $config_settings = null;
    693649
    694650    /**
     
    697653     * @access private
    698654     */
    699     var $item_limit = 0;
     655    public $item_limit = 0;
    700656
    701657    /**
     
    704660     * @access private
    705661     */
    706     var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
     662    public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
    707663
    708664    /**
     
    711667     * @access private
    712668     */
    713     var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
     669    public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
    714670
    715671    /**
    716672     * The SimplePie class contains feed level data and options
    717673     *
    718      * There are two ways that you can create a new SimplePie object. The first
    719      * is by passing a feed URL as a parameter to the SimplePie constructor
    720      * (as well as optionally setting the cache location and cache expiry). This
    721      * will initialise the whole feed with all of the default settings, and you
    722      * can begin accessing methods and properties immediately.
    723      *
    724      * The second way is to create the SimplePie object with no parameters
    725      * at all. This will enable you to set configuration options. After setting
     674     * To use SimplePie, create the SimplePie object with no parameters. You can
     675     * then set configuration options using the provided methods. After setting
    726676     * them, you must initialise the feed using $feed->init(). At that point the
    727      * object's methods and properties will be available to you. This format is
    728      * what is used throughout this documentation.
    729      *
    730      * @access public
     677     * object's methods and properties will be available to you.
     678     *
     679     * Previously, it was possible to pass in the feed URL along with cache
     680     * options directly into the constructor. This has been removed as of 1.3 as
     681     * it caused a lot of confusion.
     682     *
    731683     * @since 1.0 Preview Release
    732      * @param string $feed_url This is the URL you want to parse.
    733      * @param string $cache_location This is where you want the cache to be stored.
    734      * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
    735      */
    736     function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
    737     {
     684     */
     685    public function __construct()
     686    {
     687        if (version_compare(PHP_VERSION, '5.2', '<'))
     688        {
     689            trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
     690            die();
     691        }
     692
    738693        // Other objects, instances created here so we can set options on them
    739         $this->sanitize =& new SimplePie_Sanitize;
    740 
    741         // Set options if they're passed to the constructor
    742         if ($cache_location !== null)
    743         {
    744             $this->set_cache_location($cache_location);
    745         }
    746 
    747         if ($cache_duration !== null)
    748         {
    749             $this->set_cache_duration($cache_duration);
    750         }
    751 
    752         // Only init the script if we're passed a feed URL
    753         if ($feed_url !== null)
    754         {
    755             $this->set_feed_url($feed_url);
    756             $this->init();
     694        $this->sanitize = new SimplePie_Sanitize();
     695        $this->registry = new SimplePie_Registry();
     696
     697        if (func_num_args() > 0)
     698        {
     699            trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.');
    757700        }
    758701    }
     
    761704     * Used for converting object to a string
    762705     */
    763     function __toString()
     706    public function __toString()
    764707    {
    765708        return md5(serialize($this->data));
     
    769712     * Remove items that link back to this before destroying this object
    770713     */
    771     function __destruct()
     714    public function __destruct()
    772715    {
    773716        if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
     
    793736
    794737    /**
    795      * Force the given data/URL to be treated as a feed no matter what it
    796      * appears like
    797      *
    798      * @access public
     738     * Force the given data/URL to be treated as a feed
     739     *
     740     * This tells SimplePie to ignore the content-type provided by the server.
     741     * Be careful when using this option, as it will also disable autodiscovery.
     742     *
    799743     * @since 1.1
    800744     * @param bool $enable Force the given data/URL to be treated as a feed
    801745     */
    802     function force_feed($enable = false)
     746    public function force_feed($enable = false)
    803747    {
    804748        $this->force_feed = (bool) $enable;
     
    806750
    807751    /**
    808      * This is the URL of the feed you want to parse.
     752     * Set the URL of the feed you want to parse
    809753     *
    810754     * This allows you to enter the URL of the feed you want to parse, or the
     
    816760     * additional processing and resources.
    817761     *
    818      * @access public
    819762     * @since 1.0 Preview Release
    820      * @param mixed $url This is the URL (or array of URLs) that you want to parse.
    821      * @see SimplePie::set_raw_data()
    822      */
    823     function set_feed_url($url)
    824     {
     763     * @see set_raw_data()
     764     * @param string|array $url This is the URL (or array of URLs) that you want to parse.
     765     */
     766    public function set_feed_url($url)
     767    {
     768        $this->multifeed_url = array();
    825769        if (is_array($url))
    826770        {
    827             $this->multifeed_url = array();
    828771            foreach ($url as $value)
    829772            {
    830                 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
     773                $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
    831774            }
    832775        }
    833776        else
    834777        {
    835             $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
    836         }
    837     }
    838 
    839     /**
    840      * Provides an instance of SimplePie_File to use as a feed
    841      *
    842      * @access public
    843      * @param object &$file Instance of SimplePie_File (or subclass)
     778            $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
     779        }
     780    }
     781
     782    /**
     783     * Set an instance of {@see SimplePie_File} to use as a feed
     784     *
     785     * @param SimplePie_File &$file
    844786     * @return bool True on success, false on failure
    845787     */
    846     function set_file(&$file)
    847     {
    848         if (is_a($file, 'SimplePie_File'))
     788    public function set_file(&$file)
     789    {
     790        if ($file instanceof SimplePie_File)
    849791        {
    850792            $this->feed_url = $file->url;
     
    856798
    857799    /**
     800     * Set the raw XML data to parse
     801     *
    858802     * Allows you to use a string of RSS/Atom data instead of a remote feed.
    859803     *
     
    862806     * takes precedence.
    863807     *
    864      * @access public
    865808     * @since 1.0 Beta 3
    866809     * @param string $data RSS or Atom data as a string.
    867      * @see SimplePie::set_feed_url()
    868      */
    869     function set_raw_data($data)
     810     * @see set_feed_url()
     811     */
     812    public function set_raw_data($data)
    870813    {
    871814        $this->raw_data = $data;
     
    873816
    874817    /**
    875      * Allows you to override the default timeout for fetching remote feeds.
     818     * Set the the default timeout for fetching remote feeds
    876819     *
    877820     * This allows you to change the maximum time the feed's server to respond
    878821     * and send the feed back.
    879822     *
    880      * @access public
    881823     * @since 1.0 Beta 3
    882824     * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
    883825     */
    884     function set_timeout($timeout = 10)
     826    public function set_timeout($timeout = 10)
    885827    {
    886828        $this->timeout = (int) $timeout;
     
    888830
    889831    /**
    890      * Forces SimplePie to use fsockopen() instead of the preferred cURL
    891      * functions.
    892      *
    893      * @access public
     832     * Force SimplePie to use fsockopen() instead of cURL
     833     *
    894834     * @since 1.0 Beta 3
    895835     * @param bool $enable Force fsockopen() to be used
    896836     */
    897     function force_fsockopen($enable = false)
     837    public function force_fsockopen($enable = false)
    898838    {
    899839        $this->force_fsockopen = (bool) $enable;
     
    901841
    902842    /**
    903      * Outputs the raw XML content of the feed, after it has gone through
    904      * SimplePie's filters.
    905      *
    906      * Used only for debugging, this function will output the XML content as
    907      * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
    908      * before trying to parse it. Many parts of the feed are re-written in
    909      * memory, and in the end, you have a parsable feed. XML dump shows you the
    910      * actual XML that SimplePie tries to parse, which may or may not be very
    911      * different from the original feed.
    912      *
    913      * @access public
    914      * @since 1.0 Preview Release
    915      * @param bool $enable Enable XML dump
    916      */
    917     function enable_xml_dump($enable = false)
    918     {
    919         $this->xml_dump = (bool) $enable;
    920     }
    921 
    922     /**
    923      * Enables/disables caching in SimplePie.
     843     * Enable/disable caching in SimplePie.
    924844     *
    925845     * This option allows you to disable caching all-together in SimplePie.
    926846     * However, disabling the cache can lead to longer load times.
    927847     *
    928      * @access public
    929848     * @since 1.0 Preview Release
    930849     * @param bool $enable Enable caching
    931850     */
    932     function enable_cache($enable = true)
     851    public function enable_cache($enable = true)
    933852    {
    934853        $this->cache = (bool) $enable;
     
    936855
    937856    /**
    938      * Set the length of time (in seconds) that the contents of a feed
    939      * will be cached.
    940      *
    941      * @access public
    942      * @param int $seconds The feed content cache duration.
    943      */
    944     function set_cache_duration($seconds = 3600)
     857     * Set the length of time (in seconds) that the contents of a feed will be
     858     * cached
     859     *
     860     * @param int $seconds The feed content cache duration
     861     */
     862    public function set_cache_duration($seconds = 3600)
    945863    {
    946864        $this->cache_duration = (int) $seconds;
     
    948866
    949867    /**
    950      * Set the length of time (in seconds) that the autodiscovered feed
    951      * URL will be cached.
    952      *
    953      * @access public
     868     * Set the length of time (in seconds) that the autodiscovered feed URL will
     869     * be cached
     870     *
    954871     * @param int $seconds The autodiscovered feed URL cache duration.
    955872     */
    956     function set_autodiscovery_cache_duration($seconds = 604800)
     873    public function set_autodiscovery_cache_duration($seconds = 604800)
    957874    {
    958875        $this->autodiscovery_cache_duration = (int) $seconds;
     
    960877
    961878    /**
    962      * Set the file system location where the cached files should be stored.
    963      *
    964      * @access public
     879     * Set the file system location where the cached files should be stored
     880     *
    965881     * @param string $location The file system location.
    966882     */
    967     function set_cache_location($location = './cache')
     883    public function set_cache_location($location = './cache')
    968884    {
    969885        $this->cache_location = (string) $location;
     
    971887
    972888    /**
    973      * Determines whether feed items should be sorted into reverse chronological order.
    974      *
    975      * @access public
     889     * Set whether feed items should be sorted into reverse chronological order
     890     *
    976891     * @param bool $enable Sort as reverse chronological order.
    977892     */
    978     function enable_order_by_date($enable = true)
     893    public function enable_order_by_date($enable = true)
    979894    {
    980895        $this->order_by_date = (bool) $enable;
     
    982897
    983898    /**
    984      * Allows you to override the character encoding reported by the feed.
    985      *
    986      * @access public
    987      * @param string $encoding Character encoding.
    988      */
    989     function set_input_encoding($encoding = false)
     899     * Set the character encoding used to parse the feed
     900     *
     901     * This overrides the encoding reported by the feed, however it will fall
     902     * back to the normal encoding detection if the override fails
     903     *
     904     * @param string $encoding Character encoding
     905     */
     906    public function set_input_encoding($encoding = false)
    990907    {
    991908        if ($encoding)
     
    1002919     * Set how much feed autodiscovery to do
    1003920     *
    1004      * @access public
    1005921     * @see SIMPLEPIE_LOCATOR_NONE
    1006922     * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
     
    1010926     * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
    1011927     * @see SIMPLEPIE_LOCATOR_ALL
    1012      * @param int $level Feed Autodiscovery Level (level can be a
    1013      * combination of the above constants, see bitwise OR operator)
    1014      */
    1015     function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
     928     * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
     929     */
     930    public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
    1016931    {
    1017932        $this->autodiscovery = (int) $level;
     
    1019934
    1020935    /**
    1021      * Allows you to change which class SimplePie uses for caching.
     936     * Get the class registry
     937     *
     938     * Use this to override SimplePie's default classes
     939     * @see SimplePie_Registry
     940     * @return SimplePie_Registry
     941     */
     942    public function &get_registry()
     943    {
     944        return $this->registry;
     945    }
     946
     947    /**#@+
    1022948     * Useful when you are overloading or extending SimplePie's default classes.
    1023949     *
    1024      * @access public
    1025      * @param string $class Name of custom class.
    1026      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
     950     * @deprecated Use {@see get_registry()} instead
    1027951     * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1028      */
    1029     function set_cache_class($class = 'SimplePie_Cache')
    1030     {
    1031         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
    1032         {
    1033             $this->cache_class = $class;
    1034             return true;
    1035         }
    1036         return false;
    1037     }
    1038 
    1039     /**
    1040      * Allows you to change which class SimplePie uses for auto-discovery.
    1041      * Useful when you are overloading or extending SimplePie's default classes.
    1042      *
    1043      * @access public
    1044      * @param string $class Name of custom class.
    1045      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1046      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1047      */
    1048     function set_locator_class($class = 'SimplePie_Locator')
    1049     {
    1050         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
    1051         {
    1052             $this->locator_class = $class;
    1053             return true;
    1054         }
    1055         return false;
    1056     }
    1057 
    1058     /**
    1059      * Allows you to change which class SimplePie uses for XML parsing.
    1060      * Useful when you are overloading or extending SimplePie's default classes.
    1061      *
    1062      * @access public
    1063      * @param string $class Name of custom class.
    1064      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1065      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1066      */
    1067     function set_parser_class($class = 'SimplePie_Parser')
    1068     {
    1069         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
    1070         {
    1071             $this->parser_class = $class;
    1072             return true;
    1073         }
    1074         return false;
    1075     }
    1076 
    1077     /**
    1078      * Allows you to change which class SimplePie uses for remote file fetching.
    1079      * Useful when you are overloading or extending SimplePie's default classes.
    1080      *
    1081      * @access public
    1082      * @param string $class Name of custom class.
    1083      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1084      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1085      */
    1086     function set_file_class($class = 'SimplePie_File')
    1087     {
    1088         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
    1089         {
    1090             $this->file_class = $class;
    1091             return true;
    1092         }
    1093         return false;
    1094     }
    1095 
    1096     /**
    1097      * Allows you to change which class SimplePie uses for data sanitization.
    1098      * Useful when you are overloading or extending SimplePie's default classes.
    1099      *
    1100      * @access public
    1101      * @param string $class Name of custom class.
    1102      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1103      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1104      */
    1105     function set_sanitize_class($class = 'SimplePie_Sanitize')
    1106     {
    1107         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
    1108         {
    1109             $this->sanitize =& new $class;
    1110             return true;
    1111         }
    1112         return false;
    1113     }
    1114 
    1115     /**
    1116      * Allows you to change which class SimplePie uses for handling feed items.
    1117      * Useful when you are overloading or extending SimplePie's default classes.
    1118      *
    1119      * @access public
    1120      * @param string $class Name of custom class.
    1121      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1122      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1123      */
    1124     function set_item_class($class = 'SimplePie_Item')
    1125     {
    1126         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
    1127         {
    1128             $this->item_class = $class;
    1129             return true;
    1130         }
    1131         return false;
    1132     }
    1133 
    1134     /**
    1135      * Allows you to change which class SimplePie uses for handling author data.
    1136      * Useful when you are overloading or extending SimplePie's default classes.
    1137      *
    1138      * @access public
    1139      * @param string $class Name of custom class.
    1140      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1141      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1142      */
    1143     function set_author_class($class = 'SimplePie_Author')
    1144     {
    1145         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
    1146         {
    1147             $this->author_class = $class;
    1148             return true;
    1149         }
    1150         return false;
    1151     }
    1152 
    1153     /**
    1154      * Allows you to change which class SimplePie uses for handling category data.
    1155      * Useful when you are overloading or extending SimplePie's default classes.
    1156      *
    1157      * @access public
    1158      * @param string $class Name of custom class.
    1159      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1160      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1161      */
    1162     function set_category_class($class = 'SimplePie_Category')
    1163     {
    1164         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
    1165         {
    1166             $this->category_class = $class;
    1167             return true;
    1168         }
    1169         return false;
    1170     }
    1171 
    1172     /**
    1173      * Allows you to change which class SimplePie uses for feed enclosures.
    1174      * Useful when you are overloading or extending SimplePie's default classes.
    1175      *
    1176      * @access public
    1177      * @param string $class Name of custom class.
    1178      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1179      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1180      */
    1181     function set_enclosure_class($class = 'SimplePie_Enclosure')
    1182     {
    1183         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
    1184         {
    1185             $this->enclosure_class = $class;
    1186             return true;
    1187         }
    1188         return false;
    1189     }
    1190 
    1191     /**
    1192      * Allows you to change which class SimplePie uses for <media:text> captions
    1193      * Useful when you are overloading or extending SimplePie's default classes.
    1194      *
    1195      * @access public
    1196      * @param string $class Name of custom class.
    1197      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1198      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1199      */
    1200     function set_caption_class($class = 'SimplePie_Caption')
    1201     {
    1202         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
    1203         {
    1204             $this->caption_class = $class;
    1205             return true;
    1206         }
    1207         return false;
    1208     }
    1209 
    1210     /**
    1211      * Allows you to change which class SimplePie uses for <media:copyright>
    1212      * Useful when you are overloading or extending SimplePie's default classes.
    1213      *
    1214      * @access public
    1215      * @param string $class Name of custom class.
    1216      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1217      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1218      */
    1219     function set_copyright_class($class = 'SimplePie_Copyright')
    1220     {
    1221         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
    1222         {
    1223             $this->copyright_class = $class;
    1224             return true;
    1225         }
    1226         return false;
    1227     }
    1228 
    1229     /**
    1230      * Allows you to change which class SimplePie uses for <media:credit>
    1231      * Useful when you are overloading or extending SimplePie's default classes.
    1232      *
    1233      * @access public
    1234      * @param string $class Name of custom class.
    1235      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1236      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1237      */
    1238     function set_credit_class($class = 'SimplePie_Credit')
    1239     {
    1240         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
    1241         {
    1242             $this->credit_class = $class;
    1243             return true;
    1244         }
    1245         return false;
    1246     }
    1247 
    1248     /**
    1249      * Allows you to change which class SimplePie uses for <media:rating>
    1250      * Useful when you are overloading or extending SimplePie's default classes.
    1251      *
    1252      * @access public
    1253      * @param string $class Name of custom class.
    1254      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1255      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1256      */
    1257     function set_rating_class($class = 'SimplePie_Rating')
    1258     {
    1259         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
    1260         {
    1261             $this->rating_class = $class;
    1262             return true;
    1263         }
    1264         return false;
    1265     }
    1266 
    1267     /**
    1268      * Allows you to change which class SimplePie uses for <media:restriction>
    1269      * Useful when you are overloading or extending SimplePie's default classes.
    1270      *
    1271      * @access public
    1272      * @param string $class Name of custom class.
    1273      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1274      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1275      */
    1276     function set_restriction_class($class = 'SimplePie_Restriction')
    1277     {
    1278         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
    1279         {
    1280             $this->restriction_class = $class;
    1281             return true;
    1282         }
    1283         return false;
    1284     }
    1285 
    1286     /**
    1287      * Allows you to change which class SimplePie uses for content-type sniffing.
    1288      * Useful when you are overloading or extending SimplePie's default classes.
    1289      *
    1290      * @access public
    1291      * @param string $class Name of custom class.
    1292      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1293      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1294      */
    1295     function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
    1296     {
    1297         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
    1298         {
    1299             $this->content_type_sniffer_class = $class;
    1300             return true;
    1301         }
    1302         return false;
    1303     }
    1304 
    1305     /**
    1306      * Allows you to change which class SimplePie uses item sources.
    1307      * Useful when you are overloading or extending SimplePie's default classes.
    1308      *
    1309      * @access public
    1310      * @param string $class Name of custom class.
    1311      * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
    1312      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
    1313      */
    1314     function set_source_class($class = 'SimplePie_Source')
    1315     {
    1316         if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
    1317         {
    1318             $this->source_class = $class;
    1319             return true;
    1320         }
    1321         return false;
    1322     }
    1323 
    1324     /**
    1325      * Allows you to override the default user agent string.
    1326      *
    1327      * @access public
     952     * @param string $class Name of custom class
     953     * @return boolean True on success, false otherwise
     954     */
     955    /**
     956     * Set which class SimplePie uses for caching
     957     */
     958    public function set_cache_class($class = 'SimplePie_Cache')
     959    {
     960        return $this->registry->register('Cache', $class, true);
     961    }
     962
     963    /**
     964     * Set which class SimplePie uses for auto-discovery
     965     */
     966    public function set_locator_class($class = 'SimplePie_Locator')
     967    {
     968        return $this->registry->register('Locator', $class, true);
     969    }
     970
     971    /**
     972     * Set which class SimplePie uses for XML parsing
     973     */
     974    public function set_parser_class($class = 'SimplePie_Parser')
     975    {
     976        return $this->registry->register('Parser', $class, true);
     977    }
     978
     979    /**
     980     * Set which class SimplePie uses for remote file fetching
     981     */
     982    public function set_file_class($class = 'SimplePie_File')
     983    {
     984        return $this->registry->register('File', $class, true);
     985    }
     986
     987    /**
     988     * Set which class SimplePie uses for data sanitization
     989     */
     990    public function set_sanitize_class($class = 'SimplePie_Sanitize')
     991    {
     992        return $this->registry->register('Sanitize', $class, true);
     993    }
     994
     995    /**
     996     * Set which class SimplePie uses for handling feed items
     997     */
     998    public function set_item_class($class = 'SimplePie_Item')
     999    {
     1000        return $this->registry->register('Item', $class, true);
     1001    }
     1002
     1003    /**
     1004     * Set which class SimplePie uses for handling author data
     1005     */
     1006    public function set_author_class($class = 'SimplePie_Author')
     1007    {
     1008        return $this->registry->register('Author', $class, true);
     1009    }
     1010
     1011    /**
     1012     * Set which class SimplePie uses for handling category data
     1013     */
     1014    public function set_category_class($class = 'SimplePie_Category')
     1015    {
     1016        return $this->registry->register('Category', $class, true);
     1017    }
     1018
     1019    /**
     1020     * Set which class SimplePie uses for feed enclosures
     1021     */
     1022    public function set_enclosure_class($class = 'SimplePie_Enclosure')
     1023    {
     1024        return $this->registry->register('Enclosure', $class, true);
     1025    }
     1026
     1027    /**
     1028     * Set which class SimplePie uses for `<media:text>` captions
     1029     */
     1030    public function set_caption_class($class = 'SimplePie_Caption')
     1031    {
     1032        return $this->registry->register('Caption', $class, true);
     1033    }
     1034
     1035    /**
     1036     * Set which class SimplePie uses for `<media:copyright>`
     1037     */
     1038    public function set_copyright_class($class = 'SimplePie_Copyright')
     1039    {
     1040        return $this->registry->register('Copyright', $class, true);
     1041    }
     1042
     1043    /**
     1044     * Set which class SimplePie uses for `<media:credit>`
     1045     */
     1046    public function set_credit_class($class = 'SimplePie_Credit')
     1047    {
     1048        return $this->registry->register('Credit', $class, true);
     1049    }
     1050
     1051    /**
     1052     * Set which class SimplePie uses for `<media:rating>`
     1053     */
     1054    public function set_rating_class($class = 'SimplePie_Rating')
     1055    {
     1056        return $this->registry->register('Rating', $class, true);
     1057    }
     1058
     1059    /**
     1060     * Set which class SimplePie uses for `<media:restriction>`
     1061     */
     1062    public function set_restriction_class($class = 'SimplePie_Restriction')
     1063    {
     1064        return $this->registry->register('Restriction', $class, true);
     1065    }
     1066
     1067    /**
     1068     * Set which class SimplePie uses for content-type sniffing
     1069     */
     1070    public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
     1071    {
     1072        return $this->registry->register('Content_Type_Sniffer', $class, true);
     1073    }
     1074
     1075    /**
     1076     * Set which class SimplePie uses item sources
     1077     */
     1078    public function set_source_class($class = 'SimplePie_Source')
     1079    {
     1080        return $this->registry->register('Source', $class, true);
     1081    }
     1082    /**#@-*/
     1083
     1084    /**
     1085     * Set the user agent string
     1086     *
    13281087     * @param string $ua New user agent string.
    13291088     */
    1330     function set_useragent($ua = SIMPLEPIE_USERAGENT)
     1089    public function set_useragent($ua = SIMPLEPIE_USERAGENT)
    13311090    {
    13321091        $this->useragent = (string) $ua;
     
    13361095     * Set callback function to create cache filename with
    13371096     *
    1338      * @access public
    13391097     * @param mixed $function Callback function
    13401098     */
    1341     function set_cache_name_function($function = 'md5')
     1099    public function set_cache_name_function($function = 'md5')
    13421100    {
    13431101        if (is_callable($function))
     
    13481106
    13491107    /**
    1350      * Set javascript query string parameter
    1351      *
    1352      * @access public
    1353      * @param mixed $get Javascript query string parameter
    1354      */
    1355     function set_javascript($get = 'js')
    1356     {
    1357         if ($get)
    1358         {
    1359             $this->javascript = (string) $get;
    1360         }
    1361         else
    1362         {
    1363             $this->javascript = false;
    1364         }
    1365     }
    1366 
    1367     /**
    1368      * Set options to make SP as fast as possible.  Forgoes a
    1369      * substantial amount of data sanitization in favor of speed.
    1370      *
    1371      * @access public
     1108     * Set options to make SP as fast as possible
     1109     *
     1110     * Forgoes a substantial amount of data sanitization in favor of speed. This
     1111     * turns SimplePie into a dumb parser of feeds.
     1112     *
    13721113     * @param bool $set Whether to set them or not
    13731114     */
    1374     function set_stupidly_fast($set = false)
     1115    public function set_stupidly_fast($set = false)
    13751116    {
    13761117        if ($set)
     
    13881129     * Set maximum number of feeds to check with autodiscovery
    13891130     *
    1390      * @access public
    13911131     * @param int $max Maximum number of feeds to check
    13921132     */
    1393     function set_max_checked_feeds($max = 10)
     1133    public function set_max_checked_feeds($max = 10)
    13941134    {
    13951135        $this->max_checked_feeds = (int) $max;
    13961136    }
    13971137
    1398     function remove_div($enable = true)
     1138    public function remove_div($enable = true)
    13991139    {
    14001140        $this->sanitize->remove_div($enable);
    14011141    }
    14021142
    1403     function strip_htmltags($tags = '', $encode = null)
     1143    public function strip_htmltags($tags = '', $encode = null)
    14041144    {
    14051145        if ($tags === '')
     
    14141154    }
    14151155
    1416     function encode_instead_of_strip($enable = true)
     1156    public function encode_instead_of_strip($enable = true)
    14171157    {
    14181158        $this->sanitize->encode_instead_of_strip($enable);
    14191159    }
    14201160
    1421     function strip_attributes($attribs = '')
     1161    public function strip_attributes($attribs = '')
    14221162    {
    14231163        if ($attribs === '')
     
    14281168    }
    14291169
    1430     function set_output_encoding($encoding = 'UTF-8')
     1170    /**
     1171     * Set the output encoding
     1172     *
     1173     * Allows you to override SimplePie's output to match that of your webpage.
     1174     * This is useful for times when your webpages are not being served as
     1175     * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and
     1176     * is similar to {@see set_input_encoding()}.
     1177     *
     1178     * It should be noted, however, that not all character encodings can support
     1179     * all characters.  If your page is being served as ISO-8859-1 and you try
     1180     * to display a Japanese feed, you'll likely see garbled characters.
     1181     * Because of this, it is highly recommended to ensure that your webpages
     1182     * are served as UTF-8.
     1183     *
     1184     * The number of supported character encodings depends on whether your web
     1185     * host supports {@link http://php.net/mbstring mbstring},
     1186     * {@link http://php.net/iconv iconv}, or both. See
     1187     * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
     1188     * more information.
     1189     *
     1190     * @param string $encoding
     1191     */
     1192    public function set_output_encoding($encoding = 'UTF-8')
    14311193    {
    14321194        $this->sanitize->set_output_encoding($encoding);
    14331195    }
    14341196
    1435     function strip_comments($strip = false)
     1197    public function strip_comments($strip = false)
    14361198    {
    14371199        $this->sanitize->strip_comments($strip);
     
    14421204     * containing URLs that need to be resolved relative to the feed
    14431205     *
    1444      * @access public
     1206     * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
     1207     * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
     1208     * |q|@cite
     1209     *
    14451210     * @since 1.0
    1446      * @param array $element_attribute Element/attribute key/value pairs
    1447      */
    1448     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'))
     1211     * @param array|null $element_attribute Element/attribute key/value pairs, null for default
     1212     */
     1213    public function set_url_replacements($element_attribute = null)
    14491214    {
    14501215        $this->sanitize->set_url_replacements($element_attribute);
     
    14521217
    14531218    /**
    1454      * Set the handler to enable the display of cached favicons.
    1455      *
    1456      * @access public
    1457      * @param str $page Web-accessible path to the handler_favicon.php file.
    1458      * @param str $qs The query string that the value should be passed to.
    1459      */
    1460     function set_favicon_handler($page = false, $qs = 'i')
    1461     {
    1462         if ($page !== false)
    1463         {
    1464             $this->favicon_handler = $page . '?' . $qs . '=';
    1465         }
    1466         else
    1467         {
    1468             $this->favicon_handler = '';
    1469         }
    1470     }
    1471 
    1472     /**
    14731219     * Set the handler to enable the display of cached images.
    14741220     *
    1475      * @access public
    14761221     * @param str $page Web-accessible path to the handler_image.php file.
    14771222     * @param str $qs The query string that the value should be passed to.
    14781223     */
    1479     function set_image_handler($page = false, $qs = 'i')
     1224    public function set_image_handler($page = false, $qs = 'i')
    14801225    {
    14811226        if ($page !== false)
     
    14901235
    14911236    /**
    1492      * Set the limit for items returned per-feed with multifeeds.
    1493      *
    1494      * @access public
     1237     * Set the limit for items returned per-feed with multifeeds
     1238     *
    14951239     * @param integer $limit The maximum number of items to return.
    14961240     */
    1497     function set_item_limit($limit = 0)
     1241    public function set_item_limit($limit = 0)
    14981242    {
    14991243        $this->item_limit = (int) $limit;
    15001244    }
    15011245
    1502     function init()
     1246    /**
     1247     * Initialize the feed object
     1248     *
     1249     * This is what makes everything happen.  Period.  This is where all of the
     1250     * configuration options get processed, feeds are fetched, cached, and
     1251     * parsed, and all of that other good stuff.
     1252     *
     1253     * @return boolean True if successful, false otherwise
     1254     */
     1255    public function init()
    15031256    {
    15041257        // Check absolute bare minimum requirements.
    1505         if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
     1258        if (!extension_loaded('xml') || !extension_loaded('pcre'))
    15061259        {
    15071260            return false;
     
    15241277        }
    15251278
    1526         if (isset($_GET[$this->javascript]))
    1527         {
    1528             SimplePie_Misc::output_javascript();
    1529             exit;
     1279        if (method_exists($this->sanitize, 'set_registry'))
     1280        {
     1281            $this->sanitize->set_registry($this->registry);
    15301282        }
    15311283
    15321284        // Pass whatever was set with config options over to the sanitizer.
    1533         $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
    1534         $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
    1535 
    1536         if ($this->feed_url !== null || $this->raw_data !== null)
    1537         {
    1538             $this->data = array();
     1285        // Pass the classes in for legacy support; new classes should use the registry instead
     1286        $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
     1287        $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
     1288
     1289        if (!empty($this->multifeed_url))
     1290        {
     1291            $i = 0;
     1292            $success = 0;
    15391293            $this->multifeed_objects = array();
    1540             $cache = false;
    1541 
    1542             if ($this->feed_url !== null)
    1543             {
    1544                 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
    1545                 // Decide whether to enable caching
    1546                 if ($this->cache && $parsed_feed_url['scheme'] !== '')
    1547                 {
    1548                     $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
    1549                 }
    1550                 // If it's enabled and we don't want an XML dump, use the cache
    1551                 if ($cache && !$this->xml_dump)
    1552                 {
    1553                     // Load the Cache
    1554                     $this->data = $cache->load();
    1555                     if (!empty($this->data))
     1294            $this->error = array();
     1295            foreach ($this->multifeed_url as $url)
     1296            {
     1297                $this->multifeed_objects[$i] = clone $this;
     1298                $this->multifeed_objects[$i]->set_feed_url($url);
     1299                $single_success = $this->multifeed_objects[$i]->init();
     1300                $success |= $single_success;
     1301                if (!$single_success)
     1302                {
     1303                    $this->error[$i] = $this->multifeed_objects[$i]->error();
     1304                }
     1305                $i++;
     1306            }
     1307            return (bool) $success;
     1308        }
     1309        elseif ($this->feed_url === null && $this->raw_data === null)
     1310        {
     1311            return false;
     1312        }
     1313
     1314        $this->error = null;
     1315        $this->data = array();
     1316        $this->multifeed_objects = array();
     1317        $cache = false;
     1318
     1319        if ($this->feed_url !== null)
     1320        {
     1321            $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
     1322
     1323            // Decide whether to enable caching
     1324            if ($this->cache && $parsed_feed_url['scheme'] !== '')
     1325            {
     1326                $cache = $this->registry->call('Cache', 'create', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
     1327            }
     1328
     1329            // Fetch the data via SimplePie_File into $this->raw_data
     1330            if (($fetched = $this->fetch_data($cache)) === true)
     1331            {
     1332                return true;
     1333            }
     1334            elseif ($fetched === false) {
     1335                return false;
     1336            }
     1337
     1338            list($headers, $sniffed) = $fetched;
     1339        }
     1340
     1341        // Set up array of possible encodings
     1342        $encodings = array();
     1343
     1344        // First check to see if input has been overridden.
     1345        if ($this->input_encoding !== false)
     1346        {
     1347            $encodings[] = $this->input_encoding;
     1348        }
     1349
     1350        $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
     1351        $text_types = array('text/xml', 'text/xml-external-parsed-entity');
     1352
     1353        // RFC 3023 (only applies to sniffed content)
     1354        if (isset($sniffed))
     1355        {
     1356            if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
     1357            {
     1358                if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
     1359                {
     1360                    $encodings[] = strtoupper($charset[1]);
     1361                }
     1362                $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
     1363                $encodings[] = 'UTF-8';
     1364            }
     1365            elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
     1366            {
     1367                if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
     1368                {
     1369                    $encodings[] = $charset[1];
     1370                }
     1371                $encodings[] = 'US-ASCII';
     1372            }
     1373            // Text MIME-type default
     1374            elseif (substr($sniffed, 0, 5) === 'text/')
     1375            {
     1376                $encodings[] = 'US-ASCII';
     1377            }
     1378        }
     1379
     1380        // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
     1381        $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
     1382        $encodings[] = 'UTF-8';
     1383        $encodings[] = 'ISO-8859-1';
     1384
     1385        // There's no point in trying an encoding twice
     1386        $encodings = array_unique($encodings);
     1387
     1388        // Loop through each possible encoding, till we return something, or run out of possibilities
     1389        foreach ($encodings as $encoding)
     1390        {
     1391            // Change the encoding to UTF-8 (as we always use UTF-8 internally)
     1392            if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
     1393            {
     1394                // Create new parser
     1395                $parser = $this->registry->create('Parser');
     1396
     1397                // If it's parsed fine
     1398                if ($parser->parse($utf8_data, 'UTF-8'))
     1399                {
     1400                    $this->data = $parser->get_data();
     1401                    if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
    15561402                    {
    1557                         // If the cache is for an outdated build of SimplePie
    1558                         if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
     1403                        $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
     1404                        $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
     1405                        return false;
     1406                    }
     1407
     1408                    if (isset($headers))
     1409                    {
     1410                        $this->data['headers'] = $headers;
     1411                    }
     1412                    $this->data['build'] = SIMPLEPIE_BUILD;
     1413
     1414                    // Cache the file if caching is enabled
     1415                    if ($cache && !$cache->save($this))
     1416                    {
     1417                        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);
     1418                    }
     1419                    return true;
     1420                }
     1421            }
     1422        }
     1423
     1424        if (isset($parser))
     1425        {
     1426            // We have an error, just set SimplePie_Misc::error to it and quit
     1427            $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());
     1428        }
     1429        else
     1430        {
     1431            $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.';
     1432        }
     1433
     1434        $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
     1435
     1436        return false;
     1437    }
     1438
     1439    /**
     1440     * Fetch the data via SimplePie_File
     1441     *
     1442     * If the data is already cached, attempt to fetch it from there instead
     1443     * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
     1444     * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
     1445     */
     1446    protected function fetch_data(&$cache)
     1447    {
     1448        // If it's enabled, use the cache
     1449        if ($cache)
     1450        {
     1451            // Load the Cache
     1452            $this->data = $cache->load();
     1453            if (!empty($this->data))
     1454            {
     1455                // If the cache is for an outdated build of SimplePie
     1456                if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
     1457                {
     1458                    $cache->unlink();
     1459                    $this->data = array();
     1460                }
     1461                // If we've hit a collision just rerun it with caching disabled
     1462                elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
     1463                {
     1464                    $cache = false;
     1465                    $this->data = array();
     1466                }
     1467                // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
     1468                elseif (isset($this->data['feed_url']))
     1469                {
     1470                    // If the autodiscovery cache is still valid use it.
     1471                    if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
     1472                    {
     1473                        // Do not need to do feed autodiscovery yet.
     1474                        if ($this->data['feed_url'] !== $this->data['url'])
    15591475                        {
    1560                             $cache->unlink();
    1561                             $this->data = array();
     1476                            $this->set_feed_url($this->data['feed_url']);
     1477                            return $this->init();
    15621478                        }
    1563                         // If we've hit a collision just rerun it with caching disabled
    1564                         elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
    1565                         {
    1566                             $cache = false;
    1567                             $this->data = array();
    1568                         }
    1569                         // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
    1570                         elseif (isset($this->data['feed_url']))
    1571                         {
    1572                             // If the autodiscovery cache is still valid use it.
    1573                             if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
    1574                             {
    1575                                 // Do not need to do feed autodiscovery yet.
    1576                                 if ($this->data['feed_url'] === $this->data['url'])
    1577                                 {
    1578                                     $cache->unlink();
    1579                                     $this->data = array();
    1580                                 }
    1581                                 else
    1582                                 {
    1583                                     $this->set_feed_url($this->data['feed_url']);
    1584                                     return $this->init();
    1585                                 }
    1586                             }
    1587                         }
    1588                         // Check if the cache has been updated
    1589                         elseif ($cache->mtime() + $this->cache_duration < time())
    1590                         {
    1591                             // If we have last-modified and/or etag set
    1592                             if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
    1593                             {
    1594                                 $headers = array();
    1595                                 if (isset($this->data['headers']['last-modified']))
    1596                                 {
    1597                                     $headers['if-modified-since'] = $this->data['headers']['last-modified'];
    1598                                 }
    1599                                 if (isset($this->data['headers']['etag']))
    1600                                 {
    1601                                     $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
    1602                                 }
    1603                                 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
    1604                                 if ($file->success)
    1605                                 {
    1606                                     if ($file->status_code === 304)
    1607                                     {
    1608                                         $cache->touch();
    1609                                         return true;
    1610                                     }
    1611                                     else
    1612                                     {
    1613                                         $headers = $file->headers;
    1614                                     }
    1615                                 }
    1616                                 else
    1617                                 {
    1618                                     unset($file);
    1619                                 }
    1620                             }
    1621                         }
    1622                         // If the cache is still valid, just return true
    1623                         else
    1624                         {
    1625                             return true;
    1626                         }
    1627                     }
    1628                     // If the cache is empty, delete it
    1629                     else
    1630                     {
     1479
    16311480                        $cache->unlink();
    16321481                        $this->data = array();
    16331482                    }
    16341483                }
    1635                 // 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.
    1636                 if (!isset($file))
    1637                 {
    1638                     if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
     1484                // Check if the cache has been updated
     1485                elseif ($cache->mtime() + $this->cache_duration < time())
     1486                {
     1487                    // If we have last-modified and/or etag set
     1488                    if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
    16391489                    {
    1640                         $file =& $this->file;
    1641                     }
    1642                     else
    1643                     {
    1644                         $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
    1645                     }
    1646                 }
    1647                 // If the file connection has an error, set SimplePie::error to that and quit
    1648                 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
    1649                 {
    1650                     $this->error = $file->error;
    1651                     if (!empty($this->data))
    1652                     {
    1653                         return true;
    1654                     }
    1655                     else
    1656                     {
    1657                         return false;
    1658                     }
    1659                 }
    1660 
    1661                 if (!$this->force_feed)
    1662                 {
    1663                     // Check if the supplied URL is a feed, if it isn't, look for it.
    1664                     $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
    1665                     if (!$locate->is_feed($file))
    1666                     {
    1667                         // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
    1668                         unset($file);
    1669                         if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
     1490                        $headers = array(
     1491                            'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
     1492                        );
     1493                        if (isset($this->data['headers']['last-modified']))
    16701494                        {
    1671                             if ($cache)
     1495                            $headers['if-modified-since'] = $this->data['headers']['last-modified'];
     1496                        }
     1497                        if (isset($this->data['headers']['etag']))
     1498                        {
     1499                            $headers['if-none-match'] = $this->data['headers']['etag'];
     1500                        }
     1501
     1502                        $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
     1503
     1504                        if ($file->success)
     1505                        {
     1506                            if ($file->status_code === 304)
    16721507                            {
    1673                                 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
    1674                                 if (!$cache->save($this))
    1675                                 {
    1676                                     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);
    1677                                 }
    1678                                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
     1508                                $cache->touch();
     1509                                return true;
    16791510                            }
    1680                             $this->feed_url = $file->url;
    16811511                        }
    16821512                        else
    16831513                        {
    1684                             $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.";
    1685                             SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
    1686                             return false;
     1514                            unset($file);
    16871515                        }
    16881516                    }
    1689                     $locate = null;
    1690                 }
    1691 
    1692                 $headers = $file->headers;
    1693                 $data = $file->body;
    1694                 $sniffer =& new $this->content_type_sniffer_class($file);
    1695                 $sniffed = $sniffer->get_type();
    1696             }
     1517                }
     1518                // If the cache is still valid, just return true
     1519                else
     1520                {
     1521                    $this->raw_data = false;
     1522                    return true;
     1523                }
     1524            }
     1525            // If the cache is empty, delete it
    16971526            else
    16981527            {
    1699                 $data = $this->raw_data;
    1700             }
    1701 
    1702             // Set up array of possible encodings
    1703             $encodings = array();
    1704 
    1705             // First check to see if input has been overridden.
    1706             if ($this->input_encoding !== false)
    1707             {
    1708                 $encodings[] = $this->input_encoding;
    1709             }
    1710 
    1711             $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
    1712             $text_types = array('text/xml', 'text/xml-external-parsed-entity');
    1713 
    1714             // RFC 3023 (only applies to sniffed content)
    1715             if (isset($sniffed))
    1716             {
    1717                 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
    1718                 {
    1719                     if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
     1528                $cache->unlink();
     1529                $this->data = array();
     1530            }
     1531        }
     1532        // 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.
     1533        if (!isset($file))
     1534        {
     1535            if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
     1536            {
     1537                $file =& $this->file;
     1538            }
     1539            else
     1540            {
     1541                $headers = array(
     1542                    'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
     1543                );
     1544                $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
     1545            }
     1546        }
     1547        // If the file connection has an error, set SimplePie::error to that and quit
     1548        if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
     1549        {
     1550            $this->error = $file->error;
     1551            return !empty($this->data);
     1552        }
     1553
     1554        if (!$this->force_feed)
     1555        {
     1556            // Check if the supplied URL is a feed, if it isn't, look for it.
     1557            $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
     1558
     1559            if (!$locate->is_feed($file))
     1560            {
     1561                // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
     1562                unset($file);
     1563                if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
     1564                {
     1565                    $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.";
     1566                    $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
     1567                    return false;
     1568                }
     1569                if ($cache)
     1570                {
     1571                    $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
     1572                    if (!$cache->save($this))
    17201573                    {
    1721                         $encodings[] = strtoupper($charset[1]);
     1574                        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);
    17221575                    }
    1723                     $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
    1724                     $encodings[] = 'UTF-8';
    1725                 }
    1726                 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
    1727                 {
    1728                     if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
    1729                     {
    1730                         $encodings[] = $charset[1];
    1731                     }
    1732                     $encodings[] = 'US-ASCII';
    1733                 }
    1734                 // Text MIME-type default
    1735                 elseif (substr($sniffed, 0, 5) === 'text/')
    1736                 {
    1737                     $encodings[] = 'US-ASCII';
    1738                 }
    1739             }
    1740 
    1741             // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
    1742             $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
    1743             $encodings[] = 'UTF-8';
    1744             $encodings[] = 'ISO-8859-1';
    1745 
    1746             // There's no point in trying an encoding twice
    1747             $encodings = array_unique($encodings);
    1748 
    1749             // If we want the XML, just output that with the most likely encoding and quit
    1750             if ($this->xml_dump)
    1751             {
    1752                 header('Content-type: text/xml; charset=' . $encodings[0]);
    1753                 echo $data;
    1754                 exit;
    1755             }
    1756 
    1757             // Loop through each possible encoding, till we return something, or run out of possibilities
    1758             foreach ($encodings as $encoding)
    1759             {
    1760                 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
    1761                 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
    1762                 {
    1763                     // Create new parser
    1764                     $parser =& new $this->parser_class();
    1765 
    1766                     // If it's parsed fine
    1767                     if ($parser->parse($utf8_data, 'UTF-8'))
    1768                     {
    1769                         $this->data = $parser->get_data();
    1770                         if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
    1771                         {
    1772                             if (isset($headers))
    1773                             {
    1774                                 $this->data['headers'] = $headers;
    1775                             }
    1776                             $this->data['build'] = SIMPLEPIE_BUILD;
    1777 
    1778                             // Cache the file if caching is enabled
    1779                             if ($cache && !$cache->save($this))
    1780                             {
    1781                                 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);
    1782                             }
    1783                             return true;
    1784                         }
    1785                         else
    1786                         {
    1787                             $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
    1788                             SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
    1789                             return false;
    1790                         }
    1791                     }
    1792                 }
    1793             }
    1794             if (isset($parser))
    1795             {
    1796                 // We have an error, just set SimplePie_Misc::error to it and quit
    1797                 $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());
    1798             }
    1799             else
    1800             {
    1801                 $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.';
    1802             }
    1803             SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
    1804             return false;
    1805         }
    1806         elseif (!empty($this->multifeed_url))
    1807         {
    1808             $i = 0;
    1809             $success = 0;
    1810             $this->multifeed_objects = array();
    1811             foreach ($this->multifeed_url as $url)
    1812             {
    1813                 if (SIMPLEPIE_PHP5)
    1814                 {
    1815                     // This keyword needs to defy coding standards for PHP4 compatibility
    1816                     $this->multifeed_objects[$i] = clone($this);
    1817                 }
    1818                 else
    1819                 {
    1820                     $this->multifeed_objects[$i] = $this;
    1821                 }
    1822                 $this->multifeed_objects[$i]->set_feed_url($url);
    1823                 $success |= $this->multifeed_objects[$i]->init();
    1824                 $i++;
    1825             }
    1826             return (bool) $success;
    1827         }
    1828         else
    1829         {
    1830             return false;
    1831         }
    1832     }
    1833 
    1834     /**
    1835      * Return the error message for the occured error
    1836      *
    1837      * @access public
    1838      * @return string Error message
    1839      */
    1840     function error()
     1576                    $cache = $this->registry->call('Cache', 'create', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
     1577                }
     1578                $this->feed_url = $file->url;
     1579            }
     1580            $locate = null;
     1581        }
     1582
     1583        $this->raw_data = $file->body;
     1584
     1585        $headers = $file->headers;
     1586        $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
     1587        $sniffed = $sniffer->get_type();
     1588
     1589        return array($headers, $sniffed);
     1590    }
     1591
     1592    /**
     1593     * Get the error message for the occured error
     1594     *
     1595     * @return string|array Error message, or array of messages for multifeeds
     1596     */
     1597    public function error()
    18411598    {
    18421599        return $this->error;
    18431600    }
    18441601
    1845     function get_encoding()
     1602    /**
     1603     * Get the raw XML
     1604     *
     1605     * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
     1606     * the data instead of printing it.
     1607     *
     1608     * @return string|boolean Raw XML data, false if the cache is used
     1609     */
     1610    public function get_raw_data()
     1611    {
     1612        return $this->raw_data;
     1613    }
     1614
     1615    /**
     1616     * Get the character encoding used for output
     1617     *
     1618     * @since Preview Release
     1619     * @return string
     1620     */
     1621    public function get_encoding()
    18461622    {
    18471623        return $this->sanitize->output_encoding;
    18481624    }
    18491625
    1850     function handle_content_type($mime = 'text/html')
     1626    /**
     1627     * Send the content-type header with correct encoding
     1628     *
     1629     * This method ensures that the SimplePie-enabled page is being served with
     1630     * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
     1631     * and character encoding HTTP headers (character encoding determined by the
     1632     * {@see set_output_encoding} config option).
     1633     *
     1634     * This won't work properly if any content or whitespace has already been
     1635     * sent to the browser, because it relies on PHP's
     1636     * {@link http://php.net/header header()} function, and these are the
     1637     * circumstances under which the function works.
     1638     *
     1639     * Because it's setting these settings for the entire page (as is the nature
     1640     * of HTTP headers), this should only be used once per page (again, at the
     1641     * top).
     1642     *
     1643     * @param string $mime MIME type to serve the page as
     1644     */
     1645    public function handle_content_type($mime = 'text/html')
    18511646    {
    18521647        if (!headers_sent())
     
    18651660    }
    18661661
    1867     function get_type()
     1662    /**
     1663     * Get the type of the feed
     1664     *
     1665     * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
     1666     * using {@link http://php.net/language.operators.bitwise bitwise operators}
     1667     *
     1668     * @since 0.8 (usage changed to using constants in 1.0)
     1669     * @see SIMPLEPIE_TYPE_NONE Unknown.
     1670     * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
     1671     * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
     1672     * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
     1673     * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
     1674     * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
     1675     * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
     1676     * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
     1677     * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
     1678     * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
     1679     * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
     1680     * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
     1681     * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
     1682     * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
     1683     * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
     1684     * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
     1685     * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
     1686     * @return int SIMPLEPIE_TYPE_* constant
     1687     */
     1688    public function get_type()
    18681689    {
    18691690        if (!isset($this->data['type']))
     
    19461767
    19471768    /**
    1948      * Returns the URL for the favicon of the feed's website.
    1949      *
    1950      * @todo Cache atom:icon
    1951      * @access public
    1952      * @since 1.0
    1953      */
    1954     function get_favicon()
    1955     {
    1956         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
    1957         {
    1958             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
    1959         }
    1960         elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
    1961         {
    1962             $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
    1963 
    1964             if ($this->cache && $this->favicon_handler)
    1965             {
    1966                 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
    1967                 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
    1968 
    1969                 if ($cache->load())
    1970                 {
    1971                     return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
    1972                 }
    1973                 else
    1974                 {
    1975                     $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
    1976 
    1977                     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)
    1978                     {
    1979                         $sniffer =& new $this->content_type_sniffer_class($file);
    1980                         if (substr($sniffer->get_type(), 0, 6) === 'image/')
    1981                         {
    1982                             if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
    1983                             {
    1984                                 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
    1985                             }
    1986                             else
    1987                             {
    1988                                 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);
    1989                                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
    1990                             }
    1991                         }
    1992                         // not an image
    1993                         else
    1994                         {
    1995                             return false;
    1996                         }
    1997                     }
    1998                 }
    1999             }
    2000             else
    2001             {
    2002                 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
    2003             }
    2004         }
    2005         return false;
    2006     }
    2007 
    2008     /**
     1769     * Get the URL for the feed
     1770     *
     1771     * May or may not be different from the URL passed to {@see set_feed_url()},
     1772     * depending on whether auto-discovery was used.
     1773     *
     1774     * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
    20091775     * @todo If we have a perm redirect we should return the new URL
    20101776     * @todo When we make the above change, let's support <itunes:new-feed-url> as well
    20111777     * @todo Also, |atom:link|@rel=self
    2012      */
    2013     function subscribe_url()
     1778     * @return string|null
     1779     */
     1780    public function subscribe_url()
    20141781    {
    20151782        if ($this->feed_url !== null)
     
    20231790    }
    20241791
    2025     function subscribe_feed()
    2026     {
    2027         if ($this->feed_url !== null)
    2028         {
    2029             return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
    2030         }
    2031         else
    2032         {
    2033             return null;
    2034         }
    2035     }
    2036 
    2037     function subscribe_outlook()
    2038     {
    2039         if ($this->feed_url !== null)
    2040         {
    2041             return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
    2042         }
    2043         else
    2044         {
    2045             return null;
    2046         }
    2047     }
    2048 
    2049     function subscribe_podcast()
    2050     {
    2051         if ($this->feed_url !== null)
    2052         {
    2053             return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
    2054         }
    2055         else
    2056         {
    2057             return null;
    2058         }
    2059     }
    2060 
    2061     function subscribe_itunes()
    2062     {
    2063         if ($this->feed_url !== null)
    2064         {
    2065             return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
    2066         }
    2067         else
    2068         {
    2069             return null;
    2070         }
    2071     }
    2072 
    2073     /**
    2074      * Creates the subscribe_* methods' return data
    2075      *
    2076      * @access private
    2077      * @param string $feed_url String to prefix to the feed URL
    2078      * @param string $site_url String to prefix to the site URL (and
    2079      * suffix to the feed URL)
    2080      * @return mixed URL if feed exists, false otherwise
    2081      */
    2082     function subscribe_service($feed_url, $site_url = null)
    2083     {
    2084         if ($this->subscribe_url())
    2085         {
    2086             $return = $feed_url . rawurlencode($this->feed_url);
    2087             if ($site_url !== null && $this->get_link() !== null)
    2088             {
    2089                 $return .= $site_url . rawurlencode($this->get_link());
    2090             }
    2091             return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
    2092         }
    2093         else
    2094         {
    2095             return null;
    2096         }
    2097     }
    2098 
    2099     function subscribe_aol()
    2100     {
    2101         return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
    2102     }
    2103 
    2104     function subscribe_bloglines()
    2105     {
    2106         return $this->subscribe_service('http://www.bloglines.com/sub/');
    2107     }
    2108 
    2109     function subscribe_eskobo()
    2110     {
    2111         return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
    2112     }
    2113 
    2114     function subscribe_feedfeeds()
    2115     {
    2116         return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
    2117     }
    2118 
    2119     function subscribe_feedster()
    2120     {
    2121         return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
    2122     }
    2123 
    2124     function subscribe_google()
    2125     {
    2126         return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
    2127     }
    2128 
    2129     function subscribe_gritwire()
    2130     {
    2131         return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
    2132     }
    2133 
    2134     function subscribe_msn()
    2135     {
    2136         return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
    2137     }
    2138 
    2139     function subscribe_netvibes()
    2140     {
    2141         return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
    2142     }
    2143 
    2144     function subscribe_newsburst()
    2145     {
    2146         return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
    2147     }
    2148 
    2149     function subscribe_newsgator()
    2150     {
    2151         return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
    2152     }
    2153 
    2154     function subscribe_odeo()
    2155     {
    2156         return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
    2157     }
    2158 
    2159     function subscribe_podnova()
    2160     {
    2161         return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
    2162     }
    2163 
    2164     function subscribe_rojo()
    2165     {
    2166         return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
    2167     }
    2168 
    2169     function subscribe_yahoo()
    2170     {
    2171         return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
    2172     }
    2173 
    2174     function get_feed_tags($namespace, $tag)
     1792    /**
     1793     * Get data for an feed-level element
     1794     *
     1795     * This method allows you to get access to ANY element/attribute that is a
     1796     * sub-element of the opening feed tag.
     1797     *
     1798     * The return value is an indexed array of elements matching the given
     1799     * namespace and tag name. Each element has `attribs`, `data` and `child`
     1800     * subkeys. For `attribs` and `child`, these contain namespace subkeys.
     1801     * `attribs` then has one level of associative name => value data (where
     1802     * `value` is a string) after the namespace. `child` has tag-indexed keys
     1803     * after the namespace, each member of which is an indexed array matching
     1804     * this same format.
     1805     *
     1806     * For example:
     1807     * <pre>
     1808     * // This is probably a bad example because we already support
     1809     * // <media:content> natively, but it shows you how to parse through
     1810     * // the nodes.
     1811     * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
     1812     * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
     1813     * $file = $content[0]['attribs']['']['url'];
     1814     * echo $file;
     1815     * </pre>
     1816     *
     1817     * @since 1.0
     1818     * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
     1819     * @param string $namespace The URL of the XML namespace of the elements you're trying to access
     1820     * @param string $tag Tag name
     1821     * @return array
     1822     */
     1823    public function get_feed_tags($namespace, $tag)
    21751824    {
    21761825        $type = $this->get_type();
     
    22061855    }
    22071856
    2208     function get_channel_tags($namespace, $tag)
     1857    /**
     1858     * Get data for an channel-level element
     1859     *
     1860     * This method allows you to get access to ANY element/attribute in the
     1861     * channel/header section of the feed.
     1862     *
     1863     * See {@see SimplePie::get_feed_tags()} for a description of the return value
     1864     *
     1865     * @since 1.0
     1866     * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
     1867     * @param string $namespace The URL of the XML namespace of the elements you're trying to access
     1868     * @param string $tag Tag name
     1869     * @return array
     1870     */
     1871    public function get_channel_tags($namespace, $tag)
    22091872    {
    22101873        $type = $this->get_type();
     
    22491912    }
    22501913
    2251     function get_image_tags($namespace, $tag)
     1914    /**
     1915     * Get data for an channel-level element
     1916     *
     1917     * This method allows you to get access to ANY element/attribute in the
     1918     * image/logo section of the feed.
     1919     *
     1920     * See {@see SimplePie::get_feed_tags()} for a description of the return value
     1921     *
     1922     * @since 1.0
     1923     * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
     1924     * @param string $namespace The URL of the XML namespace of the elements you're trying to access
     1925     * @param string $tag Tag name
     1926     * @return array
     1927     */
     1928    public function get_image_tags($namespace, $tag)
    22521929    {
    22531930        $type = $this->get_type();
     
    22851962    }
    22861963
    2287     function get_base($element = array())
     1964    /**
     1965     * Get the base URL value from the feed
     1966     *
     1967     * Uses `<xml:base>` if available, otherwise uses the first link in the
     1968     * feed, or failing that, the URL of the feed itself.
     1969     *
     1970     * @see get_link
     1971     * @see subscribe_url
     1972     *
     1973     * @param array $element
     1974     * @return string
     1975     */
     1976    public function get_base($element = array())
    22881977    {
    22891978        if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
     
    23011990    }
    23021991
    2303     function sanitize($data, $type, $base = '')
     1992    /**
     1993     * Sanitize feed data
     1994     *
     1995     * @access private
     1996     * @see SimplePie_Sanitize::sanitize()
     1997     * @param string $data Data to sanitize
     1998     * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
     1999     * @param string $base Base URL to resolve URLs against
     2000     * @return string Sanitized data
     2001     */
     2002    public function sanitize($data, $type, $base = '')
    23042003    {
    23052004        return $this->sanitize->sanitize($data, $type, $base);
    23062005    }
    23072006
    2308     function get_title()
     2007    /**
     2008     * Get the title of the feed
     2009     *
     2010     * Uses `<atom:title>`, `<title>` or `<dc:title>`
     2011     *
     2012     * @since 1.0 (previously called `get_feed_title` since 0.8)
     2013     * @return string|null
     2014     */
     2015    public function get_title()
    23092016    {
    23102017        if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
    23112018        {
    2312             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
     2019            return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
    23132020        }
    23142021        elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
    23152022        {
    2316             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
     2023            return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
    23172024        }
    23182025        elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
     
    23422049    }
    23432050
    2344     function get_category($key = 0)
     2051    /**
     2052     * Get a category for the feed
     2053     *
     2054     * @since Unknown
     2055     * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
     2056     * @return SimplePie_Category|null
     2057     */
     2058    public function get_category($key = 0)
    23452059    {
    23462060        $categories = $this->get_categories();
     
    23552069    }
    23562070
    2357     function get_categories()
     2071    /**
     2072     * Get all categories for the feed
     2073     *
     2074     * Uses `<atom:category>`, `<category>` or `<dc:subject>`
     2075     *
     2076     * @since Unknown
     2077     * @return array|null List of {@see SimplePie_Category} objects
     2078     */
     2079    public function get_categories()
    23582080    {
    23592081        $categories = array();
     
    23762098                $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    23772099            }
    2378             $categories[] =& new $this->category_class($term, $scheme, $label);
     2100            $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
    23792101        }
    23802102        foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
     
    23912113                $scheme = null;
    23922114            }
    2393             $categories[] =& new $this->category_class($term, $scheme, null);
     2115            $categories[] = $this->registry->create('Category', array($term, $scheme, null));
    23942116        }
    23952117        foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
    23962118        {
    2397             $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
     2119            $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
    23982120        }
    23992121        foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
    24002122        {
    2401             $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
     2123            $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
    24022124        }
    24032125
    24042126        if (!empty($categories))
    24052127        {
    2406             return SimplePie_Misc::array_unique($categories);
     2128            return array_unique($categories);
    24072129        }
    24082130        else
     
    24122134    }
    24132135
    2414     function get_author($key = 0)
     2136    /**
     2137     * Get an author for the feed
     2138     *
     2139     * @since 1.1
     2140     * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
     2141     * @return SimplePie_Author|null
     2142     */
     2143    public function get_author($key = 0)
    24152144    {
    24162145        $authors = $this->get_authors();
     
    24252154    }
    24262155
    2427     function get_authors()
     2156    /**
     2157     * Get all authors for the feed
     2158     *
     2159     * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
     2160     *
     2161     * @since 1.1
     2162     * @return array|null List of {@see SimplePie_Author} objects
     2163     */
     2164    public function get_authors()
    24282165    {
    24292166        $authors = array();
     
    24472184            if ($name !== null || $email !== null || $uri !== null)
    24482185            {
    2449                 $authors[] =& new $this->author_class($name, $uri, $email);
     2186                $authors[] = $this->registry->create('Author', array($name, $uri, $email));
    24502187            }
    24512188        }
     
    24692206            if ($name !== null || $email !== null || $url !== null)
    24702207            {
    2471                 $authors[] =& new $this->author_class($name, $url, $email);
     2208                $authors[] = $this->registry->create('Author', array($name, $url, $email));
    24722209            }
    24732210        }
    24742211        foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
    24752212        {
    2476             $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
     2213            $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
    24772214        }
    24782215        foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
    24792216        {
    2480             $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
     2217            $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
    24812218        }
    24822219        foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
    24832220        {
    2484             $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
     2221            $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
    24852222        }
    24862223
    24872224        if (!empty($authors))
    24882225        {
    2489             return SimplePie_Misc::array_unique($authors);
     2226            return array_unique($authors);
    24902227        }
    24912228        else
     
    24952232    }
    24962233
    2497     function get_contributor($key = 0)
     2234    /**
     2235     * Get a contributor for the feed
     2236     *
     2237     * @since 1.1
     2238     * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
     2239     * @return SimplePie_Author|null
     2240     */
     2241    public function get_contributor($key = 0)
    24982242    {
    24992243        $contributors = $this->get_contributors();
     
    25082252    }
    25092253
    2510     function get_contributors()
     2254    /**
     2255     * Get all contributors for the feed
     2256     *
     2257     * Uses `<atom:contributor>`
     2258     *
     2259     * @since 1.1
     2260     * @return array|null List of {@see SimplePie_Author} objects
     2261     */
     2262    public function get_contributors()
    25112263    {
    25122264        $contributors = array();
     
    25302282            if ($name !== null || $email !== null || $uri !== null)
    25312283            {
    2532                 $contributors[] =& new $this->author_class($name, $uri, $email);
     2284                $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
    25332285            }
    25342286        }
     
    25522304            if ($name !== null || $email !== null || $url !== null)
    25532305            {
    2554                 $contributors[] =& new $this->author_class($name, $url, $email);
     2306                $contributors[] = $this->registry->create('Author', array($name, $url, $email));
    25552307            }
    25562308        }
     
    25582310        if (!empty($contributors))
    25592311        {
    2560             return SimplePie_Misc::array_unique($contributors);
     2312            return array_unique($contributors);
    25612313        }
    25622314        else
     
    25662318    }
    25672319
    2568     function get_link($key = 0, $rel = 'alternate')
     2320    /**
     2321     * Get a single link for the feed
     2322     *
     2323     * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
     2324     * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
     2325     * @param string $rel The relationship of the link to return
     2326     * @return string|null Link URL
     2327     */
     2328    public function get_link($key = 0, $rel = 'alternate')
    25692329    {
    25702330        $links = $this->get_links($rel);
     
    25802340
    25812341    /**
    2582      * Added for parity between the parent-level and the item/entry-level.
    2583      */
    2584     function get_permalink()
     2342     * Get the permalink for the item
     2343     *
     2344     * Returns the first link available with a relationship of "alternate".
     2345     * Identical to {@see get_link()} with key 0
     2346     *
     2347     * @see get_link
     2348     * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
     2349     * @internal Added for parity between the parent-level and the item/entry-level.
     2350     * @return string|null Link URL
     2351     */
     2352    public function get_permalink()
    25852353    {
    25862354        return $this->get_link(0);
    25872355    }
    25882356
    2589     function get_links($rel = 'alternate')
     2357    /**
     2358     * Get all links for the feed
     2359     *
     2360     * Uses `<atom:link>` or `<link>`
     2361     *
     2362     * @since Beta 2
     2363     * @param string $rel The relationship of links to return
     2364     * @return array|null Links found for the feed (strings)
     2365     */
     2366    public function get_links($rel = 'alternate')
    25902367    {
    25912368        if (!isset($this->data['links']))
     
    26312408            foreach ($keys as $key)
    26322409            {
    2633                 if (SimplePie_Misc::is_isegment_nz_nc($key))
     2410                if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
    26342411                {
    26352412                    if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
     
    26612438    }
    26622439
    2663     function get_all_discovered_feeds()
     2440    public function get_all_discovered_feeds()
    26642441    {
    26652442        return $this->all_discovered_feeds;
    26662443    }
    26672444
    2668     function get_description()
     2445    /**
     2446     * Get the content for the item
     2447     *
     2448     * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
     2449     * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
     2450     *
     2451     * @since 1.0 (previously called `get_feed_description()` since 0.8)
     2452     * @return string|null
     2453     */
     2454    public function get_description()
    26692455    {
    26702456        if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
    26712457        {
    2672             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
     2458            return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
    26732459        }
    26742460        elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
    26752461        {
    2676             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
     2462            return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
    26772463        }
    26782464        elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
     
    27102496    }
    27112497
    2712     function get_copyright()
     2498    /**
     2499     * Get the copyright info for the feed
     2500     *
     2501     * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
     2502     *
     2503     * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
     2504     * @return string|null
     2505     */
     2506    public function get_copyright()
    27132507    {
    27142508        if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
    27152509        {
    2716             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
     2510            return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
    27172511        }
    27182512        elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
    27192513        {
    2720             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
     2514            return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
    27212515        }
    27222516        elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
     
    27382532    }
    27392533
    2740     function get_language()
     2534    /**
     2535     * Get the language for the feed
     2536     *
     2537     * Uses `<language>`, `<dc:language>`, or @xml_lang
     2538     *
     2539     * @since 1.0 (previously called `get_feed_language()` since 0.8)
     2540     * @return string|null
     2541     */
     2542    public function get_language()
    27412543    {
    27422544        if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
     
    27742576    }
    27752577
    2776     function get_latitude()
     2578    /**
     2579     * Get the latitude coordinates for the item
     2580     *
     2581     * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
     2582     *
     2583     * Uses `<geo:lat>` or `<georss:point>`
     2584     *
     2585     * @since 1.0
     2586     * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
     2587     * @link http://www.georss.org/ GeoRSS
     2588     * @return string|null
     2589     */
     2590    public function get_latitude()
    27772591    {
    27782592
     
    27912605    }
    27922606
    2793     function get_longitude()
     2607    /**
     2608     * Get the longitude coordinates for the feed
     2609     *
     2610     * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
     2611     *
     2612     * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
     2613     *
     2614     * @since 1.0
     2615     * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
     2616     * @link http://www.georss.org/ GeoRSS
     2617     * @return string|null
     2618     */
     2619    public function get_longitude()
    27942620    {
    27952621        if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
     
    28112637    }
    28122638
    2813     function get_image_title()
     2639    /**
     2640     * Get the feed logo's title
     2641     *
     2642     * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
     2643     *
     2644     * Uses `<image><title>` or `<image><dc:title>`
     2645     *
     2646     * @return string|null
     2647     */
     2648    public function get_image_title()
    28142649    {
    28152650        if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
     
    28392674    }
    28402675
    2841     function get_image_url()
     2676    /**
     2677     * Get the feed logo's URL
     2678     *
     2679     * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
     2680     * have a "feed logo" URL. This points directly to the image itself.
     2681     *
     2682     * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
     2683     * `<image><title>` or `<image><dc:title>`
     2684     *
     2685     * @return string|null
     2686     */
     2687    public function get_image_url()
    28422688    {
    28432689        if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
     
    28712717    }
    28722718
    2873     function get_image_link()
     2719
     2720    /**
     2721     * Get the feed logo's link
     2722     *
     2723     * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
     2724     * points to a human-readable page that the image should link to.
     2725     *
     2726     * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
     2727     * `<image><title>` or `<image><dc:title>`
     2728     *
     2729     * @return string|null
     2730     */
     2731    public function get_image_link()
    28742732    {
    28752733        if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
     
    28912749    }
    28922750
    2893     function get_image_width()
     2751    /**
     2752     * Get the feed logo's link
     2753     *
     2754     * RSS 2.0 feeds are allowed to have a "feed logo" width.
     2755     *
     2756     * Uses `<image><width>` or defaults to 88.0 if no width is specified and
     2757     * the feed is an RSS 2.0 feed.
     2758     *
     2759     * @return int|float|null
     2760     */
     2761    public function get_image_width()
    28942762    {
    28952763        if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
     
    29072775    }
    29082776
    2909     function get_image_height()
     2777    /**
     2778     * Get the feed logo's height
     2779     *
     2780     * RSS 2.0 feeds are allowed to have a "feed logo" height.
     2781     *
     2782     * Uses `<image><height>` or defaults to 31.0 if no height is specified and
     2783     * the feed is an RSS 2.0 feed.
     2784     *
     2785     * @return int|float|null
     2786     */
     2787    public function get_image_height()
    29102788    {
    29112789        if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
     
    29232801    }
    29242802
    2925     function get_item_quantity($max = 0)
     2803    /**
     2804     * Get the number of items in the feed
     2805     *
     2806     * This is well-suited for {@link http://php.net/for for()} loops with
     2807     * {@see get_item()}
     2808     *
     2809     * @param int $max Maximum value to return. 0 for no limit
     2810     * @return int Number of items in the feed
     2811     */
     2812    public function get_item_quantity($max = 0)
    29262813    {
    29272814        $max = (int) $max;
     
    29372824    }
    29382825
    2939     function get_item($key = 0)
     2826    /**
     2827     * Get a single item from the feed
     2828     *
     2829     * This is better suited for {@link http://php.net/for for()} loops, whereas
     2830     * {@see get_items()} is better suited for
     2831     * {@link http://php.net/foreach foreach()} loops.
     2832     *
     2833     * @see get_item_quantity()
     2834     * @since Beta 2
     2835     * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1
     2836     * @return SimplePie_Item|null
     2837     */
     2838    public function get_item($key = 0)
    29402839    {
    29412840        $items = $this->get_items();
     
    29502849    }
    29512850
    2952     function get_items($start = 0, $end = 0)
     2851    /**
     2852     * Get all items from the feed
     2853     *
     2854     * This is better suited for {@link http://php.net/for for()} loops, whereas
     2855     * {@see get_items()} is better suited for
     2856     * {@link http://php.net/foreach foreach()} loops.
     2857     *
     2858     * @see get_item_quantity
     2859     * @since Beta 2
     2860     * @param int $start Index to start at
     2861     * @param int $end Number of items to return. 0 for all items after `$start`
     2862     * @return array|null List of {@see SimplePie_Item} objects
     2863     */
     2864    public function get_items($start = 0, $end = 0)
    29532865    {
    29542866        if (!isset($this->data['items']))
     
    29662878                    foreach ($keys as $key)
    29672879                    {
    2968                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
     2880                        $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
    29692881                    }
    29702882                }
     
    29742886                    foreach ($keys as $key)
    29752887                    {
    2976                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
     2888                        $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
    29772889                    }
    29782890                }
     
    29822894                    foreach ($keys as $key)
    29832895                    {
    2984                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
     2896                        $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
    29852897                    }
    29862898                }
     
    29902902                    foreach ($keys as $key)
    29912903                    {
    2992                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
     2904                        $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
    29932905                    }
    29942906                }
     
    29982910                    foreach ($keys as $key)
    29992911                    {
    3000                         $this->data['items'][] =& new $this->item_class($this, $items[$key]);
     2912                        $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
    30012913                    }
    30022914                }
     
    30242936                    if ($do_sort)
    30252937                    {
    3026                         usort($this->data['ordered_items'], array(&$this, 'sort_items'));
     2938                        usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
    30272939                    }
    30282940                }
     
    30512963
    30522964    /**
    3053      * @static
    3054      */
    3055     function sort_items($a, $b)
     2965     * Sorting callback for items
     2966     *
     2967     * @access private
     2968     * @param SimplePie $a
     2969     * @param SimplePie $b
     2970     * @return boolean
     2971     */
     2972    public static function sort_items($a, $b)
    30562973    {
    30572974        return $a->get_date('U') <= $b->get_date('U');
     
    30592976
    30602977    /**
    3061      * @static
    3062      */
    3063     function merge_items($urls, $start = 0, $end = 0, $limit = 0)
     2978     * Merge items from several feeds into one
     2979     *
     2980     * If you're merging multiple feeds together, they need to all have dates
     2981     * for the items or else SimplePie will refuse to sort them.
     2982     *
     2983     * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
     2984     * @param array $urls List of SimplePie feed objects to merge
     2985     * @param int $start Starting item
     2986     * @param int $end Number of items to return
     2987     * @param int $limit Maximum number of items per feed
     2988     * @return array
     2989     */
     2990    public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
    30642991    {
    30652992        if (is_array($urls) && sizeof($urls) > 0)
     
    30682995            foreach ($urls as $arg)
    30692996            {
    3070                 if (is_a($arg, 'SimplePie'))
     2997                if ($arg instanceof SimplePie)
    30712998                {
    30722999                    $items = array_merge($items, $arg->get_items(0, $limit));
     
    30903017            if ($do_sort)
    30913018            {
    3092                 usort($items, array('SimplePie', 'sort_items'));
     3019                usort($items, array(get_class($urls[0]), 'sort_items'));
    30933020            }
    30943021
     
    31093036    }
    31103037}
    3111 
    3112 class SimplePie_Item
    3113 {
    3114     var $feed;
    3115     var $data = array();
    3116 
    3117     function SimplePie_Item($feed, $data)
    3118     {
    3119         $this->feed = $feed;
    3120         $this->data = $data;
    3121     }
    3122 
    3123     function __toString()
    3124     {
    3125         return md5(serialize($this->data));
    3126     }
    3127 
    3128     /**
    3129      * Remove items that link back to this before destroying this object
    3130      */
    3131     function __destruct()
    3132     {
    3133         if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
    3134         {
    3135             unset($this->feed);
    3136         }
    3137     }
    3138 
    3139     function get_item_tags($namespace, $tag)
    3140     {
    3141         if (isset($this->data['child'][$namespace][$tag]))
    3142         {
    3143             return $this->data['child'][$namespace][$tag];
    3144         }
    3145         else
    3146         {
    3147             return null;
    3148         }
    3149     }
    3150 
    3151     function get_base($element = array())
    3152     {
    3153         return $this->feed->get_base($element);
    3154     }
    3155 
    3156     function sanitize($data, $type, $base = '')
    3157     {
    3158         return $this->feed->sanitize($data, $type, $base);
    3159     }
    3160 
    3161     function get_feed()
    3162     {
    3163         return $this->feed;
    3164     }
    3165 
    3166     function get_id($hash = false)
    3167     {
    3168         if (!$hash)
    3169         {
    3170             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
    3171             {
    3172                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3173             }
    3174             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
    3175             {
    3176                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3177             }
    3178             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
    3179             {
    3180                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3181             }
    3182             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
    3183             {
    3184                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3185             }
    3186             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
    3187             {
    3188                 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3189             }
    3190             elseif (($return = $this->get_permalink()) !== null)
    3191             {
    3192                 return $return;
    3193             }
    3194             elseif (($return = $this->get_title()) !== null)
    3195             {
    3196                 return $return;
    3197             }
    3198         }
    3199         if ($this->get_permalink() !== null || $this->get_title() !== null)
    3200         {
    3201             return md5($this->get_permalink() . $this->get_title());
    3202         }
    3203         else
    3204         {
    3205             return md5(serialize($this->data));
    3206         }
    3207     }
    3208 
    3209     function get_title()
    3210     {
    3211         if (!isset($this->data['title']))
    3212         {
    3213             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
    3214             {
    3215                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3216             }
    3217             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
    3218             {
    3219                 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3220             }
    3221             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
    3222             {
    3223                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    3224             }
    3225             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
    3226             {
    3227                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    3228             }
    3229             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
    3230             {
    3231                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    3232             }
    3233             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
    3234             {
    3235                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3236             }
    3237             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
    3238             {
    3239                 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3240             }
    3241             else
    3242             {
    3243                 $this->data['title'] = null;
    3244             }
    3245         }
    3246         return $this->data['title'];
    3247     }
    3248 
    3249     function get_description($description_only = false)
    3250     {
    3251         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
    3252         {
    3253             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3254         }
    3255         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
    3256         {
    3257             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3258         }
    3259         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
    3260         {
    3261             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    3262         }
    3263         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
    3264         {
    3265             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
    3266         }
    3267         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
    3268         {
    3269             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3270         }
    3271         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
    3272         {
    3273             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3274         }
    3275         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
    3276         {
    3277             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
    3278         }
    3279         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
    3280         {
    3281             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3282         }
    3283         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
    3284         {
    3285             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
    3286         }
    3287 
    3288         elseif (!$description_only)
    3289         {
    3290             return $this->get_content(true);
    3291         }
    3292         else
    3293         {
    3294             return null;
    3295         }
    3296     }
    3297 
    3298     function get_content($content_only = false)
    3299     {
    3300         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
    3301         {
    3302             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3303         }
    3304         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
    3305         {
    3306             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3307         }
    3308         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
    3309         {
    3310             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
    3311         }
    3312         elseif (!$content_only)
    3313         {
    3314             return $this->get_description(true);
    3315         }
    3316         else
    3317         {
    3318             return null;
    3319         }
    3320     }
    3321 
    3322     function get_category($key = 0)
    3323     {
    3324         $categories = $this->get_categories();
    3325         if (isset($categories[$key]))
    3326         {
    3327             return $categories[$key];
    3328         }
    3329         else
    3330         {
    3331             return null;
    3332         }
    3333     }
    3334 
    3335     function get_categories()
    3336     {
    3337         $categories = array();
    3338 
    3339         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
    3340         {
    3341             $term = null;
    3342             $scheme = null;
    3343             $label = null;
    3344             if (isset($category['attribs']['']['term']))
    3345             {
    3346                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
    3347             }
    3348             if (isset($category['attribs']['']['scheme']))
    3349             {
    3350                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    3351             }
    3352             if (isset($category['attribs']['']['label']))
    3353             {
    3354                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    3355             }
    3356             $categories[] =& new $this->feed->category_class($term, $scheme, $label);
    3357         }
    3358         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
    3359         {
    3360             // This is really the label, but keep this as the term also for BC.
    3361             // Label will also work on retrieving because that falls back to term.
    3362             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3363             if (isset($category['attribs']['']['domain']))
    3364             {
    3365                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
    3366             }
    3367             else
    3368             {
    3369                 $scheme = null;
    3370             }
    3371             $categories[] =& new $this->feed->category_class($term, $scheme, null);
    3372         }
    3373         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
    3374         {
    3375             $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    3376         }
    3377         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
    3378         {
    3379             $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    3380         }
    3381 
    3382         if (!empty($categories))
    3383         {
    3384             return SimplePie_Misc::array_unique($categories);
    3385         }
    3386         else
    3387         {
    3388             return null;
    3389         }
    3390     }
    3391 
    3392     function get_author($key = 0)
    3393     {
    3394         $authors = $this->get_authors();
    3395         if (isset($authors[$key]))
    3396         {
    3397             return $authors[$key];
    3398         }
    3399         else
    3400         {
    3401             return null;
    3402         }
    3403     }
    3404 
    3405     function get_contributor($key = 0)
    3406     {
    3407         $contributors = $this->get_contributors();
    3408         if (isset($contributors[$key]))
    3409         {
    3410             return $contributors[$key];
    3411         }
    3412         else
    3413         {
    3414             return null;
    3415         }
    3416     }
    3417 
    3418     function get_contributors()
    3419     {
    3420         $contributors = array();
    3421         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
    3422         {
    3423             $name = null;
    3424             $uri = null;
    3425             $email = null;
    3426             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
    3427             {
    3428                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3429             }
    3430             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
    3431             {
    3432                 $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]));
    3433             }
    3434             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
    3435             {
    3436                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3437             }
    3438             if ($name !== null || $email !== null || $uri !== null)
    3439             {
    3440                 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
    3441             }
    3442         }
    3443         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
    3444         {
    3445             $name = null;
    3446             $url = null;
    3447             $email = null;
    3448             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
    3449             {
    3450                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3451             }
    3452             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
    3453             {
    3454                 $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]));
    3455             }
    3456             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
    3457             {
    3458                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3459             }
    3460             if ($name !== null || $email !== null || $url !== null)
    3461             {
    3462                 $contributors[] =& new $this->feed->author_class($name, $url, $email);
    3463             }
    3464         }
    3465 
    3466         if (!empty($contributors))
    3467         {
    3468             return SimplePie_Misc::array_unique($contributors);
    3469         }
    3470         else
    3471         {
    3472             return null;
    3473         }
    3474     }
    3475 
    3476     function get_authors()
    3477     {
    3478         $authors = array();
    3479         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
    3480         {
    3481             $name = null;
    3482             $uri = null;
    3483             $email = null;
    3484             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
    3485             {
    3486                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3487             }
    3488             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
    3489             {
    3490                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
    3491             }
    3492             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
    3493             {
    3494                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3495             }
    3496             if ($name !== null || $email !== null || $uri !== null)
    3497             {
    3498                 $authors[] =& new $this->feed->author_class($name, $uri, $email);
    3499             }
    3500         }
    3501         if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
    3502         {
    3503             $name = null;
    3504             $url = null;
    3505             $email = null;
    3506             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
    3507             {
    3508                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3509             }
    3510             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
    3511             {
    3512                 $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]));
    3513             }
    3514             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
    3515             {
    3516                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3517             }
    3518             if ($name !== null || $email !== null || $url !== null)
    3519             {
    3520                 $authors[] =& new $this->feed->author_class($name, $url, $email);
    3521             }
    3522         }
    3523         if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
    3524         {
    3525             $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    3526         }
    3527         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
    3528         {
    3529             $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    3530         }
    3531         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
    3532         {
    3533             $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    3534         }
    3535         foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
    3536         {
    3537             $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    3538         }
    3539 
    3540         if (!empty($authors))
    3541         {
    3542             return SimplePie_Misc::array_unique($authors);
    3543         }
    3544         elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
    3545         {
    3546             return $authors;
    3547         }
    3548         elseif ($authors = $this->feed->get_authors())
    3549         {
    3550             return $authors;
    3551         }
    3552         else
    3553         {
    3554             return null;
    3555         }
    3556     }
    3557 
    3558     function get_copyright()
    3559     {
    3560         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
    3561         {
    3562             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    3563         }
    3564         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
    3565         {
    3566             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3567         }
    3568         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
    3569         {
    3570             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3571         }
    3572         else
    3573         {
    3574             return null;
    3575         }
    3576     }
    3577 
    3578     function get_date($date_format = 'j F Y, g:i a')
    3579     {
    3580         if (!isset($this->data['date']))
    3581         {
    3582             if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
    3583             {
    3584                 $this->data['date']['raw'] = $return[0]['data'];
    3585             }
    3586             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
    3587             {
    3588                 $this->data['date']['raw'] = $return[0]['data'];
    3589             }
    3590             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
    3591             {
    3592                 $this->data['date']['raw'] = $return[0]['data'];
    3593             }
    3594             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
    3595             {
    3596                 $this->data['date']['raw'] = $return[0]['data'];
    3597             }
    3598             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
    3599             {
    3600                 $this->data['date']['raw'] = $return[0]['data'];
    3601             }
    3602             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
    3603             {
    3604                 $this->data['date']['raw'] = $return[0]['data'];
    3605             }
    3606             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
    3607             {
    3608                 $this->data['date']['raw'] = $return[0]['data'];
    3609             }
    3610             elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
    3611             {
    3612                 $this->data['date']['raw'] = $return[0]['data'];
    3613             }
    3614 
    3615             if (!empty($this->data['date']['raw']))
    3616             {
    3617                 $parser = SimplePie_Parse_Date::get();
    3618                 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
    3619             }
    3620             else
    3621             {
    3622                 $this->data['date'] = null;
    3623             }
    3624         }
    3625         if ($this->data['date'])
    3626         {
    3627             $date_format = (string) $date_format;
    3628             switch ($date_format)
    3629             {
    3630                 case '':
    3631                     return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
    3632 
    3633                 case 'U':
    3634                     return $this->data['date']['parsed'];
    3635 
    3636                 default:
    3637                     return date($date_format, $this->data['date']['parsed']);
    3638             }
    3639         }
    3640         else
    3641         {
    3642             return null;
    3643         }
    3644     }
    3645 
    3646     function get_local_date($date_format = '%c')
    3647     {
    3648         if (!$date_format)
    3649         {
    3650             return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
    3651         }
    3652         elseif (($date = $this->get_date('U')) !== null && $date !== false)
    3653         {
    3654             return strftime($date_format, $date);
    3655         }
    3656         else
    3657         {
    3658             return null;
    3659         }
    3660     }
    3661 
    3662     function get_permalink()
    3663     {
    3664         $link = $this->get_link();
    3665         $enclosure = $this->get_enclosure(0);
    3666         if ($link !== null)
    3667         {
    3668             return $link;
    3669         }
    3670         elseif ($enclosure !== null)
    3671         {
    3672             return $enclosure->get_link();
    3673         }
    3674         else
    3675         {
    3676             return null;
    3677         }
    3678     }
    3679 
    3680     function get_link($key = 0, $rel = 'alternate')
    3681     {
    3682         $links = $this->get_links($rel);
    3683         if ($links[$key] !== null)
    3684         {
    3685             return $links[$key];
    3686         }
    3687         else
    3688         {
    3689             return null;
    3690         }
    3691     }
    3692 
    3693     function get_links($rel = 'alternate')
    3694     {
    3695         if (!isset($this->data['links']))
    3696         {
    3697             $this->data['links'] = array();
    3698             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
    3699             {
    3700                 if (isset($link['attribs']['']['href']))
    3701                 {
    3702                     $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
    3703                     $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
    3704 
    3705                 }
    3706             }
    3707             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
    3708             {
    3709                 if (isset($link['attribs']['']['href']))
    3710                 {
    3711                     $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
    3712                     $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
    3713                 }
    3714             }
    3715             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
    3716             {
    3717                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    3718             }
    3719             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
    3720             {
    3721                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    3722             }
    3723             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
    3724             {
    3725                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    3726             }
    3727             if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
    3728             {
    3729                 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
    3730                 {
    3731                     $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    3732                 }
    3733             }
    3734 
    3735             $keys = array_keys($this->data['links']);
    3736             foreach ($keys as $key)
    3737             {
    3738                 if (SimplePie_Misc::is_isegment_nz_nc($key))
    3739                 {
    3740                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
    3741                     {
    3742                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
    3743                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
    3744                     }
    3745                     else
    3746                     {
    3747                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
    3748                     }
    3749                 }
    3750                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
    3751                 {
    3752                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
    3753                 }
    3754                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
    3755             }
    3756         }
    3757         if (isset($this->data['links'][$rel]))
    3758         {
    3759             return $this->data['links'][$rel];
    3760         }
    3761         else
    3762         {
    3763             return null;
    3764         }
    3765     }
    3766 
    3767     /**
    3768      * @todo Add ability to prefer one type of content over another (in a media group).
    3769      */
    3770     function get_enclosure($key = 0, $prefer = null)
    3771     {
    3772         $enclosures = $this->get_enclosures();
    3773         if (isset($enclosures[$key]))
    3774         {
    3775             return $enclosures[$key];
    3776         }
    3777         else
    3778         {
    3779             return null;
    3780         }
    3781     }
    3782 
    3783     /**
    3784      * Grabs all available enclosures (podcasts, etc.)
    3785      *
    3786      * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
    3787      *
    3788      * 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.
    3789      *
    3790      * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
    3791      * @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).
    3792      */
    3793     function get_enclosures()
    3794     {
    3795         if (!isset($this->data['enclosures']))
    3796         {
    3797             $this->data['enclosures'] = array();
    3798 
    3799             // Elements
    3800             $captions_parent = null;
    3801             $categories_parent = null;
    3802             $copyrights_parent = null;
    3803             $credits_parent = null;
    3804             $description_parent = null;
    3805             $duration_parent = null;
    3806             $hashes_parent = null;
    3807             $keywords_parent = null;
    3808             $player_parent = null;
    3809             $ratings_parent = null;
    3810             $restrictions_parent = null;
    3811             $thumbnails_parent = null;
    3812             $title_parent = null;
    3813 
    3814             // Let's do the channel and item-level ones first, and just re-use them if we need to.
    3815             $parent = $this->get_feed();
    3816 
    3817             // CAPTIONS
    3818             if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
    3819             {
    3820                 foreach ($captions as $caption)
    3821                 {
    3822                     $caption_type = null;
    3823                     $caption_lang = null;
    3824                     $caption_startTime = null;
    3825                     $caption_endTime = null;
    3826                     $caption_text = null;
    3827                     if (isset($caption['attribs']['']['type']))
    3828                     {
    3829                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    3830                     }
    3831                     if (isset($caption['attribs']['']['lang']))
    3832                     {
    3833                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    3834                     }
    3835                     if (isset($caption['attribs']['']['start']))
    3836                     {
    3837                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
    3838                     }
    3839                     if (isset($caption['attribs']['']['end']))
    3840                     {
    3841                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
    3842                     }
    3843                     if (isset($caption['data']))
    3844                     {
    3845                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3846                     }
    3847                     $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
    3848                 }
    3849             }
    3850             elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
    3851             {
    3852                 foreach ($captions as $caption)
    3853                 {
    3854                     $caption_type = null;
    3855                     $caption_lang = null;
    3856                     $caption_startTime = null;
    3857                     $caption_endTime = null;
    3858                     $caption_text = null;
    3859                     if (isset($caption['attribs']['']['type']))
    3860                     {
    3861                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    3862                     }
    3863                     if (isset($caption['attribs']['']['lang']))
    3864                     {
    3865                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    3866                     }
    3867                     if (isset($caption['attribs']['']['start']))
    3868                     {
    3869                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
    3870                     }
    3871                     if (isset($caption['attribs']['']['end']))
    3872                     {
    3873                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
    3874                     }
    3875                     if (isset($caption['data']))
    3876                     {
    3877                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3878                     }
    3879                     $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
    3880                 }
    3881             }
    3882             if (is_array($captions_parent))
    3883             {
    3884                 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
    3885             }
    3886 
    3887             // CATEGORIES
    3888             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
    3889             {
    3890                 $term = null;
    3891                 $scheme = null;
    3892                 $label = null;
    3893                 if (isset($category['data']))
    3894                 {
    3895                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3896                 }
    3897                 if (isset($category['attribs']['']['scheme']))
    3898                 {
    3899                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    3900                 }
    3901                 else
    3902                 {
    3903                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
    3904                 }
    3905                 if (isset($category['attribs']['']['label']))
    3906                 {
    3907                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    3908                 }
    3909                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
    3910             }
    3911             foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
    3912             {
    3913                 $term = null;
    3914                 $scheme = null;
    3915                 $label = null;
    3916                 if (isset($category['data']))
    3917                 {
    3918                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3919                 }
    3920                 if (isset($category['attribs']['']['scheme']))
    3921                 {
    3922                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    3923                 }
    3924                 else
    3925                 {
    3926                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
    3927                 }
    3928                 if (isset($category['attribs']['']['label']))
    3929                 {
    3930                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    3931                 }
    3932                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
    3933             }
    3934             foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
    3935             {
    3936                 $term = null;
    3937                 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
    3938                 $label = null;
    3939                 if (isset($category['attribs']['']['text']))
    3940                 {
    3941                     $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
    3942                 }
    3943                 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
    3944 
    3945                 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
    3946                 {
    3947                     foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
    3948                     {
    3949                         if (isset($subcategory['attribs']['']['text']))
    3950                         {
    3951                             $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
    3952                         }
    3953                         $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
    3954                     }
    3955                 }
    3956             }
    3957             if (is_array($categories_parent))
    3958             {
    3959                 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
    3960             }
    3961 
    3962             // COPYRIGHT
    3963             if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
    3964             {
    3965                 $copyright_url = null;
    3966                 $copyright_label = null;
    3967                 if (isset($copyright[0]['attribs']['']['url']))
    3968                 {
    3969                     $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
    3970                 }
    3971                 if (isset($copyright[0]['data']))
    3972                 {
    3973                     $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3974                 }
    3975                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
    3976             }
    3977             elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
    3978             {
    3979                 $copyright_url = null;
    3980                 $copyright_label = null;
    3981                 if (isset($copyright[0]['attribs']['']['url']))
    3982                 {
    3983                     $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
    3984                 }
    3985                 if (isset($copyright[0]['data']))
    3986                 {
    3987                     $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    3988                 }
    3989                 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
    3990             }
    3991 
    3992             // CREDITS
    3993             if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
    3994             {
    3995                 foreach ($credits as $credit)
    3996                 {
    3997                     $credit_role = null;
    3998                     $credit_scheme = null;
    3999                     $credit_name = null;
    4000                     if (isset($credit['attribs']['']['role']))
    4001                     {
    4002                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
    4003                     }
    4004                     if (isset($credit['attribs']['']['scheme']))
    4005                     {
    4006                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4007                     }
    4008                     else
    4009                     {
    4010                         $credit_scheme = 'urn:ebu';
    4011                     }
    4012                     if (isset($credit['data']))
    4013                     {
    4014                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4015                     }
    4016                     $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
    4017                 }
    4018             }
    4019             elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
    4020             {
    4021                 foreach ($credits as $credit)
    4022                 {
    4023                     $credit_role = null;
    4024                     $credit_scheme = null;
    4025                     $credit_name = null;
    4026                     if (isset($credit['attribs']['']['role']))
    4027                     {
    4028                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
    4029                     }
    4030                     if (isset($credit['attribs']['']['scheme']))
    4031                     {
    4032                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4033                     }
    4034                     else
    4035                     {
    4036                         $credit_scheme = 'urn:ebu';
    4037                     }
    4038                     if (isset($credit['data']))
    4039                     {
    4040                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4041                     }
    4042                     $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
    4043                 }
    4044             }
    4045             if (is_array($credits_parent))
    4046             {
    4047                 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
    4048             }
    4049 
    4050             // DESCRIPTION
    4051             if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
    4052             {
    4053                 if (isset($description_parent[0]['data']))
    4054                 {
    4055                     $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4056                 }
    4057             }
    4058             elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
    4059             {
    4060                 if (isset($description_parent[0]['data']))
    4061                 {
    4062                     $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4063                 }
    4064             }
    4065 
    4066             // DURATION
    4067             if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
    4068             {
    4069                 $seconds = null;
    4070                 $minutes = null;
    4071                 $hours = null;
    4072                 if (isset($duration_parent[0]['data']))
    4073                 {
    4074                     $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4075                     if (sizeof($temp) > 0)
    4076                     {
    4077                         $seconds = (int) array_pop($temp);
    4078                     }
    4079                     if (sizeof($temp) > 0)
    4080                     {
    4081                         $minutes = (int) array_pop($temp);
    4082                         $seconds += $minutes * 60;
    4083                     }
    4084                     if (sizeof($temp) > 0)
    4085                     {
    4086                         $hours = (int) array_pop($temp);
    4087                         $seconds += $hours * 3600;
    4088                     }
    4089                     unset($temp);
    4090                     $duration_parent = $seconds;
    4091                 }
    4092             }
    4093 
    4094             // HASHES
    4095             if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
    4096             {
    4097                 foreach ($hashes_iterator as $hash)
    4098                 {
    4099                     $value = null;
    4100                     $algo = null;
    4101                     if (isset($hash['data']))
    4102                     {
    4103                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4104                     }
    4105                     if (isset($hash['attribs']['']['algo']))
    4106                     {
    4107                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
    4108                     }
    4109                     else
    4110                     {
    4111                         $algo = 'md5';
    4112                     }
    4113                     $hashes_parent[] = $algo.':'.$value;
    4114                 }
    4115             }
    4116             elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
    4117             {
    4118                 foreach ($hashes_iterator as $hash)
    4119                 {
    4120                     $value = null;
    4121                     $algo = null;
    4122                     if (isset($hash['data']))
    4123                     {
    4124                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4125                     }
    4126                     if (isset($hash['attribs']['']['algo']))
    4127                     {
    4128                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
    4129                     }
    4130                     else
    4131                     {
    4132                         $algo = 'md5';
    4133                     }
    4134                     $hashes_parent[] = $algo.':'.$value;
    4135                 }
    4136             }
    4137             if (is_array($hashes_parent))
    4138             {
    4139                 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
    4140             }
    4141 
    4142             // KEYWORDS
    4143             if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
    4144             {
    4145                 if (isset($keywords[0]['data']))
    4146                 {
    4147                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4148                     foreach ($temp as $word)
    4149                     {
    4150                         $keywords_parent[] = trim($word);
    4151                     }
    4152                 }
    4153                 unset($temp);
    4154             }
    4155             elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
    4156             {
    4157                 if (isset($keywords[0]['data']))
    4158                 {
    4159                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4160                     foreach ($temp as $word)
    4161                     {
    4162                         $keywords_parent[] = trim($word);
    4163                     }
    4164                 }
    4165                 unset($temp);
    4166             }
    4167             elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
    4168             {
    4169                 if (isset($keywords[0]['data']))
    4170                 {
    4171                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4172                     foreach ($temp as $word)
    4173                     {
    4174                         $keywords_parent[] = trim($word);
    4175                     }
    4176                 }
    4177                 unset($temp);
    4178             }
    4179             elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
    4180             {
    4181                 if (isset($keywords[0]['data']))
    4182                 {
    4183                     $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4184                     foreach ($temp as $word)
    4185                     {
    4186                         $keywords_parent[] = trim($word);
    4187                     }
    4188                 }
    4189                 unset($temp);
    4190             }
    4191             if (is_array($keywords_parent))
    4192             {
    4193                 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
    4194             }
    4195 
    4196             // PLAYER
    4197             if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
    4198             {
    4199                 if (isset($player_parent[0]['attribs']['']['url']))
    4200                 {
    4201                     $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4202                 }
    4203             }
    4204             elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
    4205             {
    4206                 if (isset($player_parent[0]['attribs']['']['url']))
    4207                 {
    4208                     $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4209                 }
    4210             }
    4211 
    4212             // RATINGS
    4213             if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
    4214             {
    4215                 foreach ($ratings as $rating)
    4216                 {
    4217                     $rating_scheme = null;
    4218                     $rating_value = null;
    4219                     if (isset($rating['attribs']['']['scheme']))
    4220                     {
    4221                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4222                     }
    4223                     else
    4224                     {
    4225                         $rating_scheme = 'urn:simple';
    4226                     }
    4227                     if (isset($rating['data']))
    4228                     {
    4229                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4230                     }
    4231                     $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    4232                 }
    4233             }
    4234             elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
    4235             {
    4236                 foreach ($ratings as $rating)
    4237                 {
    4238                     $rating_scheme = 'urn:itunes';
    4239                     $rating_value = null;
    4240                     if (isset($rating['data']))
    4241                     {
    4242                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4243                     }
    4244                     $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    4245                 }
    4246             }
    4247             elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
    4248             {
    4249                 foreach ($ratings as $rating)
    4250                 {
    4251                     $rating_scheme = null;
    4252                     $rating_value = null;
    4253                     if (isset($rating['attribs']['']['scheme']))
    4254                     {
    4255                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4256                     }
    4257                     else
    4258                     {
    4259                         $rating_scheme = 'urn:simple';
    4260                     }
    4261                     if (isset($rating['data']))
    4262                     {
    4263                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4264                     }
    4265                     $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    4266                 }
    4267             }
    4268             elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
    4269             {
    4270                 foreach ($ratings as $rating)
    4271                 {
    4272                     $rating_scheme = 'urn:itunes';
    4273                     $rating_value = null;
    4274                     if (isset($rating['data']))
    4275                     {
    4276                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4277                     }
    4278                     $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    4279                 }
    4280             }
    4281             if (is_array($ratings_parent))
    4282             {
    4283                 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
    4284             }
    4285 
    4286             // RESTRICTIONS
    4287             if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
    4288             {
    4289                 foreach ($restrictions as $restriction)
    4290                 {
    4291                     $restriction_relationship = null;
    4292                     $restriction_type = null;
    4293                     $restriction_value = null;
    4294                     if (isset($restriction['attribs']['']['relationship']))
    4295                     {
    4296                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
    4297                     }
    4298                     if (isset($restriction['attribs']['']['type']))
    4299                     {
    4300                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4301                     }
    4302                     if (isset($restriction['data']))
    4303                     {
    4304                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4305                     }
    4306                     $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    4307                 }
    4308             }
    4309             elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
    4310             {
    4311                 foreach ($restrictions as $restriction)
    4312                 {
    4313                     $restriction_relationship = 'allow';
    4314                     $restriction_type = null;
    4315                     $restriction_value = 'itunes';
    4316                     if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
    4317                     {
    4318                         $restriction_relationship = 'deny';
    4319                     }
    4320                     $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    4321                 }
    4322             }
    4323             elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
    4324             {
    4325                 foreach ($restrictions as $restriction)
    4326                 {
    4327                     $restriction_relationship = null;
    4328                     $restriction_type = null;
    4329                     $restriction_value = null;
    4330                     if (isset($restriction['attribs']['']['relationship']))
    4331                     {
    4332                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
    4333                     }
    4334                     if (isset($restriction['attribs']['']['type']))
    4335                     {
    4336                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4337                     }
    4338                     if (isset($restriction['data']))
    4339                     {
    4340                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4341                     }
    4342                     $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    4343                 }
    4344             }
    4345             elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
    4346             {
    4347                 foreach ($restrictions as $restriction)
    4348                 {
    4349                     $restriction_relationship = 'allow';
    4350                     $restriction_type = null;
    4351                     $restriction_value = 'itunes';
    4352                     if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
    4353                     {
    4354                         $restriction_relationship = 'deny';
    4355                     }
    4356                     $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    4357                 }
    4358             }
    4359             if (is_array($restrictions_parent))
    4360             {
    4361                 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
    4362             }
    4363 
    4364             // THUMBNAILS
    4365             if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
    4366             {
    4367                 foreach ($thumbnails as $thumbnail)
    4368                 {
    4369                     if (isset($thumbnail['attribs']['']['url']))
    4370                     {
    4371                         $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4372                     }
    4373                 }
    4374             }
    4375             elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
    4376             {
    4377                 foreach ($thumbnails as $thumbnail)
    4378                 {
    4379                     if (isset($thumbnail['attribs']['']['url']))
    4380                     {
    4381                         $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4382                     }
    4383                 }
    4384             }
    4385 
    4386             // TITLES
    4387             if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
    4388             {
    4389                 if (isset($title_parent[0]['data']))
    4390                 {
    4391                     $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4392                 }
    4393             }
    4394             elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
    4395             {
    4396                 if (isset($title_parent[0]['data']))
    4397                 {
    4398                     $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4399                 }
    4400             }
    4401 
    4402             // Clear the memory
    4403             unset($parent);
    4404 
    4405             // Attributes
    4406             $bitrate = null;
    4407             $channels = null;
    4408             $duration = null;
    4409             $expression = null;
    4410             $framerate = null;
    4411             $height = null;
    4412             $javascript = null;
    4413             $lang = null;
    4414             $length = null;
    4415             $medium = null;
    4416             $samplingrate = null;
    4417             $type = null;
    4418             $url = null;
    4419             $width = null;
    4420 
    4421             // Elements
    4422             $captions = null;
    4423             $categories = null;
    4424             $copyrights = null;
    4425             $credits = null;
    4426             $description = null;
    4427             $hashes = null;
    4428             $keywords = null;
    4429             $player = null;
    4430             $ratings = null;
    4431             $restrictions = null;
    4432             $thumbnails = null;
    4433             $title = null;
    4434 
    4435             // If we have media:group tags, loop through them.
    4436             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
    4437             {
    4438                 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
    4439                 {
    4440                     // If we have media:content tags, loop through them.
    4441                     foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
    4442                     {
    4443                         if (isset($content['attribs']['']['url']))
    4444                         {
    4445                             // Attributes
    4446                             $bitrate = null;
    4447                             $channels = null;
    4448                             $duration = null;
    4449                             $expression = null;
    4450                             $framerate = null;
    4451                             $height = null;
    4452                             $javascript = null;
    4453                             $lang = null;
    4454                             $length = null;
    4455                             $medium = null;
    4456                             $samplingrate = null;
    4457                             $type = null;
    4458                             $url = null;
    4459                             $width = null;
    4460 
    4461                             // Elements
    4462                             $captions = null;
    4463                             $categories = null;
    4464                             $copyrights = null;
    4465                             $credits = null;
    4466                             $description = null;
    4467                             $hashes = null;
    4468                             $keywords = null;
    4469                             $player = null;
    4470                             $ratings = null;
    4471                             $restrictions = null;
    4472                             $thumbnails = null;
    4473                             $title = null;
    4474 
    4475                             // Start checking the attributes of media:content
    4476                             if (isset($content['attribs']['']['bitrate']))
    4477                             {
    4478                                 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
    4479                             }
    4480                             if (isset($content['attribs']['']['channels']))
    4481                             {
    4482                                 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
    4483                             }
    4484                             if (isset($content['attribs']['']['duration']))
    4485                             {
    4486                                 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
    4487                             }
    4488                             else
    4489                             {
    4490                                 $duration = $duration_parent;
    4491                             }
    4492                             if (isset($content['attribs']['']['expression']))
    4493                             {
    4494                                 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
    4495                             }
    4496                             if (isset($content['attribs']['']['framerate']))
    4497                             {
    4498                                 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
    4499                             }
    4500                             if (isset($content['attribs']['']['height']))
    4501                             {
    4502                                 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
    4503                             }
    4504                             if (isset($content['attribs']['']['lang']))
    4505                             {
    4506                                 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    4507                             }
    4508                             if (isset($content['attribs']['']['fileSize']))
    4509                             {
    4510                                 $length = ceil($content['attribs']['']['fileSize']);
    4511                             }
    4512                             if (isset($content['attribs']['']['medium']))
    4513                             {
    4514                                 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
    4515                             }
    4516                             if (isset($content['attribs']['']['samplingrate']))
    4517                             {
    4518                                 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
    4519                             }
    4520                             if (isset($content['attribs']['']['type']))
    4521                             {
    4522                                 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4523                             }
    4524                             if (isset($content['attribs']['']['width']))
    4525                             {
    4526                                 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
    4527                             }
    4528                             $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4529 
    4530                             // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
    4531 
    4532                             // CAPTIONS
    4533                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
    4534                             {
    4535                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
    4536                                 {
    4537                                     $caption_type = null;
    4538                                     $caption_lang = null;
    4539                                     $caption_startTime = null;
    4540                                     $caption_endTime = null;
    4541                                     $caption_text = null;
    4542                                     if (isset($caption['attribs']['']['type']))
    4543                                     {
    4544                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4545                                     }
    4546                                     if (isset($caption['attribs']['']['lang']))
    4547                                     {
    4548                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    4549                                     }
    4550                                     if (isset($caption['attribs']['']['start']))
    4551                                     {
    4552                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
    4553                                     }
    4554                                     if (isset($caption['attribs']['']['end']))
    4555                                     {
    4556                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
    4557                                     }
    4558                                     if (isset($caption['data']))
    4559                                     {
    4560                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4561                                     }
    4562                                     $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
    4563                                 }
    4564                                 if (is_array($captions))
    4565                                 {
    4566                                     $captions = array_values(SimplePie_Misc::array_unique($captions));
    4567                                 }
    4568                             }
    4569                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
    4570                             {
    4571                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
    4572                                 {
    4573                                     $caption_type = null;
    4574                                     $caption_lang = null;
    4575                                     $caption_startTime = null;
    4576                                     $caption_endTime = null;
    4577                                     $caption_text = null;
    4578                                     if (isset($caption['attribs']['']['type']))
    4579                                     {
    4580                                         $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4581                                     }
    4582                                     if (isset($caption['attribs']['']['lang']))
    4583                                     {
    4584                                         $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    4585                                     }
    4586                                     if (isset($caption['attribs']['']['start']))
    4587                                     {
    4588                                         $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
    4589                                     }
    4590                                     if (isset($caption['attribs']['']['end']))
    4591                                     {
    4592                                         $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
    4593                                     }
    4594                                     if (isset($caption['data']))
    4595                                     {
    4596                                         $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4597                                     }
    4598                                     $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
    4599                                 }
    4600                                 if (is_array($captions))
    4601                                 {
    4602                                     $captions = array_values(SimplePie_Misc::array_unique($captions));
    4603                                 }
    4604                             }
    4605                             else
    4606                             {
    4607                                 $captions = $captions_parent;
    4608                             }
    4609 
    4610                             // CATEGORIES
    4611                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
    4612                             {
    4613                                 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
    4614                                 {
    4615                                     $term = null;
    4616                                     $scheme = null;
    4617                                     $label = null;
    4618                                     if (isset($category['data']))
    4619                                     {
    4620                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4621                                     }
    4622                                     if (isset($category['attribs']['']['scheme']))
    4623                                     {
    4624                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4625                                     }
    4626                                     else
    4627                                     {
    4628                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
    4629                                     }
    4630                                     if (isset($category['attribs']['']['label']))
    4631                                     {
    4632                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    4633                                     }
    4634                                     $categories[] =& new $this->feed->category_class($term, $scheme, $label);
    4635                                 }
    4636                             }
    4637                             if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
    4638                             {
    4639                                 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
    4640                                 {
    4641                                     $term = null;
    4642                                     $scheme = null;
    4643                                     $label = null;
    4644                                     if (isset($category['data']))
    4645                                     {
    4646                                         $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4647                                     }
    4648                                     if (isset($category['attribs']['']['scheme']))
    4649                                     {
    4650                                         $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4651                                     }
    4652                                     else
    4653                                     {
    4654                                         $scheme = 'http://search.yahoo.com/mrss/category_schema';
    4655                                     }
    4656                                     if (isset($category['attribs']['']['label']))
    4657                                     {
    4658                                         $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    4659                                     }
    4660                                     $categories[] =& new $this->feed->category_class($term, $scheme, $label);
    4661                                 }
    4662                             }
    4663                             if (is_array($categories) && is_array($categories_parent))
    4664                             {
    4665                                 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
    4666                             }
    4667                             elseif (is_array($categories))
    4668                             {
    4669                                 $categories = array_values(SimplePie_Misc::array_unique($categories));
    4670                             }
    4671                             elseif (is_array($categories_parent))
    4672                             {
    4673                                 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
    4674                             }
    4675 
    4676                             // COPYRIGHTS
    4677                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
    4678                             {
    4679                                 $copyright_url = null;
    4680                                 $copyright_label = null;
    4681                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
    4682                                 {
    4683                                     $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
    4684                                 }
    4685                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
    4686                                 {
    4687                                     $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4688                                 }
    4689                                 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
    4690                             }
    4691                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
    4692                             {
    4693                                 $copyright_url = null;
    4694                                 $copyright_label = null;
    4695                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
    4696                                 {
    4697                                     $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
    4698                                 }
    4699                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
    4700                                 {
    4701                                     $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4702                                 }
    4703                                 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
    4704                             }
    4705                             else
    4706                             {
    4707                                 $copyrights = $copyrights_parent;
    4708                             }
    4709 
    4710                             // CREDITS
    4711                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
    4712                             {
    4713                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
    4714                                 {
    4715                                     $credit_role = null;
    4716                                     $credit_scheme = null;
    4717                                     $credit_name = null;
    4718                                     if (isset($credit['attribs']['']['role']))
    4719                                     {
    4720                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
    4721                                     }
    4722                                     if (isset($credit['attribs']['']['scheme']))
    4723                                     {
    4724                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4725                                     }
    4726                                     else
    4727                                     {
    4728                                         $credit_scheme = 'urn:ebu';
    4729                                     }
    4730                                     if (isset($credit['data']))
    4731                                     {
    4732                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4733                                     }
    4734                                     $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
    4735                                 }
    4736                                 if (is_array($credits))
    4737                                 {
    4738                                     $credits = array_values(SimplePie_Misc::array_unique($credits));
    4739                                 }
    4740                             }
    4741                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
    4742                             {
    4743                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
    4744                                 {
    4745                                     $credit_role = null;
    4746                                     $credit_scheme = null;
    4747                                     $credit_name = null;
    4748                                     if (isset($credit['attribs']['']['role']))
    4749                                     {
    4750                                         $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
    4751                                     }
    4752                                     if (isset($credit['attribs']['']['scheme']))
    4753                                     {
    4754                                         $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4755                                     }
    4756                                     else
    4757                                     {
    4758                                         $credit_scheme = 'urn:ebu';
    4759                                     }
    4760                                     if (isset($credit['data']))
    4761                                     {
    4762                                         $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4763                                     }
    4764                                     $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
    4765                                 }
    4766                                 if (is_array($credits))
    4767                                 {
    4768                                     $credits = array_values(SimplePie_Misc::array_unique($credits));
    4769                                 }
    4770                             }
    4771                             else
    4772                             {
    4773                                 $credits = $credits_parent;
    4774                             }
    4775 
    4776                             // DESCRIPTION
    4777                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
    4778                             {
    4779                                 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4780                             }
    4781                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
    4782                             {
    4783                                 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4784                             }
    4785                             else
    4786                             {
    4787                                 $description = $description_parent;
    4788                             }
    4789 
    4790                             // HASHES
    4791                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
    4792                             {
    4793                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
    4794                                 {
    4795                                     $value = null;
    4796                                     $algo = null;
    4797                                     if (isset($hash['data']))
    4798                                     {
    4799                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4800                                     }
    4801                                     if (isset($hash['attribs']['']['algo']))
    4802                                     {
    4803                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
    4804                                     }
    4805                                     else
    4806                                     {
    4807                                         $algo = 'md5';
    4808                                     }
    4809                                     $hashes[] = $algo.':'.$value;
    4810                                 }
    4811                                 if (is_array($hashes))
    4812                                 {
    4813                                     $hashes = array_values(SimplePie_Misc::array_unique($hashes));
    4814                                 }
    4815                             }
    4816                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
    4817                             {
    4818                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
    4819                                 {
    4820                                     $value = null;
    4821                                     $algo = null;
    4822                                     if (isset($hash['data']))
    4823                                     {
    4824                                         $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4825                                     }
    4826                                     if (isset($hash['attribs']['']['algo']))
    4827                                     {
    4828                                         $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
    4829                                     }
    4830                                     else
    4831                                     {
    4832                                         $algo = 'md5';
    4833                                     }
    4834                                     $hashes[] = $algo.':'.$value;
    4835                                 }
    4836                                 if (is_array($hashes))
    4837                                 {
    4838                                     $hashes = array_values(SimplePie_Misc::array_unique($hashes));
    4839                                 }
    4840                             }
    4841                             else
    4842                             {
    4843                                 $hashes = $hashes_parent;
    4844                             }
    4845 
    4846                             // KEYWORDS
    4847                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
    4848                             {
    4849                                 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
    4850                                 {
    4851                                     $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4852                                     foreach ($temp as $word)
    4853                                     {
    4854                                         $keywords[] = trim($word);
    4855                                     }
    4856                                     unset($temp);
    4857                                 }
    4858                                 if (is_array($keywords))
    4859                                 {
    4860                                     $keywords = array_values(SimplePie_Misc::array_unique($keywords));
    4861                                 }
    4862                             }
    4863                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
    4864                             {
    4865                                 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
    4866                                 {
    4867                                     $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    4868                                     foreach ($temp as $word)
    4869                                     {
    4870                                         $keywords[] = trim($word);
    4871                                     }
    4872                                     unset($temp);
    4873                                 }
    4874                                 if (is_array($keywords))
    4875                                 {
    4876                                     $keywords = array_values(SimplePie_Misc::array_unique($keywords));
    4877                                 }
    4878                             }
    4879                             else
    4880                             {
    4881                                 $keywords = $keywords_parent;
    4882                             }
    4883 
    4884                             // PLAYER
    4885                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
    4886                             {
    4887                                 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4888                             }
    4889                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
    4890                             {
    4891                                 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    4892                             }
    4893                             else
    4894                             {
    4895                                 $player = $player_parent;
    4896                             }
    4897 
    4898                             // RATINGS
    4899                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
    4900                             {
    4901                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
    4902                                 {
    4903                                     $rating_scheme = null;
    4904                                     $rating_value = null;
    4905                                     if (isset($rating['attribs']['']['scheme']))
    4906                                     {
    4907                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4908                                     }
    4909                                     else
    4910                                     {
    4911                                         $rating_scheme = 'urn:simple';
    4912                                     }
    4913                                     if (isset($rating['data']))
    4914                                     {
    4915                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4916                                     }
    4917                                     $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    4918                                 }
    4919                                 if (is_array($ratings))
    4920                                 {
    4921                                     $ratings = array_values(SimplePie_Misc::array_unique($ratings));
    4922                                 }
    4923                             }
    4924                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
    4925                             {
    4926                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
    4927                                 {
    4928                                     $rating_scheme = null;
    4929                                     $rating_value = null;
    4930                                     if (isset($rating['attribs']['']['scheme']))
    4931                                     {
    4932                                         $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    4933                                     }
    4934                                     else
    4935                                     {
    4936                                         $rating_scheme = 'urn:simple';
    4937                                     }
    4938                                     if (isset($rating['data']))
    4939                                     {
    4940                                         $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4941                                     }
    4942                                     $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    4943                                 }
    4944                                 if (is_array($ratings))
    4945                                 {
    4946                                     $ratings = array_values(SimplePie_Misc::array_unique($ratings));
    4947                                 }
    4948                             }
    4949                             else
    4950                             {
    4951                                 $ratings = $ratings_parent;
    4952                             }
    4953 
    4954                             // RESTRICTIONS
    4955                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
    4956                             {
    4957                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
    4958                                 {
    4959                                     $restriction_relationship = null;
    4960                                     $restriction_type = null;
    4961                                     $restriction_value = null;
    4962                                     if (isset($restriction['attribs']['']['relationship']))
    4963                                     {
    4964                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
    4965                                     }
    4966                                     if (isset($restriction['attribs']['']['type']))
    4967                                     {
    4968                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4969                                     }
    4970                                     if (isset($restriction['data']))
    4971                                     {
    4972                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4973                                     }
    4974                                     $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    4975                                 }
    4976                                 if (is_array($restrictions))
    4977                                 {
    4978                                     $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
    4979                                 }
    4980                             }
    4981                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
    4982                             {
    4983                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
    4984                                 {
    4985                                     $restriction_relationship = null;
    4986                                     $restriction_type = null;
    4987                                     $restriction_value = null;
    4988                                     if (isset($restriction['attribs']['']['relationship']))
    4989                                     {
    4990                                         $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
    4991                                     }
    4992                                     if (isset($restriction['attribs']['']['type']))
    4993                                     {
    4994                                         $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    4995                                     }
    4996                                     if (isset($restriction['data']))
    4997                                     {
    4998                                         $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    4999                                     }
    5000                                     $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    5001                                 }
    5002                                 if (is_array($restrictions))
    5003                                 {
    5004                                     $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
    5005                                 }
    5006                             }
    5007                             else
    5008                             {
    5009                                 $restrictions = $restrictions_parent;
    5010                             }
    5011 
    5012                             // THUMBNAILS
    5013                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
    5014                             {
    5015                                 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
    5016                                 {
    5017                                     $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    5018                                 }
    5019                                 if (is_array($thumbnails))
    5020                                 {
    5021                                     $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
    5022                                 }
    5023                             }
    5024                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
    5025                             {
    5026                                 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
    5027                                 {
    5028                                     $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    5029                                 }
    5030                                 if (is_array($thumbnails))
    5031                                 {
    5032                                     $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
    5033                                 }
    5034                             }
    5035                             else
    5036                             {
    5037                                 $thumbnails = $thumbnails_parent;
    5038                             }
    5039 
    5040                             // TITLES
    5041                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
    5042                             {
    5043                                 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5044                             }
    5045                             elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
    5046                             {
    5047                                 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5048                             }
    5049                             else
    5050                             {
    5051                                 $title = $title_parent;
    5052                             }
    5053 
    5054                             $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);
    5055                         }
    5056                     }
    5057                 }
    5058             }
    5059 
    5060             // If we have standalone media:content tags, loop through them.
    5061             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
    5062             {
    5063                 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
    5064                 {
    5065                     if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
    5066                     {
    5067                         // Attributes
    5068                         $bitrate = null;
    5069                         $channels = null;
    5070                         $duration = null;
    5071                         $expression = null;
    5072                         $framerate = null;
    5073                         $height = null;
    5074                         $javascript = null;
    5075                         $lang = null;
    5076                         $length = null;
    5077                         $medium = null;
    5078                         $samplingrate = null;
    5079                         $type = null;
    5080                         $url = null;
    5081                         $width = null;
    5082 
    5083                         // Elements
    5084                         $captions = null;
    5085                         $categories = null;
    5086                         $copyrights = null;
    5087                         $credits = null;
    5088                         $description = null;
    5089                         $hashes = null;
    5090                         $keywords = null;
    5091                         $player = null;
    5092                         $ratings = null;
    5093                         $restrictions = null;
    5094                         $thumbnails = null;
    5095                         $title = null;
    5096 
    5097                         // Start checking the attributes of media:content
    5098                         if (isset($content['attribs']['']['bitrate']))
    5099                         {
    5100                             $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
    5101                         }
    5102                         if (isset($content['attribs']['']['channels']))
    5103                         {
    5104                             $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
    5105                         }
    5106                         if (isset($content['attribs']['']['duration']))
    5107                         {
    5108                             $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
    5109                         }
    5110                         else
    5111                         {
    5112                             $duration = $duration_parent;
    5113                         }
    5114                         if (isset($content['attribs']['']['expression']))
    5115                         {
    5116                             $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
    5117                         }
    5118                         if (isset($content['attribs']['']['framerate']))
    5119                         {
    5120                             $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
    5121                         }
    5122                         if (isset($content['attribs']['']['height']))
    5123                         {
    5124                             $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
    5125                         }
    5126                         if (isset($content['attribs']['']['lang']))
    5127                         {
    5128                             $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    5129                         }
    5130                         if (isset($content['attribs']['']['fileSize']))
    5131                         {
    5132                             $length = ceil($content['attribs']['']['fileSize']);
    5133                         }
    5134                         if (isset($content['attribs']['']['medium']))
    5135                         {
    5136                             $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
    5137                         }
    5138                         if (isset($content['attribs']['']['samplingrate']))
    5139                         {
    5140                             $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
    5141                         }
    5142                         if (isset($content['attribs']['']['type']))
    5143                         {
    5144                             $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    5145                         }
    5146                         if (isset($content['attribs']['']['width']))
    5147                         {
    5148                             $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
    5149                         }
    5150                         if (isset($content['attribs']['']['url']))
    5151                         {
    5152                             $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    5153                         }
    5154                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
    5155 
    5156                         // CAPTIONS
    5157                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
    5158                         {
    5159                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
    5160                             {
    5161                                 $caption_type = null;
    5162                                 $caption_lang = null;
    5163                                 $caption_startTime = null;
    5164                                 $caption_endTime = null;
    5165                                 $caption_text = null;
    5166                                 if (isset($caption['attribs']['']['type']))
    5167                                 {
    5168                                     $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    5169                                 }
    5170                                 if (isset($caption['attribs']['']['lang']))
    5171                                 {
    5172                                     $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    5173                                 }
    5174                                 if (isset($caption['attribs']['']['start']))
    5175                                 {
    5176                                     $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
    5177                                 }
    5178                                 if (isset($caption['attribs']['']['end']))
    5179                                 {
    5180                                     $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
    5181                                 }
    5182                                 if (isset($caption['data']))
    5183                                 {
    5184                                     $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5185                                 }
    5186                                 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
    5187                             }
    5188                             if (is_array($captions))
    5189                             {
    5190                                 $captions = array_values(SimplePie_Misc::array_unique($captions));
    5191                             }
    5192                         }
    5193                         else
    5194                         {
    5195                             $captions = $captions_parent;
    5196                         }
    5197 
    5198                         // CATEGORIES
    5199                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
    5200                         {
    5201                             foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
    5202                             {
    5203                                 $term = null;
    5204                                 $scheme = null;
    5205                                 $label = null;
    5206                                 if (isset($category['data']))
    5207                                 {
    5208                                     $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5209                                 }
    5210                                 if (isset($category['attribs']['']['scheme']))
    5211                                 {
    5212                                     $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    5213                                 }
    5214                                 else
    5215                                 {
    5216                                     $scheme = 'http://search.yahoo.com/mrss/category_schema';
    5217                                 }
    5218                                 if (isset($category['attribs']['']['label']))
    5219                                 {
    5220                                     $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    5221                                 }
    5222                                 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
    5223                             }
    5224                         }
    5225                         if (is_array($categories) && is_array($categories_parent))
    5226                         {
    5227                             $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
    5228                         }
    5229                         elseif (is_array($categories))
    5230                         {
    5231                             $categories = array_values(SimplePie_Misc::array_unique($categories));
    5232                         }
    5233                         elseif (is_array($categories_parent))
    5234                         {
    5235                             $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
    5236                         }
    5237                         else
    5238                         {
    5239                             $categories = null;
    5240                         }
    5241 
    5242                         // COPYRIGHTS
    5243                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
    5244                         {
    5245                             $copyright_url = null;
    5246                             $copyright_label = null;
    5247                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
    5248                             {
    5249                                 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
    5250                             }
    5251                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
    5252                             {
    5253                                 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5254                             }
    5255                             $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
    5256                         }
    5257                         else
    5258                         {
    5259                             $copyrights = $copyrights_parent;
    5260                         }
    5261 
    5262                         // CREDITS
    5263                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
    5264                         {
    5265                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
    5266                             {
    5267                                 $credit_role = null;
    5268                                 $credit_scheme = null;
    5269                                 $credit_name = null;
    5270                                 if (isset($credit['attribs']['']['role']))
    5271                                 {
    5272                                     $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
    5273                                 }
    5274                                 if (isset($credit['attribs']['']['scheme']))
    5275                                 {
    5276                                     $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    5277                                 }
    5278                                 else
    5279                                 {
    5280                                     $credit_scheme = 'urn:ebu';
    5281                                 }
    5282                                 if (isset($credit['data']))
    5283                                 {
    5284                                     $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5285                                 }
    5286                                 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
    5287                             }
    5288                             if (is_array($credits))
    5289                             {
    5290                                 $credits = array_values(SimplePie_Misc::array_unique($credits));
    5291                             }
    5292                         }
    5293                         else
    5294                         {
    5295                             $credits = $credits_parent;
    5296                         }
    5297 
    5298                         // DESCRIPTION
    5299                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
    5300                         {
    5301                             $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5302                         }
    5303                         else
    5304                         {
    5305                             $description = $description_parent;
    5306                         }
    5307 
    5308                         // HASHES
    5309                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
    5310                         {
    5311                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
    5312                             {
    5313                                 $value = null;
    5314                                 $algo = null;
    5315                                 if (isset($hash['data']))
    5316                                 {
    5317                                     $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5318                                 }
    5319                                 if (isset($hash['attribs']['']['algo']))
    5320                                 {
    5321                                     $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
    5322                                 }
    5323                                 else
    5324                                 {
    5325                                     $algo = 'md5';
    5326                                 }
    5327                                 $hashes[] = $algo.':'.$value;
    5328                             }
    5329                             if (is_array($hashes))
    5330                             {
    5331                                 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
    5332                             }
    5333                         }
    5334                         else
    5335                         {
    5336                             $hashes = $hashes_parent;
    5337                         }
    5338 
    5339                         // KEYWORDS
    5340                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
    5341                         {
    5342                             if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
    5343                             {
    5344                                 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
    5345                                 foreach ($temp as $word)
    5346                                 {
    5347                                     $keywords[] = trim($word);
    5348                                 }
    5349                                 unset($temp);
    5350                             }
    5351                             if (is_array($keywords))
    5352                             {
    5353                                 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
    5354                             }
    5355                         }
    5356                         else
    5357                         {
    5358                             $keywords = $keywords_parent;
    5359                         }
    5360 
    5361                         // PLAYER
    5362                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
    5363                         {
    5364                             $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    5365                         }
    5366                         else
    5367                         {
    5368                             $player = $player_parent;
    5369                         }
    5370 
    5371                         // RATINGS
    5372                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
    5373                         {
    5374                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
    5375                             {
    5376                                 $rating_scheme = null;
    5377                                 $rating_value = null;
    5378                                 if (isset($rating['attribs']['']['scheme']))
    5379                                 {
    5380                                     $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    5381                                 }
    5382                                 else
    5383                                 {
    5384                                     $rating_scheme = 'urn:simple';
    5385                                 }
    5386                                 if (isset($rating['data']))
    5387                                 {
    5388                                     $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5389                                 }
    5390                                 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
    5391                             }
    5392                             if (is_array($ratings))
    5393                             {
    5394                                 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
    5395                             }
    5396                         }
    5397                         else
    5398                         {
    5399                             $ratings = $ratings_parent;
    5400                         }
    5401 
    5402                         // RESTRICTIONS
    5403                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
    5404                         {
    5405                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
    5406                             {
    5407                                 $restriction_relationship = null;
    5408                                 $restriction_type = null;
    5409                                 $restriction_value = null;
    5410                                 if (isset($restriction['attribs']['']['relationship']))
    5411                                 {
    5412                                     $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
    5413                                 }
    5414                                 if (isset($restriction['attribs']['']['type']))
    5415                                 {
    5416                                     $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    5417                                 }
    5418                                 if (isset($restriction['data']))
    5419                                 {
    5420                                     $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5421                                 }
    5422                                 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
    5423                             }
    5424                             if (is_array($restrictions))
    5425                             {
    5426                                 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
    5427                             }
    5428                         }
    5429                         else
    5430                         {
    5431                             $restrictions = $restrictions_parent;
    5432                         }
    5433 
    5434                         // THUMBNAILS
    5435                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
    5436                         {
    5437                             foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
    5438                             {
    5439                                 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
    5440                             }
    5441                             if (is_array($thumbnails))
    5442                             {
    5443                                 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
    5444                             }
    5445                         }
    5446                         else
    5447                         {
    5448                             $thumbnails = $thumbnails_parent;
    5449                         }
    5450 
    5451                         // TITLES
    5452                         if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
    5453                         {
    5454                             $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5455                         }
    5456                         else
    5457                         {
    5458                             $title = $title_parent;
    5459                         }
    5460 
    5461                         $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);
    5462                     }
    5463                 }
    5464             }
    5465 
    5466             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
    5467             {
    5468                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
    5469                 {
    5470                     // Attributes
    5471                     $bitrate = null;
    5472                     $channels = null;
    5473                     $duration = null;
    5474                     $expression = null;
    5475                     $framerate = null;
    5476                     $height = null;
    5477                     $javascript = null;
    5478                     $lang = null;
    5479                     $length = null;
    5480                     $medium = null;
    5481                     $samplingrate = null;
    5482                     $type = null;
    5483                     $url = null;
    5484                     $width = null;
    5485 
    5486                     $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
    5487                     if (isset($link['attribs']['']['type']))
    5488                     {
    5489                         $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    5490                     }
    5491                     if (isset($link['attribs']['']['length']))
    5492                     {
    5493                         $length = ceil($link['attribs']['']['length']);
    5494                     }
    5495 
    5496                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
    5497                     $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);
    5498                 }
    5499             }
    5500 
    5501             foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
    5502             {
    5503                 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
    5504                 {
    5505                     // Attributes
    5506                     $bitrate = null;
    5507                     $channels = null;
    5508                     $duration = null;
    5509                     $expression = null;
    5510                     $framerate = null;
    5511                     $height = null;
    5512                     $javascript = null;
    5513                     $lang = null;
    5514                     $length = null;
    5515                     $medium = null;
    5516                     $samplingrate = null;
    5517                     $type = null;
    5518                     $url = null;
    5519                     $width = null;
    5520 
    5521                     $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
    5522                     if (isset($link['attribs']['']['type']))
    5523                     {
    5524                         $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    5525                     }
    5526                     if (isset($link['attribs']['']['length']))
    5527                     {
    5528                         $length = ceil($link['attribs']['']['length']);
    5529                     }
    5530 
    5531                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
    5532                     $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
    5533                 }
    5534             }
    5535 
    5536             if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
    5537             {
    5538                 if (isset($enclosure[0]['attribs']['']['url']))
    5539                 {
    5540                     // Attributes
    5541                     $bitrate = null;
    5542                     $channels = null;
    5543                     $duration = null;
    5544                     $expression = null;
    5545                     $framerate = null;
    5546                     $height = null;
    5547                     $javascript = null;
    5548                     $lang = null;
    5549                     $length = null;
    5550                     $medium = null;
    5551                     $samplingrate = null;
    5552                     $type = null;
    5553                     $url = null;
    5554                     $width = null;
    5555 
    5556                     $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
    5557                     if (isset($enclosure[0]['attribs']['']['type']))
    5558                     {
    5559                         $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
    5560                     }
    5561                     if (isset($enclosure[0]['attribs']['']['length']))
    5562                     {
    5563                         $length = ceil($enclosure[0]['attribs']['']['length']);
    5564                     }
    5565 
    5566                     // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
    5567                     $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
    5568                 }
    5569             }
    5570 
    5571             if (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))
    5572             {
    5573                 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
    5574                 $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);
    5575             }
    5576 
    5577             $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
    5578         }
    5579         if (!empty($this->data['enclosures']))
    5580         {
    5581             return $this->data['enclosures'];
    5582         }
    5583         else
    5584         {
    5585             return null;
    5586         }
    5587     }
    5588 
    5589     function get_latitude()
    5590     {
    5591         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
    5592         {
    5593             return (float) $return[0]['data'];
    5594         }
    5595         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))
    5596         {
    5597             return (float) $match[1];
    5598         }
    5599         else
    5600         {
    5601             return null;
    5602         }
    5603     }
    5604 
    5605     function get_longitude()
    5606     {
    5607         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
    5608         {
    5609             return (float) $return[0]['data'];
    5610         }
    5611         elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
    5612         {
    5613             return (float) $return[0]['data'];
    5614         }
    5615         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))
    5616         {
    5617             return (float) $match[2];
    5618         }
    5619         else
    5620         {
    5621             return null;
    5622         }
    5623     }
    5624 
    5625     function get_source()
    5626     {
    5627         if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
    5628         {
    5629             return new $this->feed->source_class($this, $return[0]);
    5630         }
    5631         else
    5632         {
    5633             return null;
    5634         }
    5635     }
    5636 
    5637     /**
    5638      * Creates the add_to_* methods' return data
    5639      *
    5640      * @access private
    5641      * @param string $item_url String to prefix to the item permalink
    5642      * @param string $title_url String to prefix to the item title
    5643      * (and suffix to the item permalink)
    5644      * @return mixed URL if feed exists, false otherwise
    5645      */
    5646     function add_to_service($item_url, $title_url = null, $summary_url = null)
    5647     {
    5648         if ($this->get_permalink() !== null)
    5649         {
    5650             $return = $item_url . rawurlencode($this->get_permalink());
    5651             if ($title_url !== null && $this->get_title() !== null)
    5652             {
    5653                 $return .= $title_url . rawurlencode($this->get_title());
    5654             }
    5655             if ($summary_url !== null && $this->get_description() !== null)
    5656             {
    5657                 $return .= $summary_url . rawurlencode($this->get_description());
    5658             }
    5659             return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
    5660         }
    5661         else
    5662         {
    5663             return null;
    5664         }
    5665     }
    5666 
    5667     function add_to_blinklist()
    5668     {
    5669         return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
    5670     }
    5671 
    5672     function add_to_blogmarks()
    5673     {
    5674         return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
    5675     }
    5676 
    5677     function add_to_delicious()
    5678     {
    5679         return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
    5680     }
    5681 
    5682     function add_to_digg()
    5683     {
    5684         return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
    5685     }
    5686 
    5687     function add_to_furl()
    5688     {
    5689         return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
    5690     }
    5691 
    5692     function add_to_magnolia()
    5693     {
    5694         return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
    5695     }
    5696 
    5697     function add_to_myweb20()
    5698     {
    5699         return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
    5700     }
    5701 
    5702     function add_to_newsvine()
    5703     {
    5704         return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
    5705     }
    5706 
    5707     function add_to_reddit()
    5708     {
    5709         return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
    5710     }
    5711 
    5712     function add_to_segnalo()
    5713     {
    5714         return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
    5715     }
    5716 
    5717     function add_to_simpy()
    5718     {
    5719         return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
    5720     }
    5721 
    5722     function add_to_spurl()
    5723     {
    5724         return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
    5725     }
    5726 
    5727     function add_to_wists()
    5728     {
    5729         return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
    5730     }
    5731 
    5732     function search_technorati()
    5733     {
    5734         return $this->add_to_service('http://www.technorati.com/search/');
    5735     }
    5736 }
    5737 
    5738 class SimplePie_Source
    5739 {
    5740     var $item;
    5741     var $data = array();
    5742 
    5743     function SimplePie_Source($item, $data)
    5744     {
    5745         $this->item = $item;
    5746         $this->data = $data;
    5747     }
    5748 
    5749     function __toString()
    5750     {
    5751         return md5(serialize($this->data));
    5752     }
    5753 
    5754     function get_source_tags($namespace, $tag)
    5755     {
    5756         if (isset($this->data['child'][$namespace][$tag]))
    5757         {
    5758             return $this->data['child'][$namespace][$tag];
    5759         }
    5760         else
    5761         {
    5762             return null;
    5763         }
    5764     }
    5765 
    5766     function get_base($element = array())
    5767     {
    5768         return $this->item->get_base($element);
    5769     }
    5770 
    5771     function sanitize($data, $type, $base = '')
    5772     {
    5773         return $this->item->sanitize($data, $type, $base);
    5774     }
    5775 
    5776     function get_item()
    5777     {
    5778         return $this->item;
    5779     }
    5780 
    5781     function get_title()
    5782     {
    5783         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
    5784         {
    5785             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    5786         }
    5787         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
    5788         {
    5789             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    5790         }
    5791         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, '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_RSS_090, 'title'))
    5796         {
    5797             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    5798         }
    5799         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
    5800         {
    5801             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    5802         }
    5803         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
    5804         {
    5805             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5806         }
    5807         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
    5808         {
    5809             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5810         }
    5811         else
    5812         {
    5813             return null;
    5814         }
    5815     }
    5816 
    5817     function get_category($key = 0)
    5818     {
    5819         $categories = $this->get_categories();
    5820         if (isset($categories[$key]))
    5821         {
    5822             return $categories[$key];
    5823         }
    5824         else
    5825         {
    5826             return null;
    5827         }
    5828     }
    5829 
    5830     function get_categories()
    5831     {
    5832         $categories = array();
    5833 
    5834         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
    5835         {
    5836             $term = null;
    5837             $scheme = null;
    5838             $label = null;
    5839             if (isset($category['attribs']['']['term']))
    5840             {
    5841                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
    5842             }
    5843             if (isset($category['attribs']['']['scheme']))
    5844             {
    5845                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
    5846             }
    5847             if (isset($category['attribs']['']['label']))
    5848             {
    5849                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
    5850             }
    5851             $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
    5852         }
    5853         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
    5854         {
    5855             // This is really the label, but keep this as the term also for BC.
    5856             // Label will also work on retrieving because that falls back to term.
    5857             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5858             if (isset($category['attribs']['']['domain']))
    5859             {
    5860                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
    5861             }
    5862             else
    5863             {
    5864                 $scheme = null;
    5865             }
    5866             $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
    5867         }
    5868         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
    5869         {
    5870             $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    5871         }
    5872         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
    5873         {
    5874             $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    5875         }
    5876 
    5877         if (!empty($categories))
    5878         {
    5879             return SimplePie_Misc::array_unique($categories);
    5880         }
    5881         else
    5882         {
    5883             return null;
    5884         }
    5885     }
    5886 
    5887     function get_author($key = 0)
    5888     {
    5889         $authors = $this->get_authors();
    5890         if (isset($authors[$key]))
    5891         {
    5892             return $authors[$key];
    5893         }
    5894         else
    5895         {
    5896             return null;
    5897         }
    5898     }
    5899 
    5900     function get_authors()
    5901     {
    5902         $authors = array();
    5903         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
    5904         {
    5905             $name = null;
    5906             $uri = null;
    5907             $email = null;
    5908             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
    5909             {
    5910                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5911             }
    5912             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
    5913             {
    5914                 $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]));
    5915             }
    5916             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
    5917             {
    5918                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5919             }
    5920             if ($name !== null || $email !== null || $uri !== null)
    5921             {
    5922                 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
    5923             }
    5924         }
    5925         if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
    5926         {
    5927             $name = null;
    5928             $url = null;
    5929             $email = null;
    5930             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
    5931             {
    5932                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5933             }
    5934             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
    5935             {
    5936                 $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]));
    5937             }
    5938             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
    5939             {
    5940                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5941             }
    5942             if ($name !== null || $email !== null || $url !== null)
    5943             {
    5944                 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
    5945             }
    5946         }
    5947         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
    5948         {
    5949             $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    5950         }
    5951         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
    5952         {
    5953             $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    5954         }
    5955         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
    5956         {
    5957             $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
    5958         }
    5959 
    5960         if (!empty($authors))
    5961         {
    5962             return SimplePie_Misc::array_unique($authors);
    5963         }
    5964         else
    5965         {
    5966             return null;
    5967         }
    5968     }
    5969 
    5970     function get_contributor($key = 0)
    5971     {
    5972         $contributors = $this->get_contributors();
    5973         if (isset($contributors[$key]))
    5974         {
    5975             return $contributors[$key];
    5976         }
    5977         else
    5978         {
    5979             return null;
    5980         }
    5981     }
    5982 
    5983     function get_contributors()
    5984     {
    5985         $contributors = array();
    5986         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
    5987         {
    5988             $name = null;
    5989             $uri = null;
    5990             $email = null;
    5991             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
    5992             {
    5993                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    5994             }
    5995             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
    5996             {
    5997                 $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]));
    5998             }
    5999             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
    6000             {
    6001                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6002             }
    6003             if ($name !== null || $email !== null || $uri !== null)
    6004             {
    6005                 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
    6006             }
    6007         }
    6008         foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
    6009         {
    6010             $name = null;
    6011             $url = null;
    6012             $email = null;
    6013             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
    6014             {
    6015                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6016             }
    6017             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
    6018             {
    6019                 $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]));
    6020             }
    6021             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
    6022             {
    6023                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6024             }
    6025             if ($name !== null || $email !== null || $url !== null)
    6026             {
    6027                 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
    6028             }
    6029         }
    6030 
    6031         if (!empty($contributors))
    6032         {
    6033             return SimplePie_Misc::array_unique($contributors);
    6034         }
    6035         else
    6036         {
    6037             return null;
    6038         }
    6039     }
    6040 
    6041     function get_link($key = 0, $rel = 'alternate')
    6042     {
    6043         $links = $this->get_links($rel);
    6044         if (isset($links[$key]))
    6045         {
    6046             return $links[$key];
    6047         }
    6048         else
    6049         {
    6050             return null;
    6051         }
    6052     }
    6053 
    6054     /**
    6055      * Added for parity between the parent-level and the item/entry-level.
    6056      */
    6057     function get_permalink()
    6058     {
    6059         return $this->get_link(0);
    6060     }
    6061 
    6062     function get_links($rel = 'alternate')
    6063     {
    6064         if (!isset($this->data['links']))
    6065         {
    6066             $this->data['links'] = array();
    6067             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
    6068             {
    6069                 foreach ($links as $link)
    6070                 {
    6071                     if (isset($link['attribs']['']['href']))
    6072                     {
    6073                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
    6074                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
    6075                     }
    6076                 }
    6077             }
    6078             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
    6079             {
    6080                 foreach ($links as $link)
    6081                 {
    6082                     if (isset($link['attribs']['']['href']))
    6083                     {
    6084                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
    6085                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
    6086 
    6087                     }
    6088                 }
    6089             }
    6090             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
    6091             {
    6092                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    6093             }
    6094             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
    6095             {
    6096                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    6097             }
    6098             if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
    6099             {
    6100                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
    6101             }
    6102 
    6103             $keys = array_keys($this->data['links']);
    6104             foreach ($keys as $key)
    6105             {
    6106                 if (SimplePie_Misc::is_isegment_nz_nc($key))
    6107                 {
    6108                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
    6109                     {
    6110                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
    6111                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
    6112                     }
    6113                     else
    6114                     {
    6115                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
    6116                     }
    6117                 }
    6118                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
    6119                 {
    6120                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
    6121                 }
    6122                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
    6123             }
    6124         }
    6125 
    6126         if (isset($this->data['links'][$rel]))
    6127         {
    6128             return $this->data['links'][$rel];
    6129         }
    6130         else
    6131         {
    6132             return null;
    6133         }
    6134     }
    6135 
    6136     function get_description()
    6137     {
    6138         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
    6139         {
    6140             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    6141         }
    6142         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
    6143         {
    6144             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    6145         }
    6146         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, '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_RSS_090, 'description'))
    6151         {
    6152             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    6153         }
    6154         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
    6155         {
    6156             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
    6157         }
    6158         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
    6159         {
    6160             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6161         }
    6162         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
    6163         {
    6164             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6165         }
    6166         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
    6167         {
    6168             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
    6169         }
    6170         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
    6171         {
    6172             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
    6173         }
    6174         else
    6175         {
    6176             return null;
    6177         }
    6178     }
    6179 
    6180     function get_copyright()
    6181     {
    6182         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
    6183         {
    6184             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    6185         }
    6186         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
    6187         {
    6188             return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
    6189         }
    6190         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
    6191         {
    6192             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6193         }
    6194         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
    6195         {
    6196             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6197         }
    6198         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
    6199         {
    6200             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6201         }
    6202         else
    6203         {
    6204             return null;
    6205         }
    6206     }
    6207 
    6208     function get_language()
    6209     {
    6210         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
    6211         {
    6212             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6213         }
    6214         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
    6215         {
    6216             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6217         }
    6218         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
    6219         {
    6220             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
    6221         }
    6222         elseif (isset($this->data['xml_lang']))
    6223         {
    6224             return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
    6225         }
    6226         else
    6227         {
    6228             return null;
    6229         }
    6230     }
    6231 
    6232     function get_latitude()
    6233     {
    6234         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
    6235         {
    6236             return (float) $return[0]['data'];
    6237         }
    6238         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))
    6239         {
    6240             return (float) $match[1];
    6241         }
    6242         else
    6243         {
    6244             return null;
    6245         }
    6246     }
    6247 
    6248     function get_longitude()
    6249     {
    6250         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
    6251         {
    6252             return (float) $return[0]['data'];
    6253         }
    6254         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
    6255         {
    6256             return (float) $return[0]['data'];
    6257         }
    6258         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))
    6259         {
    6260             return (float) $match[2];
    6261         }
    6262         else
    6263         {
    6264             return null;
    6265         }
    6266     }
    6267 
    6268     function get_image_url()
    6269     {
    6270         if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
    6271         {
    6272             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
    6273         }
    6274         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
    6275         {
    6276             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
    6277         }
    6278         elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
    6279         {
    6280             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
    6281         }
    6282         else
    6283         {
    6284             return null;
    6285         }
    6286     }
    6287 }
    6288 
    6289 class SimplePie_Author
    6290 {
    6291     var $name;
    6292     var $link;
    6293     var $email;
    6294 
    6295     // Constructor, used to input the data
    6296     function SimplePie_Author($name = null, $link = null, $email = null)
    6297     {
    6298         $this->name = $name;
    6299         $this->link = $link;
    6300         $this->email = $email;
    6301     }
    6302 
    6303     function __toString()
    6304     {
    6305         // There is no $this->data here
    6306         return md5(serialize($this));
    6307     }
    6308 
    6309     function get_name()
    6310     {
    6311         if ($this->name !== null)
    6312         {
    6313             return $this->name;
    6314         }
    6315         else
    6316         {
    6317             return null;
    6318         }
    6319     }
    6320 
    6321     function get_link()
    6322     {
    6323         if ($this->link !== null)
    6324         {
    6325             return $this->link;
    6326         }
    6327         else
    6328         {
    6329             return null;
    6330         }
    6331     }
    6332 
    6333     function get_email()
    6334     {
    6335         if ($this->email !== null)
    6336         {
    6337             return $this->email;
    6338         }
    6339         else
    6340         {
    6341             return null;
    6342         }
    6343     }
    6344 }
    6345 
    6346 class SimplePie_Category
    6347 {
    6348     var $term;
    6349     var $scheme;
    6350     var $label;
    6351 
    6352     // Constructor, used to input the data
    6353     function SimplePie_Category($term = null, $scheme = null, $label = null)
    6354     {
    6355         $this->term = $term;
    6356         $this->scheme = $scheme;
    6357         $this->label = $label;
    6358     }
    6359 
    6360     function __toString()
    6361     {
    6362         // There is no $this->data here
    6363         return md5(serialize($this));
    6364     }
    6365 
    6366     function get_term()
    6367     {
    6368         if ($this->term !== null)
    6369         {
    6370             return $this->term;
    6371         }
    6372         else
    6373         {
    6374             return null;
    6375         }
    6376     }
    6377 
    6378     function get_scheme()
    6379     {
    6380         if ($this->scheme !== null)
    6381         {
    6382             return $this->scheme;
    6383         }
    6384         else
    6385         {
    6386             return null;
    6387         }
    6388     }
    6389 
    6390     function get_label()
    6391     {
    6392         if ($this->label !== null)
    6393         {
    6394             return $this->label;
    6395         }
    6396         else
    6397         {
    6398             return $this->get_term();
    6399         }
    6400     }
    6401 }
    6402 
    6403 class SimplePie_Enclosure
    6404 {
    6405     var $bitrate;
    6406     var $captions;
    6407     var $categories;
    6408     var $channels;
    6409     var $copyright;
    6410     var $credits;
    6411     var $description;
    6412     var $duration;
    6413     var $expression;
    6414     var $framerate;
    6415     var $handler;
    6416     var $hashes;
    6417     var $height;
    6418     var $javascript;
    6419     var $keywords;
    6420     var $lang;
    6421     var $length;
    6422     var $link;
    6423     var $medium;
    6424     var $player;
    6425     var $ratings;
    6426     var $restrictions;
    6427     var $samplingrate;
    6428     var $thumbnails;
    6429     var $title;
    6430     var $type;
    6431     var $width;
    6432 
    6433     // Constructor, used to input the data
    6434     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)
    6435     {
    6436         $this->bitrate = $bitrate;
    6437         $this->captions = $captions;
    6438         $this->categories = $categories;
    6439         $this->channels = $channels;
    6440         $this->copyright = $copyright;
    6441         $this->credits = $credits;
    6442         $this->description = $description;
    6443         $this->duration = $duration;
    6444         $this->expression = $expression;
    6445         $this->framerate = $framerate;
    6446         $this->hashes = $hashes;
    6447         $this->height = $height;
    6448         $this->javascript = $javascript;
    6449         $this->keywords = $keywords;
    6450         $this->lang = $lang;
    6451         $this->length = $length;
    6452         $this->link = $link;
    6453         $this->medium = $medium;
    6454         $this->player = $player;
    6455         $this->ratings = $ratings;
    6456         $this->restrictions = $restrictions;
    6457         $this->samplingrate = $samplingrate;
    6458         $this->thumbnails = $thumbnails;
    6459         $this->title = $title;
    6460         $this->type = $type;
    6461         $this->width = $width;
    6462         if (class_exists('idna_convert'))
    6463         {
    6464             $idn =& new idna_convert;
    6465             $parsed = SimplePie_Misc::parse_url($link);
    6466             $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
    6467         }
    6468         $this->handler = $this->get_handler(); // Needs to load last
    6469     }
    6470 
    6471     function __toString()
    6472     {
    6473         // There is no $this->data here
    6474         return md5(serialize($this));
    6475     }
    6476 
    6477     function get_bitrate()
    6478     {
    6479         if ($this->bitrate !== null)
    6480         {
    6481             return $this->bitrate;
    6482         }
    6483         else
    6484         {
    6485             return null;
    6486         }
    6487     }
    6488 
    6489     function get_caption($key = 0)
    6490     {
    6491         $captions = $this->get_captions();
    6492         if (isset($captions[$key]))
    6493         {
    6494             return $captions[$key];
    6495         }
    6496         else
    6497         {
    6498             return null;
    6499         }
    6500     }
    6501 
    6502     function get_captions()
    6503     {
    6504         if ($this->captions !== null)
    6505         {
    6506             return $this->captions;
    6507         }
    6508         else
    6509         {
    6510             return null;
    6511         }
    6512     }
    6513 
    6514     function get_category($key = 0)
    6515     {
    6516         $categories = $this->get_categories();
    6517         if (isset($categories[$key]))
    6518         {
    6519             return $categories[$key];
    6520         }
    6521         else
    6522         {
    6523             return null;
    6524         }
    6525     }
    6526 
    6527     function get_categories()
    6528     {
    6529         if ($this->categories !== null)
    6530         {
    6531             return $this->categories;
    6532         }
    6533         else
    6534         {
    6535             return null;
    6536         }
    6537     }
    6538 
    6539     function get_channels()
    6540     {
    6541         if ($this->channels !== null)
    6542         {
    6543             return $this->channels;
    6544         }
    6545         else
    6546         {
    6547             return null;
    6548         }
    6549     }
    6550 
    6551     function get_copyright()
    6552     {
    6553         if ($this->copyright !== null)
    6554         {
    6555             return $this->copyright;
    6556         }
    6557         else
    6558         {
    6559             return null;
    6560         }
    6561     }
    6562 
    6563     function get_credit($key = 0)
    6564     {
    6565         $credits = $this->get_credits();
    6566         if (isset($credits[$key]))
    6567         {
    6568             return $credits[$key];
    6569         }
    6570         else
    6571         {
    6572             return null;
    6573         }
    6574     }
    6575 
    6576     function get_credits()
    6577     {
    6578         if ($this->credits !== null)
    6579         {
    6580             return $this->credits;
    6581         }
    6582         else
    6583         {
    6584             return null;
    6585         }
    6586     }
    6587 
    6588     function get_description()
    6589     {
    6590         if ($this->description !== null)
    6591         {
    6592             return $this->description;
    6593         }
    6594         else
    6595         {
    6596             return null;
    6597         }
    6598     }
    6599 
    6600     function get_duration($convert = false)
    6601     {
    6602         if ($this->duration !== null)
    6603         {
    6604             if ($convert)
    6605             {
    6606                 $time = SimplePie_Misc::time_hms($this->duration);
    6607                 return $time;
    6608             }
    6609             else
    6610             {
    6611                 return $this->duration;
    6612             }
    6613         }
    6614         else
    6615         {
    6616             return null;
    6617         }
    6618     }
    6619 
    6620     function get_expression()
    6621     {
    6622         if ($this->expression !== null)
    6623         {
    6624             return $this->expression;
    6625         }
    6626         else
    6627         {
    6628             return 'full';
    6629         }
    6630     }
    6631 
    6632     function get_extension()
    6633     {
    6634         if ($this->link !== null)
    6635         {
    6636             $url = SimplePie_Misc::parse_url($this->link);
    6637             if ($url['path'] !== '')
    6638             {
    6639                 return pathinfo($url['path'], PATHINFO_EXTENSION);
    6640             }
    6641         }
    6642         return null;
    6643     }
    6644 
    6645     function get_framerate()
    6646     {
    6647         if ($this->framerate !== null)
    6648         {
    6649             return $this->framerate;
    6650         }
    6651         else
    6652         {
    6653             return null;
    6654         }
    6655     }
    6656 
    6657     function get_handler()
    6658     {
    6659         return $this->get_real_type(true);
    6660     }
    6661 
    6662     function get_hash($key = 0)
    6663     {
    6664         $hashes = $this->get_hashes();
    6665         if (isset($hashes[$key]))
    6666         {
    6667             return $hashes[$key];
    6668         }
    6669         else
    6670         {
    6671             return null;
    6672         }
    6673     }
    6674 
    6675     function get_hashes()
    6676     {
    6677         if ($this->hashes !== null)
    6678         {
    6679             return $this->hashes;
    6680         }
    6681         else
    6682         {
    6683             return null;
    6684         }
    6685     }
    6686 
    6687     function get_height()
    6688     {
    6689         if ($this->height !== null)
    6690         {
    6691             return $this->height;
    6692         }
    6693         else
    6694         {
    6695             return null;
    6696         }
    6697     }
    6698 
    6699     function get_language()
    6700     {
    6701         if ($this->lang !== null)
    6702         {
    6703             return $this->lang;
    6704         }
    6705         else
    6706         {
    6707             return null;
    6708         }
    6709     }
    6710 
    6711     function get_keyword($key = 0)
    6712     {
    6713         $keywords = $this->get_keywords();
    6714         if (isset($keywords[$key]))
    6715         {
    6716             return $keywords[$key];
    6717         }
    6718         else
    6719         {
    6720             return null;
    6721         }
    6722     }
    6723 
    6724     function get_keywords()
    6725     {
    6726         if ($this->keywords !== null)
    6727         {
    6728             return $this->keywords;
    6729         }
    6730         else
    6731         {
    6732             return null;
    6733         }
    6734     }
    6735 
    6736     function get_length()
    6737     {
    6738         if ($this->length !== null)
    6739         {
    6740             return $this->length;
    6741         }
    6742         else
    6743         {
    6744             return null;
    6745         }
    6746     }
    6747 
    6748     function get_link()
    6749     {
    6750         if ($this->link !== null)
    6751         {
    6752             return urldecode($this->link);
    6753         }
    6754         else
    6755         {
    6756             return null;
    6757         }
    6758     }
    6759 
    6760     function get_medium()
    6761     {
    6762         if ($this->medium !== null)
    6763         {
    6764             return $this->medium;
    6765         }
    6766         else
    6767         {
    6768             return null;
    6769         }
    6770     }
    6771 
    6772     function get_player()
    6773     {
    6774         if ($this->player !== null)
    6775         {
    6776             return $this->player;
    6777         }
    6778         else
    6779         {
    6780             return null;
    6781         }
    6782     }
    6783 
    6784     function get_rating($key = 0)
    6785     {
    6786         $ratings = $this->get_ratings();
    6787         if (isset($ratings[$key]))
    6788         {
    6789             return $ratings[$key];
    6790         }
    6791         else
    6792         {
    6793             return null;
    6794         }
    6795     }
    6796 
    6797     function get_ratings()
    6798     {
    6799         if ($this->ratings !== null)
    6800         {
    6801             return $this->ratings;
    6802         }
    6803         else
    6804         {
    6805             return null;
    6806         }
    6807     }
    6808 
    6809     function get_restriction($key = 0)
    6810     {
    6811         $restrictions = $this->get_restrictions();
    6812         if (isset($restrictions[$key]))
    6813         {
    6814             return $restrictions[$key];
    6815         }
    6816         else
    6817         {
    6818             return null;
    6819         }
    6820     }
    6821 
    6822     function get_restrictions()
    6823     {
    6824         if ($this->restrictions !== null)
    6825         {
    6826             return $this->restrictions;
    6827         }
    6828         else
    6829         {
    6830             return null;
    6831         }
    6832     }
    6833 
    6834     function get_sampling_rate()
    6835     {
    6836         if ($this->samplingrate !== null)
    6837         {
    6838             return $this->samplingrate;
    6839         }
    6840         else
    6841         {
    6842             return null;
    6843         }
    6844     }
    6845 
    6846     function get_size()
    6847     {
    6848         $length = $this->get_length();
    6849         if ($length !== null)
    6850         {
    6851             return round($length/1048576, 2);
    6852         }
    6853         else
    6854         {
    6855             return null;
    6856         }
    6857     }
    6858 
    6859     function get_thumbnail($key = 0)
    6860     {
    6861         $thumbnails = $this->get_thumbnails();
    6862         if (isset($thumbnails[$key]))
    6863         {
    6864             return $thumbnails[$key];
    6865         }
    6866         else
    6867         {
    6868             return null;
    6869         }
    6870     }
    6871 
    6872     function get_thumbnails()
    6873     {
    6874         if ($this->thumbnails !== null)
    6875         {
    6876             return $this->thumbnails;
    6877         }
    6878         else
    6879         {
    6880             return null;
    6881         }
    6882     }
    6883 
    6884     function get_title()
    6885     {
    6886         if ($this->title !== null)
    6887         {
    6888             return $this->title;
    6889         }
    6890         else
    6891         {
    6892             return null;
    6893         }
    6894     }
    6895 
    6896     function get_type()
    6897     {
    6898         if ($this->type !== null)
    6899         {
    6900             return $this->type;
    6901         }
    6902         else
    6903         {
    6904             return null;
    6905         }
    6906     }
    6907 
    6908     function get_width()
    6909     {
    6910         if ($this->width !== null)
    6911         {
    6912             return $this->width;
    6913         }
    6914         else
    6915         {
    6916             return null;
    6917         }
    6918     }
    6919 
    6920     function native_embed($options='')
    6921     {
    6922         return $this->embed($options, true);
    6923     }
    6924 
    6925     /**
    6926      * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
    6927      */
    6928     function embed($options = '', $native = false)
    6929     {
    6930         // Set up defaults
    6931         $audio = '';
    6932         $video = '';
    6933         $alt = '';
    6934         $altclass = '';
    6935         $loop = 'false';
    6936         $width = 'auto';
    6937         $height = 'auto';
    6938         $bgcolor = '#ffffff';
    6939         $mediaplayer = '';
    6940         $widescreen = false;
    6941         $handler = $this->get_handler();
    6942         $type = $this->get_real_type();
    6943 
    6944         // Process options and reassign values as necessary
    6945         if (is_array($options))
    6946         {
    6947             extract($options);
    6948         }
    6949         else
    6950         {
    6951             $options = explode(',', $options);
    6952             foreach($options as $option)
    6953             {
    6954                 $opt = explode(':', $option, 2);
    6955                 if (isset($opt[0], $opt[1]))
    6956                 {
    6957                     $opt[0] = trim($opt[0]);
    6958                     $opt[1] = trim($opt[1]);
    6959                     switch ($opt[0])
    6960                     {
    6961                         case 'audio':
    6962                             $audio = $opt[1];
    6963                             break;
    6964 
    6965                         case 'video':
    6966                             $video = $opt[1];
    6967                             break;
    6968 
    6969                         case 'alt':
    6970                             $alt = $opt[1];
    6971                             break;
    6972 
    6973                         case 'altclass':
    6974                             $altclass = $opt[1];
    6975                             break;
    6976 
    6977                         case 'loop':
    6978                             $loop = $opt[1];
    6979                             break;
    6980 
    6981                         case 'width':
    6982                             $width = $opt[1];
    6983                             break;
    6984 
    6985                         case 'height':
    6986                             $height = $opt[1];
    6987                             break;
    6988 
    6989                         case 'bgcolor':
    6990                             $bgcolor = $opt[1];
    6991                             break;
    6992 
    6993                         case 'mediaplayer':
    6994                             $mediaplayer = $opt[1];
    6995                             break;
    6996 
    6997                         case 'widescreen':
    6998                             $widescreen = $opt[1];
    6999                             break;
    7000                     }
    7001                 }
    7002             }
    7003         }
    7004 
    7005         $mime = explode('/', $type, 2);
    7006         $mime = $mime[0];
    7007 
    7008         // Process values for 'auto'
    7009         if ($width === 'auto')
    7010         {
    7011             if ($mime === 'video')
    7012             {
    7013                 if ($height === 'auto')
    7014                 {
    7015                     $width = 480;
    7016                 }
    7017                 elseif ($widescreen)
    7018                 {
    7019                     $width = round((intval($height)/9)*16);
    7020                 }
    7021                 else
    7022                 {
    7023                     $width = round((intval($height)/3)*4);
    7024                 }
    7025             }
    7026             else
    7027             {
    7028                 $width = '100%';
    7029             }
    7030         }
    7031 
    7032         if ($height === 'auto')
    7033         {
    7034             if ($mime === 'audio')
    7035             {
    7036                 $height = 0;
    7037             }
    7038             elseif ($mime === 'video')
    7039             {
    7040                 if ($width === 'auto')
    7041                 {
    7042                     if ($widescreen)
    7043                     {
    7044                         $height = 270;
    7045                     }
    7046                     else
    7047                     {
    7048                         $height = 360;
    7049                     }
    7050                 }
    7051                 elseif ($widescreen)
    7052                 {
    7053                     $height = round((intval($width)/16)*9);
    7054                 }
    7055                 else
    7056                 {
    7057                     $height = round((intval($width)/4)*3);
    7058                 }
    7059             }
    7060             else
    7061             {
    7062                 $height = 376;
    7063             }
    7064         }
    7065         elseif ($mime === 'audio')
    7066         {
    7067             $height = 0;
    7068         }
    7069 
    7070         // Set proper placeholder value
    7071         if ($mime === 'audio')
    7072         {
    7073             $placeholder = $audio;
    7074         }
    7075         elseif ($mime === 'video')
    7076         {
    7077             $placeholder = $video;
    7078         }
    7079 
    7080         $embed = '';
    7081 
    7082         // Make sure the JS library is included
    7083         if (!$native)
    7084         {
    7085             static $javascript_outputted = null;
    7086             if (!$javascript_outputted && $this->javascript)
    7087             {
    7088                 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
    7089                 $javascript_outputted = true;
    7090             }
    7091         }
    7092 
    7093         // Odeo Feed MP3's
    7094         if ($handler === 'odeo')
    7095         {
    7096             if ($native)
    7097             {
    7098                 $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>';
    7099             }
    7100             else
    7101             {
    7102                 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
    7103             }
    7104         }
    7105 
    7106         // Flash
    7107         elseif ($handler === 'flash')
    7108         {
    7109             if ($native)
    7110             {
    7111                 $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>";
    7112             }
    7113             else
    7114             {
    7115                 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
    7116             }
    7117         }
    7118 
    7119         // Flash Media Player file types.
    7120         // Preferred handler for MP3 file types.
    7121         elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
    7122         {
    7123             $height += 20;
    7124             if ($native)
    7125             {
    7126                 $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>";
    7127             }
    7128             else
    7129             {
    7130                 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
    7131             }
    7132         }
    7133 
    7134         // QuickTime 7 file types.  Need to test with QuickTime 6.
    7135         // Only handle MP3's if the Flash Media Player is not present.
    7136         elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
    7137         {
    7138             $height += 16;
    7139             if ($native)
    7140             {
    7141                 if ($placeholder !== '')
    7142                 {
    7143                     $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>";
    7144                 }
    7145                 else
    7146                 {
    7147                     $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>";
    7148                 }
    7149             }
    7150             else
    7151             {
    7152                 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
    7153             }
    7154         }
    7155 
    7156         // Windows Media
    7157         elseif ($handler === 'wmedia')
    7158         {
    7159             $height += 45;
    7160             if ($native)
    7161             {
    7162                 $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>";
    7163             }
    7164             else
    7165             {
    7166                 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
    7167             }
    7168         }
    7169 
    7170         // Everything else
    7171         else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
    7172 
    7173         return $embed;
    7174     }
    7175 
    7176     function get_real_type($find_handler = false)
    7177     {
    7178         // If it's Odeo, let's get it out of the way.
    7179         if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
    7180         {
    7181             return 'odeo';
    7182         }
    7183 
    7184         // Mime-types by handler.
    7185         $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
    7186         $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
    7187         $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
    7188         $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
    7189         $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
    7190 
    7191         if ($this->get_type() !== null)
    7192         {
    7193             $type = strtolower($this->type);
    7194         }
    7195         else
    7196         {
    7197             $type = null;
    7198         }
    7199 
    7200         // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
    7201         if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
    7202         {
    7203             switch (strtolower($this->get_extension()))
    7204             {
    7205                 // Audio mime-types
    7206                 case 'aac':
    7207                 case 'adts':
    7208                     $type = 'audio/acc';
    7209                     break;
    7210 
    7211                 case 'aif':
    7212                 case 'aifc':
    7213                 case 'aiff':
    7214                 case 'cdda':
    7215                     $type = 'audio/aiff';
    7216                     break;
    7217 
    7218                 case 'bwf':
    7219                     $type = 'audio/wav';
    7220                     break;
    7221 
    7222                 case 'kar':
    7223                 case 'mid':
    7224                 case 'midi':
    7225                 case 'smf':
    7226                     $type = 'audio/midi';
    7227                     break;
    7228 
    7229                 case 'm4a':
    7230                     $type = 'audio/x-m4a';
    7231                     break;
    7232 
    7233                 case 'mp3':
    7234                 case 'swa':
    7235                     $type = 'audio/mp3';
    7236                     break;
    7237 
    7238                 case 'wav':
    7239                     $type = 'audio/wav';
    7240                     break;
    7241 
    7242                 case 'wax':
    7243                     $type = 'audio/x-ms-wax';
    7244                     break;
    7245 
    7246                 case 'wma':
    7247                     $type = 'audio/x-ms-wma';
    7248                     break;
    7249 
    7250                 // Video mime-types
    7251                 case '3gp':
    7252                 case '3gpp':
    7253                     $type = 'video/3gpp';
    7254                     break;
    7255 
    7256                 case '3g2':
    7257                 case '3gp2':
    7258                     $type = 'video/3gpp2';
    7259                     break;
    7260 
    7261                 case 'asf':
    7262                     $type = 'video/x-ms-asf';
    7263                     break;
    7264 
    7265                 case 'flv':
    7266                     $type = 'video/x-flv';
    7267                     break;
    7268 
    7269                 case 'm1a':
    7270                 case 'm1s':
    7271                 case 'm1v':
    7272                 case 'm15':
    7273                 case 'm75':
    7274                 case 'mp2':
    7275                 case 'mpa':
    7276                 case 'mpeg':
    7277                 case 'mpg':
    7278                 case 'mpm':
    7279                 case 'mpv':
    7280                     $type = 'video/mpeg';
    7281                     break;
    7282 
    7283                 case 'm4v':
    7284                     $type = 'video/x-m4v';
    7285                     break;
    7286 
    7287                 case 'mov':
    7288                 case 'qt':
    7289                     $type = 'video/quicktime';
    7290                     break;
    7291 
    7292                 case 'mp4':
    7293                 case 'mpg4':
    7294                     $type = 'video/mp4';
    7295                     break;
    7296 
    7297                 case 'sdv':
    7298                     $type = 'video/sd-video';
    7299                     break;
    7300 
    7301                 case 'wm':
    7302                     $type = 'video/x-ms-wm';
    7303                     break;
    7304 
    7305                 case 'wmv':
    7306                     $type = 'video/x-ms-wmv';
    7307                     break;
    7308 
    7309                 case 'wvx':
    7310                     $type = 'video/x-ms-wvx';
    7311                     break;
    7312 
    7313                 // Flash mime-types
    7314                 case 'spl':
    7315                     $type = 'application/futuresplash';
    7316                     break;
    7317 
    7318                 case 'swf':
    7319                     $type = 'application/x-shockwave-flash';
    7320                     break;
    7321             }
    7322         }
    7323 
    7324         if ($find_handler)
    7325         {
    7326             if (in_array($type, $types_flash))
    7327             {
    7328                 return 'flash';
    7329             }
    7330             elseif (in_array($type, $types_fmedia))
    7331             {
    7332                 return 'fmedia';
    7333             }
    7334             elseif (in_array($type, $types_quicktime))
    7335             {
    7336                 return 'quicktime';
    7337             }
    7338             elseif (in_array($type, $types_wmedia))
    7339             {
    7340                 return 'wmedia';
    7341             }
    7342             elseif (in_array($type, $types_mp3))
    7343             {
    7344                 return 'mp3';
    7345             }
    7346             else
    7347             {
    7348                 return null;
    7349             }
    7350         }
    7351         else
    7352         {
    7353             return $type;
    7354         }
    7355     }
    7356 }
    7357 
    7358 class SimplePie_Caption
    7359 {
    7360     var $type;
    7361     var $lang;
    7362     var $startTime;
    7363     var $endTime;
    7364     var $text;
    7365 
    7366     // Constructor, used to input the data
    7367     function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
    7368     {
    7369         $this->type = $type;
    7370         $this->lang = $lang;
    7371         $this->startTime = $startTime;
    7372         $this->endTime = $endTime;
    7373         $this->text = $text;
    7374     }
    7375 
    7376     function __toString()
    7377     {
    7378         // There is no $this->data here
    7379         return md5(serialize($this));
    7380     }
    7381 
    7382     function get_endtime()
    7383     {
    7384         if ($this->endTime !== null)
    7385         {
    7386             return $this->endTime;
    7387         }
    7388         else
    7389         {
    7390             return null;
    7391         }
    7392     }
    7393 
    7394     function get_language()
    7395     {
    7396         if ($this->lang !== null)
    7397         {
    7398             return $this->lang;
    7399         }
    7400         else
    7401         {
    7402             return null;
    7403         }
    7404     }
    7405 
    7406     function get_starttime()
    7407     {
    7408         if ($this->startTime !== null)
    7409         {
    7410             return $this->startTime;
    7411         }
    7412         else
    7413         {
    7414             return null;
    7415         }
    7416     }
    7417 
    7418     function get_text()
    7419     {
    7420         if ($this->text !== null)
    7421         {
    7422             return $this->text;
    7423         }
    7424         else
    7425         {
    7426             return null;
    7427         }
    7428     }
    7429 
    7430     function get_type()
    7431     {
    7432         if ($this->type !== null)
    7433         {
    7434             return $this->type;
    7435         }
    7436         else
    7437         {
    7438             return null;
    7439         }
    7440     }
    7441 }
    7442 
    7443 class SimplePie_Credit
    7444 {
    7445     var $role;
    7446     var $scheme;
    7447     var $name;
    7448 
    7449     // Constructor, used to input the data
    7450     function SimplePie_Credit($role = null, $scheme = null, $name = null)
    7451     {
    7452         $this->role = $role;
    7453         $this->scheme = $scheme;
    7454         $this->name = $name;
    7455     }
    7456 
    7457     function __toString()
    7458     {
    7459         // There is no $this->data here
    7460         return md5(serialize($this));
    7461     }
    7462 
    7463     function get_role()
    7464     {
    7465         if ($this->role !== null)
    7466         {
    7467             return $this->role;
    7468         }
    7469         else
    7470         {
    7471             return null;
    7472         }
    7473     }
    7474 
    7475     function get_scheme()
    7476     {
    7477         if ($this->scheme !== null)
    7478         {
    7479             return $this->scheme;
    7480         }
    7481         else
    7482         {
    7483             return null;
    7484         }
    7485     }
    7486 
    7487     function get_name()
    7488     {
    7489         if ($this->name !== null)
    7490         {
    7491             return $this->name;
    7492         }
    7493         else
    7494         {
    7495             return null;
    7496         }
    7497     }
    7498 }
    7499 
    7500 class SimplePie_Copyright
    7501 {
    7502     var $url;
    7503     var $label;
    7504 
    7505     // Constructor, used to input the data
    7506     function SimplePie_Copyright($url = null, $label = null)
    7507     {
    7508         $this->url = $url;
    7509         $this->label = $label;
    7510     }
    7511 
    7512     function __toString()
    7513     {
    7514         // There is no $this->data here
    7515         return md5(serialize($this));
    7516     }
    7517 
    7518     function get_url()
    7519     {
    7520         if ($this->url !== null)
    7521         {
    7522             return $this->url;
    7523         }
    7524         else
    7525         {
    7526             return null;
    7527         }
    7528     }
    7529 
    7530     function get_attribution()
    7531     {
    7532         if ($this->label !== null)
    7533         {
    7534             return $this->label;
    7535         }
    7536         else
    7537         {
    7538             return null;
    7539         }
    7540     }
    7541 }
    7542 
    7543 class SimplePie_Rating
    7544 {
    7545     var $scheme;
    7546     var $value;
    7547 
    7548     // Constructor, used to input the data
    7549     function SimplePie_Rating($scheme = null, $value = null)
    7550     {
    7551         $this->scheme = $scheme;
    7552         $this->value = $value;
    7553     }
    7554 
    7555     function __toString()
    7556     {
    7557         // There is no $this->data here
    7558         return md5(serialize($this));
    7559     }
    7560 
    7561     function get_scheme()
    7562     {
    7563         if ($this->scheme !== null)
    7564         {
    7565             return $this->scheme;
    7566         }
    7567         else
    7568         {
    7569             return null;
    7570         }
    7571     }
    7572 
    7573     function get_value()
    7574     {
    7575         if ($this->value !== null)
    7576         {
    7577             return $this->value;
    7578         }
    7579         else
    7580         {
    7581             return null;
    7582         }
    7583     }
    7584 }
    7585 
    7586 class SimplePie_Restriction
    7587 {
    7588     var $relationship;
    7589     var $type;
    7590     var $value;
    7591 
    7592     // Constructor, used to input the data
    7593     function SimplePie_Restriction($relationship = null, $type = null, $value = null)
    7594     {
    7595         $this->relationship = $relationship;
    7596         $this->type = $type;
    7597         $this->value = $value;
    7598     }
    7599 
    7600     function __toString()
    7601     {
    7602         // There is no $this->data here
    7603         return md5(serialize($this));
    7604     }
    7605 
    7606     function get_relationship()
    7607     {
    7608         if ($this->relationship !== null)
    7609         {
    7610             return $this->relationship;
    7611         }
    7612         else
    7613         {
    7614             return null;
    7615         }
    7616     }
    7617 
    7618     function get_type()
    7619     {
    7620         if ($this->type !== null)
    7621         {
    7622             return $this->type;
    7623         }
    7624         else
    7625         {
    7626             return null;
    7627         }
    7628     }
    7629 
    7630     function get_value()
    7631     {
    7632         if ($this->value !== null)
    7633         {
    7634             return $this->value;
    7635         }
    7636         else
    7637         {
    7638             return null;
    7639         }
    7640     }
    7641 }
    7642 
    7643 /**
    7644  * @todo Move to properly supporting RFC2616 (HTTP/1.1)
    7645  */
    7646 class SimplePie_File
    7647 {
    7648     var $url;
    7649     var $useragent;
    7650     var $success = true;
    7651     var $headers = array();
    7652     var $body;
    7653     var $status_code;
    7654     var $redirects = 0;
    7655     var $error;
    7656     var $method = SIMPLEPIE_FILE_SOURCE_NONE;
    7657 
    7658     function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
    7659     {
    7660         if (class_exists('idna_convert'))
    7661         {
    7662             $idn =& new idna_convert;
    7663             $parsed = SimplePie_Misc::parse_url($url);
    7664             $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
    7665         }
    7666         $this->url = $url;
    7667         $this->useragent = $useragent;
    7668         if (preg_match('/^http(s)?:\/\//i', $url))
    7669         {
    7670             if ($useragent === null)
    7671             {
    7672                 $useragent = ini_get('user_agent');
    7673                 $this->useragent = $useragent;
    7674             }
    7675             if (!is_array($headers))
    7676             {
    7677                 $headers = array();
    7678             }
    7679             if (!$force_fsockopen && function_exists('curl_exec'))
    7680             {
    7681                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
    7682                 $fp = curl_init();
    7683                 $headers2 = array();
    7684                 foreach ($headers as $key => $value)
    7685                 {
    7686                     $headers2[] = "$key: $value";
    7687                 }
    7688                 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
    7689                 {
    7690                     curl_setopt($fp, CURLOPT_ENCODING, '');
    7691                 }
    7692                 curl_setopt($fp, CURLOPT_URL, $url);
    7693                 curl_setopt($fp, CURLOPT_HEADER, 1);
    7694                 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
    7695                 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
    7696                 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
    7697                 curl_setopt($fp, CURLOPT_REFERER, $url);
    7698                 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
    7699                 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
    7700                 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
    7701                 {
    7702                     curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
    7703                     curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
    7704                 }
    7705 
    7706                 $this->headers = curl_exec($fp);
    7707                 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
    7708                 {
    7709                     curl_setopt($fp, CURLOPT_ENCODING, 'none');
    7710                     $this->headers = curl_exec($fp);
    7711                 }
    7712                 if (curl_errno($fp))
    7713                 {
    7714                     $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
    7715                     $this->success = false;
    7716                 }
    7717                 else
    7718                 {
    7719                     $info = curl_getinfo($fp);
    7720                     curl_close($fp);
    7721                     $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
    7722                     $this->headers = array_pop($this->headers);
    7723                     $parser =& new SimplePie_HTTP_Parser($this->headers);
    7724                     if ($parser->parse())
    7725                     {
    7726                         $this->headers = $parser->headers;
    7727                         $this->body = $parser->body;
    7728                         $this->status_code = $parser->status_code;
    7729                         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)
    7730                         {
    7731                             $this->redirects++;
    7732                             $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
    7733                             return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
    7734                         }
    7735                     }
    7736                 }
    7737             }
    7738             else
    7739             {
    7740                 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
    7741                 $url_parts = parse_url($url);
    7742                 $socket_host = $url_parts['host'];
    7743                 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
    7744                 {
    7745                     $socket_host = "ssl://$url_parts[host]";
    7746                     $url_parts['port'] = 443;
    7747                 }
    7748                 if (!isset($url_parts['port']))
    7749                 {
    7750                     $url_parts['port'] = 80;
    7751                 }
    7752                 $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
    7753                 if (!$fp)
    7754                 {
    7755                     $this->error = 'fsockopen error: ' . $errstr;
    7756                     $this->success = false;
    7757                 }
    7758                 else
    7759                 {
    7760                     stream_set_timeout($fp, $timeout);
    7761                     if (isset($url_parts['path']))
    7762                     {
    7763                         if (isset($url_parts['query']))
    7764                         {
    7765                             $get = "$url_parts[path]?$url_parts[query]";
    7766                         }
    7767                         else
    7768                         {
    7769                             $get = $url_parts['path'];
    7770                         }
    7771                     }
    7772                     else
    7773                     {
    7774                         $get = '/';
    7775                     }
    7776                     $out = "GET $get HTTP/1.0\r\n";
    7777                     $out .= "Host: $url_parts[host]\r\n";
    7778                     $out .= "User-Agent: $useragent\r\n";
    7779                     if (extension_loaded('zlib'))
    7780                     {
    7781                         $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
    7782                     }
    7783 
    7784                     if (isset($url_parts['user']) && isset($url_parts['pass']))
    7785                     {
    7786                         $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
    7787                     }
    7788                     foreach ($headers as $key => $value)
    7789                     {
    7790                         $out .= "$key: $value\r\n";
    7791                     }
    7792                     $out .= "Connection: Close\r\n\r\n";
    7793                     fwrite($fp, $out);
    7794 
    7795                     $info = stream_get_meta_data($fp);
    7796 
    7797                     $this->headers = '';
    7798                     while (!$info['eof'] && !$info['timed_out'])
    7799                     {
    7800                         $this->headers .= fread($fp, 1160);
    7801                         $info = stream_get_meta_data($fp);
    7802                     }
    7803                     if (!$info['timed_out'])
    7804                     {
    7805                         $parser =& new SimplePie_HTTP_Parser($this->headers);
    7806                         if ($parser->parse())
    7807                         {
    7808                             $this->headers = $parser->headers;
    7809                             $this->body = $parser->body;
    7810                             $this->status_code = $parser->status_code;
    7811                             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)
    7812                             {
    7813                                 $this->redirects++;
    7814                                 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
    7815                                 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
    7816                             }
    7817                             if (isset($this->headers['content-encoding']))
    7818                             {
    7819                                 // Hey, we act dumb elsewhere, so let's do that here too
    7820                                 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
    7821                                 {
    7822                                     case 'gzip':
    7823                                     case 'x-gzip':
    7824                                         $decoder =& new SimplePie_gzdecode($this->body);
    7825                                         if (!$decoder->parse())
    7826                                         {
    7827                                             $this->error = 'Unable to decode HTTP "gzip" stream';
    7828                                             $this->success = false;
    7829                                         }
    7830                                         else
    7831                                         {
    7832                                             $this->body = $decoder->data;
    7833                                         }
    7834                                         break;
    7835 
    7836                                     case 'deflate':
    7837                                         if (($body = gzuncompress($this->body)) === false)
    7838                                         {
    7839                                             if (($body = gzinflate($this->body)) === false)
    7840                                             {
    7841                                                 $this->error = 'Unable to decode HTTP "deflate" stream';
    7842                                                 $this->success = false;
    7843                                             }
    7844                                         }
    7845                                         $this->body = $body;
    7846                                         break;
    7847 
    7848                                     default:
    7849                                         $this->error = 'Unknown content coding';
    7850                                         $this->success = false;
    7851                                 }
    7852                             }
    7853                         }
    7854                     }
    7855                     else
    7856                     {
    7857                         $this->error = 'fsocket timed out';
    7858                         $this->success = false;
    7859                     }
    7860                     fclose($fp);
    7861                 }
    7862             }
    7863         }
    7864         else
    7865         {
    7866             $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
    7867             if (!$this->body = file_get_contents($url))
    7868             {
    7869                 $this->error = 'file_get_contents could not read the file';
    7870                 $this->success = false;
    7871             }
    7872         }
    7873     }
    7874 }
    7875 
    7876 /**
    7877  * HTTP Response Parser
    7878  *
    7879  * @package SimplePie
    7880  */
    7881 class SimplePie_HTTP_Parser
    7882 {
    7883     /**
    7884      * HTTP Version
    7885      *
    7886      * @access public
    7887      * @var float
    7888      */
    7889     var $http_version = 0.0;
    7890 
    7891     /**
    7892      * Status code
    7893      *
    7894      * @access public
    7895      * @var int
    7896      */
    7897     var $status_code = 0;
    7898 
    7899     /**
    7900      * Reason phrase
    7901      *
    7902      * @access public
    7903      * @var string
    7904      */
    7905     var $reason = '';
    7906 
    7907     /**
    7908      * Key/value pairs of the headers
    7909      *
    7910      * @access public
    7911      * @var array
    7912      */
    7913     var $headers = array();
    7914 
    7915     /**
    7916      * Body of the response
    7917      *
    7918      * @access public
    7919      * @var string
    7920      */
    7921     var $body = '';
    7922 
    7923     /**
    7924      * Current state of the state machine
    7925      *
    7926      * @access private
    7927      * @var string
    7928      */
    7929     var $state = 'http_version';
    7930 
    7931     /**
    7932      * Input data
    7933      *
    7934      * @access private
    7935      * @var string
    7936      */
    7937     var $data = '';
    7938 
    7939     /**
    7940      * Input data length (to avoid calling strlen() everytime this is needed)
    7941      *
    7942      * @access private
    7943      * @var int
    7944      */
    7945     var $data_length = 0;
    7946 
    7947     /**
    7948      * Current position of the pointer
    7949      *
    7950      * @var int
    7951      * @access private
    7952      */
    7953     var $position = 0;
    7954 
    7955     /**
    7956      * Name of the hedaer currently being parsed
    7957      *
    7958      * @access private
    7959      * @var string
    7960      */
    7961     var $name = '';
    7962 
    7963     /**
    7964      * Value of the hedaer currently being parsed
    7965      *
    7966      * @access private
    7967      * @var string
    7968      */
    7969     var $value = '';
    7970 
    7971     /**
    7972      * Create an instance of the class with the input data
    7973      *
    7974      * @access public
    7975      * @param string $data Input data
    7976      */
    7977     function SimplePie_HTTP_Parser($data)
    7978     {
    7979         $this->data = $data;
    7980         $this->data_length = strlen($this->data);
    7981     }
    7982 
    7983     /**
    7984      * Parse the input data
    7985      *
    7986      * @access public
    7987      * @return bool true on success, false on failure
    7988      */
    7989     function parse()
    7990     {
    7991         while ($this->state && $this->state !== 'emit' && $this->has_data())
    7992         {
    7993             $state = $this->state;
    7994             $this->$state();
    7995         }
    7996         $this->data = '';
    7997         if ($this->state === 'emit' || $this->state === 'body')
    7998         {
    7999             return true;
    8000         }
    8001         else
    8002         {
    8003             $this->http_version = '';
    8004             $this->status_code = '';
    8005             $this->reason = '';
    8006             $this->headers = array();
    8007             $this->body = '';
    8008             return false;
    8009         }
    8010     }
    8011 
    8012     /**
    8013      * Check whether there is data beyond the pointer
    8014      *
    8015      * @access private
    8016      * @return bool true if there is further data, false if not
    8017      */
    8018     function has_data()
    8019     {
    8020         return (bool) ($this->position < $this->data_length);
    8021     }
    8022 
    8023     /**
    8024      * See if the next character is LWS
    8025      *
    8026      * @access private
    8027      * @return bool true if the next character is LWS, false if not
    8028      */
    8029     function is_linear_whitespace()
    8030     {
    8031         return (bool) ($this->data[$this->position] === "\x09"
    8032             || $this->data[$this->position] === "\x20"
    8033             || ($this->data[$this->position] === "\x0A"
    8034                 && isset($this->data[$this->position + 1])
    8035                 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
    8036     }
    8037 
    8038     /**
    8039      * Parse the HTTP version
    8040      *
    8041      * @access private
    8042      */
    8043     function http_version()
    8044     {
    8045         if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
    8046         {
    8047             $len = strspn($this->data, '0123456789.', 5);
    8048             $this->http_version = substr($this->data, 5, $len);
    8049             $this->position += 5 + $len;
    8050             if (substr_count($this->http_version, '.') <= 1)
    8051             {
    8052                 $this->http_version = (float) $this->http_version;
    8053                 $this->position += strspn($this->data, "\x09\x20", $this->position);
    8054                 $this->state = 'status';
    8055             }
    8056             else
    8057             {
    8058                 $this->state = false;
    8059             }
    8060         }
    8061         else
    8062         {
    8063             $this->state = false;
    8064         }
    8065     }
    8066 
    8067     /**
    8068      * Parse the status code
    8069      *
    8070      * @access private
    8071      */
    8072     function status()
    8073     {
    8074         if ($len = strspn($this->data, '0123456789', $this->position))
    8075         {
    8076             $this->status_code = (int) substr($this->data, $this->position, $len);
    8077             $this->position += $len;
    8078             $this->state = 'reason';
    8079         }
    8080         else
    8081         {
    8082             $this->state = false;
    8083         }
    8084     }
    8085 
    8086     /**
    8087      * Parse the reason phrase
    8088      *
    8089      * @access private
    8090      */
    8091     function reason()
    8092     {
    8093         $len = strcspn($this->data, "\x0A", $this->position);
    8094         $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
    8095         $this->position += $len + 1;
    8096         $this->state = 'new_line';
    8097     }
    8098 
    8099     /**
    8100      * Deal with a new line, shifting data around as needed
    8101      *
    8102      * @access private
    8103      */
    8104     function new_line()
    8105     {
    8106         $this->value = trim($this->value, "\x0D\x20");
    8107         if ($this->name !== '' && $this->value !== '')
    8108         {
    8109             $this->name = strtolower($this->name);
    8110             if (isset($this->headers[$this->name]))
    8111             {
    8112                 $this->headers[$this->name] .= ', ' . $this->value;
    8113             }
    8114             else
    8115             {
    8116                 $this->headers[$this->name] = $this->value;
    8117             }
    8118         }
    8119         $this->name = '';
    8120         $this->value = '';
    8121         if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
    8122         {
    8123             $this->position += 2;
    8124             $this->state = 'body';
    8125         }
    8126         elseif ($this->data[$this->position] === "\x0A")
    8127         {
    8128             $this->position++;
    8129             $this->state = 'body';
    8130         }
    8131         else
    8132         {
    8133             $this->state = 'name';
    8134         }
    8135     }
    8136 
    8137     /**
    8138      * Parse a header name
    8139      *
    8140      * @access private
    8141      */
    8142     function name()
    8143     {
    8144         $len = strcspn($this->data, "\x0A:", $this->position);
    8145         if (isset($this->data[$this->position + $len]))
    8146         {
    8147             if ($this->data[$this->position + $len] === "\x0A")
    8148             {
    8149                 $this->position += $len;
    8150                 $this->state = 'new_line';
    8151             }
    8152             else
    8153             {
    8154                 $this->name = substr($this->data, $this->position, $len);
    8155                 $this->position += $len + 1;
    8156                 $this->state = 'value';
    8157             }
    8158         }
    8159         else
    8160         {
    8161             $this->state = false;
    8162         }
    8163     }
    8164 
    8165     /**
    8166      * Parse LWS, replacing consecutive LWS characters with a single space
    8167      *
    8168      * @access private
    8169      */
    8170     function linear_whitespace()
    8171     {
    8172         do
    8173         {
    8174             if (substr($this->data, $this->position, 2) === "\x0D\x0A")
    8175             {
    8176                 $this->position += 2;
    8177             }
    8178             elseif ($this->data[$this->position] === "\x0A")
    8179             {
    8180                 $this->position++;
    8181             }
    8182             $this->position += strspn($this->data, "\x09\x20", $this->position);
    8183         } while ($this->has_data() && $this->is_linear_whitespace());
    8184         $this->value .= "\x20";
    8185     }
    8186 
    8187     /**
    8188      * See what state to move to while within non-quoted header values
    8189      *
    8190      * @access private
    8191      */
    8192     function value()
    8193     {
    8194         if ($this->is_linear_whitespace())
    8195         {
    8196             $this->linear_whitespace();
    8197         }
    8198         else
    8199         {
    8200             switch ($this->data[$this->position])
    8201             {
    8202                 case '"':
    8203                     $this->position++;
    8204                     $this->state = 'quote';
    8205                     break;
    8206 
    8207                 case "\x0A":
    8208                     $this->position++;
    8209                     $this->state = 'new_line';
    8210                     break;
    8211 
    8212                 default:
    8213                     $this->state = 'value_char';
    8214                     break;
    8215             }
    8216         }
    8217     }
    8218 
    8219     /**
    8220      * Parse a header value while outside quotes
    8221      *
    8222      * @access private
    8223      */
    8224     function value_char()
    8225     {
    8226         $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
    8227         $this->value .= substr($this->data, $this->position, $len);
    8228         $this->position += $len;
    8229         $this->state = 'value';
    8230     }
    8231 
    8232     /**
    8233      * See what state to move to while within quoted header values
    8234      *
    8235      * @access private
    8236      */
    8237     function quote()
    8238     {
    8239         if ($this->is_linear_whitespace())
    8240         {
    8241             $this->linear_whitespace();
    8242         }
    8243         else
    8244         {
    8245             switch ($this->data[$this->position])
    8246             {
    8247                 case '"':
    8248                     $this->position++;
    8249                     $this->state = 'value';
    8250                     break;
    8251 
    8252                 case "\x0A":
    8253                     $this->position++;
    8254                     $this->state = 'new_line';
    8255                     break;
    8256 
    8257                 case '\\':
    8258                     $this->position++;
    8259                     $this->state = 'quote_escaped';
    8260                     break;
    8261 
    8262                 default:
    8263                     $this->state = 'quote_char';
    8264                     break;
    8265             }
    8266         }
    8267     }
    8268 
    8269     /**
    8270      * Parse a header value while within quotes
    8271      *
    8272      * @access private
    8273      */
    8274     function quote_char()
    8275     {
    8276         $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
    8277         $this->value .= substr($this->data, $this->position, $len);
    8278         $this->position += $len;
    8279         $this->state = 'value';
    8280     }
    8281 
    8282     /**
    8283      * Parse an escaped character within quotes
    8284      *
    8285      * @access private
    8286      */
    8287     function quote_escaped()
    8288     {
    8289         $this->value .= $this->data[$this->position];
    8290         $this->position++;
    8291         $this->state = 'quote';
    8292     }
    8293 
    8294     /**
    8295      * Parse the body
    8296      *
    8297      * @access private
    8298      */
    8299     function body()
    8300     {
    8301         $this->body = substr($this->data, $this->position);
    8302         $this->state = 'emit';
    8303     }
    8304 }
    8305 
    8306 /**
    8307  * gzdecode
    8308  *
    8309  * @package SimplePie
    8310  */
    8311 class SimplePie_gzdecode
    8312 {
    8313     /**
    8314      * Compressed data
    8315      *
    8316      * @access private
    8317      * @see gzdecode::$data
    8318      */
    8319     var $compressed_data;
    8320 
    8321     /**
    8322      * Size of compressed data
    8323      *
    8324      * @access private
    8325      */
    8326     var $compressed_size;
    8327 
    8328     /**
    8329      * Minimum size of a valid gzip string
    8330      *
    8331      * @access private
    8332      */
    8333     var $min_compressed_size = 18;
    8334 
    8335     /**
    8336      * Current position of pointer
    8337      *
    8338      * @access private
    8339      */
    8340     var $position = 0;
    8341 
    8342     /**
    8343      * Flags (FLG)
    8344      *
    8345      * @access private
    8346      */
    8347     var $flags;
    8348 
    8349     /**
    8350      * Uncompressed data
    8351      *
    8352      * @access public
    8353      * @see gzdecode::$compressed_data
    8354      */
    8355     var $data;
    8356 
    8357     /**
    8358      * Modified time
    8359      *
    8360      * @access public
    8361      */
    8362     var $MTIME;
    8363 
    8364     /**
    8365      * Extra Flags
    8366      *
    8367      * @access public
    8368      */
    8369     var $XFL;
    8370 
    8371     /**
    8372      * Operating System
    8373      *
    8374      * @access public
    8375      */
    8376     var $OS;
    8377 
    8378     /**
    8379      * Subfield ID 1
    8380      *
    8381      * @access public
    8382      * @see gzdecode::$extra_field
    8383      * @see gzdecode::$SI2
    8384      */
    8385     var $SI1;
    8386 
    8387     /**
    8388      * Subfield ID 2
    8389      *
    8390      * @access public
    8391      * @see gzdecode::$extra_field
    8392      * @see gzdecode::$SI1
    8393      */
    8394     var $SI2;
    8395 
    8396     /**
    8397      * Extra field content
    8398      *
    8399      * @access public
    8400      * @see gzdecode::$SI1
    8401      * @see gzdecode::$SI2
    8402      */
    8403     var $extra_field;
    8404 
    8405     /**
    8406      * Original filename
    8407      *
    8408      * @access public
    8409      */
    8410     var $filename;
    8411 
    8412     /**
    8413      * Human readable comment
    8414      *
    8415      * @access public
    8416      */
    8417     var $comment;
    8418 
    8419     /**
    8420      * Don't allow anything to be set
    8421      *
    8422      * @access public
    8423      */
    8424     function __set($name, $value)
    8425     {
    8426         trigger_error("Cannot write property $name", E_USER_ERROR);
    8427     }
    8428 
    8429     /**
    8430      * Set the compressed string and related properties
    8431      *
    8432      * @access public
    8433      */
    8434     function SimplePie_gzdecode($data)
    8435     {
    8436         $this->compressed_data = $data;
    8437         $this->compressed_size = strlen($data);
    8438     }
    8439 
    8440     /**
    8441      * Decode the GZIP stream
    8442      *
    8443      * @access public
    8444      */
    8445     function parse()
    8446     {
    8447         if ($this->compressed_size >= $this->min_compressed_size)
    8448         {
    8449             // Check ID1, ID2, and CM
    8450             if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
    8451             {
    8452                 return false;
    8453             }
    8454 
    8455             // Get the FLG (FLaGs)
    8456             $this->flags = ord($this->compressed_data[3]);
    8457 
    8458             // FLG bits above (1 << 4) are reserved
    8459             if ($this->flags > 0x1F)
    8460             {
    8461                 return false;
    8462             }
    8463 
    8464             // Advance the pointer after the above
    8465             $this->position += 4;
    8466 
    8467             // MTIME
    8468             $mtime = substr($this->compressed_data, $this->position, 4);
    8469             // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
    8470             if (current(unpack('S', "\x00\x01")) === 1)
    8471             {
    8472                 $mtime = strrev($mtime);
    8473             }
    8474             $this->MTIME = current(unpack('l', $mtime));
    8475             $this->position += 4;
    8476 
    8477             // Get the XFL (eXtra FLags)
    8478             $this->XFL = ord($this->compressed_data[$this->position++]);
    8479 
    8480             // Get the OS (Operating System)
    8481             $this->OS = ord($this->compressed_data[$this->position++]);
    8482 
    8483             // Parse the FEXTRA
    8484             if ($this->flags & 4)
    8485             {
    8486                 // Read subfield IDs
    8487                 $this->SI1 = $this->compressed_data[$this->position++];
    8488                 $this->SI2 = $this->compressed_data[$this->position++];
    8489 
    8490                 // SI2 set to zero is reserved for future use
    8491                 if ($this->SI2 === "\x00")
    8492                 {
    8493                     return false;
    8494                 }
    8495 
    8496                 // Get the length of the extra field
    8497                 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
    8498                 $this->position += 2;
    8499 
    8500                 // Check the length of the string is still valid
    8501                 $this->min_compressed_size += $len + 4;
    8502                 if ($this->compressed_size >= $this->min_compressed_size)
    8503                 {
    8504                     // Set the extra field to the given data
    8505                     $this->extra_field = substr($this->compressed_data, $this->position, $len);
    8506                     $this->position += $len;
    8507                 }
    8508                 else
    8509                 {
    8510                     return false;
    8511                 }
    8512             }
    8513 
    8514             // Parse the FNAME
    8515             if ($this->flags & 8)
    8516             {
    8517                 // Get the length of the filename
    8518                 $len = strcspn($this->compressed_data, "\x00", $this->position);
    8519 
    8520                 // Check the length of the string is still valid
    8521                 $this->min_compressed_size += $len + 1;
    8522                 if ($this->compressed_size >= $this->min_compressed_size)
    8523                 {
    8524                     // Set the original filename to the given string
    8525                     $this->filename = substr($this->compressed_data, $this->position, $len);
    8526                     $this->position += $len + 1;
    8527                 }
    8528                 else
    8529                 {
    8530                     return false;
    8531                 }
    8532             }
    8533 
    8534             // Parse the FCOMMENT
    8535             if ($this->flags & 16)
    8536             {
    8537                 // Get the length of the comment
    8538                 $len = strcspn($this->compressed_data, "\x00", $this->position);
    8539 
    8540                 // Check the length of the string is still valid
    8541                 $this->min_compressed_size += $len + 1;
    8542                 if ($this->compressed_size >= $this->min_compressed_size)
    8543                 {
    8544                     // Set the original comment to the given string
    8545                     $this->comment = substr($this->compressed_data, $this->position, $len);
    8546                     $this->position += $len + 1;
    8547                 }
    8548                 else
    8549                 {
    8550                     return false;
    8551                 }
    8552             }
    8553 
    8554             // Parse the FHCRC
    8555             if ($this->flags & 2)
    8556             {
    8557                 // Check the length of the string is still valid
    8558                 $this->min_compressed_size += $len + 2;
    8559                 if ($this->compressed_size >= $this->min_compressed_size)
    8560                 {
    8561                     // Read the CRC
    8562                     $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
    8563 
    8564                     // Check the CRC matches
    8565                     if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
    8566                     {
    8567                         $this->position += 2;
    8568                     }
    8569                     else
    8570                     {
    8571                         return false;
    8572                     }
    8573                 }
    8574                 else
    8575                 {
    8576                     return false;
    8577                 }
    8578             }
    8579 
    8580             // Decompress the actual data
    8581             if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
    8582             {
    8583                 return false;
    8584             }
    8585             else
    8586             {
    8587                 $this->position = $this->compressed_size - 8;
    8588             }
    8589 
    8590             // Check CRC of data
    8591             $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
    8592             $this->position += 4;
    8593             /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
    8594             {
    8595                 return false;
    8596             }*/
    8597 
    8598             // Check ISIZE of data
    8599             $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
    8600             $this->position += 4;
    8601             if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
    8602             {
    8603                 return false;
    8604             }
    8605 
    8606             // Wow, against all odds, we've actually got a valid gzip string
    8607             return true;
    8608         }
    8609         else
    8610         {
    8611             return false;
    8612         }
    8613     }
    8614 }
    8615 
    8616 class SimplePie_Cache
    8617 {
    8618     /**
    8619      * Don't call the constructor. Please.
    8620      *
    8621      * @access private
    8622      */
    8623     function SimplePie_Cache()
    8624     {
    8625         trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
    8626     }
    8627 
    8628     /**
    8629      * Create a new SimplePie_Cache object
    8630      *
    8631      * @static
    8632      * @access public
    8633      */
    8634     function create($location, $filename, $extension)
    8635     {
    8636         $location_iri =& new SimplePie_IRI($location);
    8637         switch ($location_iri->get_scheme())
    8638         {
    8639             case 'mysql':
    8640                 if (extension_loaded('mysql'))
    8641                 {
    8642                     return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
    8643                 }
    8644                 break;
    8645 
    8646             default:
    8647                 return new SimplePie_Cache_File($location, $filename, $extension);
    8648         }
    8649     }
    8650 }
    8651 
    8652 class SimplePie_Cache_File
    8653 {
    8654     var $location;
    8655     var $filename;
    8656     var $extension;
    8657     var $name;
    8658 
    8659     function SimplePie_Cache_File($location, $filename, $extension)
    8660     {
    8661         $this->location = $location;
    8662         $this->filename = $filename;
    8663         $this->extension = $extension;
    8664         $this->name = "$this->location/$this->filename.$this->extension";
    8665     }
    8666 
    8667     function save($data)
    8668     {
    8669         if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
    8670         {
    8671             if (is_a($data, 'SimplePie'))
    8672             {
    8673                 $data = $data->data;
    8674             }
    8675 
    8676             $data = serialize($data);
    8677 
    8678             if (function_exists('file_put_contents'))
    8679             {
    8680                 return (bool) file_put_contents($this->name, $data);
    8681             }
    8682             else
    8683             {
    8684                 $fp = fopen($this->name, 'wb');
    8685                 if ($fp)
    8686                 {
    8687                     fwrite($fp, $data);
    8688                     fclose($fp);
    8689                     return true;
    8690                 }
    8691             }
    8692         }
    8693         return false;
    8694     }
    8695 
    8696     function load()
    8697     {
    8698         if (file_exists($this->name) && is_readable($this->name))
    8699         {
    8700             return unserialize(file_get_contents($this->name));
    8701         }
    8702         return false;
    8703     }
    8704 
    8705     function mtime()
    8706     {
    8707         if (file_exists($this->name))
    8708         {
    8709             return filemtime($this->name);
    8710         }
    8711         return false;
    8712     }
    8713 
    8714     function touch()
    8715     {
    8716         if (file_exists($this->name))
    8717         {
    8718             return touch($this->name);
    8719         }
    8720         return false;
    8721     }
    8722 
    8723     function unlink()
    8724     {
    8725         if (file_exists($this->name))
    8726         {
    8727             return unlink($this->name);
    8728         }
    8729         return false;
    8730     }
    8731 }
    8732 
    8733 class SimplePie_Cache_DB
    8734 {
    8735     function prepare_simplepie_object_for_cache($data)
    8736     {
    8737         $items = $data->get_items();
    8738         $items_by_id = array();
    8739 
    8740         if (!empty($items))
    8741         {
    8742             foreach ($items as $item)
    8743             {
    8744                 $items_by_id[$item->get_id()] = $item;
    8745             }
    8746 
    8747             if (count($items_by_id) !== count($items))
    8748             {
    8749                 $items_by_id = array();
    8750                 foreach ($items as $item)
    8751                 {
    8752                     $items_by_id[$item->get_id(true)] = $item;
    8753                 }
    8754             }
    8755 
    8756             if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
    8757             {
    8758                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
    8759             }
    8760             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
    8761             {
    8762                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
    8763             }
    8764             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
    8765             {
    8766                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
    8767             }
    8768             elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
    8769             {
    8770                 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
    8771             }
    8772             else
    8773             {
    8774                 $channel = null;
    8775             }
    8776 
    8777             if ($channel !== null)
    8778             {
    8779                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
    8780                 {
    8781                     unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
    8782                 }
    8783                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
    8784                 {
    8785                     unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
    8786                 }
    8787                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
    8788                 {
    8789                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
    8790                 }
    8791                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
    8792                 {
    8793                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
    8794                 }
    8795                 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
    8796                 {
    8797                     unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
    8798                 }
    8799             }
    8800             if (isset($data->data['items']))
    8801             {
    8802                 unset($data->data['items']);
    8803             }
    8804             if (isset($data->data['ordered_items']))
    8805             {
    8806                 unset($data->data['ordered_items']);
    8807             }
    8808         }
    8809         return array(serialize($data->data), $items_by_id);
    8810     }
    8811 }
    8812 
    8813 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
    8814 {
    8815     var $mysql;
    8816     var $options;
    8817     var $id;
    8818 
    8819     function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
    8820     {
    8821         $host = $mysql_location->get_host();
    8822         if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
    8823         {
    8824             $server = ':' . substr($host, 5, -1);
    8825         }
    8826         else
    8827         {
    8828             $server = $host;
    8829             if ($mysql_location->get_port() !== null)
    8830             {
    8831                 $server .= ':' . $mysql_location->get_port();
    8832             }
    8833         }
    8834 
    8835         if (strpos($mysql_location->get_userinfo(), ':') !== false)
    8836         {
    8837             list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
    8838         }
    8839         else
    8840         {
    8841             $username = $mysql_location->get_userinfo();
    8842             $password = null;
    8843         }
    8844 
    8845         if ($this->mysql = mysql_connect($server, $username, $password))
    8846         {
    8847             $this->id = $name . $extension;
    8848             $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
    8849             if (!isset($this->options['prefix'][0]))
    8850             {
    8851                 $this->options['prefix'][0] = '';
    8852             }
    8853 
    8854             if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
    8855                 && mysql_query('SET NAMES utf8')
    8856                 && ($query = mysql_unbuffered_query('SHOW TABLES')))
    8857             {
    8858                 $db = array();
    8859                 while ($row = mysql_fetch_row($query))
    8860                 {
    8861                     $db[] = $row[0];
    8862                 }
    8863 
    8864                 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
    8865                 {
    8866                     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)))'))
    8867                     {
    8868                         $this->mysql = null;
    8869                     }
    8870                 }
    8871 
    8872                 if (!in_array($this->options['prefix'][0] . 'items', $db))
    8873                 {
    8874                     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)))'))
    8875                     {
    8876                         $this->mysql = null;
    8877                     }
    8878                 }
    8879             }
    8880             else
    8881             {
    8882                 $this->mysql = null;
    8883             }
    8884         }
    8885     }
    8886 
    8887     function save($data)
    8888     {
    8889         if ($this->mysql)
    8890         {
    8891             $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
    8892 
    8893             if (is_a($data, 'SimplePie'))
    8894             {
    8895                 if (SIMPLEPIE_PHP5)
    8896                 {
    8897                     // This keyword needs to defy coding standards for PHP4 compatibility
    8898                     $data = clone($data);
    8899                 }
    8900 
    8901                 $prepared = $this->prepare_simplepie_object_for_cache($data);
    8902 
    8903                 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
    8904                 {
    8905                     if (mysql_num_rows($query))
    8906                     {
    8907                         $items = count($prepared[1]);
    8908                         if ($items)
    8909                         {
    8910                             $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
    8911                         }
    8912                         else
    8913                         {
    8914                             $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
    8915                         }
    8916 
    8917                         if (!mysql_query($sql, $this->mysql))
    8918                         {
    8919                             return false;
    8920                         }
    8921                     }
    8922                     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))
    8923                     {
    8924                         return false;
    8925                     }
    8926 
    8927                     $ids = array_keys($prepared[1]);
    8928                     if (!empty($ids))
    8929                     {
    8930                         foreach ($ids as $id)
    8931                         {
    8932                             $database_ids[] = mysql_real_escape_string($id);
    8933                         }
    8934 
    8935                         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))
    8936                         {
    8937                             $existing_ids = array();
    8938                             while ($row = mysql_fetch_row($query))
    8939                             {
    8940                                 $existing_ids[] = $row[0];
    8941                             }
    8942 
    8943                             $new_ids = array_diff($ids, $existing_ids);
    8944 
    8945                             foreach ($new_ids as $new_id)
    8946                             {
    8947                                 if (!($date = $prepared[1][$new_id]->get_date('U')))
    8948                                 {
    8949                                     $date = time();
    8950                                 }
    8951 
    8952                                 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))
    8953                                 {
    8954                                     return false;
    8955                                 }
    8956                             }
    8957                             return true;
    8958                         }
    8959                     }
    8960                     else
    8961                     {
    8962                         return true;
    8963                     }
    8964                 }
    8965             }
    8966             elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
    8967             {
    8968                 if (mysql_num_rows($query))
    8969                 {
    8970                     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))
    8971                     {
    8972                         return true;
    8973                     }
    8974                 }
    8975                 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))
    8976                 {
    8977                     return true;
    8978                 }
    8979             }
    8980         }
    8981         return false;
    8982     }
    8983 
    8984     function load()
    8985     {
    8986         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)))
    8987         {
    8988             $data = unserialize($row[1]);
    8989 
    8990             if (isset($this->options['items'][0]))
    8991             {
    8992                 $items = (int) $this->options['items'][0];
    8993             }
    8994             else
    8995             {
    8996                 $items = (int) $row[0];
    8997             }
    8998 
    8999             if ($items !== 0)
    9000             {
    9001                 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
    9002                 {
    9003                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
    9004                 }
    9005                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
    9006                 {
    9007                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
    9008                 }
    9009                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
    9010                 {
    9011                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
    9012                 }
    9013                 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
    9014                 {
    9015                     $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
    9016                 }
    9017                 else
    9018                 {
    9019                     $feed = null;
    9020                 }
    9021 
    9022                 if ($feed !== null)
    9023                 {
    9024                     $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
    9025                     if ($items > 0)
    9026                     {
    9027                         $sql .= ' LIMIT ' . $items;
    9028                     }
    9029 
    9030                     if ($query = mysql_unbuffered_query($sql, $this->mysql))
    9031                     {
    9032                         while ($row = mysql_fetch_row($query))
    9033                         {
    9034                             $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
    9035                         }
    9036                     }
    9037                     else
    9038                     {
    9039                         return false;
    9040                     }
    9041                 }
    9042             }
    9043             return $data;
    9044         }
    9045         return false;
    9046     }
    9047 
    9048     function mtime()
    9049     {
    9050         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)))
    9051         {
    9052             return $row[0];
    9053         }
    9054         else
    9055         {
    9056             return false;
    9057         }
    9058     }
    9059 
    9060     function touch()
    9061     {
    9062         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))
    9063         {
    9064             return true;
    9065         }
    9066         else
    9067         {
    9068             return false;
    9069         }
    9070     }
    9071 
    9072     function unlink()
    9073     {
    9074         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)))
    9075         {
    9076             return true;
    9077         }
    9078         else
    9079         {
    9080             return false;
    9081         }
    9082     }
    9083 }
    9084 
    9085 class SimplePie_Misc
    9086 {
    9087     function time_hms($seconds)
    9088     {
    9089         $time = '';
    9090 
    9091         $hours = floor($seconds / 3600);
    9092         $remainder = $seconds % 3600;
    9093         if ($hours > 0)
    9094         {
    9095             $time .= $hours.':';
    9096         }
    9097 
    9098         $minutes = floor($remainder / 60);
    9099         $seconds = $remainder % 60;
    9100         if ($minutes < 10 && $hours > 0)
    9101         {
    9102             $minutes = '0' . $minutes;
    9103         }
    9104         if ($seconds < 10)
    9105         {
    9106             $seconds = '0' . $seconds;
    9107         }
    9108 
    9109         $time .= $minutes.':';
    9110         $time .= $seconds;
    9111 
    9112         return $time;
    9113     }
    9114 
    9115     function absolutize_url($relative, $base)
    9116     {
    9117         $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
    9118         return $iri->get_iri();
    9119     }
    9120 
    9121     function remove_dot_segments($input)
    9122     {
    9123         $output = '';
    9124         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
    9125         {
    9126             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
    9127             if (strpos($input, '../') === 0)
    9128             {
    9129                 $input = substr($input, 3);
    9130             }
    9131             elseif (strpos($input, './') === 0)
    9132             {
    9133                 $input = substr($input, 2);
    9134             }
    9135             // 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,
    9136             elseif (strpos($input, '/./') === 0)
    9137             {
    9138                 $input = substr_replace($input, '/', 0, 3);
    9139             }
    9140             elseif ($input === '/.')
    9141             {
    9142                 $input = '/';
    9143             }
    9144             // 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,
    9145             elseif (strpos($input, '/../') === 0)
    9146             {
    9147                 $input = substr_replace($input, '/', 0, 4);
    9148                 $output = substr_replace($output, '', strrpos($output, '/'));
    9149             }
    9150             elseif ($input === '/..')
    9151             {
    9152                 $input = '/';
    9153                 $output = substr_replace($output, '', strrpos($output, '/'));
    9154             }
    9155             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
    9156             elseif ($input === '.' || $input === '..')
    9157             {
    9158                 $input = '';
    9159             }
    9160             // 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
    9161             elseif (($pos = strpos($input, '/', 1)) !== false)
    9162             {
    9163                 $output .= substr($input, 0, $pos);
    9164                 $input = substr_replace($input, '', 0, $pos);
    9165             }
    9166             else
    9167             {
    9168                 $output .= $input;
    9169                 $input = '';
    9170             }
    9171         }
    9172         return $output . $input;
    9173     }
    9174 
    9175     function get_element($realname, $string)
    9176     {
    9177         $return = array();
    9178         $name = preg_quote($realname, '/');
    9179         if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
    9180         {
    9181             for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
    9182             {
    9183                 $return[$i]['tag'] = $realname;
    9184                 $return[$i]['full'] = $matches[$i][0][0];
    9185                 $return[$i]['offset'] = $matches[$i][0][1];
    9186                 if (strlen($matches[$i][3][0]) <= 2)
    9187                 {
    9188                     $return[$i]['self_closing'] = true;
    9189                 }
    9190                 else
    9191                 {
    9192                     $return[$i]['self_closing'] = false;
    9193                     $return[$i]['content'] = $matches[$i][4][0];
    9194                 }
    9195                 $return[$i]['attribs'] = array();
    9196                 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))
    9197                 {
    9198                     for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
    9199                     {
    9200                         if (count($attribs[$j]) === 2)
    9201                         {
    9202                             $attribs[$j][2] = $attribs[$j][1];
    9203                         }
    9204                         $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
    9205                     }
    9206                 }
    9207             }
    9208         }
    9209         return $return;
    9210     }
    9211 
    9212     function element_implode($element)
    9213     {
    9214         $full = "<$element[tag]";
    9215         foreach ($element['attribs'] as $key => $value)
    9216         {
    9217             $key = strtolower($key);
    9218             $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
    9219         }
    9220         if ($element['self_closing'])
    9221         {
    9222             $full .= ' />';
    9223         }
    9224         else
    9225         {
    9226             $full .= ">$element[content]</$element[tag]>";
    9227         }
    9228         return $full;
    9229     }
    9230 
    9231     function error($message, $level, $file, $line)
    9232     {
    9233         if ((ini_get('error_reporting') & $level) > 0)
    9234         {
    9235             switch ($level)
    9236             {
    9237                 case E_USER_ERROR:
    9238                     $note = 'PHP Error';
    9239                     break;
    9240                 case E_USER_WARNING:
    9241                     $note = 'PHP Warning';
    9242                     break;
    9243                 case E_USER_NOTICE:
    9244                     $note = 'PHP Notice';
    9245                     break;
    9246                 default:
    9247                     $note = 'Unknown Error';
    9248                     break;
    9249             }
    9250 
    9251             $log_error = true;
    9252             if (!function_exists('error_log'))
    9253             {
    9254                 $log_error = false;
    9255             }
    9256 
    9257             $log_file = @ini_get('error_log');
    9258             if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
    9259             {
    9260                 $log_error = false;
    9261             }
    9262 
    9263             if ($log_error)
    9264             {
    9265                 @error_log("$note: $message in $file on line $line", 0);
    9266             }
    9267         }
    9268 
    9269         return $message;
    9270     }
    9271 
    9272     /**
    9273      * If a file has been cached, retrieve and display it.
    9274      *
    9275      * This is most useful for caching images (get_favicon(), etc.),
    9276      * however it works for all cached files.  This WILL NOT display ANY
    9277      * file/image/page/whatever, but rather only display what has already
    9278      * been cached by SimplePie.
    9279      *
    9280      * @access public
    9281      * @see SimplePie::get_favicon()
    9282      * @param str $identifier_url URL that is used to identify the content.
    9283      * This may or may not be the actual URL of the live content.
    9284      * @param str $cache_location Location of SimplePie's cache.  Defaults
    9285      * to './cache'.
    9286      * @param str $cache_extension The file extension that the file was
    9287      * cached with.  Defaults to 'spc'.
    9288      * @param str $cache_class Name of the cache-handling class being used
    9289      * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
    9290      * as-is unless you've overloaded the class.
    9291      * @param str $cache_name_function Obsolete. Exists for backwards
    9292      * compatibility reasons only.
    9293      */
    9294     function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
    9295     {
    9296         $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
    9297 
    9298         if ($file = $cache->load())
    9299         {
    9300             if (isset($file['headers']['content-type']))
    9301             {
    9302                 header('Content-type:' . $file['headers']['content-type']);
    9303             }
    9304             else
    9305             {
    9306                 header('Content-type: application/octet-stream');
    9307             }
    9308             header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
    9309             echo $file['body'];
    9310             exit;
    9311         }
    9312 
    9313         die('Cached file for ' . $identifier_url . ' cannot be found.');
    9314     }
    9315 
    9316     function fix_protocol($url, $http = 1)
    9317     {
    9318         $url = SimplePie_Misc::normalize_url($url);
    9319         $parsed = SimplePie_Misc::parse_url($url);
    9320         if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
    9321         {
    9322             return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
    9323         }
    9324 
    9325         if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
    9326         {
    9327             return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
    9328         }
    9329 
    9330         if ($http === 2 && $parsed['scheme'] !== '')
    9331         {
    9332             return "feed:$url";
    9333         }
    9334         elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
    9335         {
    9336             return substr_replace($url, 'podcast', 0, 4);
    9337         }
    9338         elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
    9339         {
    9340             return substr_replace($url, 'itpc', 0, 4);
    9341         }
    9342         else
    9343         {
    9344             return $url;
    9345         }
    9346     }
    9347 
    9348     function parse_url($url)
    9349     {
    9350         $iri =& new SimplePie_IRI($url);
    9351         return array(
    9352             'scheme' => (string) $iri->get_scheme(),
    9353             'authority' => (string) $iri->get_authority(),
    9354             'path' => (string) $iri->get_path(),
    9355             'query' => (string) $iri->get_query(),
    9356             'fragment' => (string) $iri->get_fragment()
    9357         );
    9358     }
    9359 
    9360     function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
    9361     {
    9362         $iri =& new SimplePie_IRI('');
    9363         $iri->set_scheme($scheme);
    9364         $iri->set_authority($authority);
    9365         $iri->set_path($path);
    9366         $iri->set_query($query);
    9367         $iri->set_fragment($fragment);
    9368         return $iri->get_iri();
    9369     }
    9370 
    9371     function normalize_url($url)
    9372     {
    9373         $iri =& new SimplePie_IRI($url);
    9374         return $iri->get_iri();
    9375     }
    9376 
    9377     function percent_encoding_normalization($match)
    9378     {
    9379         $integer = hexdec($match[1]);
    9380         if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
    9381         {
    9382             return chr($integer);
    9383         }
    9384         else
    9385         {
    9386             return strtoupper($match[0]);
    9387         }
    9388     }
    9389 
    9390     /**
    9391      * Remove bad UTF-8 bytes
    9392      *
    9393      * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
    9394      * FAQ: Multilingual Forms (modified to include full ASCII range)
    9395      *
    9396      * @author Geoffrey Sneddon
    9397      * @see http://www.w3.org/International/questions/qa-forms-utf-8
    9398      * @param string $str String to remove bad UTF-8 bytes from
    9399      * @return string UTF-8 string
    9400      */
    9401     function utf8_bad_replace($str)
    9402     {
    9403         if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
    9404         {
    9405             return $return;
    9406         }
    9407         elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
    9408         {
    9409             return $return;
    9410         }
    9411         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))
    9412         {
    9413             return implode("\xEF\xBF\xBD", $matches[0]);
    9414         }
    9415         elseif ($str !== '')
    9416         {
    9417             return "\xEF\xBF\xBD";
    9418         }
    9419         else
    9420         {
    9421             return '';
    9422         }
    9423     }
    9424 
    9425     /**
    9426      * Converts a Windows-1252 encoded string to a UTF-8 encoded string
    9427      *
    9428      * @static
    9429      * @access public
    9430      * @param string $string Windows-1252 encoded string
    9431      * @return string UTF-8 encoded string
    9432      */
    9433     function windows_1252_to_utf8($string)
    9434     {
    9435         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");
    9436 
    9437         return strtr($string, $convert_table);
    9438     }
    9439 
    9440     function change_encoding($data, $input, $output)
    9441     {
    9442         $input = SimplePie_Misc::encoding($input);
    9443         $output = SimplePie_Misc::encoding($output);
    9444 
    9445         // We fail to fail on non US-ASCII bytes
    9446         if ($input === 'US-ASCII')
    9447         {
    9448             static $non_ascii_octects = '';
    9449             if (!$non_ascii_octects)
    9450             {
    9451                 for ($i = 0x80; $i <= 0xFF; $i++)
    9452                 {
    9453                     $non_ascii_octects .= chr($i);
    9454                 }
    9455             }
    9456             $data = substr($data, 0, strcspn($data, $non_ascii_octects));
    9457         }
    9458 
    9459         // This is first, as behaviour of this is completely predictable
    9460         if ($input === 'windows-1252' && $output === 'UTF-8')
    9461         {
    9462             return SimplePie_Misc::windows_1252_to_utf8($data);
    9463         }
    9464         // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
    9465         elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && in_array($input, mb_list_encodings()) && ($return = @mb_convert_encoding($data, $output, $input)))
    9466         {
    9467             return $return;
    9468         }
    9469         // This is last, as behaviour of this varies with OS userland and PHP version
    9470         elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
    9471         {
    9472             return $return;
    9473         }
    9474         // If we can't do anything, just fail
    9475         else
    9476         {
    9477             return false;
    9478         }
    9479     }
    9480 
    9481     /**
    9482      * Normalize an encoding name
    9483      *
    9484      * This is automatically generated by create.php
    9485      *
    9486      * To generate it, run `php create.php` on the command line, and copy the
    9487      * output to replace this function.
    9488      *
    9489      * @param string $charset Character set to standardise
    9490      * @return string Standardised name
    9491      */
    9492     function encoding($charset)
    9493     {
    9494         // Normalization from UTS #22
    9495         switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
    9496         {
    9497             case 'adobestandardencoding':
    9498             case 'csadobestandardencoding':
    9499                 return 'Adobe-Standard-Encoding';
    9500 
    9501             case 'adobesymbolencoding':
    9502             case 'cshppsmath':
    9503                 return 'Adobe-Symbol-Encoding';
    9504 
    9505             case 'ami1251':
    9506             case 'amiga1251':
    9507                 return 'Amiga-1251';
    9508 
    9509             case 'ansix31101983':
    9510             case 'csat5001983':
    9511             case 'csiso99naplps':
    9512             case 'isoir99':
    9513             case 'naplps':
    9514                 return 'ANSI_X3.110-1983';
    9515 
    9516             case 'arabic7':
    9517             case 'asmo449':
    9518             case 'csiso89asmo449':
    9519             case 'iso9036':
    9520             case 'isoir89':
    9521                 return 'ASMO_449';
    9522 
    9523             case 'big5':
    9524             case 'csbig5':
    9525                 return 'Big5';
    9526 
    9527             case 'big5hkscs':
    9528                 return 'Big5-HKSCS';
    9529 
    9530             case 'bocu1':
    9531             case 'csbocu1':
    9532                 return 'BOCU-1';
    9533 
    9534             case 'brf':
    9535             case 'csbrf':
    9536                 return 'BRF';
    9537 
    9538             case 'bs4730':
    9539             case 'csiso4unitedkingdom':
    9540             case 'gb':
    9541             case 'iso646gb':
    9542             case 'isoir4':
    9543             case 'uk':
    9544                 return 'BS_4730';
    9545 
    9546             case 'bsviewdata':
    9547             case 'csiso47bsviewdata':
    9548             case 'isoir47':
    9549                 return 'BS_viewdata';
    9550 
    9551             case 'cesu8':
    9552             case 'cscesu8':
    9553                 return 'CESU-8';
    9554 
    9555             case 'ca':
    9556             case 'csa71':
    9557             case 'csaz243419851':
    9558             case 'csiso121canadian1':
    9559             case 'iso646ca':
    9560             case 'isoir121':
    9561                 return 'CSA_Z243.4-1985-1';
    9562 
    9563             case 'csa72':
    9564             case 'csaz243419852':
    9565             case 'csiso122canadian2':
    9566             case 'iso646ca2':
    9567             case 'isoir122':
    9568                 return 'CSA_Z243.4-1985-2';
    9569 
    9570             case 'csaz24341985gr':
    9571             case 'csiso123csaz24341985gr':
    9572             case 'isoir123':
    9573                 return 'CSA_Z243.4-1985-gr';
    9574 
    9575             case 'csiso139csn369103':
    9576             case 'csn369103':
    9577             case 'isoir139':
    9578                 return 'CSN_369103';
    9579 
    9580             case 'csdecmcs':
    9581             case 'dec':
    9582             case 'decmcs':
    9583                 return 'DEC-MCS';
    9584 
    9585             case 'csiso21german':
    9586             case 'de':
    9587             case 'din66003':
    9588             case 'iso646de':
    9589             case 'isoir21':
    9590                 return 'DIN_66003';
    9591 
    9592             case 'csdkus':
    9593             case 'dkus':
    9594                 return 'dk-us';
    9595 
    9596             case 'csiso646danish':
    9597             case 'dk':
    9598             case 'ds2089':
    9599             case 'iso646dk':
    9600                 return 'DS_2089';
    9601 
    9602             case 'csibmebcdicatde':
    9603             case 'ebcdicatde':
    9604                 return 'EBCDIC-AT-DE';
    9605 
    9606             case 'csebcdicatdea':
    9607             case 'ebcdicatdea':
    9608                 return 'EBCDIC-AT-DE-A';
    9609 
    9610             case 'csebcdiccafr':
    9611             case 'ebcdiccafr':
    9612                 return 'EBCDIC-CA-FR';
    9613 
    9614             case 'csebcdicdkno':
    9615             case 'ebcdicdkno':
    9616                 return 'EBCDIC-DK-NO';
    9617 
    9618             case 'csebcdicdknoa':
    9619             case 'ebcdicdknoa':
    9620                 return 'EBCDIC-DK-NO-A';
    9621 
    9622             case 'csebcdices':
    9623             case 'ebcdices':
    9624                 return 'EBCDIC-ES';
    9625 
    9626             case 'csebcdicesa':
    9627             case 'ebcdicesa':
    9628                 return 'EBCDIC-ES-A';
    9629 
    9630             case 'csebcdicess':
    9631             case 'ebcdicess':
    9632                 return 'EBCDIC-ES-S';
    9633 
    9634             case 'csebcdicfise':
    9635             case 'ebcdicfise':
    9636                 return 'EBCDIC-FI-SE';
    9637 
    9638             case 'csebcdicfisea':
    9639             case 'ebcdicfisea':
    9640                 return 'EBCDIC-FI-SE-A';
    9641 
    9642             case 'csebcdicfr':
    9643             case 'ebcdicfr':
    9644                 return 'EBCDIC-FR';
    9645 
    9646             case 'csebcdicit':
    9647             case 'ebcdicit':
    9648                 return 'EBCDIC-IT';
    9649 
    9650             case 'csebcdicpt':
    9651             case 'ebcdicpt':
    9652                 return 'EBCDIC-PT';
    9653 
    9654             case 'csebcdicuk':
    9655             case 'ebcdicuk':
    9656                 return 'EBCDIC-UK';
    9657 
    9658             case 'csebcdicus':
    9659             case 'ebcdicus':
    9660                 return 'EBCDIC-US';
    9661 
    9662             case 'csiso111ecmacyrillic':
    9663             case 'ecmacyrillic':
    9664             case 'isoir111':
    9665             case 'koi8e':
    9666                 return 'ECMA-cyrillic';
    9667 
    9668             case 'csiso17spanish':
    9669             case 'es':
    9670             case 'iso646es':
    9671             case 'isoir17':
    9672                 return 'ES';
    9673 
    9674             case 'csiso85spanish2':
    9675             case 'es2':
    9676             case 'iso646es2':
    9677             case 'isoir85':
    9678                 return 'ES2';
    9679 
    9680             case 'cseucpkdfmtjapanese':
    9681             case 'eucjp':
    9682             case 'extendedunixcodepackedformatforjapanese':
    9683                 return 'EUC-JP';
    9684 
    9685             case 'cseucfixwidjapanese':
    9686             case 'extendedunixcodefixedwidthforjapanese':
    9687                 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
    9688 
    9689             case 'gb18030':
    9690                 return 'GB18030';
    9691 
    9692             case 'chinese':
    9693             case 'cp936':
    9694             case 'csgb2312':
    9695             case 'csiso58gb231280':
    9696             case 'gb2312':
    9697             case 'gb231280':
    9698             case 'gbk':
    9699             case 'isoir58':
    9700             case 'ms936':
    9701             case 'windows936':
    9702                 return 'GBK';
    9703 
    9704             case 'cn':
    9705             case 'csiso57gb1988':
    9706             case 'gb198880':
    9707             case 'iso646cn':
    9708             case 'isoir57':
    9709                 return 'GB_1988-80';
    9710 
    9711             case 'csiso153gost1976874':
    9712             case 'gost1976874':
    9713             case 'isoir153':
    9714             case 'stsev35888':
    9715                 return 'GOST_19768-74';
    9716 
    9717             case 'csiso150':
    9718             case 'csiso150greekccitt':
    9719             case 'greekccitt':
    9720             case 'isoir150':
    9721                 return 'greek-ccitt';
    9722 
    9723             case 'csiso88greek7':
    9724             case 'greek7':
    9725             case 'isoir88':
    9726                 return 'greek7';
    9727 
    9728             case 'csiso18greek7old':
    9729             case 'greek7old':
    9730             case 'isoir18':
    9731                 return 'greek7-old';
    9732 
    9733             case 'cshpdesktop':
    9734             case 'hpdesktop':
    9735                 return 'HP-DeskTop';
    9736 
    9737             case 'cshplegal':
    9738             case 'hplegal':
    9739                 return 'HP-Legal';
    9740 
    9741             case 'cshpmath8':
    9742             case 'hpmath8':
    9743                 return 'HP-Math8';
    9744 
    9745             case 'cshppifont':
    9746             case 'hppifont':
    9747                 return 'HP-Pi-font';
    9748 
    9749             case 'cshproman8':
    9750             case 'hproman8':
    9751             case 'r8':
    9752             case 'roman8':
    9753                 return 'hp-roman8';
    9754 
    9755             case 'hzgb2312':
    9756                 return 'HZ-GB-2312';
    9757 
    9758             case 'csibmsymbols':
    9759             case 'ibmsymbols':
    9760                 return 'IBM-Symbols';
    9761 
    9762             case 'csibmthai':
    9763             case 'ibmthai':
    9764                 return 'IBM-Thai';
    9765 
    9766             case 'cp37':
    9767             case 'csibm37':
    9768             case 'ebcdiccpca':
    9769             case 'ebcdiccpnl':
    9770             case 'ebcdiccpus':
    9771             case 'ebcdiccpwt':
    9772             case 'ibm37':
    9773                 return 'IBM037';
    9774 
    9775             case 'cp38':
    9776             case 'csibm38':
    9777             case 'ebcdicint':
    9778             case 'ibm38':
    9779                 return 'IBM038';
    9780 
    9781             case 'cp273':
    9782             case 'csibm273':
    9783             case 'ibm273':
    9784                 return 'IBM273';
    9785 
    9786             case 'cp274':
    9787             case 'csibm274':
    9788             case 'ebcdicbe':
    9789             case 'ibm274':
    9790                 return 'IBM274';
    9791 
    9792             case 'cp275':
    9793             case 'csibm275':
    9794             case 'ebcdicbr':
    9795             case 'ibm275':
    9796                 return 'IBM275';
    9797 
    9798             case 'csibm277':
    9799             case 'ebcdiccpdk':
    9800             case 'ebcdiccpno':
    9801             case 'ibm277':
    9802                 return 'IBM277';
    9803 
    9804             case 'cp278':
    9805             case 'csibm278':
    9806             case 'ebcdiccpfi':
    9807             case 'ebcdiccpse':
    9808             case 'ibm278':
    9809                 return 'IBM278';
    9810 
    9811             case 'cp280':
    9812             case 'csibm280':
    9813             case 'ebcdiccpit':
    9814             case 'ibm280':
    9815                 return 'IBM280';
    9816 
    9817             case 'cp281':
    9818             case 'csibm281':
    9819             case 'ebcdicjpe':
    9820             case 'ibm281':
    9821                 return 'IBM281';
    9822 
    9823             case 'cp284':
    9824             case 'csibm284':
    9825             case 'ebcdiccpes':
    9826             case 'ibm284':
    9827                 return 'IBM284';
    9828 
    9829             case 'cp285':
    9830             case 'csibm285':
    9831             case 'ebcdiccpgb':
    9832             case 'ibm285':
    9833                 return 'IBM285';
    9834 
    9835             case 'cp290':
    9836             case 'csibm290':
    9837             case 'ebcdicjpkana':
    9838             case 'ibm290':
    9839                 return 'IBM290';
    9840 
    9841             case 'cp297':
    9842             case 'csibm297':
    9843             case 'ebcdiccpfr':
    9844             case 'ibm297':
    9845                 return 'IBM297';
    9846 
    9847             case 'cp420':
    9848             case 'csibm420':
    9849             case 'ebcdiccpar1':
    9850             case 'ibm420':
    9851                 return 'IBM420';
    9852 
    9853             case 'cp423':
    9854             case 'csibm423':
    9855             case 'ebcdiccpgr':
    9856             case 'ibm423':
    9857                 return 'IBM423';
    9858 
    9859             case 'cp424':
    9860             case 'csibm424':
    9861             case 'ebcdiccphe':
    9862             case 'ibm424':
    9863                 return 'IBM424';
    9864 
    9865             case '437':
    9866             case 'cp437':
    9867             case 'cspc8codepage437':
    9868             case 'ibm437':
    9869                 return 'IBM437';
    9870 
    9871             case 'cp500':
    9872             case 'csibm500':
    9873             case 'ebcdiccpbe':
    9874             case 'ebcdiccpch':
    9875             case 'ibm500':
    9876                 return 'IBM500';
    9877 
    9878             case 'cp775':
    9879             case 'cspc775baltic':
    9880             case 'ibm775':
    9881                 return 'IBM775';
    9882 
    9883             case '850':
    9884             case 'cp850':
    9885             case 'cspc850multilingual':
    9886             case 'ibm850':
    9887                 return 'IBM850';
    9888 
    9889             case '851':
    9890             case 'cp851':
    9891             case 'csibm851':
    9892             case 'ibm851':
    9893                 return 'IBM851';
    9894 
    9895             case '852':
    9896             case 'cp852':
    9897             case 'cspcp852':
    9898             case 'ibm852':
    9899                 return 'IBM852';
    9900 
    9901             case '855':
    9902             case 'cp855':
    9903             case 'csibm855':
    9904             case 'ibm855':
    9905                 return 'IBM855';
    9906 
    9907             case '857':
    9908             case 'cp857':
    9909             case 'csibm857':
    9910             case 'ibm857':
    9911                 return 'IBM857';
    9912 
    9913             case 'ccsid858':
    9914             case 'cp858':
    9915             case 'ibm858':
    9916             case 'pcmultilingual850euro':
    9917                 return 'IBM00858';
    9918 
    9919             case '860':
    9920             case 'cp860':
    9921             case 'csibm860':
    9922             case 'ibm860':
    9923                 return 'IBM860';
    9924 
    9925             case '861':
    9926             case 'cp861':
    9927             case 'cpis':
    9928             case 'csibm861':
    9929             case 'ibm861':
    9930                 return 'IBM861';
    9931 
    9932             case '862':
    9933             case 'cp862':
    9934             case 'cspc862latinhebrew':
    9935             case 'ibm862':
    9936                 return 'IBM862';
    9937 
    9938             case '863':
    9939             case 'cp863':
    9940             case 'csibm863':
    9941             case 'ibm863':
    9942                 return 'IBM863';
    9943 
    9944             case 'cp864':
    9945             case 'csibm864':
    9946             case 'ibm864':
    9947                 return 'IBM864';
    9948 
    9949             case '865':
    9950             case 'cp865':
    9951             case 'csibm865':
    9952             case 'ibm865':
    9953                 return 'IBM865';
    9954 
    9955             case '866':
    9956             case 'cp866':
    9957             case 'csibm866':
    9958             case 'ibm866':
    9959                 return 'IBM866';
    9960 
    9961             case 'cp868':
    9962             case 'cpar':
    9963             case 'csibm868':
    9964             case 'ibm868':
    9965                 return 'IBM868';
    9966 
    9967             case '869':
    9968             case 'cp869':
    9969             case 'cpgr':
    9970             case 'csibm869':
    9971             case 'ibm869':
    9972                 return 'IBM869';
    9973 
    9974             case 'cp870':
    9975             case 'csibm870':
    9976             case 'ebcdiccproece':
    9977             case 'ebcdiccpyu':
    9978             case 'ibm870':
    9979                 return 'IBM870';
    9980 
    9981             case 'cp871':
    9982             case 'csibm871':
    9983             case 'ebcdiccpis':
    9984             case 'ibm871':
    9985                 return 'IBM871';
    9986 
    9987             case 'cp880':
    9988             case 'csibm880':
    9989             case 'ebcdiccyrillic':
    9990             case 'ibm880':
    9991                 return 'IBM880';
    9992 
    9993             case 'cp891':
    9994             case 'csibm891':
    9995             case 'ibm891':
    9996                 return 'IBM891';
    9997 
    9998             case 'cp903':
    9999             case 'csibm903':
    10000             case 'ibm903':
    10001                 return 'IBM903';
    10002 
    10003             case '904':
    10004             case 'cp904':
    10005             case 'csibbm904':
    10006             case 'ibm904':
    10007                 return 'IBM904';
    10008 
    10009             case 'cp905':
    10010             case 'csibm905':
    10011             case 'ebcdiccptr':
    10012             case 'ibm905':
    10013                 return 'IBM905';
    10014 
    10015             case 'cp918':
    10016             case 'csibm918':
    10017             case 'ebcdiccpar2':
    10018             case 'ibm918':
    10019                 return 'IBM918';
    10020 
    10021             case 'ccsid924':
    10022             case 'cp924':
    10023             case 'ebcdiclatin9euro':
    10024             case 'ibm924':
    10025                 return 'IBM00924';
    10026 
    10027             case 'cp1026':
    10028             case 'csibm1026':
    10029             case 'ibm1026':
    10030                 return 'IBM1026';
    10031 
    10032             case 'ibm1047':
    10033                 return 'IBM1047';
    10034 
    10035             case 'ccsid1140':
    10036             case 'cp1140':
    10037             case 'ebcdicus37euro':
    10038             case 'ibm1140':
    10039                 return 'IBM01140';
    10040 
    10041             case 'ccsid1141':
    10042             case 'cp1141':
    10043             case 'ebcdicde273euro':
    10044             case 'ibm1141':
    10045                 return 'IBM01141';
    10046 
    10047             case 'ccsid1142':
    10048             case 'cp1142':
    10049             case 'ebcdicdk277euro':
    10050             case 'ebcdicno277euro':
    10051             case 'ibm1142':
    10052                 return 'IBM01142';
    10053 
    10054             case 'ccsid1143':
    10055             case 'cp1143':
    10056             case 'ebcdicfi278euro':
    10057             case 'ebcdicse278euro':
    10058             case 'ibm1143':
    10059                 return 'IBM01143';
    10060 
    10061             case 'ccsid1144':
    10062             case 'cp1144':
    10063             case 'ebcdicit280euro':
    10064             case 'ibm1144':
    10065                 return 'IBM01144';
    10066 
    10067             case 'ccsid1145':
    10068             case 'cp1145':
    10069             case 'ebcdices284euro':
    10070             case 'ibm1145':
    10071                 return 'IBM01145';
    10072 
    10073             case 'ccsid1146':
    10074             case 'cp1146':
    10075             case 'ebcdicgb285euro':
    10076             case 'ibm1146':
    10077                 return 'IBM01146';
    10078 
    10079             case 'ccsid1147':
    10080             case 'cp1147':
    10081             case 'ebcdicfr297euro':
    10082             case 'ibm1147':
    10083                 return 'IBM01147';
    10084 
    10085             case 'ccsid1148':
    10086             case 'cp1148':
    10087             case 'ebcdicinternational500euro':
    10088             case 'ibm1148':
    10089                 return 'IBM01148';
    10090 
    10091             case 'ccsid1149':
    10092             case 'cp1149':
    10093             case 'ebcdicis871euro':
    10094             case 'ibm1149':
    10095                 return 'IBM01149';
    10096 
    10097             case 'csiso143iecp271':
    10098             case 'iecp271':
    10099             case 'isoir143':
    10100                 return 'IEC_P27-1';
    10101 
    10102             case 'csiso49inis':
    10103             case 'inis':
    10104             case 'isoir49':
    10105                 return 'INIS';
    10106 
    10107             case 'csiso50inis8':
    10108             case 'inis8':
    10109             case 'isoir50':
    10110                 return 'INIS-8';
    10111 
    10112             case 'csiso51iniscyrillic':
    10113             case 'iniscyrillic':
    10114             case 'isoir51':
    10115                 return 'INIS-cyrillic';
    10116 
    10117             case 'csinvariant':
    10118             case 'invariant':
    10119                 return 'INVARIANT';
    10120 
    10121             case 'iso2022cn':
    10122                 return 'ISO-2022-CN';
    10123 
    10124             case 'iso2022cnext':
    10125                 return 'ISO-2022-CN-EXT';
    10126 
    10127             case 'csiso2022jp':
    10128             case 'iso2022jp':
    10129                 return 'ISO-2022-JP';
    10130 
    10131             case 'csiso2022jp2':
    10132             case 'iso2022jp2':
    10133                 return 'ISO-2022-JP-2';
    10134 
    10135             case 'csiso2022kr':
    10136             case 'iso2022kr':
    10137                 return 'ISO-2022-KR';
    10138 
    10139             case 'cswindows30latin1':
    10140             case 'iso88591windows30latin1':
    10141                 return 'ISO-8859-1-Windows-3.0-Latin-1';
    10142 
    10143             case 'cswindows31latin1':
    10144             case 'iso88591windows31latin1':
    10145                 return 'ISO-8859-1-Windows-3.1-Latin-1';
    10146 
    10147             case 'csisolatin2':
    10148             case 'iso88592':
    10149             case 'iso885921987':
    10150             case 'isoir101':
    10151             case 'l2':
    10152             case 'latin2':
    10153                 return 'ISO-8859-2';
    10154 
    10155             case 'cswindows31latin2':
    10156             case 'iso88592windowslatin2':
    10157                 return 'ISO-8859-2-Windows-Latin-2';
    10158 
    10159             case 'csisolatin3':
    10160             case 'iso88593':
    10161             case 'iso885931988':
    10162             case 'isoir109':
    10163             case 'l3':
    10164             case 'latin3':
    10165                 return 'ISO-8859-3';
    10166 
    10167             case 'csisolatin4':
    10168             case 'iso88594':
    10169             case 'iso885941988':
    10170             case 'isoir110':
    10171             case 'l4':
    10172             case 'latin4':
    10173                 return 'ISO-8859-4';
    10174 
    10175             case 'csisolatincyrillic':
    10176             case 'cyrillic':
    10177             case 'iso88595':
    10178             case 'iso885951988':
    10179             case 'isoir144':
    10180                 return 'ISO-8859-5';
    10181 
    10182             case 'arabic':
    10183             case 'asmo708':
    10184             case 'csisolatinarabic':
    10185             case 'ecma114':
    10186             case 'iso88596':
    10187             case 'iso885961987':
    10188             case 'isoir127':
    10189                 return 'ISO-8859-6';
    10190 
    10191             case 'csiso88596e':
    10192             case 'iso88596e':
    10193                 return 'ISO-8859-6-E';
    10194 
    10195             case 'csiso88596i':
    10196             case 'iso88596i':
    10197                 return 'ISO-8859-6-I';
    10198 
    10199             case 'csisolatingreek':
    10200             case 'ecma118':
    10201             case 'elot928':
    10202             case 'greek':
    10203             case 'greek8':
    10204             case 'iso88597':
    10205             case 'iso885971987':
    10206             case 'isoir126':
    10207                 return 'ISO-8859-7';
    10208 
    10209             case 'csisolatinhebrew':
    10210             case 'hebrew':
    10211             case 'iso88598':
    10212             case 'iso885981988':
    10213             case 'isoir138':
    10214                 return 'ISO-8859-8';
    10215 
    10216             case 'csiso88598e':
    10217             case 'iso88598e':
    10218                 return 'ISO-8859-8-E';
    10219 
    10220             case 'csiso88598i':
    10221             case 'iso88598i':
    10222                 return 'ISO-8859-8-I';
    10223 
    10224             case 'cswindows31latin5':
    10225             case 'iso88599windowslatin5':
    10226                 return 'ISO-8859-9-Windows-Latin-5';
    10227 
    10228             case 'csisolatin6':
    10229             case 'iso885910':
    10230             case 'iso8859101992':
    10231             case 'isoir157':
    10232             case 'l6':
    10233             case 'latin6':
    10234                 return 'ISO-8859-10';
    10235 
    10236             case 'iso885913':
    10237                 return 'ISO-8859-13';
    10238 
    10239             case 'iso885914':
    10240             case 'iso8859141998':
    10241             case 'isoceltic':
    10242             case 'isoir199':
    10243             case 'l8':
    10244             case 'latin8':
    10245                 return 'ISO-8859-14';
    10246 
    10247             case 'iso885915':
    10248             case 'latin9':
    10249                 return 'ISO-8859-15';
    10250 
    10251             case 'iso885916':
    10252             case 'iso8859162001':
    10253             case 'isoir226':
    10254             case 'l10':
    10255             case 'latin10':
    10256                 return 'ISO-8859-16';
    10257 
    10258             case 'iso10646j1':
    10259                 return 'ISO-10646-J-1';
    10260 
    10261             case 'csunicode':
    10262             case 'iso10646ucs2':
    10263                 return 'ISO-10646-UCS-2';
    10264 
    10265             case 'csucs4':
    10266             case 'iso10646ucs4':
    10267                 return 'ISO-10646-UCS-4';
    10268 
    10269             case 'csunicodeascii':
    10270             case 'iso10646ucsbasic':
    10271                 return 'ISO-10646-UCS-Basic';
    10272 
    10273             case 'csunicodelatin1':
    10274             case 'iso10646':
    10275             case 'iso10646unicodelatin1':
    10276                 return 'ISO-10646-Unicode-Latin1';
    10277 
    10278             case 'csiso10646utf1':
    10279             case 'iso10646utf1':
    10280                 return 'ISO-10646-UTF-1';
    10281 
    10282             case 'csiso115481':
    10283             case 'iso115481':
    10284             case 'isotr115481':
    10285                 return 'ISO-11548-1';
    10286 
    10287             case 'csiso90':
    10288             case 'isoir90':
    10289                 return 'iso-ir-90';
    10290 
    10291             case 'csunicodeibm1261':
    10292             case 'isounicodeibm1261':
    10293                 return 'ISO-Unicode-IBM-1261';
    10294 
    10295             case 'csunicodeibm1264':
    10296             case 'isounicodeibm1264':
    10297                 return 'ISO-Unicode-IBM-1264';
    10298 
    10299             case 'csunicodeibm1265':
    10300             case 'isounicodeibm1265':
    10301                 return 'ISO-Unicode-IBM-1265';
    10302 
    10303             case 'csunicodeibm1268':
    10304             case 'isounicodeibm1268':
    10305                 return 'ISO-Unicode-IBM-1268';
    10306 
    10307             case 'csunicodeibm1276':
    10308             case 'isounicodeibm1276':
    10309                 return 'ISO-Unicode-IBM-1276';
    10310 
    10311             case 'csiso646basic1983':
    10312             case 'iso646basic1983':
    10313             case 'ref':
    10314                 return 'ISO_646.basic:1983';
    10315 
    10316             case 'csiso2intlrefversion':
    10317             case 'irv':
    10318             case 'iso646irv1983':
    10319             case 'isoir2':
    10320                 return 'ISO_646.irv:1983';
    10321 
    10322             case 'csiso2033':
    10323             case 'e13b':
    10324             case 'iso20331983':
    10325             case 'isoir98':
    10326                 return 'ISO_2033-1983';
    10327 
    10328             case 'csiso5427cyrillic':
    10329             case 'iso5427':
    10330             case 'isoir37':
    10331                 return 'ISO_5427';
    10332 
    10333             case 'iso5427cyrillic1981':
    10334             case 'iso54271981':
    10335             case 'isoir54':
    10336                 return 'ISO_5427:1981';
    10337 
    10338             case 'csiso5428greek':
    10339             case 'iso54281980':
    10340             case 'isoir55':
    10341                 return 'ISO_5428:1980';
    10342 
    10343             case 'csiso6937add':
    10344             case 'iso6937225':
    10345             case 'isoir152':
    10346                 return 'ISO_6937-2-25';
    10347 
    10348             case 'csisotextcomm':
    10349             case 'iso69372add':
    10350             case 'isoir142':
    10351                 return 'ISO_6937-2-add';
    10352 
    10353             case 'csiso8859supp':
    10354             case 'iso8859supp':
    10355             case 'isoir154':
    10356             case 'latin125':
    10357                 return 'ISO_8859-supp';
    10358 
    10359             case 'csiso10367box':
    10360             case 'iso10367box':
    10361             case 'isoir155':
    10362                 return 'ISO_10367-box';
    10363 
    10364             case 'csiso15italian':
    10365             case 'iso646it':
    10366             case 'isoir15':
    10367             case 'it':
    10368                 return 'IT';
    10369 
    10370             case 'csiso13jisc6220jp':
    10371             case 'isoir13':
    10372             case 'jisc62201969':
    10373             case 'jisc62201969jp':
    10374             case 'katakana':
    10375             case 'x2017':
    10376                 return 'JIS_C6220-1969-jp';
    10377 
    10378             case 'csiso14jisc6220ro':
    10379             case 'iso646jp':
    10380             case 'isoir14':
    10381             case 'jisc62201969ro':
    10382             case 'jp':
    10383                 return 'JIS_C6220-1969-ro';
    10384 
    10385             case 'csiso42jisc62261978':
    10386             case 'isoir42':
    10387             case 'jisc62261978':
    10388                 return 'JIS_C6226-1978';
    10389 
    10390             case 'csiso87jisx208':
    10391             case 'isoir87':
    10392             case 'jisc62261983':
    10393             case 'jisx2081983':
    10394             case 'x208':
    10395                 return 'JIS_C6226-1983';
    10396 
    10397             case 'csiso91jisc62291984a':
    10398             case 'isoir91':
    10399             case 'jisc62291984a':
    10400             case 'jpocra':
    10401                 return 'JIS_C6229-1984-a';
    10402 
    10403             case 'csiso92jisc62991984b':
    10404             case 'iso646jpocrb':
    10405             case 'isoir92':
    10406             case 'jisc62291984b':
    10407             case 'jpocrb':
    10408                 return 'JIS_C6229-1984-b';
    10409 
    10410             case 'csiso93jis62291984badd':
    10411             case 'isoir93':
    10412             case 'jisc62291984badd':
    10413             case 'jpocrbadd':
    10414                 return 'JIS_C6229-1984-b-add';
    10415 
    10416             case 'csiso94jis62291984hand':
    10417             case 'isoir94':
    10418             case 'jisc62291984hand':
    10419             case 'jpocrhand':
    10420                 return 'JIS_C6229-1984-hand';
    10421 
    10422             case 'csiso95jis62291984handadd':
    10423             case 'isoir95':
    10424             case 'jisc62291984handadd':
    10425             case 'jpocrhandadd':
    10426                 return 'JIS_C6229-1984-hand-add';
    10427 
    10428             case 'csiso96jisc62291984kana':
    10429             case 'isoir96':
    10430             case 'jisc62291984kana':
    10431                 return 'JIS_C6229-1984-kana';
    10432 
    10433             case 'csjisencoding':
    10434             case 'jisencoding':
    10435                 return 'JIS_Encoding';
    10436 
    10437             case 'cshalfwidthkatakana':
    10438             case 'jisx201':
    10439             case 'x201':
    10440                 return 'JIS_X0201';
    10441 
    10442             case 'csiso159jisx2121990':
    10443             case 'isoir159':
    10444             case 'jisx2121990':
    10445             case 'x212':
    10446                 return 'JIS_X0212-1990';
    10447 
    10448             case 'csiso141jusib1002':
    10449             case 'iso646yu':
    10450             case 'isoir141':
    10451             case 'js':
    10452             case 'jusib1002':
    10453             case 'yu':
    10454                 return 'JUS_I.B1.002';
    10455 
    10456             case 'csiso147macedonian':
    10457             case 'isoir147':
    10458             case 'jusib1003mac':
    10459             case 'macedonian':
    10460                 return 'JUS_I.B1.003-mac';
    10461 
    10462             case 'csiso146serbian':
    10463             case 'isoir146':
    10464             case 'jusib1003serb':
    10465             case 'serbian':
    10466                 return 'JUS_I.B1.003-serb';
    10467 
    10468             case 'koi7switched':
    10469                 return 'KOI7-switched';
    10470 
    10471             case 'cskoi8r':
    10472             case 'koi8r':
    10473                 return 'KOI8-R';
    10474 
    10475             case 'koi8u':
    10476                 return 'KOI8-U';
    10477 
    10478             case 'csksc5636':
    10479             case 'iso646kr':
    10480             case 'ksc5636':
    10481                 return 'KSC5636';
    10482 
    10483             case 'cskz1048':
    10484             case 'kz1048':
    10485             case 'rk1048':
    10486             case 'strk10482002':
    10487                 return 'KZ-1048';
    10488 
    10489             case 'csiso19latingreek':
    10490             case 'isoir19':
    10491             case 'latingreek':
    10492                 return 'latin-greek';
    10493 
    10494             case 'csiso27latingreek1':
    10495             case 'isoir27':
    10496             case 'latingreek1':
    10497                 return 'Latin-greek-1';
    10498 
    10499             case 'csiso158lap':
    10500             case 'isoir158':
    10501             case 'lap':
    10502             case 'latinlap':
    10503                 return 'latin-lap';
    10504 
    10505             case 'csmacintosh':
    10506             case 'mac':
    10507             case 'macintosh':
    10508                 return 'macintosh';
    10509 
    10510             case 'csmicrosoftpublishing':
    10511             case 'microsoftpublishing':
    10512                 return 'Microsoft-Publishing';
    10513 
    10514             case 'csmnem':
    10515             case 'mnem':
    10516                 return 'MNEM';
    10517 
    10518             case 'csmnemonic':
    10519             case 'mnemonic':
    10520                 return 'MNEMONIC';
    10521 
    10522             case 'csiso86hungarian':
    10523             case 'hu':
    10524             case 'iso646hu':
    10525             case 'isoir86':
    10526             case 'msz77953':
    10527                 return 'MSZ_7795.3';
    10528 
    10529             case 'csnatsdano':
    10530             case 'isoir91':
    10531             case 'natsdano':
    10532                 return 'NATS-DANO';
    10533 
    10534             case 'csnatsdanoadd':
    10535             case 'isoir92':
    10536             case 'natsdanoadd':
    10537                 return 'NATS-DANO-ADD';
    10538 
    10539             case 'csnatssefi':
    10540             case 'isoir81':
    10541             case 'natssefi':
    10542                 return 'NATS-SEFI';
    10543 
    10544             case 'csnatssefiadd':
    10545             case 'isoir82':
    10546             case 'natssefiadd':
    10547                 return 'NATS-SEFI-ADD';
    10548 
    10549             case 'csiso151cuba':
    10550             case 'cuba':
    10551             case 'iso646cu':
    10552             case 'isoir151':
    10553             case 'ncnc1081':
    10554                 return 'NC_NC00-10:81';
    10555 
    10556             case 'csiso69french':
    10557             case 'fr':
    10558             case 'iso646fr':
    10559             case 'isoir69':
    10560             case 'nfz62010':
    10561                 return 'NF_Z_62-010';
    10562 
    10563             case 'csiso25french':
    10564             case 'iso646fr1':
    10565             case 'isoir25':
    10566             case 'nfz620101973':
    10567                 return 'NF_Z_62-010_(1973)';
    10568 
    10569             case 'csiso60danishnorwegian':
    10570             case 'csiso60norwegian1':
    10571             case 'iso646no':
    10572             case 'isoir60':
    10573             case 'no':
    10574             case 'ns45511':
    10575                 return 'NS_4551-1';
    10576 
    10577             case 'csiso61norwegian2':
    10578             case 'iso646no2':
    10579             case 'isoir61':
    10580             case 'no2':
    10581             case 'ns45512':
    10582                 return 'NS_4551-2';
    10583 
    10584             case 'osdebcdicdf3irv':
    10585                 return 'OSD_EBCDIC_DF03_IRV';
    10586 
    10587             case 'osdebcdicdf41':
    10588                 return 'OSD_EBCDIC_DF04_1';
    10589 
    10590             case 'osdebcdicdf415':
    10591                 return 'OSD_EBCDIC_DF04_15';
    10592 
    10593             case 'cspc8danishnorwegian':
    10594             case 'pc8danishnorwegian':
    10595                 return 'PC8-Danish-Norwegian';
    10596 
    10597             case 'cspc8turkish':
    10598             case 'pc8turkish':
    10599                 return 'PC8-Turkish';
    10600 
    10601             case 'csiso16portuguese':
    10602             case 'iso646pt':
    10603             case 'isoir16':
    10604             case 'pt':
    10605                 return 'PT';
    10606 
    10607             case 'csiso84portuguese2':
    10608             case 'iso646pt2':
    10609             case 'isoir84':
    10610             case 'pt2':
    10611                 return 'PT2';
    10612 
    10613             case 'cp154':
    10614             case 'csptcp154':
    10615             case 'cyrillicasian':
    10616             case 'pt154':
    10617             case 'ptcp154':
    10618                 return 'PTCP154';
    10619 
    10620             case 'scsu':
    10621                 return 'SCSU';
    10622 
    10623             case 'csiso10swedish':
    10624             case 'fi':
    10625             case 'iso646fi':
    10626             case 'iso646se':
    10627             case 'isoir10':
    10628             case 'se':
    10629             case 'sen850200b':
    10630                 return 'SEN_850200_B';
    10631 
    10632             case 'csiso11swedishfornames':
    10633             case 'iso646se2':
    10634             case 'isoir11':
    10635             case 'se2':
    10636             case 'sen850200c':
    10637                 return 'SEN_850200_C';
    10638 
    10639             case 'csiso102t617bit':
    10640             case 'isoir102':
    10641             case 't617bit':
    10642                 return 'T.61-7bit';
    10643 
    10644             case 'csiso103t618bit':
    10645             case 'isoir103':
    10646             case 't61':
    10647             case 't618bit':
    10648                 return 'T.61-8bit';
    10649 
    10650             case 'csiso128t101g2':
    10651             case 'isoir128':
    10652             case 't101g2':
    10653                 return 'T.101-G2';
    10654 
    10655             case 'cstscii':
    10656             case 'tscii':
    10657                 return 'TSCII';
    10658 
    10659             case 'csunicode11':
    10660             case 'unicode11':
    10661                 return 'UNICODE-1-1';
    10662 
    10663             case 'csunicode11utf7':
    10664             case 'unicode11utf7':
    10665                 return 'UNICODE-1-1-UTF-7';
    10666 
    10667             case 'csunknown8bit':
    10668             case 'unknown8bit':
    10669                 return 'UNKNOWN-8BIT';
    10670 
    10671             case 'ansix341968':
    10672             case 'ansix341986':
    10673             case 'ascii':
    10674             case 'cp367':
    10675             case 'csascii':
    10676             case 'ibm367':
    10677             case 'iso646irv1991':
    10678             case 'iso646us':
    10679             case 'isoir6':
    10680             case 'us':
    10681             case 'usascii':
    10682                 return 'US-ASCII';
    10683 
    10684             case 'csusdk':
    10685             case 'usdk':
    10686                 return 'us-dk';
    10687 
    10688             case 'utf7':
    10689                 return 'UTF-7';
    10690 
    10691             case 'utf8':
    10692                 return 'UTF-8';
    10693 
    10694             case 'utf16':
    10695                 return 'UTF-16';
    10696 
    10697             case 'utf16be':
    10698                 return 'UTF-16BE';
    10699 
    10700             case 'utf16le':
    10701                 return 'UTF-16LE';
    10702 
    10703             case 'utf32':
    10704                 return 'UTF-32';
    10705 
    10706             case 'utf32be':
    10707                 return 'UTF-32BE';
    10708 
    10709             case 'utf32le':
    10710                 return 'UTF-32LE';
    10711 
    10712             case 'csventurainternational':
    10713             case 'venturainternational':
    10714                 return 'Ventura-International';
    10715 
    10716             case 'csventuramath':
    10717             case 'venturamath':
    10718                 return 'Ventura-Math';
    10719 
    10720             case 'csventuraus':
    10721             case 'venturaus':
    10722                 return 'Ventura-US';
    10723 
    10724             case 'csiso70videotexsupp1':
    10725             case 'isoir70':
    10726             case 'videotexsuppl':
    10727                 return 'videotex-suppl';
    10728 
    10729             case 'csviqr':
    10730             case 'viqr':
    10731                 return 'VIQR';
    10732 
    10733             case 'csviscii':
    10734             case 'viscii':
    10735                 return 'VISCII';
    10736 
    10737             case 'csshiftjis':
    10738             case 'cswindows31j':
    10739             case 'mskanji':
    10740             case 'shiftjis':
    10741             case 'windows31j':
    10742                 return 'Windows-31J';
    10743 
    10744             case 'iso885911':
    10745             case 'tis620':
    10746                 return 'windows-874';
    10747 
    10748             case 'cseuckr':
    10749             case 'csksc56011987':
    10750             case 'euckr':
    10751             case 'isoir149':
    10752             case 'korean':
    10753             case 'ksc5601':
    10754             case 'ksc56011987':
    10755             case 'ksc56011989':
    10756             case 'windows949':
    10757                 return 'windows-949';
    10758 
    10759             case 'windows1250':
    10760                 return 'windows-1250';
    10761 
    10762             case 'windows1251':
    10763                 return 'windows-1251';
    10764 
    10765             case 'cp819':
    10766             case 'csisolatin1':
    10767             case 'ibm819':
    10768             case 'iso88591':
    10769             case 'iso885911987':
    10770             case 'isoir100':
    10771             case 'l1':
    10772             case 'latin1':
    10773             case 'windows1252':
    10774                 return 'windows-1252';
    10775 
    10776             case 'windows1253':
    10777                 return 'windows-1253';
    10778 
    10779             case 'csisolatin5':
    10780             case 'iso88599':
    10781             case 'iso885991989':
    10782             case 'isoir148':
    10783             case 'l5':
    10784             case 'latin5':
    10785             case 'windows1254':
    10786                 return 'windows-1254';
    10787 
    10788             case 'windows1255':
    10789                 return 'windows-1255';
    10790 
    10791             case 'windows1256':
    10792                 return 'windows-1256';
    10793 
    10794             case 'windows1257':
    10795                 return 'windows-1257';
    10796 
    10797             case 'windows1258':
    10798                 return 'windows-1258';
    10799 
    10800             default:
    10801                 return $charset;
    10802         }
    10803     }
    10804 
    10805     function get_curl_version()
    10806     {
    10807         if (is_array($curl = curl_version()))
    10808         {
    10809             $curl = $curl['version'];
    10810         }
    10811         elseif (substr($curl, 0, 5) === 'curl/')
    10812         {
    10813             $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
    10814         }
    10815         elseif (substr($curl, 0, 8) === 'libcurl/')
    10816         {
    10817             $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
    10818         }
    10819         else
    10820         {
    10821             $curl = 0;
    10822         }
    10823         return $curl;
    10824     }
    10825 
    10826     function is_subclass_of($class1, $class2)
    10827     {
    10828         if (func_num_args() !== 2)
    10829         {
    10830             trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
    10831         }
    10832         elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
    10833         {
    10834             return is_subclass_of($class1, $class2);
    10835         }
    10836         elseif (is_string($class1) && is_string($class2))
    10837         {
    10838             if (class_exists($class1))
    10839             {
    10840                 if (class_exists($class2))
    10841                 {
    10842                     $class2 = strtolower($class2);
    10843                     while ($class1 = strtolower(get_parent_class($class1)))
    10844                     {
    10845                         if ($class1 === $class2)
    10846                         {
    10847                             return true;
    10848                         }
    10849                     }
    10850                 }
    10851             }
    10852             else
    10853             {
    10854                 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
    10855             }
    10856         }
    10857         return false;
    10858     }
    10859 
    10860     /**
    10861      * Strip HTML comments
    10862      *
    10863      * @access public
    10864      * @param string $data Data to strip comments from
    10865      * @return string Comment stripped string
    10866      */
    10867     function strip_comments($data)
    10868     {
    10869         $output = '';
    10870         while (($start = strpos($data, '<!--')) !== false)
    10871         {
    10872             $output .= substr($data, 0, $start);
    10873             if (($end = strpos($data, '-->', $start)) !== false)
    10874             {
    10875                 $data = substr_replace($data, '', 0, $end + 3);
    10876             }
    10877             else
    10878             {
    10879                 $data = '';
    10880             }
    10881         }
    10882         return $output . $data;
    10883     }
    10884 
    10885     function parse_date($dt)
    10886     {
    10887         $parser = SimplePie_Parse_Date::get();
    10888         return $parser->parse($dt);
    10889     }
    10890 
    10891     /**
    10892      * Decode HTML entities
    10893      *
    10894      * @static
    10895      * @access public
    10896      * @param string $data Input data
    10897      * @return string Output data
    10898      */
    10899     function entities_decode($data)
    10900     {
    10901         $decoder =& new SimplePie_Decode_HTML_Entities($data);
    10902         return $decoder->parse();
    10903     }
    10904 
    10905     /**
    10906      * Remove RFC822 comments
    10907      *
    10908      * @access public
    10909      * @param string $data Data to strip comments from
    10910      * @return string Comment stripped string
    10911      */
    10912     function uncomment_rfc822($string)
    10913     {
    10914         $string = (string) $string;
    10915         $position = 0;
    10916         $length = strlen($string);
    10917         $depth = 0;
    10918 
    10919         $output = '';
    10920 
    10921         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
    10922         {
    10923             $output .= substr($string, $position, $pos - $position);
    10924             $position = $pos + 1;
    10925             if ($string[$pos - 1] !== '\\')
    10926             {
    10927                 $depth++;
    10928                 while ($depth && $position < $length)
    10929                 {
    10930                     $position += strcspn($string, '()', $position);
    10931                     if ($string[$position - 1] === '\\')
    10932                     {
    10933                         $position++;
    10934                         continue;
    10935                     }
    10936                     elseif (isset($string[$position]))
    10937                     {
    10938                         switch ($string[$position])
    10939                         {
    10940                             case '(':
    10941                                 $depth++;
    10942                                 break;
    10943 
    10944                             case ')':
    10945                                 $depth--;
    10946                                 break;
    10947                         }
    10948                         $position++;
    10949                     }
    10950                     else
    10951                     {
    10952                         break;
    10953                     }
    10954                 }
    10955             }
    10956             else
    10957             {
    10958                 $output .= '(';
    10959             }
    10960         }
    10961         $output .= substr($string, $position);
    10962 
    10963         return $output;
    10964     }
    10965 
    10966     function parse_mime($mime)
    10967     {
    10968         if (($pos = strpos($mime, ';')) === false)
    10969         {
    10970             return trim($mime);
    10971         }
    10972         else
    10973         {
    10974             return trim(substr($mime, 0, $pos));
    10975         }
    10976     }
    10977 
    10978     function htmlspecialchars_decode($string, $quote_style)
    10979     {
    10980         if (function_exists('htmlspecialchars_decode'))
    10981         {
    10982             return htmlspecialchars_decode($string, $quote_style);
    10983         }
    10984         else
    10985         {
    10986             return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
    10987         }
    10988     }
    10989 
    10990     function atom_03_construct_type($attribs)
    10991     {
    10992         if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
    10993         {
    10994             $mode = SIMPLEPIE_CONSTRUCT_BASE64;
    10995         }
    10996         else
    10997         {
    10998             $mode = SIMPLEPIE_CONSTRUCT_NONE;
    10999         }
    11000         if (isset($attribs['']['type']))
    11001         {
    11002             switch (strtolower(trim($attribs['']['type'])))
    11003             {
    11004                 case 'text':
    11005                 case 'text/plain':
    11006                     return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
    11007 
    11008                 case 'html':
    11009                 case 'text/html':
    11010                     return SIMPLEPIE_CONSTRUCT_HTML | $mode;
    11011 
    11012                 case 'xhtml':
    11013                 case 'application/xhtml+xml':
    11014                     return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
    11015 
    11016                 default:
    11017                     return SIMPLEPIE_CONSTRUCT_NONE | $mode;
    11018             }
    11019         }
    11020         else
    11021         {
    11022             return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
    11023         }
    11024     }
    11025 
    11026     function atom_10_construct_type($attribs)
    11027     {
    11028         if (isset($attribs['']['type']))
    11029         {
    11030             switch (strtolower(trim($attribs['']['type'])))
    11031             {
    11032                 case 'text':
    11033                     return SIMPLEPIE_CONSTRUCT_TEXT;
    11034 
    11035                 case 'html':
    11036                     return SIMPLEPIE_CONSTRUCT_HTML;
    11037 
    11038                 case 'xhtml':
    11039                     return SIMPLEPIE_CONSTRUCT_XHTML;
    11040 
    11041                 default:
    11042                     return SIMPLEPIE_CONSTRUCT_NONE;
    11043             }
    11044         }
    11045         return SIMPLEPIE_CONSTRUCT_TEXT;
    11046     }
    11047 
    11048     function atom_10_content_construct_type($attribs)
    11049     {
    11050         if (isset($attribs['']['type']))
    11051         {
    11052             $type = strtolower(trim($attribs['']['type']));
    11053             switch ($type)
    11054             {
    11055                 case 'text':
    11056                     return SIMPLEPIE_CONSTRUCT_TEXT;
    11057 
    11058                 case 'html':
    11059                     return SIMPLEPIE_CONSTRUCT_HTML;
    11060 
    11061                 case 'xhtml':
    11062                     return SIMPLEPIE_CONSTRUCT_XHTML;
    11063             }
    11064             if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
    11065             {
    11066                 return SIMPLEPIE_CONSTRUCT_NONE;
    11067             }
    11068             else
    11069             {
    11070                 return SIMPLEPIE_CONSTRUCT_BASE64;
    11071             }
    11072         }
    11073         else
    11074         {
    11075             return SIMPLEPIE_CONSTRUCT_TEXT;
    11076         }
    11077     }
    11078 
    11079     function is_isegment_nz_nc($string)
    11080     {
    11081         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);
    11082     }
    11083 
    11084     function space_seperated_tokens($string)
    11085     {
    11086         $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
    11087         $string_length = strlen($string);
    11088 
    11089         $position = strspn($string, $space_characters);
    11090         $tokens = array();
    11091 
    11092         while ($position < $string_length)
    11093         {
    11094             $len = strcspn($string, $space_characters, $position);
    11095             $tokens[] = substr($string, $position, $len);
    11096             $position += $len;
    11097             $position += strspn($string, $space_characters, $position);
    11098         }
    11099 
    11100         return $tokens;
    11101     }
    11102 
    11103     function array_unique($array)
    11104     {
    11105         if (version_compare(PHP_VERSION, '5.2', '>='))
    11106         {
    11107             return array_unique($array);
    11108         }
    11109         else
    11110         {
    11111             $array = (array) $array;
    11112             $new_array = array();
    11113             $new_array_strings = array();
    11114             foreach ($array as $key => $value)
    11115             {
    11116                 if (is_object($value))
    11117                 {
    11118                     if (method_exists($value, '__toString'))
    11119                     {
    11120                         $cmp = $value->__toString();
    11121                     }
    11122                     else
    11123                     {
    11124                         trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
    11125                     }
    11126                 }
    11127                 elseif (is_array($value))
    11128                 {
    11129                     $cmp = (string) reset($value);
    11130                 }
    11131                 else
    11132                 {
    11133                     $cmp = (string) $value;
    11134                 }
    11135                 if (!in_array($cmp, $new_array_strings))
    11136                 {
    11137                     $new_array[$key] = $value;
    11138                     $new_array_strings[] = $cmp;
    11139                 }
    11140             }
    11141             return $new_array;
    11142         }
    11143     }
    11144 
    11145     /**
    11146      * Converts a unicode codepoint to a UTF-8 character
    11147      *
    11148      * @static
    11149      * @access public
    11150      * @param int $codepoint Unicode codepoint
    11151      * @return string UTF-8 character
    11152      */
    11153     function codepoint_to_utf8($codepoint)
    11154     {
    11155         $codepoint = (int) $codepoint;
    11156         if ($codepoint < 0)
    11157         {
    11158             return false;
    11159         }
    11160         else if ($codepoint <= 0x7f)
    11161         {
    11162             return chr($codepoint);
    11163         }
    11164         else if ($codepoint <= 0x7ff)
    11165         {
    11166             return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
    11167         }
    11168         else if ($codepoint <= 0xffff)
    11169         {
    11170             return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
    11171         }
    11172         else if ($codepoint <= 0x10ffff)
    11173         {
    11174             return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
    11175         }
    11176         else
    11177         {
    11178             // U+FFFD REPLACEMENT CHARACTER
    11179             return "\xEF\xBF\xBD";
    11180         }
    11181     }
    11182 
    11183     /**
    11184      * Re-implementation of PHP 5's stripos()
    11185      *
    11186      * Returns the numeric position of the first occurrence of needle in the
    11187      * haystack string.
    11188      *
    11189      * @static
    11190      * @access string
    11191      * @param object $haystack
    11192      * @param string $needle Note that the needle may be a string of one or more
    11193      *     characters. If needle is not a string, it is converted to an integer
    11194      *     and applied as the ordinal value of a character.
    11195      * @param int $offset The optional offset parameter allows you to specify which
    11196      *     character in haystack to start searching. The position returned is still
    11197      *     relative to the beginning of haystack.
    11198      * @return bool If needle is not found, stripos() will return boolean false.
    11199      */
    11200     function stripos($haystack, $needle, $offset = 0)
    11201     {
    11202         if (function_exists('stripos'))
    11203         {
    11204             return stripos($haystack, $needle, $offset);
    11205         }
    11206         else
    11207         {
    11208             if (is_string($needle))
    11209             {
    11210                 $needle = strtolower($needle);
    11211             }
    11212             elseif (is_int($needle) || is_bool($needle) || is_double($needle))
    11213             {
    11214                 $needle = strtolower(chr($needle));
    11215             }
    11216             else
    11217             {
    11218                 trigger_error('needle is not a string or an integer', E_USER_WARNING);
    11219                 return false;
    11220             }
    11221 
    11222             return strpos(strtolower($haystack), $needle, $offset);
    11223         }
    11224     }
    11225 
    11226     /**
    11227      * Similar to parse_str()
    11228      *
    11229      * Returns an associative array of name/value pairs, where the value is an
    11230      * array of values that have used the same name
    11231      *
    11232      * @static
    11233      * @access string
    11234      * @param string $str The input string.
    11235      * @return array
    11236      */
    11237     function parse_str($str)
    11238     {
    11239         $return = array();
    11240         $str = explode('&', $str);
    11241 
    11242         foreach ($str as $section)
    11243         {
    11244             if (strpos($section, '=') !== false)
    11245             {
    11246                 list($name, $value) = explode('=', $section, 2);
    11247                 $return[urldecode($name)][] = urldecode($value);
    11248             }
    11249             else
    11250             {
    11251                 $return[urldecode($section)][] = null;
    11252             }
    11253         }
    11254 
    11255         return $return;
    11256     }
    11257 
    11258     /**
    11259      * Detect XML encoding, as per XML 1.0 Appendix F.1
    11260      *
    11261      * @todo Add support for EBCDIC
    11262      * @param string $data XML data
    11263      * @return array Possible encodings
    11264      */
    11265     function xml_encoding($data)
    11266     {
    11267         // UTF-32 Big Endian BOM
    11268         if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
    11269         {
    11270             $encoding[] = 'UTF-32BE';
    11271         }
    11272         // UTF-32 Little Endian BOM
    11273         elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
    11274         {
    11275             $encoding[] = 'UTF-32LE';
    11276         }
    11277         // UTF-16 Big Endian BOM
    11278         elseif (substr($data, 0, 2) === "\xFE\xFF")
    11279         {
    11280             $encoding[] = 'UTF-16BE';
    11281         }
    11282         // UTF-16 Little Endian BOM
    11283         elseif (substr($data, 0, 2) === "\xFF\xFE")
    11284         {
    11285             $encoding[] = 'UTF-16LE';
    11286         }
    11287         // UTF-8 BOM
    11288         elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
    11289         {
    11290             $encoding[] = 'UTF-8';
    11291         }
    11292         // UTF-32 Big Endian Without BOM
    11293         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")
    11294         {
    11295             if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
    11296             {
    11297                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
    11298                 if ($parser->parse())
    11299                 {
    11300                     $encoding[] = $parser->encoding;
    11301                 }
    11302             }
    11303             $encoding[] = 'UTF-32BE';
    11304         }
    11305         // UTF-32 Little Endian Without BOM
    11306         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")
    11307         {
    11308             if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
    11309             {
    11310                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
    11311                 if ($parser->parse())
    11312                 {
    11313                     $encoding[] = $parser->encoding;
    11314                 }
    11315             }
    11316             $encoding[] = 'UTF-32LE';
    11317         }
    11318         // UTF-16 Big Endian Without BOM
    11319         elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
    11320         {
    11321             if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
    11322             {
    11323                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
    11324                 if ($parser->parse())
    11325                 {
    11326                     $encoding[] = $parser->encoding;
    11327                 }
    11328             }
    11329             $encoding[] = 'UTF-16BE';
    11330         }
    11331         // UTF-16 Little Endian Without BOM
    11332         elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
    11333         {
    11334             if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
    11335             {
    11336                 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
    11337                 if ($parser->parse())
    11338                 {
    11339                     $encoding[] = $parser->encoding;
    11340                 }
    11341             }
    11342             $encoding[] = 'UTF-16LE';
    11343         }
    11344         // US-ASCII (or superset)
    11345         elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
    11346         {
    11347             if ($pos = strpos($data, "\x3F\x3E"))
    11348             {
    11349                 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
    11350                 if ($parser->parse())
    11351                 {
    11352                     $encoding[] = $parser->encoding;
    11353                 }
    11354             }
    11355             $encoding[] = 'UTF-8';
    11356         }
    11357         // Fallback to UTF-8
    11358         else
    11359         {
    11360             $encoding[] = 'UTF-8';
    11361         }
    11362         return $encoding;
    11363     }
    11364 
    11365     function output_javascript()
    11366     {
    11367         if (function_exists('ob_gzhandler'))
    11368         {
    11369             ob_start('ob_gzhandler');
    11370         }
    11371         header('Content-type: text/javascript; charset: UTF-8');
    11372         header('Cache-Control: must-revalidate');
    11373         header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
    11374         ?>
    11375 function embed_odeo(link) {
    11376     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>');
    11377 }
    11378 
    11379 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
    11380     if (placeholder != '') {
    11381         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>');
    11382     }
    11383     else {
    11384         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>');
    11385     }
    11386 }
    11387 
    11388 function embed_flash(bgcolor, width, height, link, loop, type) {
    11389     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>');
    11390 }
    11391 
    11392 function embed_flv(width, height, link, placeholder, loop, player) {
    11393     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>');
    11394 }
    11395 
    11396 function embed_wmedia(width, height, link) {
    11397     document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
    11398 }
    11399         <?php
    11400     }
    11401 
    11402 
    11403 
    11404     /**
    11405      * Format debugging information
    11406      */
    11407     function debug($sp)
    11408     {
    11409         $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
    11410         $info .= 'PHP ' . PHP_VERSION . "\n";
    11411         if ($sp->error() !== null)
    11412         {
    11413             $info .= 'Error occurred: ' . $sp->error() . "\n";
    11414         }
    11415         else
    11416         {
    11417             $info .= "No error found.\n";
    11418         }
    11419         $info .= "Extensions:\n";
    11420         $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
    11421         foreach ($extensions as $ext)
    11422         {
    11423             if (extension_loaded($ext))
    11424             {
    11425                 $info .= "    $ext loaded\n";
    11426                 switch ($ext)
    11427                 {
    11428                     case 'pcre':
    11429                         $info .= '      Version ' . PCRE_VERSION . "\n";
    11430                         break;
    11431                     case 'curl':
    11432                         $version = curl_version();
    11433                         $info .= '      Version ' . $version['version'] . "\n";
    11434                         break;
    11435                     case 'mbstring':
    11436                         $info .= '      Overloading: ' . mb_get_info('func_overload') . "\n";
    11437                         break;
    11438                     case 'iconv':
    11439                         $info .= '      Version ' . ICONV_VERSION . "\n";
    11440                         break;
    11441                     case 'xml':
    11442                         $info .= '      Version ' . LIBXML_DOTTED_VERSION . "\n";
    11443                         break;
    11444                 }
    11445             }
    11446             else
    11447             {
    11448                 $info .= "    $ext not loaded\n";
    11449             }
    11450         }
    11451         return $info;
    11452     }
    11453 }
    11454 
    11455 /**
    11456  * Decode HTML Entities
    11457  *
    11458  * This implements HTML5 as of revision 967 (2007-06-28)
    11459  *
    11460  * @package SimplePie
    11461  */
    11462 class SimplePie_Decode_HTML_Entities
    11463 {
    11464     /**
    11465      * Data to be parsed
    11466      *
    11467      * @access private
    11468      * @var string
    11469      */
    11470     var $data = '';
    11471 
    11472     /**
    11473      * Currently consumed bytes
    11474      *
    11475      * @access private
    11476      * @var string
    11477      */
    11478     var $consumed = '';
    11479 
    11480     /**
    11481      * Position of the current byte being parsed
    11482      *
    11483      * @access private
    11484      * @var int
    11485      */
    11486     var $position = 0;
    11487 
    11488     /**
    11489      * Create an instance of the class with the input data
    11490      *
    11491      * @access public
    11492      * @param string $data Input data
    11493      */
    11494     function SimplePie_Decode_HTML_Entities($data)
    11495     {
    11496         $this->data = $data;
    11497     }
    11498 
    11499     /**
    11500      * Parse the input data
    11501      *
    11502      * @access public
    11503      * @return string Output data
    11504      */
    11505     function parse()
    11506     {
    11507         while (($this->position = strpos($this->data, '&', $this->position)) !== false)
    11508         {
    11509             $this->consume();
    11510             $this->entity();
    11511             $this->consumed = '';
    11512         }
    11513         return $this->data;
    11514     }
    11515 
    11516     /**
    11517      * Consume the next byte
    11518      *
    11519      * @access private
    11520      * @return mixed The next byte, or false, if there is no more data
    11521      */
    11522     function consume()
    11523     {
    11524         if (isset($this->data[$this->position]))
    11525         {
    11526             $this->consumed .= $this->data[$this->position];
    11527             return $this->data[$this->position++];
    11528         }
    11529         else
    11530         {
    11531             return false;
    11532         }
    11533     }
    11534 
    11535     /**
    11536      * Consume a range of characters
    11537      *
    11538      * @access private
    11539      * @param string $chars Characters to consume
    11540      * @return mixed A series of characters that match the range, or false
    11541      */
    11542     function consume_range($chars)
    11543     {
    11544         if ($len = strspn($this->data, $chars, $this->position))
    11545         {
    11546             $data = substr($this->data, $this->position, $len);
    11547             $this->consumed .= $data;
    11548             $this->position += $len;
    11549             return $data;
    11550         }
    11551         else
    11552         {
    11553             return false;
    11554         }
    11555     }
    11556 
    11557     /**
    11558      * Unconsume one byte
    11559      *
    11560      * @access private
    11561      */
    11562     function unconsume()
    11563     {
    11564         $this->consumed = substr($this->consumed, 0, -1);
    11565         $this->position--;
    11566     }
    11567 
    11568     /**
    11569      * Decode an entity
    11570      *
    11571      * @access private
    11572      */
    11573     function entity()
    11574     {
    11575         switch ($this->consume())
    11576         {
    11577             case "\x09":
    11578             case "\x0A":
    11579             case "\x0B":
    11580             case "\x0B":
    11581             case "\x0C":
    11582             case "\x20":
    11583             case "\x3C":
    11584             case "\x26":
    11585             case false:
    11586                 break;
    11587 
    11588             case "\x23":
    11589                 switch ($this->consume())
    11590                 {
    11591                     case "\x78":
    11592                     case "\x58":
    11593                         $range = '0123456789ABCDEFabcdef';
    11594                         $hex = true;
    11595                         break;
    11596 
    11597                     default:
    11598                         $range = '0123456789';
    11599                         $hex = false;
    11600                         $this->unconsume();
    11601                         break;
    11602                 }
    11603 
    11604                 if ($codepoint = $this->consume_range($range))
    11605                 {
    11606                     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");
    11607 
    11608                     if ($hex)
    11609                     {
    11610                         $codepoint = hexdec($codepoint);
    11611                     }
    11612                     else
    11613                     {
    11614                         $codepoint = intval($codepoint);
    11615                     }
    11616 
    11617                     if (isset($windows_1252_specials[$codepoint]))
    11618                     {
    11619                         $replacement = $windows_1252_specials[$codepoint];
    11620                     }
    11621                     else
    11622                     {
    11623                         $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
    11624                     }
    11625 
    11626                     if (!in_array($this->consume(), array(';', false), true))
    11627                     {
    11628                         $this->unconsume();
    11629                     }
    11630 
    11631                     $consumed_length = strlen($this->consumed);
    11632                     $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
    11633                     $this->position += strlen($replacement) - $consumed_length;
    11634                 }
    11635                 break;
    11636 
    11637             default:
    11638                 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");
    11639 
    11640                 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
    11641                 {
    11642                     $consumed = substr($this->consumed, 1);
    11643                     if (isset($entities[$consumed]))
    11644                     {
    11645                         $match = $consumed;
    11646                     }
    11647                 }
    11648 
    11649                 if ($match !== null)
    11650                 {
    11651                     $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
    11652                     $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
    11653                 }
    11654                 break;
    11655         }
    11656     }
    11657 }
    11658 
    11659 /**
    11660  * IRI parser/serialiser
    11661  *
    11662  * @package SimplePie
    11663  */
    11664 class SimplePie_IRI
    11665 {
    11666     /**
    11667      * Scheme
    11668      *
    11669      * @access private
    11670      * @var string
    11671      */
    11672     var $scheme;
    11673 
    11674     /**
    11675      * User Information
    11676      *
    11677      * @access private
    11678      * @var string
    11679      */
    11680     var $userinfo;
    11681 
    11682     /**
    11683      * Host
    11684      *
    11685      * @access private
    11686      * @var string
    11687      */
    11688     var $host;
    11689 
    11690     /**
    11691      * Port
    11692      *
    11693      * @access private
    11694      * @var string
    11695      */
    11696     var $port;
    11697 
    11698     /**
    11699      * Path
    11700      *
    11701      * @access private
    11702      * @var string
    11703      */
    11704     var $path;
    11705 
    11706     /**
    11707      * Query
    11708      *
    11709      * @access private
    11710      * @var string
    11711      */
    11712     var $query;
    11713 
    11714     /**
    11715      * Fragment
    11716      *
    11717      * @access private
    11718      * @var string
    11719      */
    11720     var $fragment;
    11721 
    11722     /**
    11723      * Whether the object represents a valid IRI
    11724      *
    11725      * @access private
    11726      * @var array
    11727      */
    11728     var $valid = array();
    11729 
    11730     /**
    11731      * Return the entire IRI when you try and read the object as a string
    11732      *
    11733      * @access public
    11734      * @return string
    11735      */
    11736     function __toString()
    11737     {
    11738         return $this->get_iri();
    11739     }
    11740 
    11741     /**
    11742      * Create a new IRI object, from a specified string
    11743      *
    11744      * @access public
    11745      * @param string $iri
    11746      * @return SimplePie_IRI
    11747      */
    11748     function SimplePie_IRI($iri)
    11749     {
    11750         $iri = (string) $iri;
    11751         if ($iri !== '')
    11752         {
    11753             $parsed = $this->parse_iri($iri);
    11754             $this->set_scheme($parsed['scheme']);
    11755             $this->set_authority($parsed['authority']);
    11756             $this->set_path($parsed['path']);
    11757             $this->set_query($parsed['query']);
    11758             $this->set_fragment($parsed['fragment']);
    11759         }
    11760     }
    11761 
    11762     /**
    11763      * Create a new IRI object by resolving a relative IRI
    11764      *
    11765      * @static
    11766      * @access public
    11767      * @param SimplePie_IRI $base Base IRI
    11768      * @param string $relative Relative IRI
    11769      * @return SimplePie_IRI
    11770      */
    11771     function absolutize($base, $relative)
    11772     {
    11773         $relative = (string) $relative;
    11774         if ($relative !== '')
    11775         {
    11776             $relative =& new SimplePie_IRI($relative);
    11777             if ($relative->get_scheme() !== null)
    11778             {
    11779                 $target = $relative;
    11780             }
    11781             elseif ($base->get_iri() !== null)
    11782             {
    11783                 if ($relative->get_authority() !== null)
    11784                 {
    11785                     $target = $relative;
    11786                     $target->set_scheme($base->get_scheme());
    11787                 }
    11788                 else
    11789                 {
    11790                     $target =& new SimplePie_IRI('');
    11791                     $target->set_scheme($base->get_scheme());
    11792                     $target->set_userinfo($base->get_userinfo());
    11793                     $target->set_host($base->get_host());
    11794                     $target->set_port($base->get_port());
    11795                     if ($relative->get_path() !== null)
    11796                     {
    11797                         if (strpos($relative->get_path(), '/') === 0)
    11798                         {
    11799                             $target->set_path($relative->get_path());
    11800                         }
    11801                         elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
    11802                         {
    11803                             $target->set_path('/' . $relative->get_path());
    11804                         }
    11805                         elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
    11806                         {
    11807                             $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
    11808                         }
    11809                         else
    11810                         {
    11811                             $target->set_path($relative->get_path());
    11812                         }
    11813                         $target->set_query($relative->get_query());
    11814                     }
    11815                     else
    11816                     {
    11817                         $target->set_path($base->get_path());
    11818                         if ($relative->get_query() !== null)
    11819                         {
    11820                             $target->set_query($relative->get_query());
    11821                         }
    11822                         elseif ($base->get_query() !== null)
    11823                         {
    11824                             $target->set_query($base->get_query());
    11825                         }
    11826                     }
    11827                 }
    11828                 $target->set_fragment($relative->get_fragment());
    11829             }
    11830             else
    11831             {
    11832                 // No base URL, just return the relative URL
    11833                 $target = $relative;
    11834             }
    11835         }
    11836         else
    11837         {
    11838             $target = $base;
    11839         }
    11840         return $target;
    11841     }
    11842 
    11843     /**
    11844      * Parse an IRI into scheme/authority/path/query/fragment segments
    11845      *
    11846      * @access private
    11847      * @param string $iri
    11848      * @return array
    11849      */
    11850     function parse_iri($iri)
    11851     {
    11852         preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
    11853         for ($i = count($match); $i <= 9; $i++)
    11854         {
    11855             $match[$i] = '';
    11856         }
    11857         return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
    11858     }
    11859 
    11860     /**
    11861      * Remove dot segments from a path
    11862      *
    11863      * @access private
    11864      * @param string $input
    11865      * @return string
    11866      */
    11867     function remove_dot_segments($input)
    11868     {
    11869         $output = '';
    11870         while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
    11871         {
    11872             // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
    11873             if (strpos($input, '../') === 0)
    11874             {
    11875                 $input = substr($input, 3);
    11876             }
    11877             elseif (strpos($input, './') === 0)
    11878             {
    11879                 $input = substr($input, 2);
    11880             }
    11881             // 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,
    11882             elseif (strpos($input, '/./') === 0)
    11883             {
    11884                 $input = substr_replace($input, '/', 0, 3);
    11885             }
    11886             elseif ($input === '/.')
    11887             {
    11888                 $input = '/';
    11889             }
    11890             // 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,
    11891             elseif (strpos($input, '/../') === 0)
    11892             {
    11893                 $input = substr_replace($input, '/', 0, 4);
    11894                 $output = substr_replace($output, '', strrpos($output, '/'));
    11895             }
    11896             elseif ($input === '/..')
    11897             {
    11898                 $input = '/';
    11899                 $output = substr_replace($output, '', strrpos($output, '/'));
    11900             }
    11901             // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
    11902             elseif ($input === '.' || $input === '..')
    11903             {
    11904                 $input = '';
    11905             }
    11906             // 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
    11907             elseif (($pos = strpos($input, '/', 1)) !== false)
    11908             {
    11909                 $output .= substr($input, 0, $pos);
    11910                 $input = substr_replace($input, '', 0, $pos);
    11911             }
    11912             else
    11913             {
    11914                 $output .= $input;
    11915                 $input = '';
    11916             }
    11917         }
    11918         return $output . $input;
    11919     }
    11920 
    11921     /**
    11922      * Replace invalid character with percent encoding
    11923      *
    11924      * @param string $string Input string
    11925      * @param string $valid_chars Valid characters
    11926      * @param int $case Normalise case
    11927      * @return string
    11928      */
    11929     function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false)
    11930     {
    11931         // Normalize as many pct-encoded sections as possible
    11932         $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
    11933 
    11934         // Replace invalid percent characters
    11935         $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
    11936 
    11937         // Add unreserved and % to $valid_chars (the latter is safe because all
    11938         // pct-encoded sections are now valid).
    11939         $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
    11940 
    11941         // Now replace any bytes that aren't allowed with their pct-encoded versions
    11942         $position = 0;
    11943         $strlen = strlen($string);
    11944         while (($position += strspn($string, $valid_chars, $position)) < $strlen)
    11945         {
    11946             $value = ord($string[$position]);
    11947 
    11948             // Start position
    11949             $start = $position;
    11950 
    11951             // By default we are valid
    11952             $valid = true;
    11953 
    11954             // No one byte sequences are valid due to the while.
    11955             // Two byte sequence:
    11956             if (($value & 0xE0) === 0xC0)
    11957             {
    11958                 $character = ($value & 0x1F) << 6;
    11959                 $length = 2;
    11960                 $remaining = 1;
    11961             }
    11962             // Three byte sequence:
    11963             elseif (($value & 0xF0) === 0xE0)
    11964             {
    11965                 $character = ($value & 0x0F) << 12;
    11966                 $length = 3;
    11967                 $remaining = 2;
    11968             }
    11969             // Four byte sequence:
    11970             elseif (($value & 0xF8) === 0xF0)
    11971             {
    11972                 $character = ($value & 0x07) << 18;
    11973                 $length = 4;
    11974                 $remaining = 3;
    11975             }
    11976             // Invalid byte:
    11977             else
    11978             {
    11979                 $valid = false;
    11980                 $length = 1;
    11981                 $remaining = 0;
    11982             }
    11983 
    11984             if ($remaining)
    11985             {
    11986                 if ($position + $length <= $strlen)
    11987                 {
    11988                     for ($position++; $remaining; $position++)
    11989                     {
    11990                         $value = ord($string[$position]);
    11991 
    11992                         // Check that the byte is valid, then add it to the character:
    11993                         if (($value & 0xC0) === 0x80)
    11994                         {
    11995                             $character |= ($value & 0x3F) << (--$remaining * 6);
    11996                         }
    11997                         // If it is invalid, count the sequence as invalid and reprocess the current byte:
    11998                         else
    11999                         {
    12000                             $valid = false;
    12001                             $position--;
    12002                             break;
    12003                         }
    12004                     }
    12005                 }
    12006                 else
    12007                 {
    12008                     $position = $strlen - 1;
    12009                     $valid = false;
    12010                 }
    12011             }
    12012 
    12013             // Percent encode anything invalid or not in ucschar
    12014             if (
    12015                 // Invalid sequences
    12016                 !$valid
    12017                 // Non-shortest form sequences are invalid
    12018                 || $length > 1 && $character <= 0x7F
    12019                 || $length > 2 && $character <= 0x7FF
    12020                 || $length > 3 && $character <= 0xFFFF
    12021                 // Outside of range of ucschar codepoints
    12022                 // Noncharacters
    12023                 || ($character & 0xFFFE) === 0xFFFE
    12024                 || $character >= 0xFDD0 && $character <= 0xFDEF
    12025                 || (
    12026                     // Everything else not in ucschar
    12027                        $character > 0xD7FF && $character < 0xF900
    12028                     || $character < 0xA0
    12029                     || $character > 0xEFFFD
    12030                 )
    12031                 && (
    12032                     // Everything not in iprivate, if it applies
    12033                        !$iprivate
    12034                     || $character < 0xE000
    12035                     || $character > 0x10FFFD
    12036                 )
    12037             )
    12038             {
    12039                 // If we were a character, pretend we weren't, but rather an error.
    12040                 if ($valid)
    12041                     $position--;
    12042 
    12043                 for ($j = $start; $j <= $position; $j++)
    12044                 {
    12045                     $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
    12046                     $j += 2;
    12047                     $position += 2;
    12048                     $strlen += 2;
    12049                 }
    12050             }
    12051         }
    12052 
    12053         // Normalise case
    12054         if ($case & SIMPLEPIE_LOWERCASE)
    12055         {
    12056             $string = strtolower($string);
    12057         }
    12058         elseif ($case & SIMPLEPIE_UPPERCASE)
    12059         {
    12060             $string = strtoupper($string);
    12061         }
    12062 
    12063         return $string;
    12064     }
    12065 
    12066     /**
    12067      * Callback function for preg_replace_callback.
    12068      *
    12069      * Removes sequences of percent encoded bytes that represent UTF-8
    12070      * encoded characters in iunreserved
    12071      *
    12072      * @access private
    12073      * @param array $match PCRE match
    12074      * @return string Replacement
    12075      */
    12076     function remove_iunreserved_percent_encoded($match)
    12077     {
    12078         // As we just have valid percent encoded sequences we can just explode
    12079         // and ignore the first member of the returned array (an empty string).
    12080         $bytes = explode('%', $match[0]);
    12081 
    12082         // Initialize the new string (this is what will be returned) and that
    12083         // there are no bytes remaining in the current sequence (unsurprising
    12084         // at the first byte!).
    12085         $string = '';
    12086         $remaining = 0;
    12087 
    12088         // Loop over each and every byte, and set $value to its value
    12089         for ($i = 1, $len = count($bytes); $i < $len; $i++)
    12090         {
    12091             $value = hexdec($bytes[$i]);
    12092 
    12093             // If we're the first byte of sequence:
    12094             if (!$remaining)
    12095             {
    12096                 // Start position
    12097                 $start = $i;
    12098 
    12099                 // By default we are valid
    12100                 $valid = true;
    12101 
    12102                 // One byte sequence:
    12103                 if ($value <= 0x7F)
    12104                 {
    12105                     $character = $value;
    12106                     $length = 1;
    12107                 }
    12108                 // Two byte sequence:
    12109                 elseif (($value & 0xE0) === 0xC0)
    12110                 {
    12111                     $character = ($value & 0x1F) << 6;
    12112                     $length = 2;
    12113                     $remaining = 1;
    12114                 }
    12115                 // Three byte sequence:
    12116                 elseif (($value & 0xF0) === 0xE0)
    12117                 {
    12118                     $character = ($value & 0x0F) << 12;
    12119                     $length = 3;
    12120                     $remaining = 2;
    12121                 }
    12122                 // Four byte sequence:
    12123                 elseif (($value & 0xF8) === 0xF0)
    12124                 {
    12125                     $character = ($value & 0x07) << 18;
    12126                     $length = 4;
    12127                     $remaining = 3;
    12128                 }
    12129                 // Invalid byte:
    12130                 else
    12131                 {
    12132                     $valid = false;
    12133                     $remaining = 0;
    12134                 }
    12135             }
    12136             // Continuation byte:
    12137             else
    12138             {
    12139                 // Check that the byte is valid, then add it to the character:
    12140                 if (($value & 0xC0) === 0x80)
    12141                 {
    12142                     $remaining--;
    12143                     $character |= ($value & 0x3F) << ($remaining * 6);
    12144                 }
    12145                 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
    12146                 else
    12147                 {
    12148                     $valid = false;
    12149                     $remaining = 0;
    12150                     $i--;
    12151                 }
    12152             }
    12153 
    12154             // If we've reached the end of the current byte sequence, append it to Unicode::$data
    12155             if (!$remaining)
    12156             {
    12157                 // Percent encode anything invalid or not in iunreserved
    12158                 if (
    12159                     // Invalid sequences
    12160                     !$valid
    12161                     // Non-shortest form sequences are invalid
    12162                     || $length > 1 && $character <= 0x7F
    12163                     || $length > 2 && $character <= 0x7FF
    12164                     || $length > 3 && $character <= 0xFFFF
    12165                     // Outside of range of iunreserved codepoints
    12166                     || $character < 0x2D
    12167                     || $character > 0xEFFFD
    12168                     // Noncharacters
    12169                     || ($character & 0xFFFE) === 0xFFFE
    12170                     || $character >= 0xFDD0 && $character <= 0xFDEF
    12171                     // Everything else not in iunreserved (this is all BMP)
    12172                     || $character === 0x2F
    12173                     || $character > 0x39 && $character < 0x41
    12174                     || $character > 0x5A && $character < 0x61
    12175                     || $character > 0x7A && $character < 0x7E
    12176                     || $character > 0x7E && $character < 0xA0
    12177                     || $character > 0xD7FF && $character < 0xF900
    12178                 )
    12179                 {
    12180                     for ($j = $start; $j <= $i; $j++)
    12181                     {
    12182                         $string .= '%' . strtoupper($bytes[$j]);
    12183                     }
    12184                 }
    12185                 else
    12186                 {
    12187                     for ($j = $start; $j <= $i; $j++)
    12188                     {
    12189                         $string .= chr(hexdec($bytes[$j]));
    12190                     }
    12191                 }
    12192             }
    12193         }
    12194 
    12195         // If we have any bytes left over they are invalid (i.e., we are
    12196         // mid-way through a multi-byte sequence)
    12197         if ($remaining)
    12198         {
    12199             for ($j = $start; $j < $len; $j++)
    12200             {
    12201                 $string .= '%' . strtoupper($bytes[$j]);
    12202             }
    12203         }
    12204 
    12205         return $string;
    12206     }
    12207 
    12208     /**
    12209      * Check if the object represents a valid IRI
    12210      *
    12211      * @access public
    12212      * @return bool
    12213      */
    12214     function is_valid()
    12215     {
    12216         return array_sum($this->valid) === count($this->valid);
    12217     }
    12218 
    12219     /**
    12220      * Set the scheme. Returns true on success, false on failure (if there are
    12221      * any invalid characters).
    12222      *
    12223      * @access public
    12224      * @param string $scheme
    12225      * @return bool
    12226      */
    12227     function set_scheme($scheme)
    12228     {
    12229         if ($scheme === null || $scheme === '')
    12230         {
    12231             $this->scheme = null;
    12232         }
    12233         else
    12234         {
    12235             $len = strlen($scheme);
    12236             switch (true)
    12237             {
    12238                 case $len > 1:
    12239                     if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
    12240                     {
    12241                         $this->scheme = null;
    12242                         $this->valid[__FUNCTION__] = false;
    12243                         return false;
    12244                     }
    12245 
    12246                 case $len > 0:
    12247                     if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
    12248                     {
    12249                         $this->scheme = null;
    12250                         $this->valid[__FUNCTION__] = false;
    12251                         return false;
    12252                     }
    12253             }
    12254             $this->scheme = strtolower($scheme);
    12255         }
    12256         $this->valid[__FUNCTION__] = true;
    12257         return true;
    12258     }
    12259 
    12260     /**
    12261      * Set the authority. Returns true on success, false on failure (if there are
    12262      * any invalid characters).
    12263      *
    12264      * @access public
    12265      * @param string $authority
    12266      * @return bool
    12267      */
    12268     function set_authority($authority)
    12269     {
    12270         if (($userinfo_end = strrpos($authority, '@')) !== false)
    12271         {
    12272             $userinfo = substr($authority, 0, $userinfo_end);
    12273             $authority = substr($authority, $userinfo_end + 1);
    12274         }
    12275         else
    12276         {
    12277             $userinfo = null;
    12278         }
    12279 
    12280         if (($port_start = strpos($authority, ':')) !== false)
    12281         {
    12282             $port = substr($authority, $port_start + 1);
    12283             $authority = substr($authority, 0, $port_start);
    12284         }
    12285         else
    12286         {
    12287             $port = null;
    12288         }
    12289 
    12290         return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
    12291     }
    12292 
    12293     /**
    12294      * Set the userinfo.
    12295      *
    12296      * @access public
    12297      * @param string $userinfo
    12298      * @return bool
    12299      */
    12300     function set_userinfo($userinfo)
    12301     {
    12302         if ($userinfo === null || $userinfo === '')
    12303         {
    12304             $this->userinfo = null;
    12305         }
    12306         else
    12307         {
    12308             $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
    12309         }
    12310         $this->valid[__FUNCTION__] = true;
    12311         return true;
    12312     }
    12313 
    12314     /**
    12315      * Set the host. Returns true on success, false on failure (if there are
    12316      * any invalid characters).
    12317      *
    12318      * @access public
    12319      * @param string $host
    12320      * @return bool
    12321      */
    12322     function set_host($host)
    12323     {
    12324         if ($host === null || $host === '')
    12325         {
    12326             $this->host = null;
    12327             $this->valid[__FUNCTION__] = true;
    12328             return true;
    12329         }
    12330         elseif ($host[0] === '[' && substr($host, -1) === ']')
    12331         {
    12332             if (SimplePie_Net_IPv6::checkIPv6(substr($host, 1, -1)))
    12333             {
    12334                 $this->host = $host;
    12335                 $this->valid[__FUNCTION__] = true;
    12336                 return true;
    12337             }
    12338             else
    12339             {
    12340                 $this->host = null;
    12341                 $this->valid[__FUNCTION__] = false;
    12342                 return false;
    12343             }
    12344         }
    12345         else
    12346         {
    12347             $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
    12348             $this->valid[__FUNCTION__] = true;
    12349             return true;
    12350         }
    12351     }
    12352 
    12353     /**
    12354      * Set the port. Returns true on success, false on failure (if there are
    12355      * any invalid characters).
    12356      *
    12357      * @access public
    12358      * @param string $port
    12359      * @return bool
    12360      */
    12361     function set_port($port)
    12362     {
    12363         if ($port === null || $port === '')
    12364         {
    12365             $this->port = null;
    12366             $this->valid[__FUNCTION__] = true;
    12367             return true;
    12368         }
    12369         elseif (strspn($port, '0123456789') === strlen($port))
    12370         {
    12371             $this->port = (int) $port;
    12372             $this->valid[__FUNCTION__] = true;
    12373             return true;
    12374         }
    12375         else
    12376         {
    12377             $this->port = null;
    12378             $this->valid[__FUNCTION__] = false;
    12379             return false;
    12380         }
    12381     }
    12382 
    12383     /**
    12384      * Set the path.
    12385      *
    12386      * @access public
    12387      * @param string $path
    12388      * @return bool
    12389      */
    12390     function set_path($path)
    12391     {
    12392         if ($path === null || $path === '')
    12393         {
    12394             $this->path = null;
    12395             $this->valid[__FUNCTION__] = true;
    12396             return true;
    12397         }
    12398         elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
    12399         {
    12400             $this->path = null;
    12401             $this->valid[__FUNCTION__] = false;
    12402             return false;
    12403         }
    12404         else
    12405         {
    12406             $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
    12407             if ($this->scheme !== null)
    12408             {
    12409                 $this->path = $this->remove_dot_segments($this->path);
    12410             }
    12411             $this->valid[__FUNCTION__] = true;
    12412             return true;
    12413         }
    12414     }
    12415 
    12416     /**
    12417      * Set the query.
    12418      *
    12419      * @access public
    12420      * @param string $query
    12421      * @return bool
    12422      */
    12423     function set_query($query)
    12424     {
    12425         if ($query === null || $query === '')
    12426         {
    12427             $this->query = null;
    12428         }
    12429         else
    12430         {
    12431             $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
    12432         }
    12433         $this->valid[__FUNCTION__] = true;
    12434         return true;
    12435     }
    12436 
    12437     /**
    12438      * Set the fragment.
    12439      *
    12440      * @access public
    12441      * @param string $fragment
    12442      * @return bool
    12443      */
    12444     function set_fragment($fragment)
    12445     {
    12446         if ($fragment === null || $fragment === '')
    12447         {
    12448             $this->fragment = null;
    12449         }
    12450         else
    12451         {
    12452             $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
    12453         }
    12454         $this->valid[__FUNCTION__] = true;
    12455         return true;
    12456     }
    12457 
    12458     /**
    12459      * Get the complete IRI
    12460      *
    12461      * @access public
    12462      * @return string
    12463      */
    12464     function get_iri()
    12465     {
    12466         $iri = '';
    12467         if ($this->scheme !== null)
    12468         {
    12469             $iri .= $this->scheme . ':';
    12470         }
    12471         if (($authority = $this->get_authority()) !== null)
    12472         {
    12473             $iri .= '//' . $authority;
    12474         }
    12475         if ($this->path !== null)
    12476         {
    12477             $iri .= $this->path;
    12478         }
    12479         if ($this->query !== null)
    12480         {
    12481             $iri .= '?' . $this->query;
    12482         }
    12483         if ($this->fragment !== null)
    12484         {
    12485             $iri .= '#' . $this->fragment;
    12486         }
    12487 
    12488         if ($iri !== '')
    12489         {
    12490             return $iri;
    12491         }
    12492         else
    12493         {
    12494             return null;
    12495         }
    12496     }
    12497 
    12498     /**
    12499      * Get the scheme
    12500      *
    12501      * @access public
    12502      * @return string
    12503      */
    12504     function get_scheme()
    12505     {
    12506         return $this->scheme;
    12507     }
    12508 
    12509     /**
    12510      * Get the complete authority
    12511      *
    12512      * @access public
    12513      * @return string
    12514      */
    12515     function get_authority()
    12516     {
    12517         $authority = '';
    12518         if ($this->userinfo !== null)
    12519         {
    12520             $authority .= $this->userinfo . '@';
    12521         }
    12522         if ($this->host !== null)
    12523         {
    12524             $authority .= $this->host;
    12525         }
    12526         if ($this->port !== null)
    12527         {
    12528             $authority .= ':' . $this->port;
    12529         }
    12530 
    12531         if ($authority !== '')
    12532         {
    12533             return $authority;
    12534         }
    12535         else
    12536         {
    12537             return null;
    12538         }
    12539     }
    12540 
    12541     /**
    12542      * Get the user information
    12543      *
    12544      * @access public
    12545      * @return string
    12546      */
    12547     function get_userinfo()
    12548     {
    12549         return $this->userinfo;
    12550     }
    12551 
    12552     /**
    12553      * Get the host
    12554      *
    12555      * @access public
    12556      * @return string
    12557      */
    12558     function get_host()
    12559     {
    12560         return $this->host;
    12561     }
    12562 
    12563     /**
    12564      * Get the port
    12565      *
    12566      * @access public
    12567      * @return string
    12568      */
    12569     function get_port()
    12570     {
    12571         return $this->port;
    12572     }
    12573 
    12574     /**
    12575      * Get the path
    12576      *
    12577      * @access public
    12578      * @return string
    12579      */
    12580     function get_path()
    12581     {
    12582         return $this->path;
    12583     }
    12584 
    12585     /**
    12586      * Get the query
    12587      *
    12588      * @access public
    12589      * @return string
    12590      */
    12591     function get_query()
    12592     {
    12593         return $this->query;
    12594     }
    12595 
    12596     /**
    12597      * Get the fragment
    12598      *
    12599      * @access public
    12600      * @return string
    12601      */
    12602     function get_fragment()
    12603     {
    12604         return $this->fragment;
    12605     }
    12606 }
    12607 
    12608 /**
    12609  * Class to validate and to work with IPv6 addresses.
    12610  *
    12611  * @package SimplePie
    12612  * @copyright 2003-2005 The PHP Group
    12613  * @license http://www.opensource.org/licenses/bsd-license.php
    12614  * @link http://pear.php.net/package/Net_IPv6
    12615  * @author Alexander Merz <alexander.merz@web.de>
    12616  * @author elfrink at introweb dot nl
    12617  * @author Josh Peck <jmp at joshpeck dot org>
    12618  * @author Geoffrey Sneddon <geoffers@gmail.com>
    12619  */
    12620 class SimplePie_Net_IPv6
    12621 {
    12622     /**
    12623      * Removes a possible existing netmask specification of an IP address.
    12624      *
    12625      * @param string $ip the (compressed) IP as Hex representation
    12626      * @return string the IP the without netmask
    12627      * @since 1.1.0
    12628      * @access public
    12629      * @static
    12630      */
    12631     function removeNetmaskSpec($ip)
    12632     {
    12633         if (strpos($ip, '/') !== false)
    12634         {
    12635             list($addr, $nm) = explode('/', $ip);
    12636         }
    12637         else
    12638         {
    12639             $addr = $ip;
    12640         }
    12641         return $addr;
    12642     }
    12643 
    12644     /**
    12645      * Uncompresses an IPv6 address
    12646      *
    12647      * RFC 2373 allows you to compress zeros in an address to '::'. This
    12648      * function expects an valid IPv6 address and expands the '::' to
    12649      * the required zeros.
    12650      *
    12651      * Example:  FF01::101  ->  FF01:0:0:0:0:0:0:101
    12652      *           ::1        ->  0:0:0:0:0:0:0:1
    12653      *
    12654      * @access public
    12655      * @static
    12656      * @param string $ip a valid IPv6-address (hex format)
    12657      * @return string the uncompressed IPv6-address (hex format)
    12658      */
    12659     function Uncompress($ip)
    12660     {
    12661         $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
    12662         $c1 = -1;
    12663         $c2 = -1;
    12664         if (strpos($ip, '::') !== false)
    12665         {
    12666             list($ip1, $ip2) = explode('::', $ip);
    12667             if ($ip1 === '')
    12668             {
    12669                 $c1 = -1;
    12670             }
    12671             else
    12672             {
    12673                 $pos = 0;
    12674                 if (($pos = substr_count($ip1, ':')) > 0)
    12675                 {
    12676                     $c1 = $pos;
    12677                 }
    12678                 else
    12679                 {
    12680                     $c1 = 0;
    12681                 }
    12682             }
    12683             if ($ip2 === '')
    12684             {
    12685                 $c2 = -1;
    12686             }
    12687             else
    12688             {
    12689                 $pos = 0;
    12690                 if (($pos = substr_count($ip2, ':')) > 0)
    12691                 {
    12692                     $c2 = $pos;
    12693                 }
    12694                 else
    12695                 {
    12696                     $c2 = 0;
    12697                 }
    12698             }
    12699             if (strstr($ip2, '.'))
    12700             {
    12701                 $c2++;
    12702             }
    12703             // ::
    12704             if ($c1 === -1 && $c2 === -1)
    12705             {
    12706                 $uip = '0:0:0:0:0:0:0:0';
    12707             }
    12708             // ::xxx
    12709             else if ($c1 === -1)
    12710             {
    12711                 $fill = str_repeat('0:', 7 - $c2);
    12712                 $uip =  str_replace('::', $fill, $uip);
    12713             }
    12714             // xxx::
    12715             else if ($c2 === -1)
    12716             {
    12717                 $fill = str_repeat(':0', 7 - $c1);
    12718                 $uip =  str_replace('::', $fill, $uip);
    12719             }
    12720             // xxx::xxx
    12721             else
    12722             {
    12723                 $fill = str_repeat(':0:', 6 - $c2 - $c1);
    12724                 $uip =  str_replace('::', $fill, $uip);
    12725                 $uip =  str_replace('::', ':', $uip);
    12726             }
    12727         }
    12728         return $uip;
    12729     }
    12730 
    12731     /**
    12732      * Splits an IPv6 address into the IPv6 and a possible IPv4 part
    12733      *
    12734      * RFC 2373 allows you to note the last two parts of an IPv6 address as
    12735      * an IPv4 compatible address
    12736      *
    12737      * Example:  0:0:0:0:0:0:13.1.68.3
    12738      *           0:0:0:0:0:FFFF:129.144.52.38
    12739      *
    12740      * @access public
    12741      * @static
    12742      * @param string $ip a valid IPv6-address (hex format)
    12743      * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
    12744      */
    12745     function SplitV64($ip)
    12746     {
    12747         $ip = SimplePie_Net_IPv6::Uncompress($ip);
    12748         if (strstr($ip, '.'))
    12749         {
    12750             $pos = strrpos($ip, ':');
    12751             $ip[$pos] = '_';
    12752             $ipPart = explode('_', $ip);
    12753             return $ipPart;
    12754         }
    12755         else
    12756         {
    12757             return array($ip, '');
    12758         }
    12759     }
    12760 
    12761     /**
    12762      * Checks an IPv6 address
    12763      *
    12764      * Checks if the given IP is IPv6-compatible
    12765      *
    12766      * @access public
    12767      * @static
    12768      * @param string $ip a valid IPv6-address
    12769      * @return bool true if $ip is an IPv6 address
    12770      */
    12771     function checkIPv6($ip)
    12772     {
    12773         $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
    12774         $count = 0;
    12775         if (!empty($ipPart[0]))
    12776         {
    12777             $ipv6 = explode(':', $ipPart[0]);
    12778             for ($i = 0; $i < count($ipv6); $i++)
    12779             {
    12780                 $dec = hexdec($ipv6[$i]);
    12781                 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
    12782                 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
    12783                 {
    12784                     $count++;
    12785                 }
    12786             }
    12787             if ($count === 8)
    12788             {
    12789                 return true;
    12790             }
    12791             elseif ($count === 6 && !empty($ipPart[1]))
    12792             {
    12793                 $ipv4 = explode('.', $ipPart[1]);
    12794                 $count = 0;
    12795                 foreach ($ipv4 as $ipv4_part)
    12796                 {
    12797                     if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
    12798                     {
    12799                         $count++;
    12800                     }
    12801                 }
    12802                 if ($count === 4)
    12803                 {
    12804                     return true;
    12805                 }
    12806             }
    12807             else
    12808             {
    12809                 return false;
    12810             }
    12811 
    12812         }
    12813         else
    12814         {
    12815             return false;
    12816         }
    12817     }
    12818 }
    12819 
    12820 /**
    12821  * Date Parser
    12822  *
    12823  * @package SimplePie
    12824  */
    12825 class SimplePie_Parse_Date
    12826 {
    12827     /**
    12828      * Input data
    12829      *
    12830      * @access protected
    12831      * @var string
    12832      */
    12833     var $date;
    12834 
    12835     /**
    12836      * List of days, calendar day name => ordinal day number in the week
    12837      *
    12838      * @access protected
    12839      * @var array
    12840      */
    12841     var $day = array(
    12842         // English
    12843         'mon' => 1,
    12844         'monday' => 1,
    12845         'tue' => 2,
    12846         'tuesday' => 2,
    12847         'wed' => 3,
    12848         'wednesday' => 3,
    12849         'thu' => 4,
    12850         'thursday' => 4,
    12851         'fri' => 5,
    12852         'friday' => 5,
    12853         'sat' => 6,
    12854         'saturday' => 6,
    12855         'sun' => 7,
    12856         'sunday' => 7,
    12857         // Dutch
    12858         'maandag' => 1,
    12859         'dinsdag' => 2,
    12860         'woensdag' => 3,
    12861         'donderdag' => 4,
    12862         'vrijdag' => 5,
    12863         'zaterdag' => 6,
    12864         'zondag' => 7,
    12865         // French
    12866         'lundi' => 1,
    12867         'mardi' => 2,
    12868         'mercredi' => 3,
    12869         'jeudi' => 4,
    12870         'vendredi' => 5,
    12871         'samedi' => 6,
    12872         'dimanche' => 7,
    12873         // German
    12874         'montag' => 1,
    12875         'dienstag' => 2,
    12876         'mittwoch' => 3,
    12877         'donnerstag' => 4,
    12878         'freitag' => 5,
    12879         'samstag' => 6,
    12880         'sonnabend' => 6,
    12881         'sonntag' => 7,
    12882         // Italian
    12883         'lunedì' => 1,
    12884         'martedì' => 2,
    12885         'mercoledì' => 3,
    12886         'giovedì' => 4,
    12887         'venerdì' => 5,
    12888         'sabato' => 6,
    12889         'domenica' => 7,
    12890         // Spanish
    12891         'lunes' => 1,
    12892         'martes' => 2,
    12893         'miércoles' => 3,
    12894         'jueves' => 4,
    12895         'viernes' => 5,
    12896         'sábado' => 6,
    12897         'domingo' => 7,
    12898         // Finnish
    12899         'maanantai' => 1,
    12900         'tiistai' => 2,
    12901         'keskiviikko' => 3,
    12902         'torstai' => 4,
    12903         'perjantai' => 5,
    12904         'lauantai' => 6,
    12905         'sunnuntai' => 7,
    12906         // Hungarian
    12907         'hétfő' => 1,
    12908         'kedd' => 2,
    12909         'szerda' => 3,
    12910         'csütörtok' => 4,
    12911         'péntek' => 5,
    12912         'szombat' => 6,
    12913         'vasárnap' => 7,
    12914         // Greek
    12915         'Δευ' => 1,
    12916         'Τρι' => 2,
    12917         'Τετ' => 3,
    12918         'Πεμ' => 4,
    12919         'Παρ' => 5,
    12920         'Σαβ' => 6,
    12921         'Κυρ' => 7,
    12922     );
    12923 
    12924     /**
    12925      * List of months, calendar month name => calendar month number
    12926      *
    12927      * @access protected
    12928      * @var array
    12929      */
    12930     var $month = array(
    12931         // English
    12932         'jan' => 1,
    12933         'january' => 1,
    12934         'feb' => 2,
    12935         'february' => 2,
    12936         'mar' => 3,
    12937         'march' => 3,
    12938         'apr' => 4,
    12939         'april' => 4,
    12940         'may' => 5,
    12941         // No long form of May
    12942         'jun' => 6,
    12943         'june' => 6,
    12944         'jul' => 7,
    12945         'july' => 7,
    12946         'aug' => 8,
    12947         'august' => 8,
    12948         'sep' => 9,
    12949         'september' => 8,
    12950         'oct' => 10,
    12951         'october' => 10,
    12952         'nov' => 11,
    12953         'november' => 11,
    12954         'dec' => 12,
    12955         'december' => 12,
    12956         // Dutch
    12957         'januari' => 1,
    12958         'februari' => 2,
    12959         'maart' => 3,
    12960         'april' => 4,
    12961         'mei' => 5,
    12962         'juni' => 6,
    12963         'juli' => 7,
    12964         'augustus' => 8,
    12965         'september' => 9,
    12966         'oktober' => 10,
    12967         'november' => 11,
    12968         'december' => 12,
    12969         // French
    12970         'janvier' => 1,
    12971         'février' => 2,
    12972         'mars' => 3,
    12973         'avril' => 4,
    12974         'mai' => 5,
    12975         'juin' => 6,
    12976         'juillet' => 7,
    12977         'août' => 8,
    12978         'septembre' => 9,
    12979         'octobre' => 10,
    12980         'novembre' => 11,
    12981         'décembre' => 12,
    12982         // German
    12983         'januar' => 1,
    12984         'februar' => 2,
    12985         'märz' => 3,
    12986         'april' => 4,
    12987         'mai' => 5,
    12988         'juni' => 6,
    12989         'juli' => 7,
    12990         'august' => 8,
    12991         'september' => 9,
    12992         'oktober' => 10,
    12993         'november' => 11,
    12994         'dezember' => 12,
    12995         // Italian
    12996         'gennaio' => 1,
    12997         'febbraio' => 2,
    12998         'marzo' => 3,
    12999         'aprile' => 4,
    13000         'maggio' => 5,
    13001         'giugno' => 6,
    13002         'luglio' => 7,
    13003         'agosto' => 8,
    13004         'settembre' => 9,
    13005         'ottobre' => 10,
    13006         'novembre' => 11,
    13007         'dicembre' => 12,
    13008         // Spanish
    13009         'enero' => 1,
    13010         'febrero' => 2,
    13011         'marzo' => 3,
    13012         'abril' => 4,
    13013         'mayo' => 5,
    13014         'junio' => 6,
    13015         'julio' => 7,
    13016         'agosto' => 8,
    13017         'septiembre' => 9,
    13018         'setiembre' => 9,
    13019         'octubre' => 10,
    13020         'noviembre' => 11,
    13021         'diciembre' => 12,
    13022         // Finnish
    13023         'tammikuu' => 1,
    13024         'helmikuu' => 2,
    13025         'maaliskuu' => 3,
    13026         'huhtikuu' => 4,
    13027         'toukokuu' => 5,
    13028         'kesäkuu' => 6,
    13029         'heinäkuu' => 7,
    13030         'elokuu' => 8,
    13031         'suuskuu' => 9,
    13032         'lokakuu' => 10,
    13033         'marras' => 11,
    13034         'joulukuu' => 12,
    13035         // Hungarian
    13036         'január' => 1,
    13037         'február' => 2,
    13038         'március' => 3,
    13039         'április' => 4,
    13040         'május' => 5,
    13041         'június' => 6,
    13042         'július' => 7,
    13043         'augusztus' => 8,
    13044         'szeptember' => 9,
    13045         'október' => 10,
    13046         'november' => 11,
    13047         'december' => 12,
    13048         // Greek
    13049         'Ιαν' => 1,
    13050         'Φεβ' => 2,
    13051         'Μάώ' => 3,
    13052         'Μαώ' => 3,
    13053         'Απρ' => 4,
    13054         'Μάι' => 5,
    13055         'Μαϊ' => 5,
    13056         'Μαι' => 5,
    13057         'Ιούν' => 6,
    13058         'Ιον' => 6,
    13059         'Ιούλ' => 7,
    13060         'Ιολ' => 7,
    13061         'Αύγ' => 8,
    13062         'Αυγ' => 8,
    13063         'Σεπ' => 9,
    13064         'Οκτ' => 10,
    13065         'Νοέ' => 11,
    13066         'Δεκ' => 12,
    13067     );
    13068 
    13069     /**
    13070      * List of timezones, abbreviation => offset from UTC
    13071      *
    13072      * @access protected
    13073      * @var array
    13074      */
    13075     var $timezone = array(
    13076         'ACDT' => 37800,
    13077         'ACIT' => 28800,
    13078         'ACST' => 34200,
    13079         'ACT' => -18000,
    13080         'ACWDT' => 35100,
    13081         'ACWST' => 31500,
    13082         'AEDT' => 39600,
    13083         'AEST' => 36000,
    13084         'AFT' => 16200,
    13085         'AKDT' => -28800,
    13086         'AKST' => -32400,
    13087         'AMDT' => 18000,
    13088         'AMT' => -14400,
    13089         'ANAST' => 46800,
    13090         'ANAT' => 43200,
    13091         'ART' => -10800,
    13092         'AZOST' => -3600,
    13093         'AZST' => 18000,
    13094         'AZT' => 14400,
    13095         'BIOT' => 21600,
    13096         'BIT' => -43200,
    13097         'BOT' => -14400,
    13098         'BRST' => -7200,
    13099         'BRT' => -10800,
    13100         'BST' => 3600,
    13101         'BTT' => 21600,
    13102         'CAST' => 18000,
    13103         'CAT' => 7200,
    13104         'CCT' => 23400,
    13105         'CDT' => -18000,
    13106         'CEDT' => 7200,
    13107         'CET' => 3600,
    13108         'CGST' => -7200,
    13109         'CGT' => -10800,
    13110         'CHADT' => 49500,
    13111         'CHAST' => 45900,
    13112         'CIST' => -28800,
    13113         'CKT' => -36000,
    13114         'CLDT' => -10800,
    13115         'CLST' => -14400,
    13116         'COT' => -18000,
    13117         'CST' => -21600,
    13118         'CVT' => -3600,
    13119         'CXT' => 25200,
    13120         'DAVT' => 25200,
    13121         'DTAT' => 36000,
    13122         'EADT' => -18000,
    13123         'EAST' => -21600,
    13124         'EAT' => 10800,
    13125         'ECT' => -18000,
    13126         'EDT' => -14400,
    13127         'EEST' => 10800,
    13128         'EET' => 7200,
    13129         'EGT' => -3600,
    13130         'EKST' => 21600,
    13131         'EST' => -18000,
    13132         'FJT' => 43200,
    13133         'FKDT' => -10800,
    13134         'FKST' => -14400,
    13135         'FNT' => -7200,
    13136         'GALT' => -21600,
    13137         'GEDT' => 14400,
    13138         'GEST' => 10800,
    13139         'GFT' => -10800,
    13140         'GILT' => 43200,
    13141         'GIT' => -32400,
    13142         'GST' => 14400,
    13143         'GST' => -7200,
    13144         'GYT' => -14400,
    13145         'HAA' => -10800,
    13146         'HAC' => -18000,
    13147         'HADT' => -32400,
    13148         'HAE' => -14400,
    13149         'HAP' => -25200,
    13150         'HAR' => -21600,
    13151         'HAST' => -36000,
    13152         'HAT' => -9000,
    13153         'HAY' => -28800,
    13154         'HKST' => 28800,
    13155         'HMT' => 18000,
    13156         'HNA' => -14400,
    13157         'HNC' => -21600,
    13158         'HNE' => -18000,
    13159         'HNP' => -28800,
    13160         'HNR' => -25200,
    13161         'HNT' => -12600,
    13162         'HNY' => -32400,
    13163         'IRDT' => 16200,
    13164         'IRKST' => 32400,
    13165         'IRKT' => 28800,
    13166         'IRST' => 12600,
    13167         'JFDT' => -10800,
    13168         'JFST' => -14400,
    13169         'JST' => 32400,
    13170         'KGST' => 21600,
    13171         'KGT' => 18000,
    13172         'KOST' => 39600,
    13173         'KOVST' => 28800,
    13174         'KOVT' => 25200,
    13175         'KRAST' => 28800,
    13176         'KRAT' => 25200,
    13177         'KST' => 32400,
    13178         'LHDT' => 39600,
    13179         'LHST' => 37800,
    13180         'LINT' => 50400,
    13181         'LKT' => 21600,
    13182         'MAGST' => 43200,
    13183         'MAGT' => 39600,
    13184         'MAWT' => 21600,
    13185         'MDT' => -21600,
    13186         'MESZ' => 7200,
    13187         'MEZ' => 3600,
    13188         'MHT' => 43200,
    13189         'MIT' => -34200,
    13190         'MNST' => 32400,
    13191         'MSDT' => 14400,
    13192         'MSST' => 10800,
    13193         'MST' => -25200,
    13194         'MUT' => 14400,
    13195         'MVT' => 18000,
    13196         'MYT' => 28800,
    13197         'NCT' => 39600,
    13198         'NDT' => -9000,
    13199         'NFT' => 41400,
    13200         'NMIT' => 36000,
    13201         'NOVST' => 25200,
    13202         'NOVT' => 21600,
    13203         'NPT' => 20700,
    13204         'NRT' => 43200,
    13205         'NST' => -12600,
    13206         'NUT' => -39600,
    13207         'NZDT' => 46800,
    13208         'NZST' => 43200,
    13209         'OMSST' => 25200,
    13210         'OMST' => 21600,
    13211         'PDT' => -25200,
    13212         'PET' => -18000,
    13213         'PETST' => 46800,
    13214         'PETT' => 43200,
    13215         'PGT' => 36000,
    13216         'PHOT' => 46800,
    13217         'PHT' => 28800,
    13218         'PKT' => 18000,
    13219         'PMDT' => -7200,
    13220         'PMST' => -10800,
    13221         'PONT' => 39600,
    13222         'PST' => -28800,
    13223         'PWT' => 32400,
    13224         'PYST' => -10800,
    13225         'PYT' => -14400,
    13226         'RET' => 14400,
    13227         'ROTT' => -10800,
    13228         'SAMST' => 18000,
    13229         'SAMT' => 14400,
    13230         'SAST' => 7200,
    13231         'SBT' => 39600,
    13232         'SCDT' => 46800,
    13233         'SCST' => 43200,
    13234         'SCT' => 14400,
    13235         'SEST' => 3600,
    13236         'SGT' => 28800,
    13237         'SIT' => 28800,
    13238         'SRT' => -10800,
    13239         'SST' => -39600,
    13240         'SYST' => 10800,
    13241         'SYT' => 7200,
    13242         'TFT' => 18000,
    13243         'THAT' => -36000,
    13244         'TJT' => 18000,
    13245         'TKT' => -36000,
    13246         'TMT' => 18000,
    13247         'TOT' => 46800,
    13248         'TPT' => 32400,
    13249         'TRUT' => 36000,
    13250         'TVT' => 43200,
    13251         'TWT' => 28800,
    13252         'UYST' => -7200,
    13253         'UYT' => -10800,
    13254         'UZT' => 18000,
    13255         'VET' => -14400,
    13256         'VLAST' => 39600,
    13257         'VLAT' => 36000,
    13258         'VOST' => 21600,
    13259         'VUT' => 39600,
    13260         'WAST' => 7200,
    13261         'WAT' => 3600,
    13262         'WDT' => 32400,
    13263         'WEST' => 3600,
    13264         'WFT' => 43200,
    13265         'WIB' => 25200,
    13266         'WIT' => 32400,
    13267         'WITA' => 28800,
    13268         'WKST' => 18000,
    13269         'WST' => 28800,
    13270         'YAKST' => 36000,
    13271         'YAKT' => 32400,
    13272         'YAPT' => 36000,
    13273         'YEKST' => 21600,
    13274         'YEKT' => 18000,
    13275     );
    13276 
    13277     /**
    13278      * Cached PCRE for SimplePie_Parse_Date::$day
    13279      *
    13280      * @access protected
    13281      * @var string
    13282      */
    13283     var $day_pcre;
    13284 
    13285     /**
    13286      * Cached PCRE for SimplePie_Parse_Date::$month
    13287      *
    13288      * @access protected
    13289      * @var string
    13290      */
    13291     var $month_pcre;
    13292 
    13293     /**
    13294      * Array of user-added callback methods
    13295      *
    13296      * @access private
    13297      * @var array
    13298      */
    13299     var $built_in = array();
    13300 
    13301     /**
    13302      * Array of user-added callback methods
    13303      *
    13304      * @access private
    13305      * @var array
    13306      */
    13307     var $user = array();
    13308 
    13309     /**
    13310      * Create new SimplePie_Parse_Date object, and set self::day_pcre,
    13311      * self::month_pcre, and self::built_in
    13312      *
    13313      * @access private
    13314      */
    13315     function SimplePie_Parse_Date()
    13316     {
    13317         $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
    13318         $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
    13319 
    13320         static $cache;
    13321         if (!isset($cache[get_class($this)]))
    13322         {
    13323             $all_methods = get_class_methods($this);
    13324 
    13325             foreach ($all_methods as $method)
    13326             {
    13327                 if (strtolower(substr($method, 0, 5)) === 'date_')
    13328                 {
    13329                     $cache[get_class($this)][] = $method;
    13330                 }
    13331             }
    13332         }
    13333 
    13334         foreach ($cache[get_class($this)] as $method)
    13335         {
    13336             $this->built_in[] = $method;
    13337         }
    13338     }
    13339 
    13340     /**
    13341      * Get the object
    13342      *
    13343      * @access public
    13344      */
    13345     function get()
    13346     {
    13347         static $object;
    13348         if (!$object)
    13349         {
    13350             $object =& new SimplePie_Parse_Date;
    13351         }
    13352         return $object;
    13353     }
    13354 
    13355     /**
    13356      * Parse a date
    13357      *
    13358      * @final
    13359      * @access public
    13360      * @param string $date Date to parse
    13361      * @return int Timestamp corresponding to date string, or false on failure
    13362      */
    13363     function parse($date)
    13364     {
    13365         foreach ($this->user as $method)
    13366         {
    13367             if (($returned = call_user_func($method, $date)) !== false)
    13368             {
    13369                 return $returned;
    13370             }
    13371         }
    13372 
    13373         foreach ($this->built_in as $method)
    13374         {
    13375             if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
    13376             {
    13377                 return $returned;
    13378             }
    13379         }
    13380 
    13381         return false;
    13382     }
    13383 
    13384     /**
    13385      * Add a callback method to parse a date
    13386      *
    13387      * @final
    13388      * @access public
    13389      * @param callback $callback
    13390      */
    13391     function add_callback($callback)
    13392     {
    13393         if (is_callable($callback))
    13394         {
    13395             $this->user[] = $callback;
    13396         }
    13397         else
    13398         {
    13399             trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
    13400         }
    13401     }
    13402 
    13403     /**
    13404      * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
    13405      * well as allowing any of upper or lower case "T", horizontal tabs, or
    13406      * spaces to be used as the time seperator (including more than one))
    13407      *
    13408      * @access protected
    13409      * @return int Timestamp
    13410      */
    13411     function date_w3cdtf($date)
    13412     {
    13413         static $pcre;
    13414         if (!$pcre)
    13415         {
    13416             $year = '([0-9]{4})';
    13417             $month = $day = $hour = $minute = $second = '([0-9]{2})';
    13418             $decimal = '([0-9]*)';
    13419             $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
    13420             $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
    13421         }
    13422         if (preg_match($pcre, $date, $match))
    13423         {
    13424             /*
    13425             Capturing subpatterns:
    13426             1: Year
    13427             2: Month
    13428             3: Day
    13429             4: Hour
    13430             5: Minute
    13431             6: Second
    13432             7: Decimal fraction of a second
    13433             8: Zulu
    13434             9: Timezone ±
    13435             10: Timezone hours
    13436             11: Timezone minutes
    13437             */
    13438 
    13439             // Fill in empty matches
    13440             for ($i = count($match); $i <= 3; $i++)
    13441             {
    13442                 $match[$i] = '1';
    13443             }
    13444 
    13445             for ($i = count($match); $i <= 7; $i++)
    13446             {
    13447                 $match[$i] = '0';
    13448             }
    13449 
    13450             // Numeric timezone
    13451             if (isset($match[9]) && $match[9] !== '')
    13452             {
    13453                 $timezone = $match[10] * 3600;
    13454                 $timezone += $match[11] * 60;
    13455                 if ($match[9] === '-')
    13456                 {
    13457                     $timezone = 0 - $timezone;
    13458                 }
    13459             }
    13460             else
    13461             {
    13462                 $timezone = 0;
    13463             }
    13464 
    13465             // Convert the number of seconds to an integer, taking decimals into account
    13466             $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
    13467 
    13468             return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
    13469         }
    13470         else
    13471         {
    13472             return false;
    13473         }
    13474     }
    13475 
    13476     /**
    13477      * Remove RFC822 comments
    13478      *
    13479      * @access protected
    13480      * @param string $data Data to strip comments from
    13481      * @return string Comment stripped string
    13482      */
    13483     function remove_rfc2822_comments($string)
    13484     {
    13485         $string = (string) $string;
    13486         $position = 0;
    13487         $length = strlen($string);
    13488         $depth = 0;
    13489 
    13490         $output = '';
    13491 
    13492         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
    13493         {
    13494             $output .= substr($string, $position, $pos - $position);
    13495             $position = $pos + 1;
    13496             if ($string[$pos - 1] !== '\\')
    13497             {
    13498                 $depth++;
    13499                 while ($depth && $position < $length)
    13500                 {
    13501                     $position += strcspn($string, '()', $position);
    13502                     if ($string[$position - 1] === '\\')
    13503                     {
    13504                         $position++;
    13505                         continue;
    13506                     }
    13507                     elseif (isset($string[$position]))
    13508                     {
    13509                         switch ($string[$position])
    13510                         {
    13511                             case '(':
    13512                                 $depth++;
    13513                                 break;
    13514 
    13515                             case ')':
    13516                                 $depth--;
    13517                                 break;
    13518                         }
    13519                         $position++;
    13520                     }
    13521                     else
    13522                     {
    13523                         break;
    13524                     }
    13525                 }
    13526             }
    13527             else
    13528             {
    13529                 $output .= '(';
    13530             }
    13531         }
    13532         $output .= substr($string, $position);
    13533 
    13534         return $output;
    13535     }
    13536 
    13537     /**
    13538      * Parse RFC2822's date format
    13539      *
    13540      * @access protected
    13541      * @return int Timestamp
    13542      */
    13543     function date_rfc2822($date)
    13544     {
    13545         static $pcre;
    13546         if (!$pcre)
    13547         {
    13548             $wsp = '[\x09\x20]';
    13549             $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
    13550             $optional_fws = $fws . '?';
    13551             $day_name = $this->day_pcre;
    13552             $month = $this->month_pcre;
    13553             $day = '([0-9]{1,2})';
    13554             $hour = $minute = $second = '([0-9]{2})';
    13555             $year = '([0-9]{2,4})';
    13556             $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
    13557             $character_zone = '([A-Z]{1,5})';
    13558             $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
    13559             $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';
    13560         }
    13561         if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
    13562         {
    13563             /*
    13564             Capturing subpatterns:
    13565             1: Day name
    13566             2: Day
    13567             3: Month
    13568             4: Year
    13569             5: Hour
    13570             6: Minute
    13571             7: Second
    13572             8: Timezone ±
    13573             9: Timezone hours
    13574             10: Timezone minutes
    13575             11: Alphabetic timezone
    13576             */
    13577 
    13578             // Find the month number
    13579             $month = $this->month[strtolower($match[3])];
    13580 
    13581             // Numeric timezone
    13582             if ($match[8] !== '')
    13583             {
    13584                 $timezone = $match[9] * 3600;
    13585                 $timezone += $match[10] * 60;
    13586                 if ($match[8] === '-')
    13587                 {
    13588                     $timezone = 0 - $timezone;
    13589                 }
    13590             }
    13591             // Character timezone
    13592             elseif (isset($this->timezone[strtoupper($match[11])]))
    13593             {
    13594                 $timezone = $this->timezone[strtoupper($match[11])];
    13595             }
    13596             // Assume everything else to be -0000
    13597             else
    13598             {
    13599                 $timezone = 0;
    13600             }
    13601 
    13602             // Deal with 2/3 digit years
    13603             if ($match[4] < 50)
    13604             {
    13605                 $match[4] += 2000;
    13606             }
    13607             elseif ($match[4] < 1000)
    13608             {
    13609                 $match[4] += 1900;
    13610             }
    13611 
    13612             // Second is optional, if it is empty set it to zero
    13613             if ($match[7] !== '')
    13614             {
    13615                 $second = $match[7];
    13616             }
    13617             else
    13618             {
    13619                 $second = 0;
    13620             }
    13621 
    13622             return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
    13623         }
    13624         else
    13625         {
    13626             return false;
    13627         }
    13628     }
    13629 
    13630     /**
    13631      * Parse RFC850's date format
    13632      *
    13633      * @access protected
    13634      * @return int Timestamp
    13635      */
    13636     function date_rfc850($date)
    13637     {
    13638         static $pcre;
    13639         if (!$pcre)
    13640         {
    13641             $space = '[\x09\x20]+';
    13642             $day_name = $this->day_pcre;
    13643             $month = $this->month_pcre;
    13644             $day = '([0-9]{1,2})';
    13645             $year = $hour = $minute = $second = '([0-9]{2})';
    13646             $zone = '([A-Z]{1,5})';
    13647             $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
    13648         }
    13649         if (preg_match($pcre, $date, $match))
    13650         {
    13651             /*
    13652             Capturing subpatterns:
    13653             1: Day name
    13654             2: Day
    13655             3: Month
    13656             4: Year
    13657             5: Hour
    13658             6: Minute
    13659             7: Second
    13660             8: Timezone
    13661             */
    13662 
    13663             // Month
    13664             $month = $this->month[strtolower($match[3])];
    13665 
    13666             // Character timezone
    13667             if (isset($this->timezone[strtoupper($match[8])]))
    13668             {
    13669                 $timezone = $this->timezone[strtoupper($match[8])];
    13670             }
    13671             // Assume everything else to be -0000
    13672             else
    13673             {
    13674                 $timezone = 0;
    13675             }
    13676 
    13677             // Deal with 2 digit year
    13678             if ($match[4] < 50)
    13679             {
    13680                 $match[4] += 2000;
    13681             }
    13682             else
    13683             {
    13684                 $match[4] += 1900;
    13685             }
    13686 
    13687             return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
    13688         }
    13689         else
    13690         {
    13691             return false;
    13692         }
    13693     }
    13694 
    13695     /**
    13696      * Parse C99's asctime()'s date format
    13697      *
    13698      * @access protected
    13699      * @return int Timestamp
    13700      */
    13701     function date_asctime($date)
    13702     {
    13703         static $pcre;
    13704         if (!$pcre)
    13705         {
    13706             $space = '[\x09\x20]+';
    13707             $wday_name = $this->day_pcre;
    13708             $mon_name = $this->month_pcre;
    13709             $day = '([0-9]{1,2})';
    13710             $hour = $sec = $min = '([0-9]{2})';
    13711             $year = '([0-9]{4})';
    13712             $terminator = '\x0A?\x00?';
    13713             $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
    13714         }
    13715         if (preg_match($pcre, $date, $match))
    13716         {
    13717             /*
    13718             Capturing subpatterns:
    13719             1: Day name
    13720             2: Month
    13721             3: Day
    13722             4: Hour
    13723             5: Minute
    13724             6: Second
    13725             7: Year
    13726             */
    13727 
    13728             $month = $this->month[strtolower($match[2])];
    13729             return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
    13730         }
    13731         else
    13732         {
    13733             return false;
    13734         }
    13735     }
    13736 
    13737     /**
    13738      * Parse dates using strtotime()
    13739      *
    13740      * @access protected
    13741      * @return int Timestamp
    13742      */
    13743     function date_strtotime($date)
    13744     {
    13745         $strtotime = strtotime($date);
    13746         if ($strtotime === -1 || $strtotime === false)
    13747         {
    13748             return false;
    13749         }
    13750         else
    13751         {
    13752             return $strtotime;
    13753         }
    13754     }
    13755 }
    13756 
    13757 /**
    13758  * Content-type sniffing
    13759  *
    13760  * @package SimplePie
    13761  */
    13762 class SimplePie_Content_Type_Sniffer
    13763 {
    13764     /**
    13765      * File object
    13766      *
    13767      * @var SimplePie_File
    13768      * @access private
    13769      */
    13770     var $file;
    13771 
    13772     /**
    13773      * Create an instance of the class with the input file
    13774      *
    13775      * @access public
    13776      * @param SimplePie_Content_Type_Sniffer $file Input file
    13777      */
    13778     function SimplePie_Content_Type_Sniffer($file)
    13779     {
    13780         $this->file = $file;
    13781     }
    13782 
    13783     /**
    13784      * Get the Content-Type of the specified file
    13785      *
    13786      * @access public
    13787      * @return string Actual Content-Type
    13788      */
    13789     function get_type()
    13790     {
    13791         if (isset($this->file->headers['content-type']))
    13792         {
    13793             if (!isset($this->file->headers['content-encoding'])
    13794                 && ($this->file->headers['content-type'] === 'text/plain'
    13795                     || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
    13796                     || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
    13797             {
    13798                 return $this->text_or_binary();
    13799             }
    13800 
    13801             if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
    13802             {
    13803                 $official = substr($this->file->headers['content-type'], 0, $pos);
    13804             }
    13805             else
    13806             {
    13807                 $official = $this->file->headers['content-type'];
    13808             }
    13809             $official = strtolower($official);
    13810 
    13811             if ($official === 'unknown/unknown'
    13812                 || $official === 'application/unknown')
    13813             {
    13814                 return $this->unknown();
    13815             }
    13816             elseif (substr($official, -4) === '+xml'
    13817                 || $official === 'text/xml'
    13818                 || $official === 'application/xml')
    13819             {
    13820                 return $official;
    13821             }
    13822             elseif (substr($official, 0, 6) === 'image/')
    13823             {
    13824                 if ($return = $this->image())
    13825                 {
    13826                     return $return;
    13827                 }
    13828                 else
    13829                 {
    13830                     return $official;
    13831                 }
    13832             }
    13833             elseif ($official === 'text/html')
    13834             {
    13835                 return $this->feed_or_html();
    13836             }
    13837             else
    13838             {
    13839                 return $official;
    13840             }
    13841         }
    13842         else
    13843         {
    13844             return $this->unknown();
    13845         }
    13846     }
    13847 
    13848     /**
    13849      * Sniff text or binary
    13850      *
    13851      * @access private
    13852      * @return string Actual Content-Type
    13853      */
    13854     function text_or_binary()
    13855     {
    13856         if (substr($this->file->body, 0, 2) === "\xFE\xFF"
    13857             || substr($this->file->body, 0, 2) === "\xFF\xFE"
    13858             || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
    13859             || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
    13860         {
    13861             return 'text/plain';
    13862         }
    13863         elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
    13864         {
    13865             return 'application/octect-stream';
    13866         }
    13867         else
    13868         {
    13869             return 'text/plain';
    13870         }
    13871     }
    13872 
    13873     /**
    13874      * Sniff unknown
    13875      *
    13876      * @access private
    13877      * @return string Actual Content-Type
    13878      */
    13879     function unknown()
    13880     {
    13881         $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
    13882         if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
    13883             || strtolower(substr($this->file->body, $ws, 5)) === '<html'
    13884             || strtolower(substr($this->file->body, $ws, 7)) === '<script')
    13885         {
    13886             return 'text/html';
    13887         }
    13888         elseif (substr($this->file->body, 0, 5) === '%PDF-')
    13889         {
    13890             return 'application/pdf';
    13891         }
    13892         elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
    13893         {
    13894             return 'application/postscript';
    13895         }
    13896         elseif (substr($this->file->body, 0, 6) === 'GIF87a'
    13897             || substr($this->file->body, 0, 6) === 'GIF89a')
    13898         {
    13899             return 'image/gif';
    13900         }
    13901         elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
    13902         {
    13903             return 'image/png';
    13904         }
    13905         elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
    13906         {
    13907             return 'image/jpeg';
    13908         }
    13909         elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
    13910         {
    13911             return 'image/bmp';
    13912         }
    13913         else
    13914         {
    13915             return $this->text_or_binary();
    13916         }
    13917     }
    13918 
    13919     /**
    13920      * Sniff images
    13921      *
    13922      * @access private
    13923      * @return string Actual Content-Type
    13924      */
    13925     function image()
    13926     {
    13927         if (substr($this->file->body, 0, 6) === 'GIF87a'
    13928             || substr($this->file->body, 0, 6) === 'GIF89a')
    13929         {
    13930             return 'image/gif';
    13931         }
    13932         elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
    13933         {
    13934             return 'image/png';
    13935         }
    13936         elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
    13937         {
    13938             return 'image/jpeg';
    13939         }
    13940         elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
    13941         {
    13942             return 'image/bmp';
    13943         }
    13944         else
    13945         {
    13946             return false;
    13947         }
    13948     }
    13949 
    13950     /**
    13951      * Sniff HTML
    13952      *
    13953      * @access private
    13954      * @return string Actual Content-Type
    13955      */
    13956     function feed_or_html()
    13957     {
    13958         $len = strlen($this->file->body);
    13959         $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
    13960 
    13961         while ($pos < $len)
    13962         {
    13963             switch ($this->file->body[$pos])
    13964             {
    13965                 case "\x09":
    13966                 case "\x0A":
    13967                 case "\x0D":
    13968                 case "\x20":
    13969                     $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
    13970                     continue 2;
    13971 
    13972                 case '<':
    13973                     $pos++;
    13974                     break;
    13975 
    13976                 default:
    13977                     return 'text/html';
    13978             }
    13979 
    13980             if (substr($this->file->body, $pos, 3) === '!--')
    13981             {
    13982                 $pos += 3;
    13983                 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
    13984                 {
    13985                     $pos += 3;
    13986                 }
    13987                 else
    13988                 {
    13989                     return 'text/html';
    13990                 }
    13991             }
    13992             elseif (substr($this->file->body, $pos, 1) === '!')
    13993             {
    13994                 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
    13995                 {
    13996                     $pos++;
    13997                 }
    13998                 else
    13999                 {
    14000                     return 'text/html';
    14001                 }
    14002             }
    14003             elseif (substr($this->file->body, $pos, 1) === '?')
    14004             {
    14005                 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
    14006                 {
    14007                     $pos += 2;
    14008                 }
    14009                 else
    14010                 {
    14011                     return 'text/html';
    14012                 }
    14013             }
    14014             elseif (substr($this->file->body, $pos, 3) === 'rss'
    14015                 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
    14016             {
    14017                 return 'application/rss+xml';
    14018             }
    14019             elseif (substr($this->file->body, $pos, 4) === 'feed')
    14020             {
    14021                 return 'application/atom+xml';
    14022             }
    14023             else
    14024             {
    14025                 return 'text/html';
    14026             }
    14027         }
    14028 
    14029         return 'text/html';
    14030     }
    14031 }
    14032 
    14033 /**
    14034  * Parses the XML Declaration
    14035  *
    14036  * @package SimplePie
    14037  */
    14038 class SimplePie_XML_Declaration_Parser
    14039 {
    14040     /**
    14041      * XML Version
    14042      *
    14043      * @access public
    14044      * @var string
    14045      */
    14046     var $version = '1.0';
    14047 
    14048     /**
    14049      * Encoding
    14050      *
    14051      * @access public
    14052      * @var string
    14053      */
    14054     var $encoding = 'UTF-8';
    14055 
    14056     /**
    14057      * Standalone
    14058      *
    14059      * @access public
    14060      * @var bool
    14061      */
    14062     var $standalone = false;
    14063 
    14064     /**
    14065      * Current state of the state machine
    14066      *
    14067      * @access private
    14068      * @var string
    14069      */
    14070     var $state = 'before_version_name';
    14071 
    14072     /**
    14073      * Input data
    14074      *
    14075      * @access private
    14076      * @var string
    14077      */
    14078     var $data = '';
    14079 
    14080     /**
    14081      * Input data length (to avoid calling strlen() everytime this is needed)
    14082      *
    14083      * @access private
    14084      * @var int
    14085      */
    14086     var $data_length = 0;
    14087 
    14088     /**
    14089      * Current position of the pointer
    14090      *
    14091      * @var int
    14092      * @access private
    14093      */
    14094     var $position = 0;
    14095 
    14096     /**
    14097      * Create an instance of the class with the input data
    14098      *
    14099      * @access public
    14100      * @param string $data Input data
    14101      */
    14102     function SimplePie_XML_Declaration_Parser($data)
    14103     {
    14104         $this->data = $data;
    14105         $this->data_length = strlen($this->data);
    14106     }
    14107 
    14108     /**
    14109      * Parse the input data
    14110      *
    14111      * @access public
    14112      * @return bool true on success, false on failure
    14113      */
    14114     function parse()
    14115     {
    14116         while ($this->state && $this->state !== 'emit' && $this->has_data())
    14117         {
    14118             $state = $this->state;
    14119             $this->$state();
    14120         }
    14121         $this->data = '';
    14122         if ($this->state === 'emit')
    14123         {
    14124             return true;
    14125         }
    14126         else
    14127         {
    14128             $this->version = '';
    14129             $this->encoding = '';
    14130             $this->standalone = '';
    14131             return false;
    14132         }
    14133     }
    14134 
    14135     /**
    14136      * Check whether there is data beyond the pointer
    14137      *
    14138      * @access private
    14139      * @return bool true if there is further data, false if not
    14140      */
    14141     function has_data()
    14142     {
    14143         return (bool) ($this->position < $this->data_length);
    14144     }
    14145 
    14146     /**
    14147      * Advance past any whitespace
    14148      *
    14149      * @return int Number of whitespace characters passed
    14150      */
    14151     function skip_whitespace()
    14152     {
    14153         $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
    14154         $this->position += $whitespace;
    14155         return $whitespace;
    14156     }
    14157 
    14158     /**
    14159      * Read value
    14160      */
    14161     function get_value()
    14162     {
    14163         $quote = substr($this->data, $this->position, 1);
    14164         if ($quote === '"' || $quote === "'")
    14165         {
    14166             $this->position++;
    14167             $len = strcspn($this->data, $quote, $this->position);
    14168             if ($this->has_data())
    14169             {
    14170                 $value = substr($this->data, $this->position, $len);
    14171                 $this->position += $len + 1;
    14172                 return $value;
    14173             }
    14174         }
    14175         return false;
    14176     }
    14177 
    14178     function before_version_name()
    14179     {
    14180         if ($this->skip_whitespace())
    14181         {
    14182             $this->state = 'version_name';
    14183         }
    14184         else
    14185         {
    14186             $this->state = false;
    14187         }
    14188     }
    14189 
    14190     function version_name()
    14191     {
    14192         if (substr($this->data, $this->position, 7) === 'version')
    14193         {
    14194             $this->position += 7;
    14195             $this->skip_whitespace();
    14196             $this->state = 'version_equals';
    14197         }
    14198         else
    14199         {
    14200             $this->state = false;
    14201         }
    14202     }
    14203 
    14204     function version_equals()
    14205     {
    14206         if (substr($this->data, $this->position, 1) === '=')
    14207         {
    14208             $this->position++;
    14209             $this->skip_whitespace();
    14210             $this->state = 'version_value';
    14211         }
    14212         else
    14213         {
    14214             $this->state = false;
    14215         }
    14216     }
    14217 
    14218     function version_value()
    14219     {
    14220         if ($this->version = $this->get_value())
    14221         {
    14222             $this->skip_whitespace();
    14223             if ($this->has_data())
    14224             {
    14225                 $this->state = 'encoding_name';
    14226             }
    14227             else
    14228             {
    14229                 $this->state = 'emit';
    14230             }
    14231         }
    14232         else
    14233         {
    14234             $this->state = false;
    14235         }
    14236     }
    14237 
    14238     function encoding_name()
    14239     {
    14240         if (substr($this->data, $this->position, 8) === 'encoding')
    14241         {
    14242             $this->position += 8;
    14243             $this->skip_whitespace();
    14244             $this->state = 'encoding_equals';
    14245         }
    14246         else
    14247         {
    14248             $this->state = 'standalone_name';
    14249         }
    14250     }
    14251 
    14252     function encoding_equals()
    14253     {
    14254         if (substr($this->data, $this->position, 1) === '=')
    14255         {
    14256             $this->position++;
    14257             $this->skip_whitespace();
    14258             $this->state = 'encoding_value';
    14259         }
    14260         else
    14261         {
    14262             $this->state = false;
    14263         }
    14264     }
    14265 
    14266     function encoding_value()
    14267     {
    14268         if ($this->encoding = $this->get_value())
    14269         {
    14270             $this->skip_whitespace();
    14271             if ($this->has_data())
    14272             {
    14273                 $this->state = 'standalone_name';
    14274             }
    14275             else
    14276             {
    14277                 $this->state = 'emit';
    14278             }
    14279         }
    14280         else
    14281         {
    14282             $this->state = false;
    14283         }
    14284     }
    14285 
    14286     function standalone_name()
    14287     {
    14288         if (substr($this->data, $this->position, 10) === 'standalone')
    14289         {
    14290             $this->position += 10;
    14291             $this->skip_whitespace();
    14292             $this->state = 'standalone_equals';
    14293         }
    14294         else
    14295         {
    14296             $this->state = false;
    14297         }
    14298     }
    14299 
    14300     function standalone_equals()
    14301     {
    14302         if (substr($this->data, $this->position, 1) === '=')
    14303         {
    14304             $this->position++;
    14305             $this->skip_whitespace();
    14306             $this->state = 'standalone_value';
    14307         }
    14308         else
    14309         {
    14310             $this->state = false;
    14311         }
    14312     }
    14313 
    14314     function standalone_value()
    14315     {
    14316         if ($standalone = $this->get_value())
    14317         {
    14318             switch ($standalone)
    14319             {
    14320                 case 'yes':
    14321                     $this->standalone = true;
    14322                     break;
    14323 
    14324                 case 'no':
    14325                     $this->standalone = false;
    14326                     break;
    14327 
    14328                 default:
    14329                     $this->state = false;
    14330                     return;
    14331             }
    14332 
    14333             $this->skip_whitespace();
    14334             if ($this->has_data())
    14335             {
    14336                 $this->state = false;
    14337             }
    14338             else
    14339             {
    14340                 $this->state = 'emit';
    14341             }
    14342         }
    14343         else
    14344         {
    14345             $this->state = false;
    14346         }
    14347     }
    14348 }
    14349 
    14350 class SimplePie_Locator
    14351 {
    14352     var $useragent;
    14353     var $timeout;
    14354     var $file;
    14355     var $local = array();
    14356     var $elsewhere = array();
    14357     var $file_class = 'SimplePie_File';
    14358     var $cached_entities = array();
    14359     var $http_base;
    14360     var $base;
    14361     var $base_location = 0;
    14362     var $checked_feeds = 0;
    14363     var $max_checked_feeds = 10;
    14364     var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
    14365 
    14366     function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
    14367     {
    14368         $this->file =& $file;
    14369         $this->file_class = $file_class;
    14370         $this->useragent = $useragent;
    14371         $this->timeout = $timeout;
    14372         $this->max_checked_feeds = $max_checked_feeds;
    14373         $this->content_type_sniffer_class = $content_type_sniffer_class;
    14374     }
    14375 
    14376     function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
    14377     {
    14378         if ($this->is_feed($this->file))
    14379         {
    14380             return $this->file;
    14381         }
    14382 
    14383         if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
    14384         {
    14385             $sniffer =& new $this->content_type_sniffer_class($this->file);
    14386             if ($sniffer->get_type() !== 'text/html')
    14387             {
    14388                 return null;
    14389             }
    14390         }
    14391 
    14392         if ($type & ~SIMPLEPIE_LOCATOR_NONE)
    14393         {
    14394             $this->get_base();
    14395         }
    14396 
    14397         if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
    14398         {
    14399             return $working[0];
    14400         }
    14401 
    14402         if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
    14403         {
    14404             if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
    14405             {
    14406                 return $working;
    14407             }
    14408 
    14409             if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
    14410             {
    14411                 return $working;
    14412             }
    14413 
    14414             if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
    14415             {
    14416                 return $working;
    14417             }
    14418 
    14419             if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
    14420             {
    14421                 return $working;
    14422             }
    14423         }
    14424         return null;
    14425     }
    14426 
    14427     function is_feed(&$file)
    14428     {
    14429         if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
    14430         {
    14431             $sniffer =& new $this->content_type_sniffer_class($file);
    14432             $sniffed = $sniffer->get_type();
    14433             if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
    14434             {
    14435                 return true;
    14436             }
    14437             else
    14438             {
    14439                 return false;
    14440             }
    14441         }
    14442         elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
    14443         {
    14444             return true;
    14445         }
    14446         else
    14447         {
    14448             return false;
    14449         }
    14450     }
    14451 
    14452     function get_base()
    14453     {
    14454         $this->http_base = $this->file->url;
    14455         $this->base = $this->http_base;
    14456         $elements = SimplePie_Misc::get_element('base', $this->file->body);
    14457         foreach ($elements as $element)
    14458         {
    14459             if ($element['attribs']['href']['data'] !== '')
    14460             {
    14461                 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
    14462                 $this->base_location = $element['offset'];
    14463                 break;
    14464             }
    14465         }
    14466     }
    14467 
    14468     function autodiscovery()
    14469     {
    14470         $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));
    14471         $done = array();
    14472         $feeds = array();
    14473         foreach ($links as $link)
    14474         {
    14475             if ($this->checked_feeds === $this->max_checked_feeds)
    14476             {
    14477                 break;
    14478             }
    14479             if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
    14480             {
    14481                 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
    14482 
    14483                 if ($this->base_location < $link['offset'])
    14484                 {
    14485                     $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
    14486                 }
    14487                 else
    14488                 {
    14489                     $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
    14490                 }
    14491 
    14492                 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]))
    14493                 {
    14494                     $this->checked_feeds++;
    14495                     $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
    14496                     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))
    14497                     {
    14498                         $feeds[$href] = $feed;
    14499                     }
    14500                 }
    14501                 $done[] = $href;
    14502             }
    14503         }
    14504 
    14505         if (!empty($feeds))
    14506         {
    14507             return array_values($feeds);
    14508         }
    14509         else {
    14510             return null;
    14511         }
    14512     }
    14513 
    14514     function get_links()
    14515     {
    14516         $links = SimplePie_Misc::get_element('a', $this->file->body);
    14517         foreach ($links as $link)
    14518         {
    14519             if (isset($link['attribs']['href']['data']))
    14520             {
    14521                 $href = trim($link['attribs']['href']['data']);
    14522                 $parsed = SimplePie_Misc::parse_url($href);
    14523                 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
    14524                 {
    14525                     if ($this->base_location < $link['offset'])
    14526                     {
    14527                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
    14528                     }
    14529                     else
    14530                     {
    14531                         $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
    14532                     }
    14533 
    14534                     $current = SimplePie_Misc::parse_url($this->file->url);
    14535 
    14536                     if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
    14537                     {
    14538                         $this->local[] = $href;
    14539                     }
    14540                     else
    14541                     {
    14542                         $this->elsewhere[] = $href;
    14543                     }
    14544                 }
    14545             }
    14546         }
    14547         $this->local = array_unique($this->local);
    14548         $this->elsewhere = array_unique($this->elsewhere);
    14549         if (!empty($this->local) || !empty($this->elsewhere))
    14550         {
    14551             return true;
    14552         }
    14553         return null;
    14554     }
    14555 
    14556     function extension(&$array)
    14557     {
    14558         foreach ($array as $key => $value)
    14559         {
    14560             if ($this->checked_feeds === $this->max_checked_feeds)
    14561             {
    14562                 break;
    14563             }
    14564             if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
    14565             {
    14566                 $this->checked_feeds++;
    14567                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
    14568                 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))
    14569                 {
    14570                     return $feed;
    14571                 }
    14572                 else
    14573                 {
    14574                     unset($array[$key]);
    14575                 }
    14576             }
    14577         }
    14578         return null;
    14579     }
    14580 
    14581     function body(&$array)
    14582     {
    14583         foreach ($array as $key => $value)
    14584         {
    14585             if ($this->checked_feeds === $this->max_checked_feeds)
    14586             {
    14587                 break;
    14588             }
    14589             if (preg_match('/(rss|rdf|atom|xml)/i', $value))
    14590             {
    14591                 $this->checked_feeds++;
    14592                 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
    14593                 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))
    14594                 {
    14595                     return $feed;
    14596                 }
    14597                 else
    14598                 {
    14599                     unset($array[$key]);
    14600                 }
    14601             }
    14602         }
    14603         return null;
    14604     }
    14605 }
    14606 
    14607 class SimplePie_Parser
    14608 {
    14609     var $error_code;
    14610     var $error_string;
    14611     var $current_line;
    14612     var $current_column;
    14613     var $current_byte;
    14614     var $separator = ' ';
    14615     var $namespace = array('');
    14616     var $element = array('');
    14617     var $xml_base = array('');
    14618     var $xml_base_explicit = array(false);
    14619     var $xml_lang = array('');
    14620     var $data = array();
    14621     var $datas = array(array());
    14622     var $current_xhtml_construct = -1;
    14623     var $encoding;
    14624 
    14625     function parse(&$data, $encoding)
    14626     {
    14627         // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
    14628         if (strtoupper($encoding) === 'US-ASCII')
    14629         {
    14630             $this->encoding = 'UTF-8';
    14631         }
    14632         else
    14633         {
    14634             $this->encoding = $encoding;
    14635         }
    14636 
    14637         // Strip BOM:
    14638         // UTF-32 Big Endian BOM
    14639         if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
    14640         {
    14641             $data = substr($data, 4);
    14642         }
    14643         // UTF-32 Little Endian BOM
    14644         elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
    14645         {
    14646             $data = substr($data, 4);
    14647         }
    14648         // UTF-16 Big Endian BOM
    14649         elseif (substr($data, 0, 2) === "\xFE\xFF")
    14650         {
    14651             $data = substr($data, 2);
    14652         }
    14653         // UTF-16 Little Endian BOM
    14654         elseif (substr($data, 0, 2) === "\xFF\xFE")
    14655         {
    14656             $data = substr($data, 2);
    14657         }
    14658         // UTF-8 BOM
    14659         elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
    14660         {
    14661             $data = substr($data, 3);
    14662         }
    14663 
    14664         if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
    14665         {
    14666             $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
    14667             if ($declaration->parse())
    14668             {
    14669                 $data = substr($data, $pos + 2);
    14670                 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
    14671             }
    14672             else
    14673             {
    14674                 $this->error_string = 'SimplePie bug! Please report this!';
    14675                 return false;
    14676             }
    14677         }
    14678 
    14679         $return = true;
    14680 
    14681         static $xml_is_sane = null;
    14682         if ($xml_is_sane === null)
    14683         {
    14684             $parser_check = xml_parser_create();
    14685             xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
    14686             xml_parser_free($parser_check);
    14687             $xml_is_sane = isset($values[0]['value']);
    14688         }
    14689 
    14690         // Create the parser
    14691         if ($xml_is_sane)
    14692         {
    14693             $xml = xml_parser_create_ns($this->encoding, $this->separator);
    14694             xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
    14695             xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
    14696             xml_set_object($xml, $this);
    14697             xml_set_character_data_handler($xml, 'cdata');
    14698             xml_set_element_handler($xml, 'tag_open', 'tag_close');
    14699 
    14700             // Parse!
    14701             if (!xml_parse($xml, $data, true))
    14702             {
    14703                 $this->error_code = xml_get_error_code($xml);
    14704                 $this->error_string = xml_error_string($this->error_code);
    14705                 $return = false;
    14706             }
    14707             $this->current_line = xml_get_current_line_number($xml);
    14708             $this->current_column = xml_get_current_column_number($xml);
    14709             $this->current_byte = xml_get_current_byte_index($xml);
    14710             xml_parser_free($xml);
    14711             return $return;
    14712         }
    14713         else
    14714         {
    14715             libxml_clear_errors();
    14716             $xml =& new XMLReader();
    14717             $xml->xml($data);
    14718             while (@$xml->read())
    14719             {
    14720                 switch ($xml->nodeType)
    14721                 {
    14722 
    14723                     case constant('XMLReader::END_ELEMENT'):
    14724                         if ($xml->namespaceURI !== '')
    14725                         {
    14726                             $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
    14727                         }
    14728                         else
    14729                         {
    14730                             $tagName = $xml->localName;
    14731                         }
    14732                         $this->tag_close(null, $tagName);
    14733                         break;
    14734                     case constant('XMLReader::ELEMENT'):
    14735                         $empty = $xml->isEmptyElement;
    14736                         if ($xml->namespaceURI !== '')
    14737                         {
    14738                             $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
    14739                         }
    14740                         else
    14741                         {
    14742                             $tagName = $xml->localName;
    14743                         }
    14744                         $attributes = array();
    14745                         while ($xml->moveToNextAttribute())
    14746                         {
    14747                             if ($xml->namespaceURI !== '')
    14748                             {
    14749                                 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
    14750                             }
    14751                             else
    14752                             {
    14753                                 $attrName = $xml->localName;
    14754                             }
    14755                             $attributes[$attrName] = $xml->value;
    14756                         }
    14757                         $this->tag_open(null, $tagName, $attributes);
    14758                         if ($empty)
    14759                         {
    14760                             $this->tag_close(null, $tagName);
    14761                         }
    14762                         break;
    14763                     case constant('XMLReader::TEXT'):
    14764 
    14765                     case constant('XMLReader::CDATA'):
    14766                         $this->cdata(null, $xml->value);
    14767                         break;
    14768                 }
    14769             }
    14770             if ($error = libxml_get_last_error())
    14771             {
    14772                 $this->error_code = $error->code;
    14773                 $this->error_string = $error->message;
    14774                 $this->current_line = $error->line;
    14775                 $this->current_column = $error->column;
    14776                 return false;
    14777             }
    14778             else
    14779             {
    14780                 return true;
    14781             }
    14782         }
    14783     }
    14784 
    14785     function get_error_code()
    14786     {
    14787         return $this->error_code;
    14788     }
    14789 
    14790     function get_error_string()
    14791     {
    14792         return $this->error_string;
    14793     }
    14794 
    14795     function get_current_line()
    14796     {
    14797         return $this->current_line;
    14798     }
    14799 
    14800     function get_current_column()
    14801     {
    14802         return $this->current_column;
    14803     }
    14804 
    14805     function get_current_byte()
    14806     {
    14807         return $this->current_byte;
    14808     }
    14809 
    14810     function get_data()
    14811     {
    14812         return $this->data;
    14813     }
    14814 
    14815     function tag_open($parser, $tag, $attributes)
    14816     {
    14817         list($this->namespace[], $this->element[]) = $this->split_ns($tag);
    14818 
    14819         $attribs = array();
    14820         foreach ($attributes as $name => $value)
    14821         {
    14822             list($attrib_namespace, $attribute) = $this->split_ns($name);
    14823             $attribs[$attrib_namespace][$attribute] = $value;
    14824         }
    14825 
    14826         if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
    14827         {
    14828             $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
    14829             $this->xml_base_explicit[] = true;
    14830         }
    14831         else
    14832         {
    14833             $this->xml_base[] = end($this->xml_base);
    14834             $this->xml_base_explicit[] = end($this->xml_base_explicit);
    14835         }
    14836 
    14837         if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
    14838         {
    14839             $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
    14840         }
    14841         else
    14842         {
    14843             $this->xml_lang[] = end($this->xml_lang);
    14844         }
    14845 
    14846         if ($this->current_xhtml_construct >= 0)
    14847         {
    14848             $this->current_xhtml_construct++;
    14849             if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
    14850             {
    14851                 $this->data['data'] .= '<' . end($this->element);
    14852                 if (isset($attribs['']))
    14853                 {
    14854                     foreach ($attribs[''] as $name => $value)
    14855                     {
    14856                         $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
    14857                     }
    14858                 }
    14859                 $this->data['data'] .= '>';
    14860             }
    14861         }
    14862         else
    14863         {
    14864             $this->datas[] =& $this->data;
    14865             $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
    14866             $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));
    14867             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')
    14868             || (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'))
    14869             {
    14870                 $this->current_xhtml_construct = 0;
    14871             }
    14872         }
    14873     }
    14874 
    14875     function cdata($parser, $cdata)
    14876     {
    14877         if ($this->current_xhtml_construct >= 0)
    14878         {
    14879             $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
    14880         }
    14881         else
    14882         {
    14883             $this->data['data'] .= $cdata;
    14884         }
    14885     }
    14886 
    14887     function tag_close($parser, $tag)
    14888     {
    14889         if ($this->current_xhtml_construct >= 0)
    14890         {
    14891             $this->current_xhtml_construct--;
    14892             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')))
    14893             {
    14894                 $this->data['data'] .= '</' . end($this->element) . '>';
    14895             }
    14896         }
    14897         if ($this->current_xhtml_construct === -1)
    14898         {
    14899             $this->data =& $this->datas[count($this->datas) - 1];
    14900             array_pop($this->datas);
    14901         }
    14902 
    14903         array_pop($this->element);
    14904         array_pop($this->namespace);
    14905         array_pop($this->xml_base);
    14906         array_pop($this->xml_base_explicit);
    14907         array_pop($this->xml_lang);
    14908     }
    14909 
    14910     function split_ns($string)
    14911     {
    14912         static $cache = array();
    14913         if (!isset($cache[$string]))
    14914         {
    14915             if ($pos = strpos($string, $this->separator))
    14916             {
    14917                 static $separator_length;
    14918                 if (!$separator_length)
    14919                 {
    14920                     $separator_length = strlen($this->separator);
    14921                 }
    14922                 $namespace = substr($string, 0, $pos);
    14923                 $local_name = substr($string, $pos + $separator_length);
    14924                 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
    14925                 {
    14926                     $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
    14927                 }
    14928 
    14929                 // Normalize the Media RSS namespaces
    14930                 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
    14931                 {
    14932                     $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
    14933                 }
    14934                 $cache[$string] = array($namespace, $local_name);
    14935             }
    14936             else
    14937             {
    14938                 $cache[$string] = array('', $string);
    14939             }
    14940         }
    14941         return $cache[$string];
    14942     }
    14943 }
    14944 
    14945 /**
    14946  * @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
    14947  */
    14948 class SimplePie_Sanitize
    14949 {
    14950     // Private vars
    14951     var $base;
    14952 
    14953     // Options
    14954     var $remove_div = true;
    14955     var $image_handler = '';
    14956     var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
    14957     var $encode_instead_of_strip = false;
    14958     var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
    14959     var $strip_comments = false;
    14960     var $output_encoding = 'UTF-8';
    14961     var $enable_cache = true;
    14962     var $cache_location = './cache';
    14963     var $cache_name_function = 'md5';
    14964     var $cache_class = 'SimplePie_Cache';
    14965     var $file_class = 'SimplePie_File';
    14966     var $timeout = 10;
    14967     var $useragent = '';
    14968     var $force_fsockopen = false;
    14969 
    14970     var $replace_url_attributes = array(
    14971         'a' => 'href',
    14972         'area' => 'href',
    14973         'blockquote' => 'cite',
    14974         'del' => 'cite',
    14975         'form' => 'action',
    14976         'img' => array('longdesc', 'src'),
    14977         'input' => 'src',
    14978         'ins' => 'cite',
    14979         'q' => 'cite'
    14980     );
    14981 
    14982     function remove_div($enable = true)
    14983     {
    14984         $this->remove_div = (bool) $enable;
    14985     }
    14986 
    14987     function set_image_handler($page = false)
    14988     {
    14989         if ($page)
    14990         {
    14991             $this->image_handler = (string) $page;
    14992         }
    14993         else
    14994         {
    14995             $this->image_handler = false;
    14996         }
    14997     }
    14998 
    14999     function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
    15000     {
    15001         if (isset($enable_cache))
    15002         {
    15003             $this->enable_cache = (bool) $enable_cache;
    15004         }
    15005 
    15006         if ($cache_location)
    15007         {
    15008             $this->cache_location = (string) $cache_location;
    15009         }
    15010 
    15011         if ($cache_name_function)
    15012         {
    15013             $this->cache_name_function = (string) $cache_name_function;
    15014         }
    15015 
    15016         if ($cache_class)
    15017         {
    15018             $this->cache_class = (string) $cache_class;
    15019         }
    15020     }
    15021 
    15022     function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
    15023     {
    15024         if ($file_class)
    15025         {
    15026             $this->file_class = (string) $file_class;
    15027         }
    15028 
    15029         if ($timeout)
    15030         {
    15031             $this->timeout = (string) $timeout;
    15032         }
    15033 
    15034         if ($useragent)
    15035         {
    15036             $this->useragent = (string) $useragent;
    15037         }
    15038 
    15039         if ($force_fsockopen)
    15040         {
    15041             $this->force_fsockopen = (string) $force_fsockopen;
    15042         }
    15043     }
    15044 
    15045     function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
    15046     {
    15047         if ($tags)
    15048         {
    15049             if (is_array($tags))
    15050             {
    15051                 $this->strip_htmltags = $tags;
    15052             }
    15053             else
    15054             {
    15055                 $this->strip_htmltags = explode(',', $tags);
    15056             }
    15057         }
    15058         else
    15059         {
    15060             $this->strip_htmltags = false;
    15061         }
    15062     }
    15063 
    15064     function encode_instead_of_strip($encode = false)
    15065     {
    15066         $this->encode_instead_of_strip = (bool) $encode;
    15067     }
    15068 
    15069     function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
    15070     {
    15071         if ($attribs)
    15072         {
    15073             if (is_array($attribs))
    15074             {
    15075                 $this->strip_attributes = $attribs;
    15076             }
    15077             else
    15078             {
    15079                 $this->strip_attributes = explode(',', $attribs);
    15080             }
    15081         }
    15082         else
    15083         {
    15084             $this->strip_attributes = false;
    15085         }
    15086     }
    15087 
    15088     function strip_comments($strip = false)
    15089     {
    15090         $this->strip_comments = (bool) $strip;
    15091     }
    15092 
    15093     function set_output_encoding($encoding = 'UTF-8')
    15094     {
    15095         $this->output_encoding = (string) $encoding;
    15096     }
    15097 
    15098     /**
    15099      * Set element/attribute key/value pairs of HTML attributes
    15100      * containing URLs that need to be resolved relative to the feed
    15101      *
    15102      * @access public
    15103      * @since 1.0
    15104      * @param array $element_attribute Element/attribute key/value pairs
    15105      */
    15106     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'))
    15107     {
    15108         $this->replace_url_attributes = (array) $element_attribute;
    15109     }
    15110 
    15111     function sanitize($data, $type, $base = '')
    15112     {
    15113         $data = trim($data);
    15114         if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
    15115         {
    15116             if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
    15117             {
    15118                 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))
    15119                 {
    15120                     $type |= SIMPLEPIE_CONSTRUCT_HTML;
    15121                 }
    15122                 else
    15123                 {
    15124                     $type |= SIMPLEPIE_CONSTRUCT_TEXT;
    15125                 }
    15126             }
    15127 
    15128             if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
    15129             {
    15130                 $data = base64_decode($data);
    15131             }
    15132 
    15133             if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
    15134             {
    15135                 if ($this->remove_div)
    15136                 {
    15137                     $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
    15138                     $data = preg_replace('/<\/div>$/', '', $data);
    15139                 }
    15140                 else
    15141                 {
    15142                     $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
    15143                 }
    15144             }
    15145 
    15146             if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
    15147             {
    15148                 // Strip comments
    15149                 if ($this->strip_comments)
    15150                 {
    15151                     $data = SimplePie_Misc::strip_comments($data);
    15152                 }
    15153 
    15154                 // Strip out HTML tags and attributes that might cause various security problems.
    15155                 // Based on recommendations by Mark Pilgrim at:
    15156                 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
    15157                 if ($this->strip_htmltags)
    15158                 {
    15159                     foreach ($this->strip_htmltags as $tag)
    15160                     {
    15161                         $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
    15162                         while (preg_match($pcre, $data))
    15163                         {
    15164                             $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
    15165                         }
    15166                     }
    15167                 }
    15168 
    15169                 if ($this->strip_attributes)
    15170                 {
    15171                     foreach ($this->strip_attributes as $attrib)
    15172                     {
    15173                         $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);
    15174                     }
    15175                 }
    15176 
    15177                 // Replace relative URLs
    15178                 $this->base = $base;
    15179                 foreach ($this->replace_url_attributes as $element => $attributes)
    15180                 {
    15181                     $data = $this->replace_urls($data, $element, $attributes);
    15182                 }
    15183 
    15184                 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
    15185                 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
    15186                 {
    15187                     $images = SimplePie_Misc::get_element('img', $data);
    15188                     foreach ($images as $img)
    15189                     {
    15190                         if (isset($img['attribs']['src']['data']))
    15191                         {
    15192                             $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
    15193                             $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
    15194 
    15195                             if ($cache->load())
    15196                             {
    15197                                 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
    15198                                 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
    15199                             }
    15200                             else
    15201                             {
    15202                                 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
    15203                                 $headers = $file->headers;
    15204 
    15205                                 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
    15206                                 {
    15207                                     if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
    15208                                     {
    15209                                         $img['attribs']['src']['data'] = $this->image_handler . $image_url;
    15210                                         $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
    15211                                     }
    15212                                     else
    15213                                     {
    15214                                         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);
    15215                                     }
    15216                                 }
    15217                             }
    15218                         }
    15219                     }
    15220                 }
    15221 
    15222                 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
    15223                 $data = trim($data);
    15224             }
    15225 
    15226             if ($type & SIMPLEPIE_CONSTRUCT_IRI)
    15227             {
    15228                 $data = SimplePie_Misc::absolutize_url($data, $base);
    15229             }
    15230 
    15231             if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
    15232             {
    15233                 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
    15234             }
    15235 
    15236             if ($this->output_encoding !== 'UTF-8')
    15237             {
    15238                 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
    15239             }
    15240         }
    15241         return $data;
    15242     }
    15243 
    15244     function replace_urls($data, $tag, $attributes)
    15245     {
    15246         if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
    15247         {
    15248             $elements = SimplePie_Misc::get_element($tag, $data);
    15249             foreach ($elements as $element)
    15250             {
    15251                 if (is_array($attributes))
    15252                 {
    15253                     foreach ($attributes as $attribute)
    15254                     {
    15255                         if (isset($element['attribs'][$attribute]['data']))
    15256                         {
    15257                             $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
    15258                             $new_element = SimplePie_Misc::element_implode($element);
    15259                             $data = str_replace($element['full'], $new_element, $data);
    15260                             $element['full'] = $new_element;
    15261                         }
    15262                     }
    15263                 }
    15264                 elseif (isset($element['attribs'][$attributes]['data']))
    15265                 {
    15266                     $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
    15267                     $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
    15268                 }
    15269             }
    15270         }
    15271         return $data;
    15272     }
    15273 
    15274     function do_strip_htmltags($match)
    15275     {
    15276         if ($this->encode_instead_of_strip)
    15277         {
    15278             if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
    15279             {
    15280                 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
    15281                 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
    15282                 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
    15283             }
    15284             else
    15285             {
    15286                 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
    15287             }
    15288         }
    15289         elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
    15290         {
    15291             return $match[4];
    15292         }
    15293         else
    15294         {
    15295             return '';
    15296         }
    15297     }
    15298 }
    152993038endif;
    15300 ?>
Note: See TracChangeset for help on using the changeset viewer.