]> git.immae.eu Git - github/wallabag/wallabag.git/blobdiff - inc/3rdparty/libraries/simplepie/library/SimplePie.php
[change] we now use Full-Text RSS 3.1, thank you so much @fivefilters
[github/wallabag/wallabag.git] / inc / 3rdparty / libraries / simplepie / library / SimplePie.php
similarity index 62%
rename from inc/3rdparty/simplepie/SimplePie/Core.php
rename to inc/3rdparty/libraries/simplepie/library/SimplePie.php
index 82a30f2ba789b020dc32663d883cb71483368455..b33c635f15a0b1ea79bf9c19414b001a33205384 100644 (file)
@@ -5,7 +5,7 @@
  * A PHP-Based RSS and Atom Feed Framework.
  * Takes the hard work out of managing a complete RSS/Atom solution.
  *
- * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
+ * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * POSSIBILITY OF SUCH DAMAGE.
  *
  * @package SimplePie
- * @version 1.3-dev
- * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue
+ * @version 1.3.1
+ * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  * @author Ryan Parman
  * @author Geoffrey Sneddon
  * @author Ryan McCue
  * @link http://simplepie.org/ SimplePie
  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @todo phpDoc comments
  */
 
 /**
@@ -51,7 +50,7 @@ define('SIMPLEPIE_NAME', 'SimplePie');
 /**
  * SimplePie Version
  */
-define('SIMPLEPIE_VERSION', '1.3-dev');
+define('SIMPLEPIE_VERSION', '1.3.1');
 
 /**
  * SimplePie Build
@@ -373,11 +372,6 @@ define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
  */
 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', '>='));
-
 /**
  * No file source
  */
@@ -414,8 +408,9 @@ define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
  * SimplePie
  *
  * @package SimplePie
+ * @subpackage API
  */
-class SimplePie_Core
+class SimplePie
 {
        /**
         * @var array Raw data
@@ -487,13 +482,6 @@ class SimplePie_Core
         */
        public $force_feed = false;
 
-       /**
-        * @var bool Enable/Disable XML dump
-        * @see SimplePie::enable_xml_dump()
-        * @access private
-        */
-       public $xml_dump = false;
-
        /**
         * @var bool Enable/Disable Caching
         * @see SimplePie::enable_cache()
@@ -552,109 +540,11 @@ class SimplePie_Core
        public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
 
        /**
-        * @var string Class used for caching feeds
-        * @see SimplePie::set_cache_class()
-        * @access private
-        */
-       public $cache_class = 'SimplePie_Cache';
-
-       /**
-        * @var string Class used for locating feeds
-        * @see SimplePie::set_locator_class()
-        * @access private
-        */
-       public $locator_class = 'SimplePie_Locator';
-
-       /**
-        * @var string Class used for parsing feeds
-        * @see SimplePie::set_parser_class()
-        * @access private
-        */
-       public $parser_class = 'SimplePie_Parser';
-
-       /**
-        * @var string Class used for fetching feeds
-        * @see SimplePie::set_file_class()
-        * @access private
-        */
-       public $file_class = 'SimplePie_File';
-
-       /**
-        * @var string Class used for items
-        * @see SimplePie::set_item_class()
-        * @access private
-        */
-       public $item_class = 'SimplePie_Item';
-
-       /**
-        * @var string Class used for authors
-        * @see SimplePie::set_author_class()
-        * @access private
-        */
-       public $author_class = 'SimplePie_Author';
-
-       /**
-        * @var string Class used for categories
-        * @see SimplePie::set_category_class()
-        * @access private
-        */
-       public $category_class = 'SimplePie_Category';
-
-       /**
-        * @var string Class used for enclosures
-        * @see SimplePie::set_enclosures_class()
-        * @access private
-        */
-       public $enclosure_class = 'SimplePie_Enclosure';
-
-       /**
-        * @var string Class used for Media RSS <media:text> captions
-        * @see SimplePie::set_caption_class()
-        * @access private
-        */
-       public $caption_class = 'SimplePie_Caption';
-
-       /**
-        * @var string Class used for Media RSS <media:copyright>
-        * @see SimplePie::set_copyright_class()
-        * @access private
-        */
-       public $copyright_class = 'SimplePie_Copyright';
-
-       /**
-        * @var string Class used for Media RSS <media:credit>
-        * @see SimplePie::set_credit_class()
-        * @access private
-        */
-       public $credit_class = 'SimplePie_Credit';
-
-       /**
-        * @var string Class used for Media RSS <media:rating>
-        * @see SimplePie::set_rating_class()
-        * @access private
-        */
-       public $rating_class = 'SimplePie_Rating';
-
-       /**
-        * @var string Class used for Media RSS <media:restriction>
-        * @see SimplePie::set_restriction_class()
-        * @access private
-        */
-       public $restriction_class = 'SimplePie_Restriction';
-
-       /**
-        * @var string Class used for content-type sniffing
-        * @see SimplePie::set_content_type_sniffer_class()
-        * @access private
-        */
-       public $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
-
-       /**
-        * @var string Class used for item sources.
-        * @see SimplePie::set_source_class()
-        * @access private
+        * Class registry object
+        *
+        * @var SimplePie_Registry
         */
-       public $source_class = 'SimplePie_Source';
+       public $registry;
 
        /**
         * @var int Maximum number of feeds to check with autodiscovery
@@ -721,35 +611,44 @@ class SimplePie_Core
        /**
         * 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
+        * To use SimplePie, create the SimplePie object with no parameters. You can
+        * then set configuration options using the provided methods. 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.
+        * object's methods and properties will be available to you.
+        *
+        * Previously, it was possible to pass in the feed URL along with cache
+        * options directly into the constructor. This has been removed as of 1.3 as
+        * it caused a lot of confusion.
         *
-        * @access public
         * @since 1.0 Preview Release
         */
        public function __construct()
        {
-               if (version_compare(PHP_VERSION, '5.0', '<'))
+               if (version_compare(PHP_VERSION, '5.2', '<'))
                {
-                       trigger_error('PHP 4.x is no longer supported. Please upgrade to PHP 5.2 or newer.');
+                       trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
                        die();
                }
 
                // Other objects, instances created here so we can set options on them
                $this->sanitize = new SimplePie_Sanitize();
+               $this->registry = new SimplePie_Registry();
 
                if (func_num_args() > 0)
                {
-                       trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.');
+                       $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
+                       trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
+
+                       $args = func_get_args();
+                       switch (count($args)) {
+                               case 3:
+                                       $this->set_cache_duration($args[2]);
+                               case 2:
+                                       $this->set_cache_location($args[1]);
+                               case 1:
+                                       $this->set_feed_url($args[0]);
+                                       $this->init();
+                       }
                }
        }
 
@@ -788,10 +687,11 @@ class SimplePie_Core
        }
 
        /**
-        * Force the given data/URL to be treated as a feed no matter what it
-        * appears like
+        * Force the given data/URL to be treated as a feed
+        *
+        * This tells SimplePie to ignore the content-type provided by the server.
+        * Be careful when using this option, as it will also disable autodiscovery.
         *
-        * @access public
         * @since 1.1
         * @param bool $enable Force the given data/URL to be treated as a feed
         */
@@ -801,7 +701,7 @@ class SimplePie_Core
        }
 
        /**
-        * This is the URL of the feed you want to parse.
+        * Set 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
@@ -811,37 +711,35 @@ class SimplePie_Core
         * of a string for the $url. Remember that with each additional feed comes
         * additional processing and resources.
         *
-        * @access public
         * @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()
+        * @see set_raw_data()
+        * @param string|array $url This is the URL (or array of URLs) that you want to parse.
         */
        public function set_feed_url($url)
        {
+               $this->multifeed_url = array();
                if (is_array($url))
                {
-                       $this->multifeed_url = array();
                        foreach ($url as $value)
                        {
-                               $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
+                               $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
                        }
                }
                else
                {
-                       $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
+                       $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
                }
        }
 
        /**
-        * Provides an instance of SimplePie_File to use as a feed
+        * Set an instance of {@see SimplePie_File} to use as a feed
         *
-        * @access public
-        * @param object &$file Instance of SimplePie_File (or subclass)
+        * @param SimplePie_File &$file
         * @return bool True on success, false on failure
         */
        public function set_file(&$file)
        {
-               if (is_a($file, 'SimplePie_File'))
+               if ($file instanceof SimplePie_File)
                {
                        $this->feed_url = $file->url;
                        $this->file =& $file;
@@ -851,16 +749,17 @@ class SimplePie_Core
        }
 
        /**
+        * Set the raw XML data to parse
+        *
         * 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
         * takes precedence.
         *
-        * @access public
         * @since 1.0 Beta 3
         * @param string $data RSS or Atom data as a string.
-        * @see SimplePie::set_feed_url()
+        * @see set_feed_url()
         */
        public function set_raw_data($data)
        {
@@ -868,12 +767,11 @@ class SimplePie_Core
        }
 
        /**
-        * Allows you to override the default timeout for fetching remote feeds.
+        * Set the 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.
         *
-        * @access public
         * @since 1.0 Beta 3
         * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
         */
@@ -883,10 +781,8 @@ class SimplePie_Core
        }
 
        /**
-        * Forces SimplePie to use fsockopen() instead of the preferred cURL
-        * functions.
+        * Force SimplePie to use fsockopen() instead of cURL
         *
-        * @access public
         * @since 1.0 Beta 3
         * @param bool $enable Force fsockopen() to be used
         */
@@ -896,12 +792,11 @@ class SimplePie_Core
        }
 
        /**
-        * Enables/disables caching in SimplePie.
+        * Enable/disable caching in SimplePie.
         *
         * This option allows you to disable caching all-together in SimplePie.
         * However, disabling the cache can lead to longer load times.
         *
-        * @access public
         * @since 1.0 Preview Release
         * @param bool $enable Enable caching
         */
@@ -911,11 +806,10 @@ class SimplePie_Core
        }
 
        /**
-        * Set the length of time (in seconds) that the contents of a feed
-        * will be cached.
+        * Set the length of time (in seconds) that the contents of a feed will be
+        * cached
         *
-        * @access public
-        * @param int $seconds The feed content cache duration.
+        * @param int $seconds The feed content cache duration
         */
        public function set_cache_duration($seconds = 3600)
        {
@@ -923,10 +817,9 @@ class SimplePie_Core
        }
 
        /**
-        * Set the length of time (in seconds) that the autodiscovered feed
-        * URL will be cached.
+        * Set the length of time (in seconds) that the autodiscovered feed URL will
+        * be cached
         *
-        * @access public
         * @param int $seconds The autodiscovered feed URL cache duration.
         */
        public function set_autodiscovery_cache_duration($seconds = 604800)
@@ -935,9 +828,8 @@ class SimplePie_Core
        }
 
        /**
-        * Set the file system location where the cached files should be stored.
+        * Set the file system location where the cached files should be stored
         *
-        * @access public
         * @param string $location The file system location.
         */
        public function set_cache_location($location = './cache')
@@ -946,9 +838,8 @@ class SimplePie_Core
        }
 
        /**
-        * Determines whether feed items should be sorted into reverse chronological order.
+        * Set whether feed items should be sorted into reverse chronological order
         *
-        * @access public
         * @param bool $enable Sort as reverse chronological order.
         */
        public function enable_order_by_date($enable = true)
@@ -957,10 +848,12 @@ class SimplePie_Core
        }
 
        /**
-        * Allows you to override the character encoding reported by the feed.
+        * Set the character encoding used to parse the feed
+        *
+        * This overrides the encoding reported by the feed, however it will fall
+        * back to the normal encoding detection if the override fails
         *
-        * @access public
-        * @param string $encoding Character encoding.
+        * @param string $encoding Character encoding
         */
        public function set_input_encoding($encoding = false)
        {
@@ -977,7 +870,6 @@ class SimplePie_Core
        /**
         * Set how much feed autodiscovery to do
         *
-        * @access public
         * @see SIMPLEPIE_LOCATOR_NONE
         * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
         * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
@@ -985,8 +877,7 @@ class SimplePie_Core
         * @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)
+        * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
         */
        public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
        {
@@ -994,297 +885,157 @@ class SimplePie_Core
        }
 
        /**
-        * Allows you to change which class SimplePie uses for caching.
+        * Get the class registry
+        *
+        * Use this to override SimplePie's default classes
+        * @see SimplePie_Registry
+        * @return SimplePie_Registry
+        */
+       public function &get_registry()
+       {
+               return $this->registry;
+       }
+
+       /**#@+
         * Useful when you are overloading or extending SimplePie's default classes.
         *
-        * @access public
-        * @param string $class Name of custom class.
+        * @deprecated Use {@see get_registry()} instead
         * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * @param string $class Name of custom class
+        * @return boolean True on success, false otherwise
+        */
+       /**
+        * Set which class SimplePie uses for caching
         */
        public function set_cache_class($class = 'SimplePie_Cache')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
-               {
-                       $this->cache_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Cache', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for auto-discovery.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for auto-discovery
         */
        public function set_locator_class($class = 'SimplePie_Locator')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
-               {
-                       $this->locator_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Locator', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for XML parsing.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for XML parsing
         */
        public function set_parser_class($class = 'SimplePie_Parser')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
-               {
-                       $this->parser_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Parser', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for remote file fetching.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for remote file fetching
         */
        public function set_file_class($class = 'SimplePie_File')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
-               {
-                       $this->file_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('File', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for data sanitization.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for data sanitization
         */
        public function set_sanitize_class($class = 'SimplePie_Sanitize')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
-               {
-                       $this->sanitize = new $class();
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Sanitize', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for handling feed items.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for handling feed items
         */
        public function set_item_class($class = 'SimplePie_Item')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
-               {
-                       $this->item_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Item', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for handling author data.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for handling author data
         */
        public function set_author_class($class = 'SimplePie_Author')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
-               {
-                       $this->author_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Author', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for handling category data.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for handling category data
         */
        public function set_category_class($class = 'SimplePie_Category')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
-               {
-                       $this->category_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Category', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for feed enclosures.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for feed enclosures
         */
        public function set_enclosure_class($class = 'SimplePie_Enclosure')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
-               {
-                       $this->enclosure_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Enclosure', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for <media:text> captions
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for `<media:text>` captions
         */
        public function set_caption_class($class = 'SimplePie_Caption')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
-               {
-                       $this->caption_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Caption', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for <media:copyright>
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for `<media:copyright>`
         */
        public function set_copyright_class($class = 'SimplePie_Copyright')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
-               {
-                       $this->copyright_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Copyright', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for <media:credit>
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for `<media:credit>`
         */
        public function set_credit_class($class = 'SimplePie_Credit')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
-               {
-                       $this->credit_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Credit', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for <media:rating>
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for `<media:rating>`
         */
        public function set_rating_class($class = 'SimplePie_Rating')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
-               {
-                       $this->rating_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Rating', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for <media:restriction>
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for `<media:restriction>`
         */
        public function set_restriction_class($class = 'SimplePie_Restriction')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
-               {
-                       $this->restriction_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Restriction', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses for content-type sniffing.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses for content-type sniffing
         */
        public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
-               {
-                       $this->content_type_sniffer_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Content_Type_Sniffer', $class, true);
        }
 
        /**
-        * Allows you to change which class SimplePie uses item sources.
-        * Useful when you are overloading or extending SimplePie's default classes.
-        *
-        * @access public
-        * @param string $class Name of custom class.
-        * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
+        * Set which class SimplePie uses item sources
         */
        public function set_source_class($class = 'SimplePie_Source')
        {
-               if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
-               {
-                       $this->source_class = $class;
-                       return true;
-               }
-               return false;
+               return $this->registry->register('Source', $class, true);
        }
+       /**#@-*/
 
        /**
-        * Allows you to override the default user agent string.
+        * Set the user agent string
         *
-        * @access public
         * @param string $ua New user agent string.
         */
        public function set_useragent($ua = SIMPLEPIE_USERAGENT)
@@ -1295,7 +1046,6 @@ class SimplePie_Core
        /**
         * Set callback function to create cache filename with
         *
-        * @access public
         * @param mixed $function Callback function
         */
        public function set_cache_name_function($function = 'md5')
@@ -1307,10 +1057,11 @@ class SimplePie_Core
        }
 
        /**
-        * Set options to make SP as fast as possible.  Forgoes a
-        * substantial amount of data sanitization in favor of speed.
+        * Set options to make SP as fast as possible
+        *
+        * Forgoes a substantial amount of data sanitization in favor of speed. This
+        * turns SimplePie into a dumb parser of feeds.
         *
-        * @access public
         * @param bool $set Whether to set them or not
         */
        public function set_stupidly_fast($set = false)
@@ -1329,7 +1080,6 @@ class SimplePie_Core
        /**
         * Set maximum number of feeds to check with autodiscovery
         *
-        * @access public
         * @param int $max Maximum number of feeds to check
         */
        public function set_max_checked_feeds($max = 10)
@@ -1369,6 +1119,28 @@ class SimplePie_Core
                $this->sanitize->strip_attributes($attribs);
        }
 
+       /**
+        * Set the output encoding
+        *
+        * Allows you to override SimplePie's output to match that of your webpage.
+        * This is useful for times when your webpages are not being served as
+        * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and
+        * is similar to {@see set_input_encoding()}.
+        *
+        * It should be noted, however, that not all character encodings can support
+        * all characters.  If your page is being served as ISO-8859-1 and you try
+        * to display a Japanese feed, you'll likely see garbled characters.
+        * Because of this, it is highly recommended to ensure that your webpages
+        * are served as UTF-8.
+        *
+        * The number of supported character encodings depends on whether your web
+        * host supports {@link http://php.net/mbstring mbstring},
+        * {@link http://php.net/iconv iconv}, or both. See
+        * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
+        * more information.
+        *
+        * @param string $encoding
+        */
        public function set_output_encoding($encoding = 'UTF-8')
        {
                $this->sanitize->set_output_encoding($encoding);
@@ -1383,11 +1155,14 @@ class SimplePie_Core
         * Set element/attribute key/value pairs of HTML attributes
         * containing URLs that need to be resolved relative to the feed
         *
-        * @access public
+        * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
+        * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
+        * |q|@cite
+        *
         * @since 1.0
-        * @param array $element_attribute Element/attribute key/value pairs
+        * @param array|null $element_attribute Element/attribute key/value pairs, null for default
         */
-       public 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'))
+       public function set_url_replacements($element_attribute = null)
        {
                $this->sanitize->set_url_replacements($element_attribute);
        }
@@ -1395,7 +1170,6 @@ class SimplePie_Core
        /**
         * Set the handler to enable the display of cached images.
         *
-        * @access public
         * @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.
         */
@@ -1412,9 +1186,8 @@ class SimplePie_Core
        }
 
        /**
-        * Set the limit for items returned per-feed with multifeeds.
+        * Set the limit for items returned per-feed with multifeeds
         *
-        * @access public
         * @param integer $limit The maximum number of items to return.
         */
        public function set_item_limit($limit = 0)
@@ -1422,10 +1195,19 @@ class SimplePie_Core
                $this->item_limit = (int) $limit;
        }
 
+       /**
+        * Initialize the feed object
+        *
+        * This is what makes everything happen.  Period.  This is where all of the
+        * configuration options get processed, feeds are fetched, cached, and
+        * parsed, and all of that other good stuff.
+        *
+        * @return boolean True if successful, false otherwise
+        */
        public function init()
        {
                // Check absolute bare minimum requirements.
-               if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
+               if (!extension_loaded('xml') || !extension_loaded('pcre'))
                {
                        return false;
                }
@@ -1446,321 +1228,333 @@ class SimplePie_Core
                        }
                }
 
+               if (method_exists($this->sanitize, 'set_registry'))
+               {
+                       $this->sanitize->set_registry($this->registry);
+               }
+
                // 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);
+               // Pass the classes in for legacy support; new classes should use the registry instead
+               $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
+               $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
 
-               if ($this->feed_url !== null || $this->raw_data !== null)
+               if (!empty($this->multifeed_url))
                {
-                       $this->error = null;
-                       $this->data = array();
+                       $i = 0;
+                       $success = 0;
                        $this->multifeed_objects = array();
-                       $cache = false;
+                       $this->error = array();
+                       foreach ($this->multifeed_url as $url)
+                       {
+                               $this->multifeed_objects[$i] = clone $this;
+                               $this->multifeed_objects[$i]->set_feed_url($url);
+                               $single_success = $this->multifeed_objects[$i]->init();
+                               $success |= $single_success;
+                               if (!$single_success)
+                               {
+                                       $this->error[$i] = $this->multifeed_objects[$i]->error();
+                               }
+                               $i++;
+                       }
+                       return (bool) $success;
+               }
+               elseif ($this->feed_url === null && $this->raw_data === null)
+               {
+                       return false;
+               }
+
+               $this->error = null;
+               $this->data = array();
+               $this->multifeed_objects = array();
+               $cache = false;
+
+               if ($this->feed_url !== null)
+               {
+                       $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
+
+                       // Decide whether to enable caching
+                       if ($this->cache && $parsed_feed_url['scheme'] !== '')
+                       {
+                               $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
+                       }
+
+                       // Fetch the data via SimplePie_File into $this->raw_data
+                       if (($fetched = $this->fetch_data($cache)) === true)
+                       {
+                               return true;
+                       }
+                       elseif ($fetched === false) {
+                               return false;
+                       }
+
+                       list($headers, $sniffed) = $fetched;
+               }
+
+               // Set up array of possible encodings
+               $encodings = array();
+
+               // First check to see if input has been overridden.
+               if ($this->input_encoding !== false)
+               {
+                       $encodings[] = $this->input_encoding;
+               }
 
-                       if ($this->feed_url !== null)
+               $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 (isset($sniffed))
+               {
+                       if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
                        {
-                               $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
-                               // Decide whether to enable caching
-                               if ($this->cache && $parsed_feed_url['scheme'] !== '')
+                               if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
                                {
-                                       $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
+                                       $encodings[] = strtoupper($charset[1]);
                                }
-                               // If it's enabled and we don't want an XML dump, use the cache
-                               if ($cache && !$this->xml_dump)
+                               $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
+                               $encodings[] = 'UTF-8';
+                       }
+                       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))
                                {
-                                       // Load the Cache
-                                       $this->data = $cache->load();
-                                       if (!empty($this->data))
-                                       {
-                                               // If the cache is for an outdated build of SimplePie
-                                               if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
-                                               {
-                                                       $cache->unlink();
-                                                       $this->data = array();
-                                               }
-                                               // If we've hit a collision just rerun it with caching disabled
-                                               elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
-                                               {
-                                                       $cache = false;
-                                                       $this->data = array();
-                                               }
-                                               // 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'])
-                                                               {
-                                                                       $cache->unlink();
-                                                                       $this->data = array();
-                                                               }
-                                                               else
-                                                               {
-                                                                       $this->set_feed_url($this->data['feed_url']);
-                                                                       return $this->init();
-                                                               }
-                                                       }
-                                               }
-                                               // 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']))
-                                                       {
-                                                               $headers = array(
-                                                                       'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
-                                                               );
-                                                               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'];
-                                                               }
+                                       $encodings[] = $charset[1];
+                               }
+                               $encodings[] = 'US-ASCII';
+                       }
+                       // Text MIME-type default
+                       elseif (substr($sniffed, 0, 5) === 'text/')
+                       {
+                               $encodings[] = 'US-ASCII';
+                       }
+               }
 
-                                                               $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
+               // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
+               $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
+               $encodings[] = 'UTF-8';
+               $encodings[] = 'ISO-8859-1';
 
-                                                               if ($file->success)
-                                                               {
-                                                                       if ($file->status_code === 304)
-                                                                       {
-                                                                               $cache->touch();
-                                                                               return true;
-                                                                       }
-                                                                       else
-                                                                       {
-                                                                               $headers = $file->headers;
-                                                                       }
-                                                               }
-                                                               else
-                                                               {
-                                                                       unset($file);
-                                                               }
-                                                       }
-                                               }
-                                               // If the cache is still valid, just return true
-                                               else
-                                               {
-                                                       $this->raw_data = false;
-                                                       return true;
-                                               }
-                                       }
-                                       // If the cache is empty, delete it
-                                       else
+               // There's no point in trying an encoding twice
+               $encodings = array_unique($encodings);
+
+               // 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)
+                       if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
+                       {
+                               // Create new parser
+                               $parser = $this->registry->create('Parser');
+
+                               // If it's parsed fine
+                               if ($parser->parse($utf8_data, 'UTF-8'))
+                               {
+                                       $this->data = $parser->get_data();
+                                       if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
                                        {
-                                               $cache->unlink();
-                                               $this->data = array();
+                                               $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
+                                               $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
+                                               return false;
                                        }
-                               }
-                               // 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 (!isset($file))
-                               {
-                                       if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
+
+                                       if (isset($headers))
                                        {
-                                               $file =& $this->file;
+                                               $this->data['headers'] = $headers;
                                        }
-                                       else
+                                       $this->data['build'] = SIMPLEPIE_BUILD;
+
+                                       // Cache the file if caching is enabled
+                                       if ($cache && !$cache->save($this))
                                        {
-                                               $headers = array(
-                                                       'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
-                                               );
-                                               $file = new $this->file_class($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen);
+                                               trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
                                        }
+                                       return true;
+                               }
+                       }
+               }
+
+               if (isset($parser))
+               {
+                       // We have an error, just set SimplePie_Misc::error to it and quit
+                       $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
+               }
+               else
+               {
+                       $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
+               }
+
+               $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
+
+               return false;
+       }
+
+       /**
+        * Fetch the data via SimplePie_File
+        *
+        * If the data is already cached, attempt to fetch it from there instead
+        * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
+        * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
+        */
+       protected function fetch_data(&$cache)
+       {
+               // If it's enabled, use the cache
+               if ($cache)
+               {
+                       // Load the Cache
+                       $this->data = $cache->load();
+                       if (!empty($this->data))
+                       {
+                               // If the cache is for an outdated build of SimplePie
+                               if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
+                               {
+                                       $cache->unlink();
+                                       $this->data = array();
                                }
-                               // If the file connection has an error, set SimplePie::error to that and quit
-                               if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
+                               // If we've hit a collision just rerun it with caching disabled
+                               elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
                                {
-                                       $this->error = $file->error;
-                                       if (!empty($this->data))
-                                       {
-                                               return true;
-                                       }
-                                       else
+                                       $cache = false;
+                                       $this->data = array();
+                               }
+                               // 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())
                                        {
-                                               return false;
+                                               // Do not need to do feed autodiscovery yet.
+                                               if ($this->data['feed_url'] !== $this->data['url'])
+                                               {
+                                                       $this->set_feed_url($this->data['feed_url']);
+                                                       return $this->init();
+                                               }
+
+                                               $cache->unlink();
+                                               $this->data = array();
                                        }
                                }
-
-                               if (!$this->force_feed)
+                               // Check if the cache has been updated
+                               elseif ($cache->mtime() + $this->cache_duration < time())
                                {
-                                       // 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))
+                                       // If we have last-modified and/or etag set
+                                       if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
                                        {
-                                               // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
-                                               unset($file);
-                                               if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
+                                               $headers = array(
+                                                       'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
+                                               );
+                                               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 = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
+
+                                               if ($file->success)
                                                {
-                                                       if ($cache)
+                                                       if ($file->status_code === 304)
                                                        {
-                                                               $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
-                                                               if (!$cache->save($this))
-                                                               {
-                                                                       trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-                                                               }
-                                                               $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
+                                                               $cache->touch();
+                                                               return true;
                                                        }
-                                                       $this->feed_url = $file->url;
                                                }
                                                else
                                                {
-                                                       $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
-                                                       SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
-                                                       return false;
+                                                       unset($file);
                                                }
                                        }
-                                       $locate = null;
                                }
-
-                               $headers = $file->headers;
-                               $data = $file->body;
-                               $sniffer = new $this->content_type_sniffer_class($file);
-                               $sniffed = $sniffer->get_type();
+                               // If the cache is still valid, just return true
+                               else
+                               {
+                                       $this->raw_data = false;
+                                       return true;
+                               }
                        }
+                       // If the cache is empty, delete it
                        else
                        {
-                               $data = $this->raw_data;
+                               $cache->unlink();
+                               $this->data = array();
                        }
-
-                       // This is exposed via get_raw_data()
-                       $this->raw_data = $data;
-
-                       // Set up array of possible encodings
-                       $encodings = array();
-
-                       // First check to see if input has been overridden.
-                       if ($this->input_encoding !== false)
+               }
+               // 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 (!isset($file))
+               {
+                       if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
                        {
-                               $encodings[] = $this->input_encoding;
+                               $file =& $this->file;
                        }
+                       else
+                       {
+                               $headers = array(
+                                       'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
+                               );
+                               $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
+                       }
+               }
+               // If the file connection has an error, set SimplePie::error to that and quit
+               if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
+               {
+                       $this->error = $file->error;
+                       return !empty($this->data);
+               }
 
-                       $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
-                       $text_types = array('text/xml', 'text/xml-external-parsed-entity');
+               if (!$this->force_feed)
+               {
+                       // Check if the supplied URL is a feed, if it isn't, look for it.
+                       $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
 
-                       // RFC 3023 (only applies to sniffed content)
-                       if (isset($sniffed))
+                       if (!$locate->is_feed($file))
                        {
-                               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))
-                                       {
-                                               $encodings[] = strtoupper($charset[1]);
-                                       }
-                                       $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
-                                       $encodings[] = 'UTF-8';
-                               }
-                               elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
+                               // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
+                               unset($file);
+                               try
                                {
-                                       if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
+                                       if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
                                        {
-                                               $encodings[] = $charset[1];
+                                               $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
+                                               $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
+                                               return false;
                                        }
-                                       $encodings[] = 'US-ASCII';
                                }
-                               // Text MIME-type default
-                               elseif (substr($sniffed, 0, 5) === 'text/')
+                               catch (SimplePie_Exception $e)
                                {
-                                       $encodings[] = 'US-ASCII';
+                                       // This is usually because DOMDocument doesn't exist
+                                       $this->error = $e->getMessage();
+                                       $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
+                                       return false;
                                }
-                       }
-
-                       // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
-                       $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
-                       $encodings[] = 'UTF-8';
-                       $encodings[] = 'ISO-8859-1';
-
-                       // There's no point in trying an encoding twice
-                       $encodings = array_unique($encodings);
-
-                       // If we want the XML, just output that with the most likely encoding and quit
-                       if ($this->xml_dump)
-                       {
-                               header('Content-type: text/xml; charset=' . $encodings[0]);
-                               echo $data;
-                               exit;
-                       }
-
-                       // 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)
-                               if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
+                               if ($cache)
                                {
-                                       // Create new parser
-                                       $parser = new $this->parser_class();
-
-                                       // If it's parsed fine
-                                       if ($parser->parse($utf8_data, 'UTF-8'))
+                                       $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
+                                       if (!$cache->save($this))
                                        {
-                                               $this->data = $parser->get_data();
-                                               if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
-                                               {
-                                                       if (isset($headers))
-                                                       {
-                                                               $this->data['headers'] = $headers;
-                                                       }
-                                                       $this->data['build'] = SIMPLEPIE_BUILD;
-
-                                                       // Cache the file if caching is enabled
-                                                       if ($cache && !$cache->save($this))
-                                                       {
-                                                               trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-                                                       }
-                                                       return true;
-                                               }
-                                               else
-                                               {
-                                                       $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
-                                                       SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
-                                                       return false;
-                                               }
+                                               trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
                                        }
+                                       $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
                                }
+                               $this->feed_url = $file->url;
                        }
+                       $locate = null;
+               }
 
-                       if (isset($parser))
-                       {
-                               // We have an error, just set SimplePie_Misc::error to it and quit
-                               $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
-                       }
-                       else
-                       {
-                               $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
-                       }
+               $this->raw_data = $file->body;
 
-                       SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
+               $headers = $file->headers;
+               $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
+               $sniffed = $sniffer->get_type();
 
-                       return false;
-               }
-               elseif (!empty($this->multifeed_url))
-               {
-                       $i = 0;
-                       $success = 0;
-                       $this->multifeed_objects = array();
-                       foreach ($this->multifeed_url as $url)
-                       {
-                               $this->multifeed_objects[$i] = clone $this;
-                               $this->multifeed_objects[$i]->set_feed_url($url);
-                               $success |= $this->multifeed_objects[$i]->init();
-                               $i++;
-                       }
-                       return (bool) $success;
-               }
-               else
-               {
-                       return false;
-               }
+               return array($headers, $sniffed);
        }
 
        /**
-        * Return the error message for the occured error
+        * Get the error message for the occured error
         *
-        * @access public
-        * @return string Error message
+        * @return string|array Error message, or array of messages for multifeeds
         */
        public function error()
        {
@@ -1768,9 +1562,9 @@ class SimplePie_Core
        }
 
        /**
-        * Return the raw XML
+        * Get the raw XML
         *
-        * This is the same as setting `$xml_dump = true;`, but returns
+        * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
         * the data instead of printing it.
         *
         * @return string|boolean Raw XML data, false if the cache is used
@@ -1780,11 +1574,36 @@ class SimplePie_Core
                return $this->raw_data;
        }
 
+       /**
+        * Get the character encoding used for output
+        *
+        * @since Preview Release
+        * @return string
+        */
        public function get_encoding()
        {
                return $this->sanitize->output_encoding;
        }
 
+       /**
+        * Send the content-type header with correct encoding
+        *
+        * This method ensures that the SimplePie-enabled page is being served with
+        * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
+        * and character encoding HTTP headers (character encoding determined by the
+        * {@see set_output_encoding} config option).
+        *
+        * This won't work properly if any content or whitespace has already been
+        * sent to the browser, because it relies on PHP's
+        * {@link http://php.net/header header()} function, and these are the
+        * circumstances under which the function works.
+        *
+        * Because it's setting these settings for the entire page (as is the nature
+        * of HTTP headers), this should only be used once per page (again, at the
+        * top).
+        *
+        * @param string $mime MIME type to serve the page as
+        */
        public function handle_content_type($mime = 'text/html')
        {
                if (!headers_sent())
@@ -1802,6 +1621,32 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the type of the feed
+        *
+        * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
+        * using {@link http://php.net/language.operators.bitwise bitwise operators}
+        *
+        * @since 0.8 (usage changed to using constants in 1.0)
+        * @see SIMPLEPIE_TYPE_NONE Unknown.
+        * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
+        * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
+        * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
+        * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
+        * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
+        * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
+        * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
+        * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
+        * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
+        * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
+        * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
+        * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
+        * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
+        * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
+        * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
+        * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
+        * @return int SIMPLEPIE_TYPE_* constant
+        */
        public function get_type()
        {
                if (!isset($this->data['type']))
@@ -1883,9 +1728,16 @@ class SimplePie_Core
        }
 
        /**
+        * Get the URL for the feed
+        *
+        * May or may not be different from the URL passed to {@see set_feed_url()},
+        * depending on whether auto-discovery was used.
+        *
+        * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
         * @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
+        * @return string|null
         */
        public function subscribe_url()
        {
@@ -1899,6 +1751,37 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get data for an feed-level element
+        *
+        * This method allows you to get access to ANY element/attribute that is a
+        * sub-element of the opening feed tag.
+        *
+        * The return value is an indexed array of elements matching the given
+        * namespace and tag name. Each element has `attribs`, `data` and `child`
+        * subkeys. For `attribs` and `child`, these contain namespace subkeys.
+        * `attribs` then has one level of associative name => value data (where
+        * `value` is a string) after the namespace. `child` has tag-indexed keys
+        * after the namespace, each member of which is an indexed array matching
+        * this same format.
+        *
+        * For example:
+        * <pre>
+        * // This is probably a bad example because we already support
+        * // <media:content> natively, but it shows you how to parse through
+        * // the nodes.
+        * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
+        * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
+        * $file = $content[0]['attribs']['']['url'];
+        * echo $file;
+        * </pre>
+        *
+        * @since 1.0
+        * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
+        * @param string $namespace The URL of the XML namespace of the elements you're trying to access
+        * @param string $tag Tag name
+        * @return array
+        */
        public function get_feed_tags($namespace, $tag)
        {
                $type = $this->get_type();
@@ -1933,6 +1816,20 @@ class SimplePie_Core
                return null;
        }
 
+       /**
+        * Get data for an channel-level element
+        *
+        * This method allows you to get access to ANY element/attribute in the
+        * channel/header section of the feed.
+        *
+        * See {@see SimplePie::get_feed_tags()} for a description of the return value
+        *
+        * @since 1.0
+        * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
+        * @param string $namespace The URL of the XML namespace of the elements you're trying to access
+        * @param string $tag Tag name
+        * @return array
+        */
        public function get_channel_tags($namespace, $tag)
        {
                $type = $this->get_type();
@@ -1976,6 +1873,20 @@ class SimplePie_Core
                return null;
        }
 
+       /**
+        * Get data for an channel-level element
+        *
+        * This method allows you to get access to ANY element/attribute in the
+        * image/logo section of the feed.
+        *
+        * See {@see SimplePie::get_feed_tags()} for a description of the return value
+        *
+        * @since 1.0
+        * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
+        * @param string $namespace The URL of the XML namespace of the elements you're trying to access
+        * @param string $tag Tag name
+        * @return array
+        */
        public function get_image_tags($namespace, $tag)
        {
                $type = $this->get_type();
@@ -2012,6 +1923,18 @@ class SimplePie_Core
                return null;
        }
 
+       /**
+        * Get the base URL value from the feed
+        *
+        * Uses `<xml:base>` if available, otherwise uses the first link in the
+        * feed, or failing that, the URL of the feed itself.
+        *
+        * @see get_link
+        * @see subscribe_url
+        *
+        * @param array $element
+        * @return string
+        */
        public function get_base($element = array())
        {
                if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
@@ -2028,20 +1951,38 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Sanitize feed data
+        *
+        * @access private
+        * @see SimplePie_Sanitize::sanitize()
+        * @param string $data Data to sanitize
+        * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
+        * @param string $base Base URL to resolve URLs against
+        * @return string Sanitized data
+        */
        public function sanitize($data, $type, $base = '')
        {
                return $this->sanitize->sanitize($data, $type, $base);
        }
 
+       /**
+        * Get the title of the feed
+        *
+        * Uses `<atom:title>`, `<title>` or `<dc:title>`
+        *
+        * @since 1.0 (previously called `get_feed_title` since 0.8)
+        * @return string|null
+        */
        public function get_title()
        {
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
                {
-                       return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+                       return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
                }
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
                {
-                       return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+                       return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
                }
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
                {
@@ -2069,6 +2010,13 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get a category for the feed
+        *
+        * @since Unknown
+        * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
+        * @return SimplePie_Category|null
+        */
        public function get_category($key = 0)
        {
                $categories = $this->get_categories();
@@ -2082,6 +2030,14 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get all categories for the feed
+        *
+        * Uses `<atom:category>`, `<category>` or `<dc:subject>`
+        *
+        * @since Unknown
+        * @return array|null List of {@see SimplePie_Category} objects
+        */
        public function get_categories()
        {
                $categories = array();
@@ -2103,7 +2059,7 @@ class SimplePie_Core
                        {
                                $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
                        }
-                       $categories[] = new $this->category_class($term, $scheme, $label);
+                       $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
                {
@@ -2118,20 +2074,20 @@ class SimplePie_Core
                        {
                                $scheme = null;
                        }
-                       $categories[] = new $this->category_class($term, $scheme, null);
+                       $categories[] = $this->registry->create('Category', array($term, $scheme, null));
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
                {
-                       $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+                       $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
                {
-                       $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+                       $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
                }
 
                if (!empty($categories))
                {
-                       return SimplePie_Misc::array_unique($categories);
+                       return array_unique($categories);
                }
                else
                {
@@ -2139,6 +2095,13 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get an author for the feed
+        *
+        * @since 1.1
+        * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
+        * @return SimplePie_Author|null
+        */
        public function get_author($key = 0)
        {
                $authors = $this->get_authors();
@@ -2152,6 +2115,14 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get all authors for the feed
+        *
+        * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
+        *
+        * @since 1.1
+        * @return array|null List of {@see SimplePie_Author} objects
+        */
        public function get_authors()
        {
                $authors = array();
@@ -2174,7 +2145,7 @@ class SimplePie_Core
                        }
                        if ($name !== null || $email !== null || $uri !== null)
                        {
-                               $authors[] = new $this->author_class($name, $uri, $email);
+                               $authors[] = $this->registry->create('Author', array($name, $uri, $email));
                        }
                }
                if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
@@ -2196,25 +2167,25 @@ class SimplePie_Core
                        }
                        if ($name !== null || $email !== null || $url !== null)
                        {
-                               $authors[] = new $this->author_class($name, $url, $email);
+                               $authors[] = $this->registry->create('Author', array($name, $url, $email));
                        }
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
                {
-                       $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+                       $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
                {
-                       $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+                       $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
                {
-                       $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
+                       $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
                }
 
                if (!empty($authors))
                {
-                       return SimplePie_Misc::array_unique($authors);
+                       return array_unique($authors);
                }
                else
                {
@@ -2222,6 +2193,13 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get a contributor for the feed
+        *
+        * @since 1.1
+        * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
+        * @return SimplePie_Author|null
+        */
        public function get_contributor($key = 0)
        {
                $contributors = $this->get_contributors();
@@ -2235,6 +2213,14 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get all contributors for the feed
+        *
+        * Uses `<atom:contributor>`
+        *
+        * @since 1.1
+        * @return array|null List of {@see SimplePie_Author} objects
+        */
        public function get_contributors()
        {
                $contributors = array();
@@ -2257,7 +2243,7 @@ class SimplePie_Core
                        }
                        if ($name !== null || $email !== null || $uri !== null)
                        {
-                               $contributors[] = new $this->author_class($name, $uri, $email);
+                               $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
                        }
                }
                foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
@@ -2279,13 +2265,13 @@ class SimplePie_Core
                        }
                        if ($name !== null || $email !== null || $url !== null)
                        {
-                               $contributors[] = new $this->author_class($name, $url, $email);
+                               $contributors[] = $this->registry->create('Author', array($name, $url, $email));
                        }
                }
 
                if (!empty($contributors))
                {
-                       return SimplePie_Misc::array_unique($contributors);
+                       return array_unique($contributors);
                }
                else
                {
@@ -2293,6 +2279,14 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get a single link for the feed
+        *
+        * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
+        * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
+        * @param string $rel The relationship of the link to return
+        * @return string|null Link URL
+        */
        public function get_link($key = 0, $rel = 'alternate')
        {
                $links = $this->get_links($rel);
@@ -2307,13 +2301,30 @@ class SimplePie_Core
        }
 
        /**
-        * Added for parity between the parent-level and the item/entry-level.
+        * Get the permalink for the item
+        *
+        * Returns the first link available with a relationship of "alternate".
+        * Identical to {@see get_link()} with key 0
+        *
+        * @see get_link
+        * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
+        * @internal Added for parity between the parent-level and the item/entry-level.
+        * @return string|null Link URL
         */
        public function get_permalink()
        {
                return $this->get_link(0);
        }
 
+       /**
+        * Get all links for the feed
+        *
+        * Uses `<atom:link>` or `<link>`
+        *
+        * @since Beta 2
+        * @param string $rel The relationship of links to return
+        * @return array|null Links found for the feed (strings)
+        */
        public function get_links($rel = 'alternate')
        {
                if (!isset($this->data['links']))
@@ -2358,7 +2369,7 @@ class SimplePie_Core
                        $keys = array_keys($this->data['links']);
                        foreach ($keys as $key)
                        {
-                               if (SimplePie_Misc::is_isegment_nz_nc($key))
+                               if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
                                {
                                        if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
                                        {
@@ -2393,15 +2404,24 @@ class SimplePie_Core
                return $this->all_discovered_feeds;
        }
 
+       /**
+        * Get the content for the item
+        *
+        * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
+        * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
+        *
+        * @since 1.0 (previously called `get_feed_description()` since 0.8)
+        * @return string|null
+        */
        public function get_description()
        {
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
                {
-                       return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+                       return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
                }
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
                {
-                       return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+                       return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
                }
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
                {
@@ -2437,15 +2457,23 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the copyright info for the feed
+        *
+        * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
+        *
+        * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
+        * @return string|null
+        */
        public function get_copyright()
        {
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
                {
-                       return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+                       return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
                }
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
                {
-                       return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
+                       return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
                }
                elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
                {
@@ -2465,6 +2493,14 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the language for the feed
+        *
+        * Uses `<language>`, `<dc:language>`, or @xml_lang
+        *
+        * @since 1.0 (previously called `get_feed_language()` since 0.8)
+        * @return string|null
+        */
        public function get_language()
        {
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
@@ -2501,6 +2537,18 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the latitude coordinates for the item
+        *
+        * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
+        *
+        * Uses `<geo:lat>` or `<georss:point>`
+        *
+        * @since 1.0
+        * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
+        * @link http://www.georss.org/ GeoRSS
+        * @return string|null
+        */
        public function get_latitude()
        {
 
@@ -2518,6 +2566,18 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the longitude coordinates for the feed
+        *
+        * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
+        *
+        * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
+        *
+        * @since 1.0
+        * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
+        * @link http://www.georss.org/ GeoRSS
+        * @return string|null
+        */
        public function get_longitude()
        {
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
@@ -2538,6 +2598,15 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the feed logo's title
+        *
+        * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
+        *
+        * Uses `<image><title>` or `<image><dc:title>`
+        *
+        * @return string|null
+        */
        public function get_image_title()
        {
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
@@ -2566,6 +2635,17 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the feed logo's URL
+        *
+        * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
+        * have a "feed logo" URL. This points directly to the image itself.
+        *
+        * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
+        * `<image><title>` or `<image><dc:title>`
+        *
+        * @return string|null
+        */
        public function get_image_url()
        {
                if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
@@ -2598,6 +2678,18 @@ class SimplePie_Core
                }
        }
 
+
+       /**
+        * Get the feed logo's link
+        *
+        * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
+        * points to a human-readable page that the image should link to.
+        *
+        * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
+        * `<image><title>` or `<image><dc:title>`
+        *
+        * @return string|null
+        */
        public function get_image_link()
        {
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
@@ -2618,6 +2710,16 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the feed logo's link
+        *
+        * RSS 2.0 feeds are allowed to have a "feed logo" width.
+        *
+        * Uses `<image><width>` or defaults to 88.0 if no width is specified and
+        * the feed is an RSS 2.0 feed.
+        *
+        * @return int|float|null
+        */
        public function get_image_width()
        {
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
@@ -2634,6 +2736,16 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the feed logo's height
+        *
+        * RSS 2.0 feeds are allowed to have a "feed logo" height.
+        *
+        * Uses `<image><height>` or defaults to 31.0 if no height is specified and
+        * the feed is an RSS 2.0 feed.
+        *
+        * @return int|float|null
+        */
        public function get_image_height()
        {
                if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
@@ -2650,6 +2762,15 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get the number of items in the feed
+        *
+        * This is well-suited for {@link http://php.net/for for()} loops with
+        * {@see get_item()}
+        *
+        * @param int $max Maximum value to return. 0 for no limit
+        * @return int Number of items in the feed
+        */
        public function get_item_quantity($max = 0)
        {
                $max = (int) $max;
@@ -2664,6 +2785,18 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get a single item from the feed
+        *
+        * This is better suited for {@link http://php.net/for for()} loops, whereas
+        * {@see get_items()} is better suited for
+        * {@link http://php.net/foreach foreach()} loops.
+        *
+        * @see get_item_quantity()
+        * @since Beta 2
+        * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1
+        * @return SimplePie_Item|null
+        */
        public function get_item($key = 0)
        {
                $items = $this->get_items();
@@ -2677,6 +2810,19 @@ class SimplePie_Core
                }
        }
 
+       /**
+        * Get all items from the feed
+        *
+        * This is better suited for {@link http://php.net/for for()} loops, whereas
+        * {@see get_items()} is better suited for
+        * {@link http://php.net/foreach foreach()} loops.
+        *
+        * @see get_item_quantity
+        * @since Beta 2
+        * @param int $start Index to start at
+        * @param int $end Number of items to return. 0 for all items after `$start`
+        * @return array|null List of {@see SimplePie_Item} objects
+        */
        public function get_items($start = 0, $end = 0)
        {
                if (!isset($this->data['items']))
@@ -2693,7 +2839,7 @@ class SimplePie_Core
                                        $keys = array_keys($items);
                                        foreach ($keys as $key)
                                        {
-                                               $this->data['items'][] = new $this->item_class($this, $items[$key]);
+                                               $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
                                        }
                                }
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
@@ -2701,7 +2847,7 @@ class SimplePie_Core
                                        $keys = array_keys($items);
                                        foreach ($keys as $key)
                                        {
-                                               $this->data['items'][] = new $this->item_class($this, $items[$key]);
+                                               $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
                                        }
                                }
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
@@ -2709,7 +2855,7 @@ class SimplePie_Core
                                        $keys = array_keys($items);
                                        foreach ($keys as $key)
                                        {
-                                               $this->data['items'][] = new $this->item_class($this, $items[$key]);
+                                               $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
                                        }
                                }
                                if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
@@ -2717,7 +2863,7 @@ class SimplePie_Core
                                        $keys = array_keys($items);
                                        foreach ($keys as $key)
                                        {
-                                               $this->data['items'][] = new $this->item_class($this, $items[$key]);
+                                               $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
                                        }
                                }
                                if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
@@ -2725,7 +2871,7 @@ class SimplePie_Core
                                        $keys = array_keys($items);
                                        foreach ($keys as $key)
                                        {
-                                               $this->data['items'][] = new $this->item_class($this, $items[$key]);
+                                               $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
                                        }
                                }
                        }
@@ -2751,7 +2897,7 @@ class SimplePie_Core
                                        $this->data['ordered_items'] = $this->data['items'];
                                        if ($do_sort)
                                        {
-                                               usort($this->data['ordered_items'], array(&$this, 'sort_items'));
+                                               usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
                                        }
                                }
                                $items = $this->data['ordered_items'];
@@ -2778,24 +2924,98 @@ class SimplePie_Core
        }
 
        /**
-        * @static
+        * Set the favicon handler
+        *
+        * @deprecated Use your own favicon handling instead
+        */
+       public function set_favicon_handler($page = false, $qs = 'i')
+       {
+               $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
+               trigger_error('Favicon handling has been removed, please use your own handling', $level);
+               return false;
+       }
+
+       /**
+        * Get the favicon for the current feed
+        *
+        * @deprecated Use your own favicon handling instead
+        */
+       public function get_favicon()
+       {
+               $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
+               trigger_error('Favicon handling has been removed, please use your own handling', $level);
+
+               if (($url = $this->get_link()) !== null)
+               {
+                       return 'http://g.etfv.co/' . urlencode($url);
+               }
+
+               return false;
+       }
+
+       /**
+        * Magic method handler
+        *
+        * @param string $method Method name
+        * @param array $args Arguments to the method
+        * @return mixed
+        */
+       public function __call($method, $args)
+       {
+               if (strpos($method, 'subscribe_') === 0)
+               {
+                       $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
+                       trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
+                       return '';
+               }
+               if ($method === 'enable_xml_dump')
+               {
+                       $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
+                       trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
+                       return false;
+               }
+
+               $class = get_class($this);
+               $trace = debug_backtrace();
+               $file = $trace[0]['file'];
+               $line = $trace[0]['line'];
+               trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
+       }
+
+       /**
+        * Sorting callback for items
+        *
+        * @access private
+        * @param SimplePie $a
+        * @param SimplePie $b
+        * @return boolean
         */
-       public function sort_items($a, $b)
+       public static function sort_items($a, $b)
        {
                return $a->get_date('U') <= $b->get_date('U');
        }
 
        /**
-        * @static
+        * Merge items from several feeds into one
+        *
+        * If you're merging multiple feeds together, they need to all have dates
+        * for the items or else SimplePie will refuse to sort them.
+        *
+        * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
+        * @param array $urls List of SimplePie feed objects to merge
+        * @param int $start Starting item
+        * @param int $end Number of items to return
+        * @param int $limit Maximum number of items per feed
+        * @return array
         */
-       public function merge_items($urls, $start = 0, $end = 0, $limit = 0)
+       public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
        {
                if (is_array($urls) && sizeof($urls) > 0)
                {
                        $items = array();
                        foreach ($urls as $arg)
                        {
-                               if (is_a($arg, 'SimplePie'))
+                               if ($arg instanceof SimplePie)
                                {
                                        $items = array_merge($items, $arg->get_items(0, $limit));
                                }
@@ -2817,7 +3037,7 @@ class SimplePie_Core
                        $item = null;
                        if ($do_sort)
                        {
-                               usort($items, array('SimplePie', 'sort_items'));
+                               usort($items, array(get_class($urls[0]), 'sort_items'));
                        }
 
                        if ($end === 0)