Source for file simplepie.inc
Documentation is available at simplepie.inc
* A PHP-Based RSS and Atom Feed Framework.
* Takes the hard work out of managing a complete RSS/Atom solution.
* Copyright (c) 2004-2007, Ryan Parman and Geoffrey Sneddon
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* * Neither the name of the SimplePie Team nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
* AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
* @author Geoffrey Sneddon
* @link http://simplepie.org/ SimplePie
* @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
define('SIMPLEPIE_NAME', 'SimplePie');
define('SIMPLEPIE_VERSION', '1.1');
define('SIMPLEPIE_BUILD', 20080102221556);
define('SIMPLEPIE_URL', 'http://simplepie.org');
* @see SimplePie::set_useragent()
define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_NONE', 0);
* Feed Link Element Autodiscovery
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
* Local Feed Extension Autodiscovery
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
* Local Feed Body Autodiscovery
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
* Remote Feed Extension Autodiscovery
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
* Remote Feed Body Autodiscovery
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
* @see SimplePie::set_autodiscovery_level()
define('SIMPLEPIE_LOCATOR_ALL', 31);
define('SIMPLEPIE_TYPE_NONE', 0);
define('SIMPLEPIE_TYPE_RSS_090', 1);
define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
* RSS 0.91 (both Netscape and Userland)
define('SIMPLEPIE_TYPE_RSS_091', 6);
define('SIMPLEPIE_TYPE_RSS_092', 8);
define('SIMPLEPIE_TYPE_RSS_093', 16);
define('SIMPLEPIE_TYPE_RSS_094', 32);
define('SIMPLEPIE_TYPE_RSS_10', 64);
define('SIMPLEPIE_TYPE_RSS_20', 128);
define('SIMPLEPIE_TYPE_RSS_RDF', 65);
* Non-RDF-based RSS (truly intended as syndication format)
define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
define('SIMPLEPIE_TYPE_RSS_ALL', 255);
define('SIMPLEPIE_TYPE_ATOM_03', 256);
define('SIMPLEPIE_TYPE_ATOM_10', 512);
define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
define('SIMPLEPIE_TYPE_ALL', 1023);
define('SIMPLEPIE_CONSTRUCT_NONE', 0);
define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
define('SIMPLEPIE_CONSTRUCT_HTML', 2);
define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
* base64-encoded construct
define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
define('SIMPLEPIE_CONSTRUCT_IRI', 16);
* A construct that might be HTML
define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
define('SIMPLEPIE_CONSTRUCT_ALL', 63);
* PCRE for HTML attributes
define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
* PCRE for XML attributes
define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
* RSS 1.0 Content Module Namespace
define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
* W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
* IANA Link Relations Registry
define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
* Whether we're running on PHP5
define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
* fsockopen() file source
define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
* file_get_contents() file source
define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
* @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
* @author Geoffrey Sneddon
* @todo Option for type of fetching (cache, not modified header, fetch, etc.)
* @var mixed Error string
* @var object Instance of SimplePie_Sanitize (or other class)
* @see SimplePie::set_sanitize_class()
* @var string SimplePie Useragent
* @see SimplePie::set_useragent()
var $useragent = SIMPLEPIE_USERAGENT;
* @see SimplePie::set_feed_url()
* @var object Instance of SimplePie_File to use as a feed
* @see SimplePie::set_file()
* @var string Raw feed data
* @see SimplePie::set_raw_data()
* @var int Timeout for fetching remote files
* @see SimplePie::set_timeout()
* @var bool Forces fsockopen() to be used for remote files instead
* of cURL, even if a new enough version is installed
* @see SimplePie::force_fsockopen()
var $force_fsockopen = false;
* @var bool Force the given data/URL to be treated as a feed no matter what
* @see SimplePie::force_feed()
* @var bool Enable/Disable XML dump
* @see SimplePie::enable_xml_dump()
* @var bool Enable/Disable Caching
* @see SimplePie::enable_cache()
* @var int Cache duration (in seconds)
* @see SimplePie::set_cache_duration()
var $cache_duration = 3600;
* @var int Auto-discovery cache duration (in seconds)
* @see SimplePie::set_autodiscovery_cache_duration()
var $autodiscovery_cache_duration = 604800; // 7 Days.
* @var string Cache location (relative to executing script)
* @see SimplePie::set_cache_location()
var $cache_location = './cache';
* @var string Function that creates the cache filename
* @see SimplePie::set_cache_name_function()
var $cache_name_function = 'md5';
* @var bool Reorder feed by date descending
* @see SimplePie::enable_order_by_date()
var $order_by_date = true;
* @var mixed Force input encoding to be set to the follow value
* (false, or anything type-cast to false, disables this feature)
* @see SimplePie::set_input_encoding()
var $input_encoding = false;
* @var int Feed Autodiscovery Level
* @see SimplePie::set_autodiscovery_level()
var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
* @var string Class used for caching feeds
* @see SimplePie::set_cache_class()
var $cache_class = 'SimplePie_Cache';
* @var string Class used for locating feeds
* @see SimplePie::set_locator_class()
var $locator_class = 'SimplePie_Locator';
* @var string Class used for parsing feeds
* @see SimplePie::set_parser_class()
var $parser_class = 'SimplePie_Parser';
* @var string Class used for fetching feeds
* @see SimplePie::set_file_class()
var $file_class = 'SimplePie_File';
* @var string Class used for items
* @see SimplePie::set_item_class()
var $item_class = 'SimplePie_Item';
* @var string Class used for authors
* @see SimplePie::set_author_class()
var $author_class = 'SimplePie_Author';
* @var string Class used for categories
* @see SimplePie::set_category_class()
var $category_class = 'SimplePie_Category';
* @var string Class used for enclosures
* @see SimplePie::set_enclosures_class()
var $enclosure_class = 'SimplePie_Enclosure';
* @var string Class used for Media RSS <media:text> captions
* @see SimplePie::set_caption_class()
var $caption_class = 'SimplePie_Caption';
* @var string Class used for Media RSS <media:copyright>
* @see SimplePie::set_copyright_class()
var $copyright_class = 'SimplePie_Copyright';
* @var string Class used for Media RSS <media:credit>
* @see SimplePie::set_credit_class()
var $credit_class = 'SimplePie_Credit';
* @var string Class used for Media RSS <media:rating>
* @see SimplePie::set_rating_class()
var $rating_class = 'SimplePie_Rating';
* @var string Class used for Media RSS <media:restriction>
* @see SimplePie::set_restriction_class()
var $restriction_class = 'SimplePie_Restriction';
* @var string Class used for content-type sniffing
* @see SimplePie::set_content_type_sniffer_class()
var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
* @var string Class used for item sources.
* @see SimplePie::set_source_class()
var $source_class = 'SimplePie_Source';
* @var mixed Set javascript query string parameter (false, or
* anything type-cast to false, disables this feature)
* @see SimplePie::set_javascript()
* @var int Maximum number of feeds to check with autodiscovery
* @see SimplePie::set_max_checked_feeds()
var $max_checked_feeds = 10;
* @var string Web-accessible path to the handler_favicon.php file.
* @see SimplePie::set_favicon_handler()
var $favicon_handler = '';
* @var string Web-accessible path to the handler_image.php file.
* @see SimplePie::set_image_handler()
* @var array Stores the URLs when multiple feeds are being initialized.
* @see SimplePie::set_feed_url()
var $multifeed_url = array();
* @var array Stores SimplePie objects when multiple feeds initialized.
var $multifeed_objects = array();
* @var array Stores the get_object_vars() array for use with multifeeds.
* @see SimplePie::set_feed_url()
var $config_settings = null;
* @var integer Stores the number of items to return per-feed with multifeeds.
* @see SimplePie::set_item_limit()
* @var array Stores the default attributes to be stripped by strip_attributes().
* @see SimplePie::strip_attributes()
var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
* @var array Stores the default tags to be stripped by strip_htmltags().
* @see SimplePie::strip_htmltags()
var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
* The SimplePie class contains feed level data and options
* There are two ways that you can create a new SimplePie object. The first
* is by passing a feed URL as a parameter to the SimplePie constructor
* (as well as optionally setting the cache location and cache expiry). This
* will initialise the whole feed with all of the default settings, and you
* can begin accessing methods and properties immediately.
* The second way is to create the SimplePie object with no parameters
* at all. This will enable you to set configuration options. After setting
* them, you must initialise the feed using $feed->init(). At that point the
* object's methods and properties will be available to you. This format is
* what is used throughout this documentation.
* @since 1.0 Preview Release
* @param string $feed_url This is the URL you want to parse.
* @param string $cache_location This is where you want the cache to be stored.
* @param int $cache_duration This is the number of seconds that you want to store the cache file for.
function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
// Other objects, instances created here so we can set options on them
// Set options if they're passed to the constructor
if ($cache_location !== null)
if ($cache_duration !== null)
// Only init the script if we're passed a feed URL
* Used for converting object to a string
* Remove items that link back to this before destroying this object
if (!empty($this->data['items']))
foreach ($this->data['items'] as $item)
unset ($this->data['items']);
if (!empty($this->data['ordered_items']))
foreach ($this->data['ordered_items'] as $item)
unset ($this->data['ordered_items']);
* Force the given data/URL to be treated as a feed no matter what it
* @param bool $enable Force the given data/URL to be treated as a feed
$this->force_feed = (bool) $enable;
* This is the URL of the feed you want to parse.
* This allows you to enter the URL of the feed you want to parse, or the
* website you want to try to use auto-discovery on. This takes priority
* You can set multiple feeds to mash together by passing an array instead
* of a string for the $url. Remember that with each additional feed comes
* additional processing and resources.
* @since 1.0 Preview Release
* @param mixed $url This is the URL (or array of URLs) that you want to parse.
* @see SimplePie::set_raw_data()
$this->multifeed_url = array();
* Provides an instance of SimplePie_File to use as a feed
* @param object &$file Instance of SimplePie_File (or subclass)
* @return bool True on success, false on failure
if (is_a($file, 'SimplePie_File'))
$this->feed_url = $file->url;
* Allows you to use a string of RSS/Atom data instead of a remote feed.
* If you have a feed available as a string in PHP, you can tell SimplePie
* to parse that data string instead of a remote feed. Any set feed URL
* @param string $data RSS or Atom data as a string.
* @see SimplePie::set_feed_url()
$this->raw_data = trim($data);
* Allows you to override the default timeout for fetching remote feeds.
* This allows you to change the maximum time the feed's server to respond
* and send the feed back.
* @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
$this->timeout = (int) $timeout;
* Forces SimplePie to use fsockopen() instead of the preferred cURL
* @param bool $enable Force fsockopen() to be used
$this->force_fsockopen = (bool) $enable;
* Outputs the raw XML content of the feed, after it has gone through
* Used only for debugging, this function will output the XML content as
* text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
* before trying to parse it. Many parts of the feed are re-written in
* memory, and in the end, you have a parsable feed. XML dump shows you the
* actual XML that SimplePie tries to parse, which may or may not be very
* different from the original feed.
* @since 1.0 Preview Release
* @param bool $enable Enable XML dump
$this->xml_dump = (bool) $enable;
* Enables/disables caching in SimplePie.
* This option allows you to disable caching all-together in SimplePie.
* However, disabling the cache can lead to longer load times.
* @since 1.0 Preview Release
* @param bool $enable Enable caching
$this->cache = (bool) $enable;
* Set the length of time (in seconds) that the contents of a feed
* @param int $seconds The feed content cache duration.
$this->cache_duration = (int) $seconds;
* Set the length of time (in seconds) that the autodiscovered feed
* @param int $seconds The autodiscovered feed URL cache duration.
$this->autodiscovery_cache_duration = (int) $seconds;
* Set the file system location where the cached files should be stored.
* @param string $location The file system location.
$this->cache_location = (string) $location;
* Determines whether feed items should be sorted into reverse chronological order.
* @param bool $enable Sort as reverse chronological order.
$this->order_by_date = (bool) $enable;
* Allows you to override the character encoding reported by the feed.
* @param string $encoding Character encoding.
$this->input_encoding = (string) $encoding;
$this->input_encoding = false;
* Set how much feed autodiscovery to do
* @see SIMPLEPIE_LOCATOR_NONE
* @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
* @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
* @see SIMPLEPIE_LOCATOR_LOCAL_BODY
* @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
* @see SIMPLEPIE_LOCATOR_REMOTE_BODY
* @see SIMPLEPIE_LOCATOR_ALL
* @param int $level Feed Autodiscovery Level (level can be a
* combination of the above constants, see bitwise OR operator)
$this->autodiscovery = (int) $level;
* Allows you to change which class SimplePie uses for caching.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->cache_class = $class;
* Allows you to change which class SimplePie uses for auto-discovery.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->locator_class = $class;
* Allows you to change which class SimplePie uses for XML parsing.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->parser_class = $class;
* Allows you to change which class SimplePie uses for remote file fetching.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->file_class = $class;
* Allows you to change which class SimplePie uses for data sanitization.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->sanitize = & new $class;
* Allows you to change which class SimplePie uses for handling feed items.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->item_class = $class;
* Allows you to change which class SimplePie uses for handling author data.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->author_class = $class;
* Allows you to change which class SimplePie uses for handling category data.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->category_class = $class;
* Allows you to change which class SimplePie uses for feed enclosures.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->enclosure_class = $class;
* Allows you to change which class SimplePie uses for <media:text> captions
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->caption_class = $class;
* Allows you to change which class SimplePie uses for <media:copyright>
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->copyright_class = $class;
* Allows you to change which class SimplePie uses for <media:credit>
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->credit_class = $class;
* Allows you to change which class SimplePie uses for <media:rating>
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->rating_class = $class;
* Allows you to change which class SimplePie uses for <media:restriction>
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->restriction_class = $class;
* Allows you to change which class SimplePie uses for content-type sniffing.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->content_type_sniffer_class = $class;
* Allows you to change which class SimplePie uses item sources.
* Useful when you are overloading or extending SimplePie's default classes.
* @param string $class Name of custom class.
* @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
* @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
$this->source_class = $class;
* Allows you to override the default user agent string.
* @param string $ua New user agent string.
$this->useragent = (string) $ua;
* Set callback function to create cache filename with
* @param mixed $function Callback function
$this->cache_name_function = $function;
* Set javascript query string parameter
* @param mixed $get Javascript query string parameter
$this->javascript = (string) $get;
$this->javascript = false;
* Set options to make SP as fast as possible. Forgoes a
* substantial amount of data sanitization in favor of speed.
* @param bool $set Whether to set them or not
* Set maximum number of feeds to check with autodiscovery
* @param int $max Maximum number of feeds to check
$this->max_checked_feeds = (int) $max;
$this->sanitize->remove_div($enable);
$tags = $this->strip_htmltags;
$this->sanitize->strip_htmltags($tags);
$this->sanitize->encode_instead_of_strip($tags);
$this->sanitize->encode_instead_of_strip($enable);
$attribs = $this->strip_attributes;
$this->sanitize->strip_attributes($attribs);
$this->sanitize->set_output_encoding($encoding);
$this->sanitize->strip_comments($strip);
* Set element/attribute key/value pairs of HTML attributes
* containing URLs that need to be resolved relative to the feed
* @param array $element_attribute Element/attribute key/value pairs
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'))
$this->sanitize->set_url_replacements($element_attribute);
* Set the handler to enable the display of cached favicons.
* @param str $page Web-accessible path to the handler_favicon.php file.
* @param str $qs The query string that the value should be passed to.
$this->favicon_handler = $page . '?' . $qs . '=';
$this->favicon_handler = '';
* Set the handler to enable the display of cached images.
* @param str $page Web-accessible path to the handler_image.php file.
* @param str $qs The query string that the value should be passed to.
$this->sanitize->set_image_handler($page . '?' . $qs . '=');
$this->image_handler = '';
* Set the limit for items returned per-feed with multifeeds.
* @param integer $limit The maximum number of items to return.
$this->item_limit = (int) $limit;
if (isset ($_GET[$this->javascript]))
header('Content-type: text/javascript; charset: UTF-8');
header('Cache-Control: must-revalidate');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
function embed_odeo(link) {
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>');
function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
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>');
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>');
function embed_flash(bgcolor, width, height, link, loop, type) {
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>');
function embed_flv(width, height, link, placeholder, loop, player) {
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>');
function embed_wmedia(width, height, link) {
document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
// Pass whatever was set with config options over to the sanitizer.
$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
$this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
if ($this->feed_url !== null || $this->raw_data !== null)
$this->multifeed_objects = array();
if ($this->feed_url !== null)
// Decide whether to enable caching
if ($this->cache && $parsed_feed_url['scheme'] !== '')
$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
// If it's enabled and we don't want an XML dump, use the cache
if ($cache && !$this->xml_dump)
$this->data = $cache->load();
// If the cache is for an outdated build of SimplePie
if (!isset ($this->data['build']) || $this->data['build'] != SIMPLEPIE_BUILD)
// If we've hit a collision just rerun it with caching disabled
elseif (isset ($this->data['url']) && $this->data['url'] != $this->feed_url)
// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
elseif (isset ($this->data['feed_url']))
// If the autodiscovery cache is still valid use it.
if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
// Do not need to do feed autodiscovery yet.
if ($this->data['feed_url'] == $this->data['url'])
// Check if the cache has been updated
elseif ($cache->mtime() + $this->cache_duration < time())
// If we have last-modified and/or etag set
if (isset ($this->data['headers']['last-modified']) || isset ($this->data['headers']['etag']))
if (isset ($this->data['headers']['last-modified']))
$headers['if-modified-since'] = $this->data['headers']['last-modified'];
if (isset ($this->data['headers']['etag']))
$headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
$file = & new $this->file_class($this->feed_url, $this->timeout/ 10, 5, $headers, $this->useragent, $this->force_fsockopen);
if ($file->status_code == 304)
$headers = $file->headers;
// If the cache is still valid, just return true
// If the cache is empty, delete it
// 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.
if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->feed_url)
$file = & new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
// If the file connection has an error, set SimplePie::error to that and quit
$this->error = $file->error;
// Check if the supplied URL is a feed, if it isn't, look for it.
$locate = & new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
if (!$locate->is_feed($file))
// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
if ($file = $locate->find($this->autodiscovery))
$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
if (!$cache->save($this))
$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
$this->feed_url = $file->url;
$this->error = "A feed could not be found at $this->feed_url";
$headers = $file->headers;
$sniffer = new $this->content_type_sniffer_class($file);
$sniffed = $sniffer->get_type();
// Set up array of possible encodings
// First check to see if input has been overridden.
if ($this->input_encoding !== false)
$encodings[] = $this->input_encoding;
$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
$text_types = array('text/xml', 'text/xml-external-parsed-entity');
// RFC 3023 (only applies to sniffed content)
if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, - 4) === '+xml')
if (isset ($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, - 4) === '+xml')
if (isset ($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
$encodings[] = $charset[1];
$encodings[] = 'US-ASCII';
// Text MIME-type default
elseif (substr($sniffed, 0, 5) === 'text/')
$encodings[] = 'US-ASCII';
// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
$encodings[] = 'ISO-8859-1';
// There's no point in trying an encoding twice
// If we want the XML, just output that with the most likely encoding and quit
header('Content-type: text/xml; charset=' . $encodings[0]);
// Loop through each possible encoding, till we return something, or run out of possibilities
foreach ($encodings as $encoding)
// Change the encoding to UTF-8 (as we always use UTF-8 internally)
$parser = & new $this->parser_class();
if ($parser->parse($utf8_data, 'UTF-8'))
$this->data = $parser->get_data();
if (isset ($this->data['child']))
$this->data['headers'] = $headers;
// Cache the file if caching is enabled
if ($cache && !$cache->save($this))
$this->error = "A feed could not be found at $this->feed_url";
// We have an error, just set SimplePie::error to it and quit
$this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
elseif (!empty($this->multifeed_url))
$this->multifeed_objects = array();
foreach ($this->multifeed_url as $url)
// This keyword needs to defy coding standards for PHP4 compatibility
$this->multifeed_objects[$i] = clone($this);
$this->multifeed_objects[$i] = $this;
$this->multifeed_objects[$i]->set_feed_url($url);
$success |= $this->multifeed_objects[$i]->init();
* Return the error message for the occured error
* @return string Error message
return $this->sanitize->output_encoding;
$header = "Content-type: $mime;";
$header .= ' charset=UTF-8';
if (!isset ($this->data['type']))
elseif (isset ($this->data['child']['']['rss']))
if (isset ($this->data['child']['']['rss'][0]['attribs']['']['version']))
switch (trim($this->data['child']['']['rss'][0]['attribs']['']['version']))
if (isset ($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
switch (trim($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
return $this->data['type'];
* Returns the URL for the favicon of the feed's website.
if ($this->cache && $this->favicon_handler)
$favicon_filename = call_user_func($this->cache_name_function, $favicon);
$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
$file = & new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
$sniffer = new $this->content_type_sniffer_class($file);
if (substr($sniffer->get_type(), 0, 6) === 'image/')
if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
* @todo If we have a perm redirect we should return the new URL
* @todo When we make the above change, let's support <itunes:new-feed-url> as well
* @todo Also, |atom:link|@rel=self
if ($this->feed_url !== null)
if ($this->feed_url !== null)
if ($this->feed_url !== null)
if ($this->feed_url !== null)
if ($this->feed_url !== null)
* Creates the subscribe_* methods' return data
* @param string $feed_url String to prefix to the feed URL
* @param string $site_url String to prefix to the site URL (and
* suffix to the feed URL)
* @return mixed URL if feed exists, false otherwise
function subscribe_service($feed_url, $site_url = null)
if ($site_url !== null && $this->get_link() !== null)
return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
return urldecode($this->subscribe_service('http://www.bloglines.com/sub/'));
return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
if (isset ($this->data['child']['']['rss'][0]['child'][$namespace][$tag]))
return $this->data['child']['']['rss'][0]['child'][$namespace][$tag];
if (isset ($channel[0]['child'][$namespace][$tag]))
return $channel[0]['child'][$namespace][$tag];
if (isset ($channel[0]['child'][$namespace][$tag]))
return $channel[0]['child'][$namespace][$tag];
if (isset ($channel[0]['child'][$namespace][$tag]))
return $channel[0]['child'][$namespace][$tag];
if (isset ($image[0]['child'][$namespace][$tag]))
return $image[0]['child'][$namespace][$tag];
if (isset ($image[0]['child'][$namespace][$tag]))
return $image[0]['child'][$namespace][$tag];
if (isset ($image[0]['child'][$namespace][$tag]))
return $image[0]['child'][$namespace][$tag];
return $element['xml_base'];
function sanitize($data, $type, $base = '')
return $this->sanitize->sanitize($data, $type, $base);
if (isset ($categories[$key]))
return $categories[$key];
if (isset ($category['attribs']['']['term']))
if (isset ($category['attribs']['']['scheme']))
if (isset ($category['attribs']['']['label']))
$categories[] = & new $this->category_class($term, $scheme, $label);
if (isset ($authors[$key]))
if ($name !== null || $email !== null || $uri !== null)
$authors[] = & new $this->author_class($name, $uri, $email);
if ($name !== null || $email !== null || $url !== null)
$authors[] = & new $this->author_class($name, $url, $email);
if (isset ($contributors[$key]))
return $contributors[$key];
if ($name !== null || $email !== null || $uri !== null)
$contributors[] = & new $this->author_class($name, $uri, $email);
if ($name !== null || $email !== null || $url !== null)
$contributors[] = & new $this->author_class($name, $url, $email);
if (!empty($contributors))
function get_link($key = 0, $rel = 'alternate')
* Added for parity between the parent-level and the item/entry-level.
if (!isset ($this->data['links']))
$this->data['links'] = array();
foreach ($links as $link)
if (isset ($link['attribs']['']['href']))
$link_rel = (isset ($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
foreach ($links as $link)
if (isset ($link['attribs']['']['href']))
$link_rel = (isset ($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
$this->data['links'][substr($key, 41)] = & $this->data['links'][$key];
$this->data['links'][$key] = array_unique($this->data['links'][$key]);
if (isset ($this->data['links'][$rel]))
return $this->data['links'][$rel];
elseif (isset ($this->data['headers']['content-language']))
return (float) $return[0]['data'];
return (float) $match[1];
return (float) $return[0]['data'];
return (float) $return[0]['data'];
return (float) $match[2];
return round($return[0]['data']);
return round($return[0]['data']);
return ($qty > $max) ? $max : $qty;
if (!empty($this->multifeed_objects))
elseif (!isset ($this->data['items']))
$this->data['items'][] = & new $this->item_class($this, $items[$key]);
$this->data['items'][] = & new $this->item_class($this, $items[$key]);
$this->data['items'][] = & new $this->item_class($this, $items[$key]);
$this->data['items'][] = & new $this->item_class($this, $items[$key]);
$this->data['items'][] = & new $this->item_class($this, $items[$key]);
if (!empty($this->data['items']))
// If we want to order it by date, check if all items have a date, and then sort it
if ($this->order_by_date)
if (!isset ($this->data['ordered_items']))
foreach ($this->data['items'] as $item)
if (!$item->get_date('U'))
$this->data['ordered_items'] = $this->data['items'];
usort($this->data['ordered_items'], array(&$this, 'sort_items'));
$items = $this->data['ordered_items'];
$items = $this->data['items'];
// Slice the data as desired
return $a->get_date('U') <= $b->get_date('U');
function merge_items($urls, $start = 0, $end = 0, $limit = 0)
if (is_a($arg, 'SimplePie'))
$items = array_merge($items, $arg->get_items(0, $limit));
trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
foreach ($items as $item)
if (!$item->get_date('U'))
usort($items, array('SimplePie', 'sort_items'));
trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
* Remove items that link back to this before destroying this object
if (isset ($this->data['child'][$namespace][$tag]))
return $this->data['child'][$namespace][$tag];
return $this->feed->get_base($element);
function sanitize($data, $type, $base = '')
return $this->feed->sanitize($data, $type, $base);
function get_id($hash = false)
elseif (($return = $this->get_title()) !== null)
if (!isset ($this->data['title']))
$this->data['title'] = null;
return $this->data['title'];
elseif (!$description_only)
if (isset ($categories[$key]))
return $categories[$key];
if (isset ($category['attribs']['']['term']))
if (isset ($category['attribs']['']['scheme']))
if (isset ($category['attribs']['']['label']))
$categories[] = & new $this->feed->category_class($term, $scheme, $label);
foreach ((array) $this->get_item_tags('', 'category') as $category)
if (isset ($authors[$key]))
if (isset ($contributors[$key]))
return $contributors[$key];
if ($name !== null || $email !== null || $uri !== null)
$contributors[] = & new $this->feed->author_class($name, $uri, $email);
if ($name !== null || $email !== null || $url !== null)
$contributors[] = & new $this->feed->author_class($name, $url, $email);
if (!empty($contributors))
* @todo Atom inheritance (item author, source author, feed author)
if ($name !== null || $email !== null || $uri !== null)
$authors[] = & new $this->feed->author_class($name, $uri, $email);
if ($name !== null || $email !== null || $url !== null)
$authors[] = & new $this->feed->author_class($name, $url, $email);
elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
elseif ($authors = $this->feed->get_authors())
function get_date($date_format = 'j F Y, g:i a')
if (!isset ($this->data['date']))
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
$this->data['date']['raw'] = $return[0]['data'];
if (!empty($this->data['date']['raw']))
$this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
$this->data['date'] = null;
$date_format = (string) $date_format;
return $this->data['date']['parsed'];
return date($date_format, $this->data['date']['parsed']);
elseif (($date = $this->get_date('U')) !== null)
elseif ($enclosure !== null)
return $enclosure->get_link();
function get_link($key = 0, $rel = 'alternate')
if ($links[$key] !== null)
if (!isset ($this->data['links']))
$this->data['links'] = array();
if (isset ($link['attribs']['']['href']))
$link_rel = (isset ($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
if (isset ($link['attribs']['']['href']))
$link_rel = (isset ($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
if (!isset ($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) == 'true')
if (isset ($this->data['links'][$rel]))
return $this->data['links'][$rel];
* @todo Add ability to prefer one type of content over another (in a media group).
if (isset ($enclosures[$key]))
return $enclosures[$key];
* Grabs all available enclosures (podcasts, etc.)
* Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
* 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.
* @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
* @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).
if (!isset ($this->data['enclosures']))
$this->data['enclosures'] = array();
$categories_parent = null;
$copyrights_parent = null;
$description_parent = null;
$restrictions_parent = null;
$thumbnails_parent = null;
// Let's do the channel and item-level ones first, and just re-use them if we need to.
foreach ($captions as $caption)
$caption_startTime = null;
if (isset ($caption['attribs']['']['type']))
if (isset ($caption['attribs']['']['lang']))
if (isset ($caption['attribs']['']['start']))
if (isset ($caption['attribs']['']['end']))
if (isset ($caption['data']))
$captions_parent[] = & new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
foreach ($captions as $caption)
$caption_startTime = null;
if (isset ($caption['attribs']['']['type']))
if (isset ($caption['attribs']['']['lang']))
if (isset ($caption['attribs']['']['start']))
if (isset ($caption['attribs']['']['end']))
if (isset ($caption['data']))
$captions_parent[] = & new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
if (isset ($category['data']))
if (isset ($category['attribs']['']['scheme']))
$scheme = 'http://search.yahoo.com/mrss/category_schema';
if (isset ($category['attribs']['']['label']))
$categories_parent[] = & new $this->feed->category_class($term, $scheme, $label);
if (isset ($category['data']))
if (isset ($category['attribs']['']['scheme']))
$scheme = 'http://search.yahoo.com/mrss/category_schema';
if (isset ($category['attribs']['']['label']))
$categories_parent[] = & new $this->feed->category_class($term, $scheme, $label);
$scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
if (isset ($category['attribs']['']['text']))
$categories_parent[] = & new $this->feed->category_class($term, $scheme, $label);
if (isset ($subcategory['attribs']['']['text']))
$categories_parent[] = & new $this->feed->category_class($term, $scheme, $label);
if (isset ($copyright[0]['attribs']['']['url']))
if (isset ($copyright[0]['data']))
$copyrights_parent = & new $this->feed->copyright_class($copyright_url, $copyright_label);
if (isset ($copyright[0]['attribs']['']['url']))
if (isset ($copyright[0]['data']))
$copyrights_parent = & new $this->feed->copyright_class($copyright_url, $copyright_label);
foreach ($credits as $credit)
if (isset ($credit['attribs']['']['role']))
if (isset ($credit['attribs']['']['scheme']))
$credit_scheme = 'urn:ebu';
if (isset ($credit['data']))
$credits_parent[] = & new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
foreach ($credits as $credit)
if (isset ($credit['attribs']['']['role']))
if (isset ($credit['attribs']['']['scheme']))
$credit_scheme = 'urn:ebu';
if (isset ($credit['data']))
$credits_parent[] = & new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
if (isset ($description_parent[0]['data']))
if (isset ($description_parent[0]['data']))
if (isset ($duration_parent[0]['data']))
$seconds += $minutes * 60;
$seconds += $hours * 3600;
$duration_parent = $seconds;
foreach ($hashes_iterator as $hash)
if (isset ($hash['data']))
if (isset ($hash['attribs']['']['algo']))
$hashes_parent[] = $algo. ':'. $value;
foreach ($hashes_iterator as $hash)
if (isset ($hash['data']))
if (isset ($hash['attribs']['']['algo']))
$hashes_parent[] = $algo. ':'. $value;
if (isset ($keywords[0]['data']))
$keywords_parent[] = trim($word);
if (isset ($keywords[0]['data']))
$keywords_parent[] = trim($word);
if (isset ($keywords[0]['data']))
$keywords_parent[] = trim($word);
if (isset ($keywords[0]['data']))
$keywords_parent[] = trim($word);
if (isset ($player_parent[0]['attribs']['']['url']))
if (isset ($player_parent[0]['attribs']['']['url']))
foreach ($ratings as $rating)
if (isset ($rating['attribs']['']['scheme']))
$rating_scheme = 'urn:simple';
if (isset ($rating['data']))
$ratings_parent[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
foreach ($ratings as $rating)
$rating_scheme = 'urn:itunes';
if (isset ($rating['data']))
$ratings_parent[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
foreach ($ratings as $rating)
if (isset ($rating['attribs']['']['scheme']))
$rating_scheme = 'urn:simple';
if (isset ($rating['data']))
$ratings_parent[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
foreach ($ratings as $rating)
$rating_scheme = 'urn:itunes';
if (isset ($rating['data']))
$ratings_parent[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
foreach ($restrictions as $restriction)
$restriction_relationship = null;
$restriction_type = null;
$restriction_value = null;
if (isset ($restriction['attribs']['']['relationship']))
if (isset ($restriction['attribs']['']['type']))
if (isset ($restriction['data']))
$restrictions_parent[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
foreach ($restrictions as $restriction)
$restriction_relationship = 'allow';
$restriction_type = null;
$restriction_value = 'itunes';
if (isset ($restriction['data']) && strtolower($restriction['data']) == 'yes')
$restriction_relationship = 'deny';
$restrictions_parent[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
foreach ($restrictions as $restriction)
$restriction_relationship = null;
$restriction_type = null;
$restriction_value = null;
if (isset ($restriction['attribs']['']['relationship']))
if (isset ($restriction['attribs']['']['type']))
if (isset ($restriction['data']))
$restrictions_parent[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
foreach ($restrictions as $restriction)
$restriction_relationship = 'allow';
$restriction_type = null;
$restriction_value = 'itunes';
if (isset ($restriction['data']) && strtolower($restriction['data']) == 'yes')
$restriction_relationship = 'deny';
$restrictions_parent[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
foreach ($thumbnails as $thumbnail)
if (isset ($thumbnail['attribs']['']['url']))
foreach ($thumbnails as $thumbnail)
if (isset ($thumbnail['attribs']['']['url']))
if (isset ($title_parent[0]['data']))
if (isset ($title_parent[0]['data']))
// If we have media:group tags, loop through them.
// If we have media:content tags, loop through them.
if (isset ($content['attribs']['']['url']))
// Start checking the attributes of media:content
if (isset ($content['attribs']['']['bitrate']))
if (isset ($content['attribs']['']['channels']))
if (isset ($content['attribs']['']['duration']))
$duration = $duration_parent;
if (isset ($content['attribs']['']['expression']))
if (isset ($content['attribs']['']['framerate']))
if (isset ($content['attribs']['']['height']))
if (isset ($content['attribs']['']['lang']))
if (isset ($content['attribs']['']['fileSize']))
$length = ceil($content['attribs']['']['fileSize']);
if (isset ($content['attribs']['']['medium']))
if (isset ($content['attribs']['']['samplingrate']))
if (isset ($content['attribs']['']['type']))
if (isset ($content['attribs']['']['width']))
// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
$caption_startTime = null;
if (isset ($caption['attribs']['']['type']))
if (isset ($caption['attribs']['']['lang']))
if (isset ($caption['attribs']['']['start']))
if (isset ($caption['attribs']['']['end']))
if (isset ($caption['data']))
$captions[] = & new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
$caption_startTime = null;
if (isset ($caption['attribs']['']['type']))
if (isset ($caption['attribs']['']['lang']))
if (isset ($caption['attribs']['']['start']))
if (isset ($caption['attribs']['']['end']))
if (isset ($caption['data']))
$captions[] = & new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
$captions = $captions_parent;
if (isset ($category['data']))
if (isset ($category['attribs']['']['scheme']))
$scheme = 'http://search.yahoo.com/mrss/category_schema';
if (isset ($category['attribs']['']['label']))
$categories[] = & new $this->feed->category_class($term, $scheme, $label);
if (isset ($category['data']))
if (isset ($category['attribs']['']['scheme']))
$scheme = 'http://search.yahoo.com/mrss/category_schema';
if (isset ($category['attribs']['']['label']))
$categories[] = & new $this->feed->category_class($term, $scheme, $label);
$copyrights = & new $this->feed->copyright_class($copyright_url, $copyright_label);
$copyrights = & new $this->feed->copyright_class($copyright_url, $copyright_label);
$copyrights = $copyrights_parent;
if (isset ($credit['attribs']['']['role']))
if (isset ($credit['attribs']['']['scheme']))
$credit_scheme = 'urn:ebu';
if (isset ($credit['data']))
$credits[] = & new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
if (isset ($credit['attribs']['']['role']))
if (isset ($credit['attribs']['']['scheme']))
$credit_scheme = 'urn:ebu';
if (isset ($credit['data']))
$credits[] = & new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
$credits = $credits_parent;
$description = $description_parent;
if (isset ($hash['data']))
if (isset ($hash['attribs']['']['algo']))
$hashes[] = $algo. ':'. $value;
if (isset ($hash['data']))
if (isset ($hash['attribs']['']['algo']))
$hashes[] = $algo. ':'. $value;
$hashes = $hashes_parent;
$keywords[] = trim($word);
$keywords[] = trim($word);
$keywords = $keywords_parent;
$player = $player_parent;
if (isset ($rating['attribs']['']['scheme']))
$rating_scheme = 'urn:simple';
if (isset ($rating['data']))
$ratings[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
if (isset ($rating['attribs']['']['scheme']))
$rating_scheme = 'urn:simple';
if (isset ($rating['data']))
$ratings[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
$ratings = $ratings_parent;
$restriction_relationship = null;
$restriction_type = null;
$restriction_value = null;
if (isset ($restriction['attribs']['']['relationship']))
if (isset ($restriction['attribs']['']['type']))
if (isset ($restriction['data']))
$restrictions[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
$restriction_relationship = null;
$restriction_type = null;
$restriction_value = null;
if (isset ($restriction['attribs']['']['relationship']))
if (isset ($restriction['attribs']['']['type']))
if (isset ($restriction['data']))
$restrictions[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
$restrictions = $restrictions_parent;
$thumbnails = $thumbnails_parent;
$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);
// If we have standalone media:content tags, loop through them.
if (isset ($content['attribs']['']['url']))
// Start checking the attributes of media:content
if (isset ($content['attribs']['']['bitrate']))
if (isset ($content['attribs']['']['channels']))
if (isset ($content['attribs']['']['duration']))
$duration = $duration_parent;
if (isset ($content['attribs']['']['expression']))
if (isset ($content['attribs']['']['framerate']))
if (isset ($content['attribs']['']['height']))
if (isset ($content['attribs']['']['lang']))
if (isset ($content['attribs']['']['fileSize']))
$length = ceil($content['attribs']['']['fileSize']);
if (isset ($content['attribs']['']['medium']))
if (isset ($content['attribs']['']['samplingrate']))
if (isset ($content['attribs']['']['type']))
if (isset ($content['attribs']['']['width']))
// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
$caption_startTime = null;
if (isset ($caption['attribs']['']['type']))
if (isset ($caption['attribs']['']['lang']))
if (isset ($caption['attribs']['']['start']))
if (isset ($caption['attribs']['']['end']))
if (isset ($caption['data']))
$captions[] = & new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
$captions = $captions_parent;
if (isset ($category['data']))
if (isset ($category['attribs']['']['scheme']))
$scheme = 'http://search.yahoo.com/mrss/category_schema';
if (isset ($category['attribs']['']['label']))
$categories[] = & new $this->feed->category_class($term, $scheme, $label);
$copyrights = & new $this->feed->copyright_class($copyright_url, $copyright_label);
$copyrights = $copyrights_parent;
if (isset ($credit['attribs']['']['role']))
if (isset ($credit['attribs']['']['scheme']))
$credit_scheme = 'urn:ebu';
if (isset ($credit['data']))
$credits[] = & new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
$credits = $credits_parent;
$description = $description_parent;
if (isset ($hash['data']))
if (isset ($hash['attribs']['']['algo']))
$hashes[] = $algo. ':'. $value;
$hashes = $hashes_parent;
$keywords[] = trim($word);
$keywords = $keywords_parent;
$player = $player_parent;
if (isset ($rating['attribs']['']['scheme']))
$rating_scheme = 'urn:simple';
if (isset ($rating['data']))
$ratings[] = & new $this->feed->rating_class($rating_scheme, $rating_value);
$ratings = $ratings_parent;
$restriction_relationship = null;
$restriction_type = null;
$restriction_value = null;
if (isset ($restriction['attribs']['']['relationship']))
if (isset ($restriction['attribs']['']['type']))
if (isset ($restriction['data']))
$restrictions[] = & new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
$restrictions = $restrictions_parent;
$thumbnails = $thumbnails_parent;
$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);
if (isset ($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
if (isset ($link['attribs']['']['type']))
if (isset ($link['attribs']['']['length']))
$length = ceil($link['attribs']['']['length']);
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
$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);
if (isset ($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] == 'enclosure')
if (isset ($link['attribs']['']['type']))
if (isset ($link['attribs']['']['length']))
$length = ceil($link['attribs']['']['length']);
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
$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);
if (isset ($enclosure[0]['attribs']['']['url']))
if (isset ($enclosure[0]['attribs']['']['type']))
if (isset ($enclosure[0]['attribs']['']['length']))
$length = ceil($enclosure[0]['attribs']['']['length']);
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
$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);
// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
$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);
if (!empty($this->data['enclosures']))
return $this->data['enclosures'];
return (float) $return[0]['data'];
return (float) $match[1];
return (float) $return[0]['data'];
return (float) $return[0]['data'];
return (float) $match[2];
return new $this->feed->source_class($this, $return[0]);
* Creates the add_to_* methods' return data
* @param string $item_url String to prefix to the item permalink
* @param string $title_url String to prefix to the item title
* (and suffix to the item permalink)
* @return mixed URL if feed exists, false otherwise
function add_to_service($item_url, $title_url = null)
if ($title_url !== null && $this->get_title() !== null)
return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
return $this->add_to_service('http://digg.com/submit?phase=2&URL=');
return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
return $this->add_to_service('http://www.technorati.com/search/');
* Remove items that link back to this before destroying this object
if (isset ($this->data['child'][$namespace][$tag]))
return $this->data['child'][$namespace][$tag];
return $this->item->get_base($element);
function sanitize($data, $type, $base = '')
return $this->item->sanitize($data, $type, $base);
if (isset ($categories[$key]))
return $categories[$key];
if (isset ($category['attribs']['']['term']))
if (isset ($category['attribs']['']['scheme']))
if (isset ($category['attribs']['']['label']))
$categories[] = & new $this->item->feed->category_class($term, $scheme, $label);
if (isset ($authors[$key]))
if ($name !== null || $email !== null || $uri !== null)
$authors[] = & new $this->item->feed->author_class($name, $uri, $email);
if ($name !== null || $email !== null || $url !== null)
$authors[] = & new $this->item->feed->author_class($name, $url, $email);
if (isset ($contributors[$key]))
return $contributors[$key];
if ($name !== null || $email !== null || $uri !== null)
$contributors[] = & new $this->item->feed->author_class($name, $uri, $email);
if ($name !== null || $email !== null || $url !== null)
$contributors[] = & new $this->item->feed->author_class($name, $url, $email);
if (!empty($contributors))
function get_link($key = 0, $rel = 'alternate')
* Added for parity between the parent-level and the item/entry-level.
if (!isset ($this->data['links']))
$this->data['links'] = array();
foreach ($links as $link)
if (isset ($link['attribs']['']['href']))
$link_rel = (isset ($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
foreach ($links as $link)
if (isset ($link['attribs']['']['href']))
$link_rel = (isset ($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
if (isset ($this->data['links'][$rel]))
return $this->data['links'][$rel];
elseif (isset ($this->data['xml_lang']))
return (float) $return[0]['data'];
return (float) $match[1];
return (float) $return[0]['data'];
return (float) $return[0]['data'];
return (float) $match[2];
// Constructor, used to input the data
// There is no $this->data here
if ($this->name !== null)
if ($this->link !== null)
if ($this->email !== null)
// Constructor, used to input the data
// There is no $this->data here
if ($this->term !== null)
if ($this->label !== null)
// Constructor, used to input the data
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)
// There is no $this->data here
if (isset ($captions[$key]))
if (isset ($categories[$key]))
return $categories[$key];
if (isset ($credits[$key]))
if ($this->link !== null)
return pathinfo($url['path'], PATHINFO_EXTENSION);
if (isset ($hashes[$key]))
if ($this->lang !== null)
if (isset ($keywords[$key]))
if ($this->link !== null)
if (isset ($ratings[$key]))
if (isset ($restrictions[$key]))
return $restrictions[$key];
return round($length/ 1048576, 2);
if (isset ($thumbnails[$key]))
return $thumbnails[$key];
if ($this->title !== null)
if ($this->type !== null)
if ($this->width !== null)
return $this->embed($options, true);
* @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
function embed($options = '', $native = false)
// Process options and reassign values as necessary
foreach($options as $option)
if (isset ($opt[0], $opt[1]))
// Process values for 'auto'
elseif ($mime == 'video')
elseif ($mime == 'audio')
// Set proper placeholder value
elseif ($mime == 'video')
// Make sure the JS library is included
static $javascript_outputted = null;
if (!$javascript_outputted && $this->javascript)
$embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
$javascript_outputted = true;
$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>';
$embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
elseif ($handler == 'flash')
$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>";
$embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
// Flash Media Player file types.
// Preferred handler for MP3 file types.
elseif ($handler == 'fmedia' || ($handler == 'mp3' && $mediaplayer != ''))
$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>";
$embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link(). '?file_extension=.'. $this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
// QuickTime 7 file types. Need to test with QuickTime 6.
// Only handle MP3's if the Flash Media Player is not present.
elseif ($handler == 'quicktime' || ($handler == 'mp3' && $mediaplayer == ''))
$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>";
$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>";
$embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
elseif ($handler == 'wmedia')
$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>";
$embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
// If it's Odeo, let's get it out of the way.
// Mime-types by handler.
$types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
$types_fmedia = array('video/flv', 'video/x-flv'); // Flash Media Player
$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
$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
$types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
// If we encounter an unsupported mime-type, check the file extension and guess intelligently.
if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
$type = 'audio/x-ms-wax';
$type = 'audio/x-ms-wma';
$type = 'video/x-ms-asf';
$type = 'video/quicktime';
$type = 'video/sd-video';
$type = 'video/x-ms-wmv';
$type = 'video/x-ms-wvx';
$type = 'application/futuresplash';
$type = 'application/x-shockwave-flash';
elseif (in_array($type, $types_quicktime))
// Constructor, used to input the data
function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
// There is no $this->data here
if ($this->lang !== null)
if ($this->text !== null)
if ($this->type !== null)
// Constructor, used to input the data
// There is no $this->data here
if ($this->role !== null)
if ($this->name !== null)
// Constructor, used to input the data
// There is no $this->data here
if ($this->label !== null)
// Constructor, used to input the data
// There is no $this->data here
if ($this->value !== null)
// Constructor, used to input the data
// There is no $this->data here
if ($this->type !== null)
if ($this->value !== null)
* @todo Move to properly supporting RFC2616 (HTTP/1.1)
var $method = SIMPLEPIE_FILE_SOURCE_NONE;
function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
$useragent = ini_get('user_agent');
foreach ($headers as $key => $value)
$headers2[] = "$key: $value";
curl_setopt($fp, CURLOPT_ENCODING, '');
curl_setopt($fp, CURLOPT_URL, $url);
curl_setopt($fp, CURLOPT_HEADER, 1);
curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($fp, CURLOPT_REFERER, $url);
curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
if (curl_errno($fp) == 23 || curl_errno($fp) == 61)
curl_setopt($fp, CURLOPT_ENCODING, 'none');
$this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
$info = curl_getinfo($fp);
$this->body = $parser->body;
return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
if (isset ($url_parts['scheme']) && strtolower($url_parts['scheme']) == 'https')
$url_parts['host'] = "ssl://$url_parts[host]";
$url_parts['port'] = 443;
if (!isset ($url_parts['port']))
$fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
$this->error = 'fsockopen error: ' . $errstr;
if (isset ($url_parts['path']))
if (isset ($url_parts['query']))
$get = "$url_parts[path]?$url_parts[query]";
$get = $url_parts['path'];
$out = "GET $get HTTP/1.0\r\n";
$out .= "Host: $url_parts[host]\r\n";
$out .= "User-Agent: $useragent\r\n";
$out .= "Accept-Encoding: gzip,deflate\r\n";
if (isset ($url_parts['user']) && isset ($url_parts['pass']))
$out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
foreach ($headers as $key => $value)
$out .= "$key: $value\r\n";
$out .= "Connection: Close\r\n\r\n";
while (!$info['eof'] && !$info['timed_out'])
$this->body = $parser->body;
return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
if (isset ($this->headers['content-encoding']) && ($this->headers['content-encoding'] == 'gzip' || $this->headers['content-encoding'] == 'deflate'))
if (substr($this->body, 0, 8) == "\x1f\x8b\x08\x00\x00\x00\x00\x00")
$this->error = 'fsocket timed out';
$this->error = 'file_get_contents could not read the file';
* Key/value pairs of the headers
* Current state of the state machine
var $state = 'http_version';
* Input data length (to avoid calling strlen() everytime this is needed)
* Current position of the pointer
* Name of the hedaer currently being parsed
* Value of the hedaer currently being parsed
* Create an instance of the class with the input data
* @param string $data Input data
$this->data_length = strlen($this->data);
* @return bool true on success, false on failure
while ($this->state && $this->state !== 'emit' && $this->has_data())
if ($this->state === 'emit')
* Check whether there is data beyond the pointer
* @return bool true if there is further data, false if not
return (bool) ($this->position < $this->data_length);
* See if the next character is LWS
* @return bool true if the next character is LWS, false if not
function is_linear_whitespace()
return (bool) ($this->data[$this->position] === "\x09"
|| $this->data[$this->position] === "\x20"
|| ($this->data[$this->position] === "\x0A"
&& isset ($this->data[$this->position + 1])
&& ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
$len = strspn($this->data, '0123456789.', 5);
$this->position += 5 + $len;
$this->position += strspn($this->data, "\x09\x20", $this->position);
if ($len = strspn($this->data, '0123456789', $this->position))
* Parse the reason phrase
$len = strcspn($this->data, "\x0A", $this->position);
$this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
$this->position += $len + 1;
$this->state = 'new_line';
* Deal with a new line, shifting data around as needed
$this->value = trim($this->value, "\x0D\x20");
if ($this->name !== '' && $this->value !== '')
if (isset ($this->headers[$this->name]))
$this->headers[$this->name] .= ', ' . $this->value;
$this->headers[$this->name] = $this->value;
if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
elseif ($this->data[$this->position] === "\x0A")
$len = strcspn($this->data, "\x0A:", $this->position);
if (isset ($this->data[$this->position + $len]))
if ($this->data[$this->position + $len] === "\x0A")
$this->state = 'new_line';
$this->name = substr($this->data, $this->position, $len);
$this->position += $len + 1;
* Parse LWS, replacing consecutive LWS characters with a single space
function linear_whitespace()
if (substr($this->data, $this->position, 2) === "\x0D\x0A")
elseif ($this->data[$this->position] === "\x0A")
$this->position += strspn($this->data, "\x09\x20", $this->position);
} while ($this->has_data() && $this->is_linear_whitespace());
* See what state to move to while within non-quoted header values
if ($this->is_linear_whitespace())
$this->linear_whitespace();
switch ($this->data[$this->position])
$this->state = 'new_line';
$this->state = 'value_char';
* Parse a header value while outside quotes
$len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
$this->value .= substr($this->data, $this->position, $len);
* See what state to move to while within quoted header values
if ($this->is_linear_whitespace())
$this->linear_whitespace();
switch ($this->data[$this->position])
$this->state = 'new_line';
$this->state = 'quote_escaped';
$this->state = 'quote_char';
* Parse a header value while within quotes
$len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
$this->value .= substr($this->data, $this->position, $len);
* Parse an escaped character within quotes
$this->value .= $this->data[$this->position];
$this->body = substr($this->data, $this->position);
* Don't call the constructor. Please.
function SimplePie_Cache()
trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
* Create a new SimplePie_Cache object
function create($location, $filename, $extension)
if (is_a($data, 'SimplePie'))
$hours = floor($seconds / 3600);
$remainder = $seconds % 3600;
$minutes = floor($remainder / 60);
$seconds = $remainder % 60;
if ($minutes < 10 && $hours > 0)
$minutes = '0' . $minutes;
$seconds = '0' . $seconds;
if ($relative['scheme'] !== '')
if ($relative['authority'] !== '')
$target['scheme'] = $base['scheme'];
$target['scheme'] = $base['scheme'];
$target['authority'] = $base['authority'];
if ($relative['path'] !== '')
if (strpos($relative['path'], '/') === 0)
$target['path'] = $relative['path'];
elseif ($base['authority'] !== '' && $base['path'] === '')
$target['path'] = '/' . $relative['path'];
elseif (($last_segment = strrpos($base['path'], '/')) !== false)
$target['path'] = substr($base['path'], 0, $last_segment + 1) . $relative['path'];
$target['path'] = $relative['path'];
$target['query'] = $relative['query'];
$target['path'] = $base['path'];
if ($relative['query'] !== '')
$target['query'] = $relative['query'];
elseif ($base['query'] !== '')
$target['query'] = $base['query'];
$target['fragment'] = $relative['fragment'];
// No base URL, just return the relative URL
while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input == '.' || $input == '..')
// A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
if (strpos($input, '../') === 0)
elseif (strpos($input, './') === 0)
// 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,
elseif (strpos($input, '/./') === 0)
// 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,
elseif (strpos($input, '/../') === 0)
// D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
elseif ($input == '.' || $input == '..')
// 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
elseif (($pos = strpos($input, '/', 1)) !== false)
$output .= substr($input, 0, $pos);
for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++ )
$return[$i]['tag'] = $realname;
$return[$i]['full'] = $matches[$i][0][0];
$return[$i]['offset'] = $matches[$i][0][1];
if (strlen($matches[$i][3][0]) <= 2)
$return[$i]['self_closing'] = true;
$return[$i]['self_closing'] = false;
$return[$i]['content'] = $matches[$i][4][0];
$return[$i]['attribs'] = array();
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))
for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++ )
if (count($attribs[$j]) == 2)
$attribs[$j][2] = $attribs[$j][1];
$full = "<$element[tag]";
foreach ($element['attribs'] as $key => $value)
if ($element['self_closing'])
$full .= ">$element[content]</$element[tag]>";
function error($message, $level, $file, $line)
error_log("$note: $message in $file on line $line", 0);
* If a file has been cached, retrieve and display it.
* This is most useful for caching images (get_favicon(), etc.),
* however it works for all cached files. This WILL NOT display ANY
* file/image/page/whatever, but rather only display what has already
* been cached by SimplePie.
* @see SimplePie::get_favicon()
* @param str $identifier_url URL that is used to identify the content.
* This may or may not be the actual URL of the live content.
* @param str $cache_location Location of SimplePie's cache. Defaults
* @param str $cache_extension The file extension that the file was
* cached with. Defaults to 'spc'.
* @param str $cache_class Name of the cache-handling class being used
* in SimplePie. Defaults to 'SimplePie_Cache', and should be left
* as-is unless you've overloaded the class.
* @param str $cache_name_function Obsolete. Exists for backwards
* compatibility reasons only.
function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
$cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
if ($file = $cache->load())
if (isset ($file['headers']['content-type']))
header('Content-type:' . $file['headers']['content-type']);
header('Content-type: application/octet-stream');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
die('Cached file for ' . $identifier_url . ' cannot be found.');
if ($parsed['scheme'] !== '' && $parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')
if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
if ($http == 2 && $parsed['scheme'] !== '')
elseif ($http == 3 && strtolower($parsed['scheme']) == 'http')
elseif ($http == 4 && strtolower($parsed['scheme']) == 'http')
elseif (preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $url, $match))
for ($i = count($match); $i <= 9; $i++ )
return $cache[$url] = array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
return $cache[$url] = array('scheme' => '', 'authority' => '', 'path' => '', 'query' => '', 'fragment' => '');
function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
$return .= "//$authority";
$url = preg_replace_callback('/%([0-9A-Fa-f]{2})/', array('SimplePie_Misc', 'percent_encoding_normalization'), $url);
if ($url['authority'] !== '')
$url['authority'] = strtolower($url['authority']);
if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer == 0x2D || $integer == 0x2E || $integer == 0x5F || $integer == 0x7E)
* PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
* FAQ: Multilingual Forms (modified to include full ASCII range)
* @author Geoffrey Sneddon
* @see http://www.w3.org/International/questions/qa-forms-utf-8
* @param string $str String to remove bad UTF-8 bytes from
* @return string UTF-8 string
elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
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))
return implode("\xEF\xBF\xBD", $matches[0]);
* Converts a Windows-1252 encoded string to a UTF-8 encoded string
* @param string $string Windows-1252 encoded string
* @return string UTF-8 encoded string
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");
return strtr($string, $convert_table);
// We fail to fail on non US-ASCII bytes
if ($input === 'US-ASCII')
static $non_ascii_octects = '';
for ($i = 0x80; $i <= 0xFF; $i++ )
$non_ascii_octects .= chr($i);
elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($data, $output, $input)))
elseif ($input == 'windows-1252' && $output == 'UTF-8')
elseif ($input == 'UTF-8' && $output == 'windows-1252')
// Character sets are case-insensitive (though we'll return them in the form given in their registration)
return 'ANSI_X3.110-1983';
case 'ADOBE-STANDARD-ENCODING':
case 'CSADOBESTANDARDENCODING':
return 'Adobe-Standard-Encoding';
case 'ADOBE-SYMBOL-ENCODING':
return 'Adobe-Symbol-Encoding';
case 'CSISO4UNITEDKINGDOM':
case 'CSISO47BSVIEWDATA':
case 'CSA_Z243.4-1985-1':
case 'CSISO121CANADIAN1':
return 'CSA_Z243.4-1985-1';
case 'CSA_Z243.4-1985-2':
case 'CSISO122CANADIAN2':
return 'CSA_Z243.4-1985-2';
case 'CSA_Z243.4-1985-GR':
case 'CSISO123CSAZ24341985GR':
return 'CSA_Z243.4-1985-gr';
case 'CSISO139CSN369103':
case 'CSISO111ECMACYRILLIC':
case 'CSEUCPKDFMTJAPANESE':
case 'EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE':
case 'CSEUCFIXWIDJAPANESE':
case 'EXTENDED_UNIX_CODE_FIXED_WIDTH_FOR_JAPANESE':
return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
case 'CSISO153GOST1976874':
case 'PC-MULTILINGUAL-850+EURO':
case 'EBCDIC-LATIN9--EURO':
case 'EBCDIC-US-37+EURO':
case 'EBCDIC-DE-273+EURO':
case 'EBCDIC-DK-277+EURO':
case 'EBCDIC-NO-277+EURO':
case 'EBCDIC-FI-278+EURO':
case 'EBCDIC-SE-278+EURO':
case 'EBCDIC-IT-280+EURO':
case 'EBCDIC-ES-284+EURO':
case 'EBCDIC-GB-285+EURO':
case 'EBCDIC-FR-297+EURO':
case 'EBCDIC-INTERNATIONAL-500+EURO':
case 'EBCDIC-IS-871+EURO':
case 'CSPC850MULTILINGUAL':
case 'CSPC862LATINHEBREW':
case 'CSISO51INISCYRILLIC':
return 'ISO-10646-UCS-2';
return 'ISO-10646-UCS-4';
case 'ISO-10646-UCS-BASIC':
return 'ISO-10646-UCS-Basic';
return 'ISO-10646-UTF-1';
case 'ISO-10646-UNICODE-LATIN1':
return 'ISO-10646-Unicode-Latin1';
return 'ISO-2022-CN-EXT';
case 'CSWINDOWS30LATIN1':
case 'ISO-8859-1-WINDOWS-3.0-LATIN-1':
return 'ISO-8859-1-Windows-3.0-Latin-1';
case 'CSWINDOWS31LATIN1':
case 'ISO-8859-1-WINDOWS-3.1-LATIN-1':
return 'ISO-8859-1-Windows-3.1-Latin-1';
case 'CSWINDOWS31LATIN2':
case 'ISO-8859-2-WINDOWS-LATIN-2':
return 'ISO-8859-2-Windows-Latin-2';
case 'CSISOLATINCYRILLIC':
case 'CSWINDOWS31LATIN5':
case 'ISO-8859-9-WINDOWS-LATIN-5':
return 'ISO-8859-9-Windows-Latin-5';
case 'ISO-UNICODE-IBM-1261':
return 'ISO-Unicode-IBM-1261';
case 'ISO-UNICODE-IBM-1264':
return 'ISO-Unicode-IBM-1264';
case 'ISO-UNICODE-IBM-1265':
return 'ISO-Unicode-IBM-1265';
case 'ISO-UNICODE-IBM-1268':
return 'ISO-Unicode-IBM-1268';
case 'ISO-UNICODE-IBM-1276':
return 'ISO-Unicode-IBM-1276';
case 'CSISO5427CYRILLIC':
case 'ISO5427CYRILLIC1981':
case 'CSISO646BASIC1983':
case 'ISO_646.BASIC:1983':
return 'ISO_646.basic:1983';
case 'CSISO2INTLREFVERSION':
return 'ISO_646.irv:1983';
case 'CSISO13JISC6220JP':
case 'JIS_C6220-1969-JP':
return 'JIS_C6220-1969-jp';
case 'CSISO14JISC6220RO':
case 'JIS_C6220-1969-RO':
return 'JIS_C6220-1969-ro';
case 'CSISO42JISC62261978':
case 'CSISO91JISC62291984A':
return 'JIS_C6229-1984-a';
case 'CSISO92JISC62991984B':
return 'JIS_C6229-1984-b';
case 'CSISO93JIS62291984BADD':
case 'JIS_C6229-1984-B-ADD':
return 'JIS_C6229-1984-b-add';
case 'CSISO94JIS62291984HAND':
case 'JIS_C6229-1984-HAND':
return 'JIS_C6229-1984-hand';
case 'CSISO95JIS62291984HANDADD':
case 'JIS_C6229-1984-HAND-ADD':
return 'JIS_C6229-1984-hand-add';
case 'CSISO96JISC62291984KANA':
case 'JIS_C6229-1984-KANA':
return 'JIS_C6229-1984-kana';
case 'CSHALFWIDTHKATAKANA':
case 'CSISO159JISX02121990':
case 'CSISO141JUSIB1002':
case 'CSISO147MACEDONIAN':
return 'JUS_I.B1.003-mac';
case 'JUS_I.B1.003-SERB':
return 'JUS_I.B1.003-serb';
case 'CSISO27LATINGREEK1':
case 'CSMICROSOFTPUBLISHING':
case 'MICROSOFT-PUBLISHING':
return 'Microsoft-Publishing';
case 'NF_Z_62-010_(1973)':
return 'NF_Z_62-010_(1973)';
case 'CSISO60DANISHNORWEGIAN':
case 'CSISO60NORWEGIAN1':
case 'CSISO61NORWEGIAN2':
case 'OSD_EBCDIC_DF03_IRV':
return 'OSD_EBCDIC_DF03_IRV';
case 'OSD_EBCDIC_DF04_1':
return 'OSD_EBCDIC_DF04_1';
case 'OSD_EBCDIC_DF04_15':
return 'OSD_EBCDIC_DF04_15';
case 'CSPC8DANISHNORWEGIAN':
case 'PC8-DANISH-NORWEGIAN':
return 'PC8-Danish-Norwegian';
case 'CSISO16PORTUGUESE':
case 'CSISO84PORTUGUESE2':
case 'CSISO11SWEDISHFORNAMES':
case 'UNICODE-1-1-UTF-7':
return 'UNICODE-1-1-UTF-7';
case 'CSVENTURAINTERNATIONAL':
case 'VENTURA-INTERNATIONAL':
return 'Ventura-International';
case 'CSISO150GREEKCCITT':
case 'CSISO19LATINGREEK':
case 'CSISO70VIDEOTEXSUPP1':
$curl = $curl['version'];
elseif (substr($curl, 0, 5) == 'curl/')
$curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
elseif (substr($curl, 0, 8) == 'libcurl/')
$curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
* @param string $data Data to strip comments from
* @return string Comment stripped string
while (($start = strpos($data, '<!--')) !== false)
$output .= substr($data, 0, $start);
if (($end = strpos($data, '-->', $start)) !== false)
return $parser->parse($dt);
* @param string $data Input data
* @return string Output data
return $decoder->parse();
* @param string $data Data to strip comments from
* @return string Comment stripped string
$string = (string) $string;
while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
$output .= substr($string, $position, $pos - $position);
if ($string[$pos - 1] !== '\\')
while ($depth && $position < $length)
$position += strcspn($string, '()', $position);
if ($string[$position - 1] === '\\')
elseif (isset ($string[$position]))
switch ($string[$position])
$output .= substr($string, $position);
if (($pos = strpos($mime, ';')) === false)
if (isset ($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) == 'base64'))
if (isset ($attribs['']['type']))
case 'application/xhtml+xml':
if (isset ($attribs['']['type']))
if (isset ($attribs['']['type']))
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);
$space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
$string_length = strlen($string);
$position = strspn($string, $space_characters);
while ($position < $string_length)
$len = strcspn($string, $space_characters, $position);
$tokens[] = substr($string, $position, $len);
$position += strspn($string, $space_characters, $position);
$new_array_strings = array();
foreach ($array as $key => $value)
$cmp = $value->__toString();
$cmp = (string) reset($value);
if (!in_array($cmp, $new_array_strings))
$new_array[$key] = $value;
$new_array_strings[] = $cmp;
* Converts a unicode codepoint to a UTF-8 character
* @param int $codepoint Unicode codepoint
* @return string UTF-8 character
$codepoint = (int) $codepoint;
if (isset ($cache[$codepoint]))
return $cache[$codepoint];
return $cache[$codepoint] = false;
else if ($codepoint <= 0x7f)
return $cache[$codepoint] = chr($codepoint);
else if ($codepoint <= 0x7ff)
return $cache[$codepoint] = chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
else if ($codepoint <= 0xffff)
return $cache[$codepoint] = chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
else if ($codepoint <= 0x10ffff)
return $cache[$codepoint] = chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
// U+FFFD REPLACEMENT CHARACTER
return $cache[$codepoint] = "\xEF\xBF\xBD";
* Re-implementation of PHP 5's stripos()
* Returns the numeric position of the first occurrence of needle in the
* @param object $haystack
* @param string $needle Note that the needle may be a string of one or more
* characters. If needle is not a string, it is converted to an integer
* and applied as the ordinal value of a character.
* @param int $offset The optional offset parameter allows you to specify which
* character in haystack to start searching. The position returned is still
* relative to the beginning of haystack.
* @return bool If needle is not found, stripos() will return boolean false.
function stripos($haystack, $needle, $offset = 0)
return stripos($haystack, $needle, $offset);
trigger_error('needle is not a string or an integer', E_USER_WARNING);
* Returns an associative array of name/value pairs, where the value is an
* array of values that have used the same name
* @param string $str The input string.
foreach ($str as $section)
if (strpos($section, '=') !== false)
list ($name, $value) = explode('=', $section, 2);
* Detect XML encoding, as per XML 1.0 Appendix F.1
* @todo Add support for EBCDIC
* @param string $data XML data
* @return array Possible encodings
if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
$encoding[] = 'UTF-32BE';
// UTF-32 Little Endian BOM
elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
$encoding[] = 'UTF-32LE';
elseif (substr($data, 0, 2) === "\xFE\xFF")
$encoding[] = 'UTF-16BE';
// UTF-16 Little Endian BOM
elseif (substr($data, 0, 2) === "\xFF\xFE")
$encoding[] = 'UTF-16LE';
elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
// UTF-32 Big Endian Without BOM
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")
if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
$encoding[] = 'UTF-32BE';
// UTF-32 Little Endian Without BOM
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")
if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
$encoding[] = 'UTF-32LE';
// UTF-16 Big Endian Without BOM
elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
$encoding[] = 'UTF-16BE';
// UTF-16 Little Endian Without BOM
elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
$encoding[] = 'UTF-16LE';
// US-ASCII (or superset)
elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
if ($pos = strpos($data, "\x3F\x3E"))
* This implements HTML5 as of revision 967 (2007-06-28)
* Currently consumed bytes
* Position of the current byte being parsed
* Create an instance of the class with the input data
* @param string $data Input data
* @return string Output data
while (($this->position = strpos($this->data, '&', $this->position)) !== false)
* @return mixed The next byte, or false, if there is no more data
if (isset ($this->data[$this->position]))
$this->consumed .= $this->data[$this->position];
return $this->data[$this->position++ ];
* Consume a range of characters
* @param string $chars Characters to consume
* @return mixed A series of characters that match the range, or false
function consume_range($chars)
if ($len = strspn($this->data, $chars, $this->position))
$data = substr($this->data, $this->position, $len);
$this->consumed .= $data;
$this->consumed = substr($this->consumed, 0, - 1);
switch ($this->consume())
switch ($this->consume())
$range = '0123456789ABCDEFabcdef';
if ($codepoint = $this->consume_range($range))
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");
$codepoint = hexdec($codepoint);
$codepoint = intval($codepoint);
if (isset ($windows_1252_specials[$codepoint]))
$replacement = $windows_1252_specials[$codepoint];
$replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
if ($this->consume() != ';')
$consumed_length = strlen($this->consumed);
$this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
$this->position += strlen($replacement) - $consumed_length;
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");
for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++ )
$consumed = substr($this->consumed, 1);
if (isset ($entities[$consumed]))
$this->position += strlen($entities[$match]) - strlen($consumed) - 1;
* List of days, calendar day name => ordinal day number in the week
* List of months, calendar month name => calendar month number
* List of timezones, abbreviation => offset from UTC
* Cached PCRE for SimplePie_Parse_Date::$day
* Cached PCRE for SimplePie_Parse_Date::$month
* Array of user-added callback methods
* Array of user-added callback methods
* Create new SimplePie_Parse_Date object, and set self::day_pcre,
* self::month_pcre, and self::built_in
function SimplePie_Parse_Date()
$class = new ReflectionClass(get_class($this));
$methods = $class->getMethods();
foreach ($methods as $method)
$all_methods[] = $method->getName();
foreach ($all_methods as $method)
foreach ($cache[get_class($this)] as $method)
$this->built_in[] = $method;
* @param string $date Date to parse
* @return int Timestamp corresponding to date string, or false on failure
foreach ($this->user as $method)
foreach ($this->built_in as $method)
if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
* Add a callback method to parse a date
* @param callback $callback
$this->user[] = $callback;
trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
* Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
* well as allowing any of upper or lower case "T", horizontal tabs, or
* spaces to be used as the time seperator (including more than one))
$month = $day = $hour = $minute = $second = '([0-9]{2})';
$zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
$pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
7: Decimal fraction of a second
for ($i = count($match); $i <= 3; $i++ )
for ($i = count($match); $i <= 7; $i++ )
if (isset ($match[9]) && $match[9] !== '')
$timezone = $match[10] * 3600;
$timezone += $match[11] * 60;
$timezone = 0 - $timezone;
// Convert the number of seconds to an integer, taking decimals into account
return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
* @param string $data Data to strip comments from
* @return string Comment stripped string
$string = (string) $string;
while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
$output .= substr($string, $position, $pos - $position);
if ($string[$pos - 1] !== '\\')
while ($depth && $position < $length)
$position += strcspn($string, '()', $position);
if ($string[$position - 1] === '\\')
elseif (isset ($string[$position]))
switch ($string[$position])
$output .= substr($string, $position);
* Parse RFC2822's date format
$fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
$optional_fws = $fws . '?';
$hour = $minute = $second = '([0-9]{2})';
$num_zone = '([+\-])([0-9]{2})([0-9]{2})';
$character_zone = '([A-Z]{1,5})';
$zone = '(?:' . $num_zone . '|' . $character_zone . ')';
$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';
$timezone = $match[9] * 3600;
$timezone += $match[10] * 60;
$timezone = 0 - $timezone;
// Assume everything else to be -0000
// Deal with 2/3 digit years
elseif ($match[4] < 1000)
// Second is optional, if it is empty set it to zero
return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
* Parse RFC850's date format
$year = $hour = $minute = $second = '([0-9]{2})';
$pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
// Assume everything else to be -0000
// Deal with 2 digit year
return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
* Parse C99's asctime()'s date format
$hour = $sec = $min = '([0-9]{2})';
$terminator = '\x0A?\x00?';
$pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
* Parse dates using strtotime()
if ($strtotime === - 1 || $strtotime === false)
* Create an instance of the class with the input file
* @param SimplePie_Content_Type_Sniffer $file Input file
* Get the Content-Type of the specified file
* @return string Actual Content-Type
if (isset ($this->file->headers['content-type']))
if (!isset ($this->file->headers['content-encoding'])
&& ($this->file->headers['content-type'] === 'text/plain'
|| $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
|| $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
return $this->text_or_binary();
if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
$official = substr($this->file->headers['content-type'], 0, $pos);
$official = $this->file->headers['content-type'];
if ($official === 'unknown/unknown'
|| $official === 'application/unknown')
elseif (substr($official, - 4) === '+xml'
|| $official === 'text/xml'
|| $official === 'application/xml')
elseif (substr($official, 0, 6) === 'image/')
if ($return = $this->image())
elseif ($official === 'text/html')
return $this->feed_or_html();
* @return string Actual Content-Type
function text_or_binary()
if (substr($this->file->body, 0, 2) === "\xFE\xFF"
|| substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
|| substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
return 'application/octect-stream';
* @return string Actual Content-Type
$ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
elseif (substr($this->file->body, 0, 5) === '%PDF-')
return 'application/pdf';
elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
return 'application/postscript';
elseif (substr($this->file->body, 0, 6) === 'GIF87a'
elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
return $this->text_or_binary();
* @return string Actual Content-Type
elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
* @return string Actual Content-Type
$pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
switch ($this->file->body[$pos])
$pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
elseif (substr($this->file->body, $pos, 1) === '!')
if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
elseif (substr($this->file->body, $pos, 1) === '?')
if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
elseif (substr($this->file->body, $pos, 3) === 'rss'
|| substr($this->file->body, $pos, 7) === 'rdf:RDF')
return 'application/rss+xml';
elseif (substr($this->file->body, $pos, 4) === 'feed')
return 'application/atom+xml';
* Parses the XML Declaration
* Current state of the state machine
var $state = 'before_version_name';
* Input data length (to avoid calling strlen() everytime this is needed)
* Current position of the pointer
* Create an instance of the class with the input data
* @param string $data Input data
$this->data_length = strlen($this->data);
* @return bool true on success, false on failure
while ($this->state && $this->state !== 'emit' && $this->has_data())
if ($this->state === 'emit')
* Check whether there is data beyond the pointer
* @return bool true if there is further data, false if not
return (bool) ($this->position < $this->data_length);
* Advance past any whitespace
* @return int Number of whitespace characters passed
$whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
$this->position += $whitespace;
$quote = substr($this->data, $this->position, 1);
if ($quote === '"' || $quote === "'")
$len = strcspn($this->data, $quote, $this->position);
$value = substr($this->data, $this->position, $len);
$this->position += $len + 1;
$this->state = 'version_name';
if (substr($this->data, $this->position, 7) === 'version')
$this->state = 'version_equals';
if (substr($this->data, $this->position, 1) === '=')
$this->state = 'version_value';
$this->state = 'encoding_name';
$this->state = 'standalone_name';
if (substr($this->data, $this->position, 8) === 'encoding')
$this->state = 'encoding_equals';
if (substr($this->data, $this->position, 1) === '=')
$this->state = 'encoding_value';
$this->state = 'standalone_name';
if (substr($this->data, $this->position, 10) === 'standalone')
$this->state = 'standalone_equals';
if (substr($this->data, $this->position, 1) === '=')
$this->state = 'standalone_value';
function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
function find($type = SIMPLEPIE_LOCATOR_ALL)
$sniffer = new $this->content_type_sniffer_class($this->file);
if ($sniffer->get_type() !== 'text/html')
$sniffer = new $this->content_type_sniffer_class($file);
$sniffed = $sniffer->get_type();
if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'application/atom+xml', 'text/xml', 'application/xml', 'text/plain')))
foreach ($elements as $element)
if ($element['attribs']['href']['data'] !== '')
foreach ($links as $link)
if (isset ($link['attribs']['href']['data']) && isset ($link['attribs']['rel']['data']))
$feed = & new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
foreach ($links as $link)
if (isset ($link['attribs']['href']['data']))
$href = trim($link['attribs']['href']['data']);
if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
if ($parsed['authority'] === '' || $parsed['authority'] == $current['authority'])
foreach ($array as $key => $value)
$feed = & new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
foreach ($array as $key => $value)
$feed = & new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
function parse(&$data, $encoding)
// Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
// UTF-32 Little Endian BOM
elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
elseif (substr($data, 0, 2) === "\xFE\xFF")
// UTF-16 Little Endian BOM
elseif (substr($data, 0, 2) === "\xFF\xFE")
elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
if ($declaration->parse())
$data = substr($data, $pos + 2);
$data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
function tag_open($parser, $tag, $attributes)
elseif ($this->feed == false)
foreach ($attributes as $name => $value)
list ($attrib_namespace, $attribute) = $this->split_ns($name);
$attribs[$attrib_namespace][$attribute] = $value;
foreach ($attribs[''] as $name => $value)
$this->data['data'] .= '>';
function cdata($parser, $cdata)
$this->data['data'] .= $cdata;
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')))
if (!isset ($cache[$string]))
if ($pos = strpos($string, $this->separator))
static $separator_length;
$namespace = substr($string, 0, $pos);
$local_name = substr($string, $pos + $separator_length);
$cache[$string] = array($namespace, $local_name);
$cache[$string] = array('', $string);
* @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shortern a string while preserving HTML tags
var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
'img' => array('longdesc', 'src'),
function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
if (isset ($enable_cache))
if ($cache_name_function)
function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
$this->timeout = (string) $timeout;
function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
* Set element/attribute key/value pairs of HTML attributes
* containing URLs that need to be resolved relative to the feed
* @param array $element_attribute Element/attribute key/value pairs
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'))
function sanitize($data, $type, $base = '')
// Strip out HTML tags and attributes that might cause various security problems.
// Based on recommendations by Mark Pilgrim at:
// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
// If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
foreach ($images as $img)
if (isset ($img['attribs']['src']['data']))
$img['attribs']['src']['data'] = $this->image_handler . $image_url;
$file = & new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
$headers = $file->headers;
if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)))
if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
$img['attribs']['src']['data'] = $this->image_handler . $image_url;
// Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
foreach ($elements as $element)
foreach ($attributes as $attribute)
if (isset ($element['attribs'][$attribute]['data']))
$data = str_replace($element['full'], $new_element, $data);
$element['full'] = $new_element;
elseif (isset ($element['attribs'][$attributes]['data']))
return "<$match[1]$match[2]>$match[3]</$match[1]>";
|