balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-simplepie.php (96271B)


      1 <?php
      2 if ( ! class_exists( 'SimplePie', false ) ) :
      3 
      4 // Load classes we will need.
      5 require ABSPATH . WPINC . '/SimplePie/Misc.php';
      6 require ABSPATH . WPINC . '/SimplePie/Cache.php';
      7 require ABSPATH . WPINC . '/SimplePie/File.php';
      8 require ABSPATH . WPINC . '/SimplePie/Sanitize.php';
      9 require ABSPATH . WPINC . '/SimplePie/Registry.php';
     10 require ABSPATH . WPINC . '/SimplePie/IRI.php';
     11 require ABSPATH . WPINC . '/SimplePie/Locator.php';
     12 require ABSPATH . WPINC . '/SimplePie/Content/Type/Sniffer.php';
     13 require ABSPATH . WPINC . '/SimplePie/XML/Declaration/Parser.php';
     14 require ABSPATH . WPINC . '/SimplePie/Parser.php';
     15 require ABSPATH . WPINC . '/SimplePie/Item.php';
     16 require ABSPATH . WPINC . '/SimplePie/Parse/Date.php';
     17 require ABSPATH . WPINC . '/SimplePie/Author.php';
     18 
     19 /**
     20  * WordPress autoloader for SimplePie.
     21  *
     22  * @since 3.5.0
     23  */
     24 function wp_simplepie_autoload( $class ) {
     25 	if ( 0 !== strpos( $class, 'SimplePie_' ) )
     26 		return;
     27 
     28 	$file = ABSPATH . WPINC . '/' . str_replace( '_', '/', $class ) . '.php';
     29 	include $file;
     30 }
     31 
     32 /**
     33  * We autoload classes we may not need.
     34  */
     35 spl_autoload_register( 'wp_simplepie_autoload' );
     36 
     37 /**
     38  * SimplePie
     39  *
     40  * A PHP-Based RSS and Atom Feed Framework.
     41  * Takes the hard work out of managing a complete RSS/Atom solution.
     42  *
     43  * Copyright (c) 2004-2017, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
     44  * All rights reserved.
     45  *
     46  * Redistribution and use in source and binary forms, with or without modification, are
     47  * permitted provided that the following conditions are met:
     48  *
     49  * 	* Redistributions of source code must retain the above copyright notice, this list of
     50  * 	  conditions and the following disclaimer.
     51  *
     52  * 	* Redistributions in binary form must reproduce the above copyright notice, this list
     53  * 	  of conditions and the following disclaimer in the documentation and/or other materials
     54  * 	  provided with the distribution.
     55  *
     56  * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
     57  * 	  to endorse or promote products derived from this software without specific prior
     58  * 	  written permission.
     59  *
     60  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
     61  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     62  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
     63  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     64  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     65  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     67  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     68  * POSSIBILITY OF SUCH DAMAGE.
     69  *
     70  * @package SimplePie
     71  * @version 1.5.6
     72  * @copyright 2004-2017 Ryan Parman, Sam Sneddon, Ryan McCue
     73  * @author Ryan Parman
     74  * @author Sam Sneddon
     75  * @author Ryan McCue
     76  * @link http://simplepie.org/ SimplePie
     77  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
     78  */
     79 
     80 /**
     81  * SimplePie Name
     82  */
     83 define('SIMPLEPIE_NAME', 'SimplePie');
     84 
     85 /**
     86  * SimplePie Version
     87  */
     88 define('SIMPLEPIE_VERSION', '1.5.6');
     89 
     90 /**
     91  * SimplePie Build
     92  * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
     93  */
     94 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));
     95 
     96 /**
     97  * SimplePie Website URL
     98  */
     99 define('SIMPLEPIE_URL', 'http://simplepie.org');
    100 
    101 /**
    102  * SimplePie Useragent
    103  * @see SimplePie::set_useragent()
    104  */
    105 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
    106 
    107 /**
    108  * SimplePie Linkback
    109  */
    110 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
    111 
    112 /**
    113  * No Autodiscovery
    114  * @see SimplePie::set_autodiscovery_level()
    115  */
    116 define('SIMPLEPIE_LOCATOR_NONE', 0);
    117 
    118 /**
    119  * Feed Link Element Autodiscovery
    120  * @see SimplePie::set_autodiscovery_level()
    121  */
    122 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
    123 
    124 /**
    125  * Local Feed Extension Autodiscovery
    126  * @see SimplePie::set_autodiscovery_level()
    127  */
    128 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
    129 
    130 /**
    131  * Local Feed Body Autodiscovery
    132  * @see SimplePie::set_autodiscovery_level()
    133  */
    134 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
    135 
    136 /**
    137  * Remote Feed Extension Autodiscovery
    138  * @see SimplePie::set_autodiscovery_level()
    139  */
    140 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
    141 
    142 /**
    143  * Remote Feed Body Autodiscovery
    144  * @see SimplePie::set_autodiscovery_level()
    145  */
    146 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
    147 
    148 /**
    149  * All Feed Autodiscovery
    150  * @see SimplePie::set_autodiscovery_level()
    151  */
    152 define('SIMPLEPIE_LOCATOR_ALL', 31);
    153 
    154 /**
    155  * No known feed type
    156  */
    157 define('SIMPLEPIE_TYPE_NONE', 0);
    158 
    159 /**
    160  * RSS 0.90
    161  */
    162 define('SIMPLEPIE_TYPE_RSS_090', 1);
    163 
    164 /**
    165  * RSS 0.91 (Netscape)
    166  */
    167 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
    168 
    169 /**
    170  * RSS 0.91 (Userland)
    171  */
    172 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
    173 
    174 /**
    175  * RSS 0.91 (both Netscape and Userland)
    176  */
    177 define('SIMPLEPIE_TYPE_RSS_091', 6);
    178 
    179 /**
    180  * RSS 0.92
    181  */
    182 define('SIMPLEPIE_TYPE_RSS_092', 8);
    183 
    184 /**
    185  * RSS 0.93
    186  */
    187 define('SIMPLEPIE_TYPE_RSS_093', 16);
    188 
    189 /**
    190  * RSS 0.94
    191  */
    192 define('SIMPLEPIE_TYPE_RSS_094', 32);
    193 
    194 /**
    195  * RSS 1.0
    196  */
    197 define('SIMPLEPIE_TYPE_RSS_10', 64);
    198 
    199 /**
    200  * RSS 2.0
    201  */
    202 define('SIMPLEPIE_TYPE_RSS_20', 128);
    203 
    204 /**
    205  * RDF-based RSS
    206  */
    207 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
    208 
    209 /**
    210  * Non-RDF-based RSS (truly intended as syndication format)
    211  */
    212 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
    213 
    214 /**
    215  * All RSS
    216  */
    217 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
    218 
    219 /**
    220  * Atom 0.3
    221  */
    222 define('SIMPLEPIE_TYPE_ATOM_03', 256);
    223 
    224 /**
    225  * Atom 1.0
    226  */
    227 define('SIMPLEPIE_TYPE_ATOM_10', 512);
    228 
    229 /**
    230  * All Atom
    231  */
    232 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
    233 
    234 /**
    235  * All feed types
    236  */
    237 define('SIMPLEPIE_TYPE_ALL', 1023);
    238 
    239 /**
    240  * No construct
    241  */
    242 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
    243 
    244 /**
    245  * Text construct
    246  */
    247 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
    248 
    249 /**
    250  * HTML construct
    251  */
    252 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
    253 
    254 /**
    255  * XHTML construct
    256  */
    257 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
    258 
    259 /**
    260  * base64-encoded construct
    261  */
    262 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
    263 
    264 /**
    265  * IRI construct
    266  */
    267 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
    268 
    269 /**
    270  * A construct that might be HTML
    271  */
    272 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
    273 
    274 /**
    275  * All constructs
    276  */
    277 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
    278 
    279 /**
    280  * Don't change case
    281  */
    282 define('SIMPLEPIE_SAME_CASE', 1);
    283 
    284 /**
    285  * Change to lowercase
    286  */
    287 define('SIMPLEPIE_LOWERCASE', 2);
    288 
    289 /**
    290  * Change to uppercase
    291  */
    292 define('SIMPLEPIE_UPPERCASE', 4);
    293 
    294 /**
    295  * PCRE for HTML attributes
    296  */
    297 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
    298 
    299 /**
    300  * PCRE for XML attributes
    301  */
    302 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
    303 
    304 /**
    305  * XML Namespace
    306  */
    307 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
    308 
    309 /**
    310  * Atom 1.0 Namespace
    311  */
    312 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
    313 
    314 /**
    315  * Atom 0.3 Namespace
    316  */
    317 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
    318 
    319 /**
    320  * RDF Namespace
    321  */
    322 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
    323 
    324 /**
    325  * RSS 0.90 Namespace
    326  */
    327 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
    328 
    329 /**
    330  * RSS 1.0 Namespace
    331  */
    332 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
    333 
    334 /**
    335  * RSS 1.0 Content Module Namespace
    336  */
    337 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
    338 
    339 /**
    340  * RSS 2.0 Namespace
    341  * (Stupid, I know, but I'm certain it will confuse people less with support.)
    342  */
    343 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
    344 
    345 /**
    346  * DC 1.0 Namespace
    347  */
    348 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
    349 
    350 /**
    351  * DC 1.1 Namespace
    352  */
    353 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
    354 
    355 /**
    356  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
    357  */
    358 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
    359 
    360 /**
    361  * GeoRSS Namespace
    362  */
    363 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
    364 
    365 /**
    366  * Media RSS Namespace
    367  */
    368 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
    369 
    370 /**
    371  * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
    372  */
    373 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
    374 
    375 /**
    376  * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
    377  */
    378 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
    379 
    380 /**
    381  * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
    382  */
    383 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
    384 
    385 /**
    386  * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
    387  */
    388 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
    389 
    390 /**
    391  * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
    392  */
    393 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
    394 
    395 /**
    396  * iTunes RSS Namespace
    397  */
    398 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
    399 
    400 /**
    401  * XHTML Namespace
    402  */
    403 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
    404 
    405 /**
    406  * IANA Link Relations Registry
    407  */
    408 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
    409 
    410 /**
    411  * No file source
    412  */
    413 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
    414 
    415 /**
    416  * Remote file source
    417  */
    418 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
    419 
    420 /**
    421  * Local file source
    422  */
    423 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
    424 
    425 /**
    426  * fsockopen() file source
    427  */
    428 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
    429 
    430 /**
    431  * cURL file source
    432  */
    433 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
    434 
    435 /**
    436  * file_get_contents() file source
    437  */
    438 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
    439 
    440 
    441 
    442 /**
    443  * SimplePie
    444  *
    445  * @package SimplePie
    446  * @subpackage API
    447  */
    448 class SimplePie
    449 {
    450 	/**
    451 	 * @var array Raw data
    452 	 * @access private
    453 	 */
    454 	public $data = array();
    455 
    456 	/**
    457 	 * @var mixed Error string
    458 	 * @access private
    459 	 */
    460 	public $error;
    461 
    462 	/**
    463 	 * @var object Instance of SimplePie_Sanitize (or other class)
    464 	 * @see SimplePie::set_sanitize_class()
    465 	 * @access private
    466 	 */
    467 	public $sanitize;
    468 
    469 	/**
    470 	 * @var string SimplePie Useragent
    471 	 * @see SimplePie::set_useragent()
    472 	 * @access private
    473 	 */
    474 	public $useragent = SIMPLEPIE_USERAGENT;
    475 
    476 	/**
    477 	 * @var string Feed URL
    478 	 * @see SimplePie::set_feed_url()
    479 	 * @access private
    480 	 */
    481 	public $feed_url;
    482 
    483 	/**
    484 	 * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently
    485 	 * @see SimplePie::subscribe_url()
    486 	 * @access private
    487 	 */
    488 	public $permanent_url = null;
    489 
    490 	/**
    491 	 * @var object Instance of SimplePie_File to use as a feed
    492 	 * @see SimplePie::set_file()
    493 	 * @access private
    494 	 */
    495 	public $file;
    496 
    497 	/**
    498 	 * @var string Raw feed data
    499 	 * @see SimplePie::set_raw_data()
    500 	 * @access private
    501 	 */
    502 	public $raw_data;
    503 
    504 	/**
    505 	 * @var int Timeout for fetching remote files
    506 	 * @see SimplePie::set_timeout()
    507 	 * @access private
    508 	 */
    509 	public $timeout = 10;
    510 
    511 	/**
    512 	 * @var array Custom curl options
    513 	 * @see SimplePie::set_curl_options()
    514 	 * @access private
    515 	 */
    516 	public $curl_options = array();
    517 
    518 	/**
    519 	 * @var bool Forces fsockopen() to be used for remote files instead
    520 	 * of cURL, even if a new enough version is installed
    521 	 * @see SimplePie::force_fsockopen()
    522 	 * @access private
    523 	 */
    524 	public $force_fsockopen = false;
    525 
    526 	/**
    527 	 * @var bool Force the given data/URL to be treated as a feed no matter what
    528 	 * it appears like
    529 	 * @see SimplePie::force_feed()
    530 	 * @access private
    531 	 */
    532 	public $force_feed = false;
    533 
    534 	/**
    535 	 * @var bool Enable/Disable Caching
    536 	 * @see SimplePie::enable_cache()
    537 	 * @access private
    538 	 */
    539 	public $cache = true;
    540 
    541 	/**
    542 	 * @var bool Force SimplePie to fallback to expired cache, if enabled,
    543 	 * when feed is unavailable.
    544 	 * @see SimplePie::force_cache_fallback()
    545 	 * @access private
    546 	 */
    547 	public $force_cache_fallback = false;
    548 
    549 	/**
    550 	 * @var int Cache duration (in seconds)
    551 	 * @see SimplePie::set_cache_duration()
    552 	 * @access private
    553 	 */
    554 	public $cache_duration = 3600;
    555 
    556 	/**
    557 	 * @var int Auto-discovery cache duration (in seconds)
    558 	 * @see SimplePie::set_autodiscovery_cache_duration()
    559 	 * @access private
    560 	 */
    561 	public $autodiscovery_cache_duration = 604800; // 7 Days.
    562 
    563 	/**
    564 	 * @var string Cache location (relative to executing script)
    565 	 * @see SimplePie::set_cache_location()
    566 	 * @access private
    567 	 */
    568 	public $cache_location = './cache';
    569 
    570 	/**
    571 	 * @var string Function that creates the cache filename
    572 	 * @see SimplePie::set_cache_name_function()
    573 	 * @access private
    574 	 */
    575 	public $cache_name_function = 'md5';
    576 
    577 	/**
    578 	 * @var bool Reorder feed by date descending
    579 	 * @see SimplePie::enable_order_by_date()
    580 	 * @access private
    581 	 */
    582 	public $order_by_date = true;
    583 
    584 	/**
    585 	 * @var mixed Force input encoding to be set to the follow value
    586 	 * (false, or anything type-cast to false, disables this feature)
    587 	 * @see SimplePie::set_input_encoding()
    588 	 * @access private
    589 	 */
    590 	public $input_encoding = false;
    591 
    592 	/**
    593 	 * @var int Feed Autodiscovery Level
    594 	 * @see SimplePie::set_autodiscovery_level()
    595 	 * @access private
    596 	 */
    597 	public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
    598 
    599 	/**
    600 	 * Class registry object
    601 	 *
    602 	 * @var SimplePie_Registry
    603 	 */
    604 	public $registry;
    605 
    606 	/**
    607 	 * @var int Maximum number of feeds to check with autodiscovery
    608 	 * @see SimplePie::set_max_checked_feeds()
    609 	 * @access private
    610 	 */
    611 	public $max_checked_feeds = 10;
    612 
    613 	/**
    614 	 * @var array All the feeds found during the autodiscovery process
    615 	 * @see SimplePie::get_all_discovered_feeds()
    616 	 * @access private
    617 	 */
    618 	public $all_discovered_feeds = array();
    619 
    620 	/**
    621 	 * @var string Web-accessible path to the handler_image.php file.
    622 	 * @see SimplePie::set_image_handler()
    623 	 * @access private
    624 	 */
    625 	public $image_handler = '';
    626 
    627 	/**
    628 	 * @var array Stores the URLs when multiple feeds are being initialized.
    629 	 * @see SimplePie::set_feed_url()
    630 	 * @access private
    631 	 */
    632 	public $multifeed_url = array();
    633 
    634 	/**
    635 	 * @var array Stores SimplePie objects when multiple feeds initialized.
    636 	 * @access private
    637 	 */
    638 	public $multifeed_objects = array();
    639 
    640 	/**
    641 	 * @var array Stores the get_object_vars() array for use with multifeeds.
    642 	 * @see SimplePie::set_feed_url()
    643 	 * @access private
    644 	 */
    645 	public $config_settings = null;
    646 
    647 	/**
    648 	 * @var integer Stores the number of items to return per-feed with multifeeds.
    649 	 * @see SimplePie::set_item_limit()
    650 	 * @access private
    651 	 */
    652 	public $item_limit = 0;
    653 
    654 	/**
    655 	 * @var bool Stores if last-modified and/or etag headers were sent with the
    656 	 * request when checking a feed.
    657 	 */
    658 	public $check_modified = false;
    659 
    660 	/**
    661 	 * @var array Stores the default attributes to be stripped by strip_attributes().
    662 	 * @see SimplePie::strip_attributes()
    663 	 * @access private
    664 	 */
    665 	public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
    666 
    667 	/**
    668 	 * @var array Stores the default attributes to add to different tags by add_attributes().
    669 	 * @see SimplePie::add_attributes()
    670 	 * @access private
    671 	 */
    672 	public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'));
    673 
    674 	/**
    675 	 * @var array Stores the default tags to be stripped by strip_htmltags().
    676 	 * @see SimplePie::strip_htmltags()
    677 	 * @access private
    678 	 */
    679 	public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
    680 
    681 	/**
    682 	 * @var bool Should we throw exceptions, or use the old-style error property?
    683 	 * @access private
    684 	 */
    685 	public $enable_exceptions = false;
    686 
    687 	/**
    688 	 * The SimplePie class contains feed level data and options
    689 	 *
    690 	 * To use SimplePie, create the SimplePie object with no parameters. You can
    691 	 * then set configuration options using the provided methods. After setting
    692 	 * them, you must initialise the feed using $feed->init(). At that point the
    693 	 * object's methods and properties will be available to you.
    694 	 *
    695 	 * Previously, it was possible to pass in the feed URL along with cache
    696 	 * options directly into the constructor. This has been removed as of 1.3 as
    697 	 * it caused a lot of confusion.
    698 	 *
    699 	 * @since 1.0 Preview Release
    700 	 */
    701 	public function __construct()
    702 	{
    703 		if (version_compare(PHP_VERSION, '5.6', '<'))
    704 		{
    705 			trigger_error('Please upgrade to PHP 5.6 or newer.');
    706 			die();
    707 		}
    708 
    709 		// Other objects, instances created here so we can set options on them
    710 		$this->sanitize = new SimplePie_Sanitize();
    711 		$this->registry = new SimplePie_Registry();
    712 
    713 		if (func_num_args() > 0)
    714 		{
    715 			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
    716 			trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_duration() directly.', $level);
    717 
    718 			$args = func_get_args();
    719 			switch (count($args)) {
    720 				case 3:
    721 					$this->set_cache_duration($args[2]);
    722 				case 2:
    723 					$this->set_cache_location($args[1]);
    724 				case 1:
    725 					$this->set_feed_url($args[0]);
    726 					$this->init();
    727 			}
    728 		}
    729 	}
    730 
    731 	/**
    732 	 * Used for converting object to a string
    733 	 */
    734 	public function __toString()
    735 	{
    736 		return md5(serialize($this->data));
    737 	}
    738 
    739 	/**
    740 	 * Remove items that link back to this before destroying this object
    741 	 */
    742 	public function __destruct()
    743 	{
    744 		if (!gc_enabled())
    745 		{
    746 			if (!empty($this->data['items']))
    747 			{
    748 				foreach ($this->data['items'] as $item)
    749 				{
    750 					$item->__destruct();
    751 				}
    752 				unset($item, $this->data['items']);
    753 			}
    754 			if (!empty($this->data['ordered_items']))
    755 			{
    756 				foreach ($this->data['ordered_items'] as $item)
    757 				{
    758 					$item->__destruct();
    759 				}
    760 				unset($item, $this->data['ordered_items']);
    761 			}
    762 		}
    763 	}
    764 
    765 	/**
    766 	 * Force the given data/URL to be treated as a feed
    767 	 *
    768 	 * This tells SimplePie to ignore the content-type provided by the server.
    769 	 * Be careful when using this option, as it will also disable autodiscovery.
    770 	 *
    771 	 * @since 1.1
    772 	 * @param bool $enable Force the given data/URL to be treated as a feed
    773 	 */
    774 	public function force_feed($enable = false)
    775 	{
    776 		$this->force_feed = (bool) $enable;
    777 	}
    778 
    779 	/**
    780 	 * Set the URL of the feed you want to parse
    781 	 *
    782 	 * This allows you to enter the URL of the feed you want to parse, or the
    783 	 * website you want to try to use auto-discovery on. This takes priority
    784 	 * over any set raw data.
    785 	 *
    786 	 * You can set multiple feeds to mash together by passing an array instead
    787 	 * of a string for the $url. Remember that with each additional feed comes
    788 	 * additional processing and resources.
    789 	 *
    790 	 * @since 1.0 Preview Release
    791 	 * @see set_raw_data()
    792 	 * @param string|array $url This is the URL (or array of URLs) that you want to parse.
    793 	 */
    794 	public function set_feed_url($url)
    795 	{
    796 		$this->multifeed_url = array();
    797 		if (is_array($url))
    798 		{
    799 			foreach ($url as $value)
    800 			{
    801 				$this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
    802 			}
    803 		}
    804 		else
    805 		{
    806 			$this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
    807 			$this->permanent_url = $this->feed_url;
    808 		}
    809 	}
    810 
    811 	/**
    812 	 * Set an instance of {@see SimplePie_File} to use as a feed
    813 	 *
    814 	 * @param SimplePie_File &$file
    815 	 * @return bool True on success, false on failure
    816 	 */
    817 	public function set_file(&$file)
    818 	{
    819 		if ($file instanceof SimplePie_File)
    820 		{
    821 			$this->feed_url = $file->url;
    822 			$this->permanent_url = $this->feed_url;
    823 			$this->file =& $file;
    824 			return true;
    825 		}
    826 		return false;
    827 	}
    828 
    829 	/**
    830 	 * Set the raw XML data to parse
    831 	 *
    832 	 * Allows you to use a string of RSS/Atom data instead of a remote feed.
    833 	 *
    834 	 * If you have a feed available as a string in PHP, you can tell SimplePie
    835 	 * to parse that data string instead of a remote feed. Any set feed URL
    836 	 * takes precedence.
    837 	 *
    838 	 * @since 1.0 Beta 3
    839 	 * @param string $data RSS or Atom data as a string.
    840 	 * @see set_feed_url()
    841 	 */
    842 	public function set_raw_data($data)
    843 	{
    844 		$this->raw_data = $data;
    845 	}
    846 
    847 	/**
    848 	 * Set the default timeout for fetching remote feeds
    849 	 *
    850 	 * This allows you to change the maximum time the feed's server to respond
    851 	 * and send the feed back.
    852 	 *
    853 	 * @since 1.0 Beta 3
    854 	 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
    855 	 */
    856 	public function set_timeout($timeout = 10)
    857 	{
    858 		$this->timeout = (int) $timeout;
    859 	}
    860 
    861 	/**
    862 	 * Set custom curl options
    863 	 *
    864 	 * This allows you to change default curl options
    865 	 *
    866 	 * @since 1.0 Beta 3
    867 	 * @param array $curl_options Curl options to add to default settings
    868 	 */
    869 	public function set_curl_options(array $curl_options = array())
    870 	{
    871 		$this->curl_options = $curl_options;
    872 	}
    873 
    874 	/**
    875 	 * Force SimplePie to use fsockopen() instead of cURL
    876 	 *
    877 	 * @since 1.0 Beta 3
    878 	 * @param bool $enable Force fsockopen() to be used
    879 	 */
    880 	public function force_fsockopen($enable = false)
    881 	{
    882 		$this->force_fsockopen = (bool) $enable;
    883 	}
    884 
    885 	/**
    886 	 * Enable/disable caching in SimplePie.
    887 	 *
    888 	 * This option allows you to disable caching all-together in SimplePie.
    889 	 * However, disabling the cache can lead to longer load times.
    890 	 *
    891 	 * @since 1.0 Preview Release
    892 	 * @param bool $enable Enable caching
    893 	 */
    894 	public function enable_cache($enable = true)
    895 	{
    896 		$this->cache = (bool) $enable;
    897 	}
    898 
    899 	/**
    900 	 * SimplePie to continue to fall back to expired cache, if enabled, when
    901 	 * feed is unavailable.
    902 	 *
    903 	 * This tells SimplePie to ignore any file errors and fall back to cache
    904 	 * instead. This only works if caching is enabled and cached content
    905 	 * still exists.
    906 
    907 	 * @param bool $enable Force use of cache on fail.
    908 	 */
    909 	public function force_cache_fallback($enable = false)
    910 	{
    911 		$this->force_cache_fallback= (bool) $enable;
    912 	}
    913 
    914 	/**
    915 	 * Set the length of time (in seconds) that the contents of a feed will be
    916 	 * cached
    917 	 *
    918 	 * @param int $seconds The feed content cache duration
    919 	 */
    920 	public function set_cache_duration($seconds = 3600)
    921 	{
    922 		$this->cache_duration = (int) $seconds;
    923 	}
    924 
    925 	/**
    926 	 * Set the length of time (in seconds) that the autodiscovered feed URL will
    927 	 * be cached
    928 	 *
    929 	 * @param int $seconds The autodiscovered feed URL cache duration.
    930 	 */
    931 	public function set_autodiscovery_cache_duration($seconds = 604800)
    932 	{
    933 		$this->autodiscovery_cache_duration = (int) $seconds;
    934 	}
    935 
    936 	/**
    937 	 * Set the file system location where the cached files should be stored
    938 	 *
    939 	 * @param string $location The file system location.
    940 	 */
    941 	public function set_cache_location($location = './cache')
    942 	{
    943 		$this->cache_location = (string) $location;
    944 	}
    945 
    946 	/**
    947 	 * Set whether feed items should be sorted into reverse chronological order
    948 	 *
    949 	 * @param bool $enable Sort as reverse chronological order.
    950 	 */
    951 	public function enable_order_by_date($enable = true)
    952 	{
    953 		$this->order_by_date = (bool) $enable;
    954 	}
    955 
    956 	/**
    957 	 * Set the character encoding used to parse the feed
    958 	 *
    959 	 * This overrides the encoding reported by the feed, however it will fall
    960 	 * back to the normal encoding detection if the override fails
    961 	 *
    962 	 * @param string $encoding Character encoding
    963 	 */
    964 	public function set_input_encoding($encoding = false)
    965 	{
    966 		if ($encoding)
    967 		{
    968 			$this->input_encoding = (string) $encoding;
    969 		}
    970 		else
    971 		{
    972 			$this->input_encoding = false;
    973 		}
    974 	}
    975 
    976 	/**
    977 	 * Set how much feed autodiscovery to do
    978 	 *
    979 	 * @see SIMPLEPIE_LOCATOR_NONE
    980 	 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
    981 	 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
    982 	 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
    983 	 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
    984 	 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
    985 	 * @see SIMPLEPIE_LOCATOR_ALL
    986 	 * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
    987 	 */
    988 	public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
    989 	{
    990 		$this->autodiscovery = (int) $level;
    991 	}
    992 
    993 	/**
    994 	 * Get the class registry
    995 	 *
    996 	 * Use this to override SimplePie's default classes
    997 	 * @see SimplePie_Registry
    998 	 * @return SimplePie_Registry
    999 	 */
   1000 	public function &get_registry()
   1001 	{
   1002 		return $this->registry;
   1003 	}
   1004 
   1005 	/**#@+
   1006 	 * Useful when you are overloading or extending SimplePie's default classes.
   1007 	 *
   1008 	 * @deprecated Use {@see get_registry()} instead
   1009 	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
   1010 	 * @param string $class Name of custom class
   1011 	 * @return boolean True on success, false otherwise
   1012 	 */
   1013 	/**
   1014 	 * Set which class SimplePie uses for caching
   1015 	 */
   1016 	public function set_cache_class($class = 'SimplePie_Cache')
   1017 	{
   1018 		return $this->registry->register('Cache', $class, true);
   1019 	}
   1020 
   1021 	/**
   1022 	 * Set which class SimplePie uses for auto-discovery
   1023 	 */
   1024 	public function set_locator_class($class = 'SimplePie_Locator')
   1025 	{
   1026 		return $this->registry->register('Locator', $class, true);
   1027 	}
   1028 
   1029 	/**
   1030 	 * Set which class SimplePie uses for XML parsing
   1031 	 */
   1032 	public function set_parser_class($class = 'SimplePie_Parser')
   1033 	{
   1034 		return $this->registry->register('Parser', $class, true);
   1035 	}
   1036 
   1037 	/**
   1038 	 * Set which class SimplePie uses for remote file fetching
   1039 	 */
   1040 	public function set_file_class($class = 'SimplePie_File')
   1041 	{
   1042 		return $this->registry->register('File', $class, true);
   1043 	}
   1044 
   1045 	/**
   1046 	 * Set which class SimplePie uses for data sanitization
   1047 	 */
   1048 	public function set_sanitize_class($class = 'SimplePie_Sanitize')
   1049 	{
   1050 		return $this->registry->register('Sanitize', $class, true);
   1051 	}
   1052 
   1053 	/**
   1054 	 * Set which class SimplePie uses for handling feed items
   1055 	 */
   1056 	public function set_item_class($class = 'SimplePie_Item')
   1057 	{
   1058 		return $this->registry->register('Item', $class, true);
   1059 	}
   1060 
   1061 	/**
   1062 	 * Set which class SimplePie uses for handling author data
   1063 	 */
   1064 	public function set_author_class($class = 'SimplePie_Author')
   1065 	{
   1066 		return $this->registry->register('Author', $class, true);
   1067 	}
   1068 
   1069 	/**
   1070 	 * Set which class SimplePie uses for handling category data
   1071 	 */
   1072 	public function set_category_class($class = 'SimplePie_Category')
   1073 	{
   1074 		return $this->registry->register('Category', $class, true);
   1075 	}
   1076 
   1077 	/**
   1078 	 * Set which class SimplePie uses for feed enclosures
   1079 	 */
   1080 	public function set_enclosure_class($class = 'SimplePie_Enclosure')
   1081 	{
   1082 		return $this->registry->register('Enclosure', $class, true);
   1083 	}
   1084 
   1085 	/**
   1086 	 * Set which class SimplePie uses for `<media:text>` captions
   1087 	 */
   1088 	public function set_caption_class($class = 'SimplePie_Caption')
   1089 	{
   1090 		return $this->registry->register('Caption', $class, true);
   1091 	}
   1092 
   1093 	/**
   1094 	 * Set which class SimplePie uses for `<media:copyright>`
   1095 	 */
   1096 	public function set_copyright_class($class = 'SimplePie_Copyright')
   1097 	{
   1098 		return $this->registry->register('Copyright', $class, true);
   1099 	}
   1100 
   1101 	/**
   1102 	 * Set which class SimplePie uses for `<media:credit>`
   1103 	 */
   1104 	public function set_credit_class($class = 'SimplePie_Credit')
   1105 	{
   1106 		return $this->registry->register('Credit', $class, true);
   1107 	}
   1108 
   1109 	/**
   1110 	 * Set which class SimplePie uses for `<media:rating>`
   1111 	 */
   1112 	public function set_rating_class($class = 'SimplePie_Rating')
   1113 	{
   1114 		return $this->registry->register('Rating', $class, true);
   1115 	}
   1116 
   1117 	/**
   1118 	 * Set which class SimplePie uses for `<media:restriction>`
   1119 	 */
   1120 	public function set_restriction_class($class = 'SimplePie_Restriction')
   1121 	{
   1122 		return $this->registry->register('Restriction', $class, true);
   1123 	}
   1124 
   1125 	/**
   1126 	 * Set which class SimplePie uses for content-type sniffing
   1127 	 */
   1128 	public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
   1129 	{
   1130 		return $this->registry->register('Content_Type_Sniffer', $class, true);
   1131 	}
   1132 
   1133 	/**
   1134 	 * Set which class SimplePie uses item sources
   1135 	 */
   1136 	public function set_source_class($class = 'SimplePie_Source')
   1137 	{
   1138 		return $this->registry->register('Source', $class, true);
   1139 	}
   1140 	/**#@-*/
   1141 
   1142 	/**
   1143 	 * Set the user agent string
   1144 	 *
   1145 	 * @param string $ua New user agent string.
   1146 	 */
   1147 	public function set_useragent($ua = SIMPLEPIE_USERAGENT)
   1148 	{
   1149 		$this->useragent = (string) $ua;
   1150 	}
   1151 
   1152 	/**
   1153 	 * Set callback function to create cache filename with
   1154 	 *
   1155 	 * @param mixed $function Callback function
   1156 	 */
   1157 	public function set_cache_name_function($function = 'md5')
   1158 	{
   1159 		if (is_callable($function))
   1160 		{
   1161 			$this->cache_name_function = $function;
   1162 		}
   1163 	}
   1164 
   1165 	/**
   1166 	 * Set options to make SP as fast as possible
   1167 	 *
   1168 	 * Forgoes a substantial amount of data sanitization in favor of speed. This
   1169 	 * turns SimplePie into a dumb parser of feeds.
   1170 	 *
   1171 	 * @param bool $set Whether to set them or not
   1172 	 */
   1173 	public function set_stupidly_fast($set = false)
   1174 	{
   1175 		if ($set)
   1176 		{
   1177 			$this->enable_order_by_date(false);
   1178 			$this->remove_div(false);
   1179 			$this->strip_comments(false);
   1180 			$this->strip_htmltags(false);
   1181 			$this->strip_attributes(false);
   1182 			$this->add_attributes(false);
   1183 			$this->set_image_handler(false);
   1184 		}
   1185 	}
   1186 
   1187 	/**
   1188 	 * Set maximum number of feeds to check with autodiscovery
   1189 	 *
   1190 	 * @param int $max Maximum number of feeds to check
   1191 	 */
   1192 	public function set_max_checked_feeds($max = 10)
   1193 	{
   1194 		$this->max_checked_feeds = (int) $max;
   1195 	}
   1196 
   1197 	public function remove_div($enable = true)
   1198 	{
   1199 		$this->sanitize->remove_div($enable);
   1200 	}
   1201 
   1202 	public function strip_htmltags($tags = '', $encode = null)
   1203 	{
   1204 		if ($tags === '')
   1205 		{
   1206 			$tags = $this->strip_htmltags;
   1207 		}
   1208 		$this->sanitize->strip_htmltags($tags);
   1209 		if ($encode !== null)
   1210 		{
   1211 			$this->sanitize->encode_instead_of_strip($tags);
   1212 		}
   1213 	}
   1214 
   1215 	public function encode_instead_of_strip($enable = true)
   1216 	{
   1217 		$this->sanitize->encode_instead_of_strip($enable);
   1218 	}
   1219 
   1220 	public function strip_attributes($attribs = '')
   1221 	{
   1222 		if ($attribs === '')
   1223 		{
   1224 			$attribs = $this->strip_attributes;
   1225 		}
   1226 		$this->sanitize->strip_attributes($attribs);
   1227 	}
   1228 
   1229 	public function add_attributes($attribs = '')
   1230 	{
   1231 		if ($attribs === '')
   1232 		{
   1233 			$attribs = $this->add_attributes;
   1234 		}
   1235 		$this->sanitize->add_attributes($attribs);
   1236 	}
   1237 
   1238 	/**
   1239 	 * Set the output encoding
   1240 	 *
   1241 	 * Allows you to override SimplePie's output to match that of your webpage.
   1242 	 * This is useful for times when your webpages are not being served as
   1243 	 * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and
   1244 	 * is similar to {@see set_input_encoding()}.
   1245 	 *
   1246 	 * It should be noted, however, that not all character encodings can support
   1247 	 * all characters. If your page is being served as ISO-8859-1 and you try
   1248 	 * to display a Japanese feed, you'll likely see garbled characters.
   1249 	 * Because of this, it is highly recommended to ensure that your webpages
   1250 	 * are served as UTF-8.
   1251 	 *
   1252 	 * The number of supported character encodings depends on whether your web
   1253 	 * host supports {@link http://php.net/mbstring mbstring},
   1254 	 * {@link http://php.net/iconv iconv}, or both. See
   1255 	 * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
   1256 	 * more information.
   1257 	 *
   1258 	 * @param string $encoding
   1259 	 */
   1260 	public function set_output_encoding($encoding = 'UTF-8')
   1261 	{
   1262 		$this->sanitize->set_output_encoding($encoding);
   1263 	}
   1264 
   1265 	public function strip_comments($strip = false)
   1266 	{
   1267 		$this->sanitize->strip_comments($strip);
   1268 	}
   1269 
   1270 	/**
   1271 	 * Set element/attribute key/value pairs of HTML attributes
   1272 	 * containing URLs that need to be resolved relative to the feed
   1273 	 *
   1274 	 * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
   1275 	 * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
   1276 	 * |q|@cite
   1277 	 *
   1278 	 * @since 1.0
   1279 	 * @param array|null $element_attribute Element/attribute key/value pairs, null for default
   1280 	 */
   1281 	public function set_url_replacements($element_attribute = null)
   1282 	{
   1283 		$this->sanitize->set_url_replacements($element_attribute);
   1284 	}
   1285 
   1286 	/**
   1287 	 * Set the handler to enable the display of cached images.
   1288 	 *
   1289 	 * @param string $page Web-accessible path to the handler_image.php file.
   1290 	 * @param string $qs The query string that the value should be passed to.
   1291 	 */
   1292 	public function set_image_handler($page = false, $qs = 'i')
   1293 	{
   1294 		if ($page !== false)
   1295 		{
   1296 			$this->sanitize->set_image_handler($page . '?' . $qs . '=');
   1297 		}
   1298 		else
   1299 		{
   1300 			$this->image_handler = '';
   1301 		}
   1302 	}
   1303 
   1304 	/**
   1305 	 * Set the limit for items returned per-feed with multifeeds
   1306 	 *
   1307 	 * @param integer $limit The maximum number of items to return.
   1308 	 */
   1309 	public function set_item_limit($limit = 0)
   1310 	{
   1311 		$this->item_limit = (int) $limit;
   1312 	}
   1313 
   1314 	/**
   1315 	 * Enable throwing exceptions
   1316 	 *
   1317 	 * @param boolean $enable Should we throw exceptions, or use the old-style error property?
   1318 	 */
   1319 	public function enable_exceptions($enable = true)
   1320 	{
   1321 		$this->enable_exceptions = $enable;
   1322 	}
   1323 
   1324 	/**
   1325 	 * Initialize the feed object
   1326 	 *
   1327 	 * This is what makes everything happen. Period. This is where all of the
   1328 	 * configuration options get processed, feeds are fetched, cached, and
   1329 	 * parsed, and all of that other good stuff.
   1330 	 *
   1331 	 * @return boolean True if successful, false otherwise
   1332 	 */
   1333 	public function init()
   1334 	{
   1335 		// Check absolute bare minimum requirements.
   1336 		if (!extension_loaded('xml') || !extension_loaded('pcre'))
   1337 		{
   1338 			$this->error = 'XML or PCRE extensions not loaded!';
   1339 			return false;
   1340 		}
   1341 		// Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
   1342 		elseif (!extension_loaded('xmlreader'))
   1343 		{
   1344 			static $xml_is_sane = null;
   1345 			if ($xml_is_sane === null)
   1346 			{
   1347 				$parser_check = xml_parser_create();
   1348 				xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
   1349 				xml_parser_free($parser_check);
   1350 				$xml_is_sane = isset($values[0]['value']);
   1351 			}
   1352 			if (!$xml_is_sane)
   1353 			{
   1354 				return false;
   1355 			}
   1356 		}
   1357 
   1358 		// The default sanitize class gets set in the constructor, check if it has
   1359 		// changed.
   1360 		if ($this->registry->get_class('Sanitize') !== 'SimplePie_Sanitize') {
   1361 			$this->sanitize = $this->registry->create('Sanitize');
   1362 		}
   1363 		if (method_exists($this->sanitize, 'set_registry'))
   1364 		{
   1365 			$this->sanitize->set_registry($this->registry);
   1366 		}
   1367 
   1368 		// Pass whatever was set with config options over to the sanitizer.
   1369 		// Pass the classes in for legacy support; new classes should use the registry instead
   1370 		$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
   1371 		$this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options);
   1372 
   1373 		if (!empty($this->multifeed_url))
   1374 		{
   1375 			$i = 0;
   1376 			$success = 0;
   1377 			$this->multifeed_objects = array();
   1378 			$this->error = array();
   1379 			foreach ($this->multifeed_url as $url)
   1380 			{
   1381 				$this->multifeed_objects[$i] = clone $this;
   1382 				$this->multifeed_objects[$i]->set_feed_url($url);
   1383 				$single_success = $this->multifeed_objects[$i]->init();
   1384 				$success |= $single_success;
   1385 				if (!$single_success)
   1386 				{
   1387 					$this->error[$i] = $this->multifeed_objects[$i]->error();
   1388 				}
   1389 				$i++;
   1390 			}
   1391 			return (bool) $success;
   1392 		}
   1393 		elseif ($this->feed_url === null && $this->raw_data === null)
   1394 		{
   1395 			return false;
   1396 		}
   1397 
   1398 		$this->error = null;
   1399 		$this->data = array();
   1400 		$this->check_modified = false;
   1401 		$this->multifeed_objects = array();
   1402 		$cache = false;
   1403 
   1404 		if ($this->feed_url !== null)
   1405 		{
   1406 			$parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
   1407 
   1408 			// Decide whether to enable caching
   1409 			if ($this->cache && $parsed_feed_url['scheme'] !== '')
   1410 			{
   1411 				$url = $this->feed_url . ($this->force_feed ? '#force_feed' : '');
   1412 				$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $url), 'spc'));
   1413 			}
   1414 
   1415 			// Fetch the data via SimplePie_File into $this->raw_data
   1416 			if (($fetched = $this->fetch_data($cache)) === true)
   1417 			{
   1418 				return true;
   1419 			}
   1420 			elseif ($fetched === false) {
   1421 				return false;
   1422 			}
   1423 
   1424 			list($headers, $sniffed) = $fetched;
   1425 		}
   1426 
   1427 		// Empty response check
   1428 		if(empty($this->raw_data)){
   1429 			$this->error = "A feed could not be found at `$this->feed_url`. Empty body.";
   1430 			$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
   1431 			return false;
   1432 		}
   1433 
   1434 		// Set up array of possible encodings
   1435 		$encodings = array();
   1436 
   1437 		// First check to see if input has been overridden.
   1438 		if ($this->input_encoding !== false)
   1439 		{
   1440 			$encodings[] = strtoupper($this->input_encoding);
   1441 		}
   1442 
   1443 		$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
   1444 		$text_types = array('text/xml', 'text/xml-external-parsed-entity');
   1445 
   1446 		// RFC 3023 (only applies to sniffed content)
   1447 		if (isset($sniffed))
   1448 		{
   1449 			if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
   1450 			{
   1451 				if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
   1452 				{
   1453 					$encodings[] = strtoupper($charset[1]);
   1454 				}
   1455 				$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
   1456 				$encodings[] = 'UTF-8';
   1457 			}
   1458 			elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
   1459 			{
   1460 				if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
   1461 				{
   1462 					$encodings[] = strtoupper($charset[1]);
   1463 				}
   1464 				$encodings[] = 'US-ASCII';
   1465 			}
   1466 			// Text MIME-type default
   1467 			elseif (substr($sniffed, 0, 5) === 'text/')
   1468 			{
   1469 				$encodings[] = 'UTF-8';
   1470 			}
   1471 		}
   1472 
   1473 		// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
   1474 		$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
   1475 		$encodings[] = 'UTF-8';
   1476 		$encodings[] = 'ISO-8859-1';
   1477 
   1478 		// There's no point in trying an encoding twice
   1479 		$encodings = array_unique($encodings);
   1480 
   1481 		// Loop through each possible encoding, till we return something, or run out of possibilities
   1482 		foreach ($encodings as $encoding)
   1483 		{
   1484 			// Change the encoding to UTF-8 (as we always use UTF-8 internally)
   1485 			if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
   1486 			{
   1487 				// Create new parser
   1488 				$parser = $this->registry->create('Parser');
   1489 
   1490 				// If it's parsed fine
   1491 				if ($parser->parse($utf8_data, 'UTF-8', $this->permanent_url))
   1492 				{
   1493 					$this->data = $parser->get_data();
   1494 					if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
   1495 					{
   1496 						$this->error = "A feed could not be found at `$this->feed_url`. This does not appear to be a valid RSS or Atom feed.";
   1497 						$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
   1498 						return false;
   1499 					}
   1500 
   1501 					if (isset($headers))
   1502 					{
   1503 						$this->data['headers'] = $headers;
   1504 					}
   1505 					$this->data['build'] = SIMPLEPIE_BUILD;
   1506 
   1507 					// Cache the file if caching is enabled
   1508 					if ($cache && !$cache->save($this))
   1509 					{
   1510 						trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
   1511 					}
   1512 					return true;
   1513 				}
   1514 			}
   1515 		}
   1516 
   1517 		if (isset($parser))
   1518 		{
   1519 			// We have an error, just set SimplePie_Misc::error to it and quit
   1520 			$this->error = $this->feed_url;
   1521 			$this->error .= sprintf(' is invalid XML, 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());
   1522 		}
   1523 		else
   1524 		{
   1525 			$this->error = 'The data could not be converted to UTF-8.';
   1526 			if (!extension_loaded('mbstring') && !extension_loaded('iconv') && !class_exists('\UConverter')) {
   1527 				$this->error .= ' You MUST have either the iconv, mbstring or intl (PHP 5.5+) extension installed and enabled.';
   1528 			} else {
   1529 				$missingExtensions = array();
   1530 				if (!extension_loaded('iconv')) {
   1531 					$missingExtensions[] = 'iconv';
   1532 				}
   1533 				if (!extension_loaded('mbstring')) {
   1534 					$missingExtensions[] = 'mbstring';
   1535 				}
   1536 				if (!class_exists('\UConverter')) {
   1537 					$missingExtensions[] = 'intl (PHP 5.5+)';
   1538 				}
   1539 				$this->error .= ' Try installing/enabling the ' . implode(' or ', $missingExtensions) . ' extension.';
   1540 			}
   1541 		}
   1542 
   1543 		$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
   1544 
   1545 		return false;
   1546 	}
   1547 
   1548 	/**
   1549 	 * Fetch the data via SimplePie_File
   1550 	 *
   1551 	 * If the data is already cached, attempt to fetch it from there instead
   1552 	 * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
   1553 	 * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
   1554 	 */
   1555 	protected function fetch_data(&$cache)
   1556 	{
   1557 		// If it's enabled, use the cache
   1558 		if ($cache)
   1559 		{
   1560 			// Load the Cache
   1561 			$this->data = $cache->load();
   1562 			if (!empty($this->data))
   1563 			{
   1564 				// If the cache is for an outdated build of SimplePie
   1565 				if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
   1566 				{
   1567 					$cache->unlink();
   1568 					$this->data = array();
   1569 				}
   1570 				// If we've hit a collision just rerun it with caching disabled
   1571 				elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
   1572 				{
   1573 					$cache = false;
   1574 					$this->data = array();
   1575 				}
   1576 				// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
   1577 				elseif (isset($this->data['feed_url']))
   1578 				{
   1579 					// If the autodiscovery cache is still valid use it.
   1580 					if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
   1581 					{
   1582 						// Do not need to do feed autodiscovery yet.
   1583 						if ($this->data['feed_url'] !== $this->data['url'])
   1584 						{
   1585 							$this->set_feed_url($this->data['feed_url']);
   1586 							return $this->init();
   1587 						}
   1588 
   1589 						$cache->unlink();
   1590 						$this->data = array();
   1591 					}
   1592 				}
   1593 				// Check if the cache has been updated
   1594 				elseif ($cache->mtime() + $this->cache_duration < time())
   1595 				{
   1596 					// Want to know if we tried to send last-modified and/or etag headers
   1597 					// when requesting this file. (Note that it's up to the file to
   1598 					// support this, but we don't always send the headers either.)
   1599 					$this->check_modified = true;
   1600 					if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
   1601 					{
   1602 						$headers = array(
   1603 							'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',
   1604 						);
   1605 						if (isset($this->data['headers']['last-modified']))
   1606 						{
   1607 							$headers['if-modified-since'] = $this->data['headers']['last-modified'];
   1608 						}
   1609 						if (isset($this->data['headers']['etag']))
   1610 						{
   1611 							$headers['if-none-match'] = $this->data['headers']['etag'];
   1612 						}
   1613 
   1614 						$file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
   1615 
   1616 						if ($file->success)
   1617 						{
   1618 							if ($file->status_code === 304)
   1619 							{
   1620 								// Set raw_data to false here too, to signify that the cache
   1621 								// is still valid.
   1622 								$this->raw_data = false;
   1623 								$cache->touch();
   1624 								return true;
   1625 							}
   1626 						}
   1627 						else
   1628 						{
   1629 							$this->check_modified = false;
   1630 							if($this->force_cache_fallback)
   1631 							{
   1632 								$cache->touch();
   1633 								return true;
   1634 							}
   1635 
   1636 							unset($file);
   1637 						}
   1638 					}
   1639 				}
   1640 				// If the cache is still valid, just return true
   1641 				else
   1642 				{
   1643 					$this->raw_data = false;
   1644 					return true;
   1645 				}
   1646 			}
   1647 			// If the cache is empty, delete it
   1648 			else
   1649 			{
   1650 				$cache->unlink();
   1651 				$this->data = array();
   1652 			}
   1653 		}
   1654 		// 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.
   1655 		if (!isset($file))
   1656 		{
   1657 			if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
   1658 			{
   1659 				$file =& $this->file;
   1660 			}
   1661 			else
   1662 			{
   1663 				$headers = array(
   1664 					'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',
   1665 				);
   1666 				$file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
   1667 			}
   1668 		}
   1669 		// If the file connection has an error, set SimplePie::error to that and quit
   1670 		if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
   1671 		{
   1672 			$this->error = $file->error;
   1673 			return !empty($this->data);
   1674 		}
   1675 
   1676 		if (!$this->force_feed)
   1677 		{
   1678 			// Check if the supplied URL is a feed, if it isn't, look for it.
   1679 			$locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds, $this->force_fsockopen, $this->curl_options));
   1680 
   1681 			if (!$locate->is_feed($file))
   1682 			{
   1683 				$copyStatusCode = $file->status_code;
   1684 				$copyContentType = $file->headers['content-type'];
   1685 				try
   1686 				{
   1687 					$microformats = false;
   1688 					if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
   1689 						$doc = new DOMDocument();
   1690 						@$doc->loadHTML($file->body);
   1691 						$xpath = new DOMXpath($doc);
   1692 						// Check for both h-feed and h-entry, as both a feed with no entries
   1693 						// and a list of entries without an h-feed wrapper are both valid.
   1694 						$query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
   1695 							'contains(concat(" ", @class, " "), " h-entry ")]';
   1696 						$result = $xpath->query($query);
   1697 						$microformats = $result->length !== 0;
   1698 					}
   1699 					// Now also do feed discovery, but if microformats were found don't
   1700 					// overwrite the current value of file.
   1701 					$discovered = $locate->find($this->autodiscovery,
   1702 					                            $this->all_discovered_feeds);
   1703 					if ($microformats)
   1704 					{
   1705 						if ($hub = $locate->get_rel_link('hub'))
   1706 						{
   1707 							$self = $locate->get_rel_link('self');
   1708 							$this->store_links($file, $hub, $self);
   1709 						}
   1710 						// Push the current file onto all_discovered feeds so the user can
   1711 						// be shown this as one of the options.
   1712 						if (isset($this->all_discovered_feeds)) {
   1713 							$this->all_discovered_feeds[] = $file;
   1714 						}
   1715 					}
   1716 					else
   1717 					{
   1718 						if ($discovered)
   1719 						{
   1720 							$file = $discovered;
   1721 						}
   1722 						else
   1723 						{
   1724 							// We need to unset this so that if SimplePie::set_file() has
   1725 							// been called that object is untouched
   1726 							unset($file);
   1727 							$this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`";
   1728 							$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
   1729 							return false;
   1730 						}
   1731 					}
   1732 				}
   1733 				catch (SimplePie_Exception $e)
   1734 				{
   1735 					// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
   1736 					unset($file);
   1737 					// This is usually because DOMDocument doesn't exist
   1738 					$this->error = $e->getMessage();
   1739 					$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
   1740 					return false;
   1741 				}
   1742 				if ($cache)
   1743 				{
   1744 					$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
   1745 					if (!$cache->save($this))
   1746 					{
   1747 						trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
   1748 					}
   1749 					$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
   1750 				}
   1751 			}
   1752 			$this->feed_url = $file->url;
   1753 			$locate = null;
   1754 		}
   1755 
   1756 		$this->raw_data = $file->body;
   1757 		$this->permanent_url = $file->permanent_url;
   1758 		$headers = $file->headers;
   1759 		$sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
   1760 		$sniffed = $sniffer->get_type();
   1761 
   1762 		return array($headers, $sniffed);
   1763 	}
   1764 
   1765 	/**
   1766 	 * Get the error message for the occured error
   1767 	 *
   1768 	 * @return string|array Error message, or array of messages for multifeeds
   1769 	 */
   1770 	public function error()
   1771 	{
   1772 		return $this->error;
   1773 	}
   1774 
   1775 	/**
   1776 	 * Get the raw XML
   1777 	 *
   1778 	 * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
   1779 	 * the data instead of printing it.
   1780 	 *
   1781 	 * @return string|boolean Raw XML data, false if the cache is used
   1782 	 */
   1783 	public function get_raw_data()
   1784 	{
   1785 		return $this->raw_data;
   1786 	}
   1787 
   1788 	/**
   1789 	 * Get the character encoding used for output
   1790 	 *
   1791 	 * @since Preview Release
   1792 	 * @return string
   1793 	 */
   1794 	public function get_encoding()
   1795 	{
   1796 		return $this->sanitize->output_encoding;
   1797 	}
   1798 
   1799 	/**
   1800 	 * Send the content-type header with correct encoding
   1801 	 *
   1802 	 * This method ensures that the SimplePie-enabled page is being served with
   1803 	 * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
   1804 	 * and character encoding HTTP headers (character encoding determined by the
   1805 	 * {@see set_output_encoding} config option).
   1806 	 *
   1807 	 * This won't work properly if any content or whitespace has already been
   1808 	 * sent to the browser, because it relies on PHP's
   1809 	 * {@link http://php.net/header header()} function, and these are the
   1810 	 * circumstances under which the function works.
   1811 	 *
   1812 	 * Because it's setting these settings for the entire page (as is the nature
   1813 	 * of HTTP headers), this should only be used once per page (again, at the
   1814 	 * top).
   1815 	 *
   1816 	 * @param string $mime MIME type to serve the page as
   1817 	 */
   1818 	public function handle_content_type($mime = 'text/html')
   1819 	{
   1820 		if (!headers_sent())
   1821 		{
   1822 			$header = "Content-type: $mime;";
   1823 			if ($this->get_encoding())
   1824 			{
   1825 				$header .= ' charset=' . $this->get_encoding();
   1826 			}
   1827 			else
   1828 			{
   1829 				$header .= ' charset=UTF-8';
   1830 			}
   1831 			header($header);
   1832 		}
   1833 	}
   1834 
   1835 	/**
   1836 	 * Get the type of the feed
   1837 	 *
   1838 	 * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
   1839 	 * using {@link http://php.net/language.operators.bitwise bitwise operators}
   1840 	 *
   1841 	 * @since 0.8 (usage changed to using constants in 1.0)
   1842 	 * @see SIMPLEPIE_TYPE_NONE Unknown.
   1843 	 * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
   1844 	 * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
   1845 	 * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
   1846 	 * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
   1847 	 * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
   1848 	 * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
   1849 	 * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
   1850 	 * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
   1851 	 * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
   1852 	 * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
   1853 	 * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
   1854 	 * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
   1855 	 * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
   1856 	 * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
   1857 	 * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
   1858 	 * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
   1859 	 * @return int SIMPLEPIE_TYPE_* constant
   1860 	 */
   1861 	public function get_type()
   1862 	{
   1863 		if (!isset($this->data['type']))
   1864 		{
   1865 			$this->data['type'] = SIMPLEPIE_TYPE_ALL;
   1866 			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
   1867 			{
   1868 				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
   1869 			}
   1870 			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
   1871 			{
   1872 				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
   1873 			}
   1874 			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
   1875 			{
   1876 				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
   1877 				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
   1878 				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
   1879 				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
   1880 				{
   1881 					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
   1882 				}
   1883 				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
   1884 				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
   1885 				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
   1886 				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
   1887 				{
   1888 					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
   1889 				}
   1890 			}
   1891 			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
   1892 			{
   1893 				$this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
   1894 				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
   1895 				{
   1896 					switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
   1897 					{
   1898 						case '0.91':
   1899 							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
   1900 							if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
   1901 							{
   1902 								switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
   1903 								{
   1904 									case '0':
   1905 										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
   1906 										break;
   1907 
   1908 									case '24':
   1909 										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
   1910 										break;
   1911 								}
   1912 							}
   1913 							break;
   1914 
   1915 						case '0.92':
   1916 							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
   1917 							break;
   1918 
   1919 						case '0.93':
   1920 							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
   1921 							break;
   1922 
   1923 						case '0.94':
   1924 							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
   1925 							break;
   1926 
   1927 						case '2.0':
   1928 							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
   1929 							break;
   1930 					}
   1931 				}
   1932 			}
   1933 			else
   1934 			{
   1935 				$this->data['type'] = SIMPLEPIE_TYPE_NONE;
   1936 			}
   1937 		}
   1938 		return $this->data['type'];
   1939 	}
   1940 
   1941 	/**
   1942 	 * Get the URL for the feed
   1943 	 *
   1944 	 * When the 'permanent' mode is enabled, returns the original feed URL,
   1945 	 * except in the case of an `HTTP 301 Moved Permanently` status response,
   1946 	 * in which case the location of the first redirection is returned.
   1947 	 *
   1948 	 * When the 'permanent' mode is disabled (default),
   1949 	 * may or may not be different from the URL passed to {@see set_feed_url()},
   1950 	 * depending on whether auto-discovery was used, and whether there were
   1951 	 * any redirects along the way.
   1952 	 *
   1953 	 * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
   1954 	 * @todo Support <itunes:new-feed-url>
   1955 	 * @todo Also, |atom:link|@rel=self
   1956 	 * @param bool $permanent Permanent mode to return only the original URL or the first redirection
   1957 	 * iff it is a 301 redirection
   1958 	 * @return string|null
   1959 	 */
   1960 	public function subscribe_url($permanent = false)
   1961 	{
   1962 		if ($permanent)
   1963 		{
   1964 			if ($this->permanent_url !== null)
   1965 			{
   1966 				// sanitize encodes ampersands which are required when used in a url.
   1967 				return str_replace('&amp;', '&',
   1968 				                   $this->sanitize($this->permanent_url,
   1969 				                                   SIMPLEPIE_CONSTRUCT_IRI));
   1970 			}
   1971 		}
   1972 		else
   1973 		{
   1974 			if ($this->feed_url !== null)
   1975 			{
   1976 				return str_replace('&amp;', '&',
   1977 				                   $this->sanitize($this->feed_url,
   1978 				                                   SIMPLEPIE_CONSTRUCT_IRI));
   1979 			}
   1980 		}
   1981 		return null;
   1982 	}
   1983 
   1984 	/**
   1985 	 * Get data for an feed-level element
   1986 	 *
   1987 	 * This method allows you to get access to ANY element/attribute that is a
   1988 	 * sub-element of the opening feed tag.
   1989 	 *
   1990 	 * The return value is an indexed array of elements matching the given
   1991 	 * namespace and tag name. Each element has `attribs`, `data` and `child`
   1992 	 * subkeys. For `attribs` and `child`, these contain namespace subkeys.
   1993 	 * `attribs` then has one level of associative name => value data (where
   1994 	 * `value` is a string) after the namespace. `child` has tag-indexed keys
   1995 	 * after the namespace, each member of which is an indexed array matching
   1996 	 * this same format.
   1997 	 *
   1998 	 * For example:
   1999 	 * <pre>
   2000 	 * // This is probably a bad example because we already support
   2001 	 * // <media:content> natively, but it shows you how to parse through
   2002 	 * // the nodes.
   2003 	 * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
   2004 	 * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
   2005 	 * $file = $content[0]['attribs']['']['url'];
   2006 	 * echo $file;
   2007 	 * </pre>
   2008 	 *
   2009 	 * @since 1.0
   2010 	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
   2011 	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
   2012 	 * @param string $tag Tag name
   2013 	 * @return array
   2014 	 */
   2015 	public function get_feed_tags($namespace, $tag)
   2016 	{
   2017 		$type = $this->get_type();
   2018 		if ($type & SIMPLEPIE_TYPE_ATOM_10)
   2019 		{
   2020 			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
   2021 			{
   2022 				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
   2023 			}
   2024 		}
   2025 		if ($type & SIMPLEPIE_TYPE_ATOM_03)
   2026 		{
   2027 			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
   2028 			{
   2029 				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
   2030 			}
   2031 		}
   2032 		if ($type & SIMPLEPIE_TYPE_RSS_RDF)
   2033 		{
   2034 			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
   2035 			{
   2036 				return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
   2037 			}
   2038 		}
   2039 		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
   2040 		{
   2041 			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
   2042 			{
   2043 				return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
   2044 			}
   2045 		}
   2046 		return null;
   2047 	}
   2048 
   2049 	/**
   2050 	 * Get data for an channel-level element
   2051 	 *
   2052 	 * This method allows you to get access to ANY element/attribute in the
   2053 	 * channel/header section of the feed.
   2054 	 *
   2055 	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
   2056 	 *
   2057 	 * @since 1.0
   2058 	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
   2059 	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
   2060 	 * @param string $tag Tag name
   2061 	 * @return array
   2062 	 */
   2063 	public function get_channel_tags($namespace, $tag)
   2064 	{
   2065 		$type = $this->get_type();
   2066 		if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
   2067 		{
   2068 			if ($return = $this->get_feed_tags($namespace, $tag))
   2069 			{
   2070 				return $return;
   2071 			}
   2072 		}
   2073 		if ($type & SIMPLEPIE_TYPE_RSS_10)
   2074 		{
   2075 			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
   2076 			{
   2077 				if (isset($channel[0]['child'][$namespace][$tag]))
   2078 				{
   2079 					return $channel[0]['child'][$namespace][$tag];
   2080 				}
   2081 			}
   2082 		}
   2083 		if ($type & SIMPLEPIE_TYPE_RSS_090)
   2084 		{
   2085 			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
   2086 			{
   2087 				if (isset($channel[0]['child'][$namespace][$tag]))
   2088 				{
   2089 					return $channel[0]['child'][$namespace][$tag];
   2090 				}
   2091 			}
   2092 		}
   2093 		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
   2094 		{
   2095 			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
   2096 			{
   2097 				if (isset($channel[0]['child'][$namespace][$tag]))
   2098 				{
   2099 					return $channel[0]['child'][$namespace][$tag];
   2100 				}
   2101 			}
   2102 		}
   2103 		return null;
   2104 	}
   2105 
   2106 	/**
   2107 	 * Get data for an channel-level element
   2108 	 *
   2109 	 * This method allows you to get access to ANY element/attribute in the
   2110 	 * image/logo section of the feed.
   2111 	 *
   2112 	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
   2113 	 *
   2114 	 * @since 1.0
   2115 	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
   2116 	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
   2117 	 * @param string $tag Tag name
   2118 	 * @return array
   2119 	 */
   2120 	public function get_image_tags($namespace, $tag)
   2121 	{
   2122 		$type = $this->get_type();
   2123 		if ($type & SIMPLEPIE_TYPE_RSS_10)
   2124 		{
   2125 			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
   2126 			{
   2127 				if (isset($image[0]['child'][$namespace][$tag]))
   2128 				{
   2129 					return $image[0]['child'][$namespace][$tag];
   2130 				}
   2131 			}
   2132 		}
   2133 		if ($type & SIMPLEPIE_TYPE_RSS_090)
   2134 		{
   2135 			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
   2136 			{
   2137 				if (isset($image[0]['child'][$namespace][$tag]))
   2138 				{
   2139 					return $image[0]['child'][$namespace][$tag];
   2140 				}
   2141 			}
   2142 		}
   2143 		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
   2144 		{
   2145 			if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
   2146 			{
   2147 				if (isset($image[0]['child'][$namespace][$tag]))
   2148 				{
   2149 					return $image[0]['child'][$namespace][$tag];
   2150 				}
   2151 			}
   2152 		}
   2153 		return null;
   2154 	}
   2155 
   2156 	/**
   2157 	 * Get the base URL value from the feed
   2158 	 *
   2159 	 * Uses `<xml:base>` if available, otherwise uses the first link in the
   2160 	 * feed, or failing that, the URL of the feed itself.
   2161 	 *
   2162 	 * @see get_link
   2163 	 * @see subscribe_url
   2164 	 *
   2165 	 * @param array $element
   2166 	 * @return string
   2167 	 */
   2168 	public function get_base($element = array())
   2169 	{
   2170 		if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
   2171 		{
   2172 			return $element['xml_base'];
   2173 		}
   2174 		elseif ($this->get_link() !== null)
   2175 		{
   2176 			return $this->get_link();
   2177 		}
   2178 
   2179 		return $this->subscribe_url();
   2180 	}
   2181 
   2182 	/**
   2183 	 * Sanitize feed data
   2184 	 *
   2185 	 * @access private
   2186 	 * @see SimplePie_Sanitize::sanitize()
   2187 	 * @param string $data Data to sanitize
   2188 	 * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
   2189 	 * @param string $base Base URL to resolve URLs against
   2190 	 * @return string Sanitized data
   2191 	 */
   2192 	public function sanitize($data, $type, $base = '')
   2193 	{
   2194 		try
   2195 		{
   2196 			return $this->sanitize->sanitize($data, $type, $base);
   2197 		}
   2198 		catch (SimplePie_Exception $e)
   2199 		{
   2200 			if (!$this->enable_exceptions)
   2201 			{
   2202 				$this->error = $e->getMessage();
   2203 				$this->registry->call('Misc', 'error', array($this->error, E_USER_WARNING, $e->getFile(), $e->getLine()));
   2204 				return '';
   2205 			}
   2206 
   2207 			throw $e;
   2208 		}
   2209 	}
   2210 
   2211 	/**
   2212 	 * Get the title of the feed
   2213 	 *
   2214 	 * Uses `<atom:title>`, `<title>` or `<dc:title>`
   2215 	 *
   2216 	 * @since 1.0 (previously called `get_feed_title` since 0.8)
   2217 	 * @return string|null
   2218 	 */
   2219 	public function get_title()
   2220 	{
   2221 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
   2222 		{
   2223 			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
   2224 		}
   2225 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
   2226 		{
   2227 			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
   2228 		}
   2229 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
   2230 		{
   2231 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
   2232 		}
   2233 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
   2234 		{
   2235 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
   2236 		}
   2237 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
   2238 		{
   2239 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
   2240 		}
   2241 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
   2242 		{
   2243 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2244 		}
   2245 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
   2246 		{
   2247 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2248 		}
   2249 
   2250 		return null;
   2251 	}
   2252 
   2253 	/**
   2254 	 * Get a category for the feed
   2255 	 *
   2256 	 * @since Unknown
   2257 	 * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
   2258 	 * @return SimplePie_Category|null
   2259 	 */
   2260 	public function get_category($key = 0)
   2261 	{
   2262 		$categories = $this->get_categories();
   2263 		if (isset($categories[$key]))
   2264 		{
   2265 			return $categories[$key];
   2266 		}
   2267 
   2268 		return null;
   2269 	}
   2270 
   2271 	/**
   2272 	 * Get all categories for the feed
   2273 	 *
   2274 	 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
   2275 	 *
   2276 	 * @since Unknown
   2277 	 * @return array|null List of {@see SimplePie_Category} objects
   2278 	 */
   2279 	public function get_categories()
   2280 	{
   2281 		$categories = array();
   2282 
   2283 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
   2284 		{
   2285 			$term = null;
   2286 			$scheme = null;
   2287 			$label = null;
   2288 			if (isset($category['attribs']['']['term']))
   2289 			{
   2290 				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
   2291 			}
   2292 			if (isset($category['attribs']['']['scheme']))
   2293 			{
   2294 				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
   2295 			}
   2296 			if (isset($category['attribs']['']['label']))
   2297 			{
   2298 				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
   2299 			}
   2300 			$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
   2301 		}
   2302 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
   2303 		{
   2304 			// This is really the label, but keep this as the term also for BC.
   2305 			// Label will also work on retrieving because that falls back to term.
   2306 			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2307 			if (isset($category['attribs']['']['domain']))
   2308 			{
   2309 				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
   2310 			}
   2311 			else
   2312 			{
   2313 				$scheme = null;
   2314 			}
   2315 			$categories[] = $this->registry->create('Category', array($term, $scheme, null));
   2316 		}
   2317 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
   2318 		{
   2319 			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
   2320 		}
   2321 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
   2322 		{
   2323 			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
   2324 		}
   2325 
   2326 		if (!empty($categories))
   2327 		{
   2328 			return array_unique($categories);
   2329 		}
   2330 
   2331 		return null;
   2332 	}
   2333 
   2334 	/**
   2335 	 * Get an author for the feed
   2336 	 *
   2337 	 * @since 1.1
   2338 	 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
   2339 	 * @return SimplePie_Author|null
   2340 	 */
   2341 	public function get_author($key = 0)
   2342 	{
   2343 		$authors = $this->get_authors();
   2344 		if (isset($authors[$key]))
   2345 		{
   2346 			return $authors[$key];
   2347 		}
   2348 
   2349 		return null;
   2350 	}
   2351 
   2352 	/**
   2353 	 * Get all authors for the feed
   2354 	 *
   2355 	 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
   2356 	 *
   2357 	 * @since 1.1
   2358 	 * @return array|null List of {@see SimplePie_Author} objects
   2359 	 */
   2360 	public function get_authors()
   2361 	{
   2362 		$authors = array();
   2363 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
   2364 		{
   2365 			$name = null;
   2366 			$uri = null;
   2367 			$email = null;
   2368 			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
   2369 			{
   2370 				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2371 			}
   2372 			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
   2373 			{
   2374 				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
   2375 			}
   2376 			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
   2377 			{
   2378 				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2379 			}
   2380 			if ($name !== null || $email !== null || $uri !== null)
   2381 			{
   2382 				$authors[] = $this->registry->create('Author', array($name, $uri, $email));
   2383 			}
   2384 		}
   2385 		if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
   2386 		{
   2387 			$name = null;
   2388 			$url = null;
   2389 			$email = null;
   2390 			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
   2391 			{
   2392 				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2393 			}
   2394 			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
   2395 			{
   2396 				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
   2397 			}
   2398 			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
   2399 			{
   2400 				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2401 			}
   2402 			if ($name !== null || $email !== null || $url !== null)
   2403 			{
   2404 				$authors[] = $this->registry->create('Author', array($name, $url, $email));
   2405 			}
   2406 		}
   2407 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
   2408 		{
   2409 			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
   2410 		}
   2411 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
   2412 		{
   2413 			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
   2414 		}
   2415 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
   2416 		{
   2417 			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
   2418 		}
   2419 
   2420 		if (!empty($authors))
   2421 		{
   2422 			return array_unique($authors);
   2423 		}
   2424 
   2425 		return null;
   2426 	}
   2427 
   2428 	/**
   2429 	 * Get a contributor for the feed
   2430 	 *
   2431 	 * @since 1.1
   2432 	 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
   2433 	 * @return SimplePie_Author|null
   2434 	 */
   2435 	public function get_contributor($key = 0)
   2436 	{
   2437 		$contributors = $this->get_contributors();
   2438 		if (isset($contributors[$key]))
   2439 		{
   2440 			return $contributors[$key];
   2441 		}
   2442 
   2443 		return null;
   2444 	}
   2445 
   2446 	/**
   2447 	 * Get all contributors for the feed
   2448 	 *
   2449 	 * Uses `<atom:contributor>`
   2450 	 *
   2451 	 * @since 1.1
   2452 	 * @return array|null List of {@see SimplePie_Author} objects
   2453 	 */
   2454 	public function get_contributors()
   2455 	{
   2456 		$contributors = array();
   2457 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
   2458 		{
   2459 			$name = null;
   2460 			$uri = null;
   2461 			$email = null;
   2462 			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
   2463 			{
   2464 				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2465 			}
   2466 			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
   2467 			{
   2468 				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
   2469 			}
   2470 			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
   2471 			{
   2472 				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2473 			}
   2474 			if ($name !== null || $email !== null || $uri !== null)
   2475 			{
   2476 				$contributors[] = $this->registry->create('Author', array($name, $uri, $email));
   2477 			}
   2478 		}
   2479 		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
   2480 		{
   2481 			$name = null;
   2482 			$url = null;
   2483 			$email = null;
   2484 			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
   2485 			{
   2486 				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2487 			}
   2488 			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
   2489 			{
   2490 				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
   2491 			}
   2492 			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
   2493 			{
   2494 				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2495 			}
   2496 			if ($name !== null || $email !== null || $url !== null)
   2497 			{
   2498 				$contributors[] = $this->registry->create('Author', array($name, $url, $email));
   2499 			}
   2500 		}
   2501 
   2502 		if (!empty($contributors))
   2503 		{
   2504 			return array_unique($contributors);
   2505 		}
   2506 
   2507 		return null;
   2508 	}
   2509 
   2510 	/**
   2511 	 * Get a single link for the feed
   2512 	 *
   2513 	 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
   2514 	 * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
   2515 	 * @param string $rel The relationship of the link to return
   2516 	 * @return string|null Link URL
   2517 	 */
   2518 	public function get_link($key = 0, $rel = 'alternate')
   2519 	{
   2520 		$links = $this->get_links($rel);
   2521 		if (isset($links[$key]))
   2522 		{
   2523 			return $links[$key];
   2524 		}
   2525 
   2526 		return null;
   2527 	}
   2528 
   2529 	/**
   2530 	 * Get the permalink for the item
   2531 	 *
   2532 	 * Returns the first link available with a relationship of "alternate".
   2533 	 * Identical to {@see get_link()} with key 0
   2534 	 *
   2535 	 * @see get_link
   2536 	 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
   2537 	 * @internal Added for parity between the parent-level and the item/entry-level.
   2538 	 * @return string|null Link URL
   2539 	 */
   2540 	public function get_permalink()
   2541 	{
   2542 		return $this->get_link(0);
   2543 	}
   2544 
   2545 	/**
   2546 	 * Get all links for the feed
   2547 	 *
   2548 	 * Uses `<atom:link>` or `<link>`
   2549 	 *
   2550 	 * @since Beta 2
   2551 	 * @param string $rel The relationship of links to return
   2552 	 * @return array|null Links found for the feed (strings)
   2553 	 */
   2554 	public function get_links($rel = 'alternate')
   2555 	{
   2556 		if (!isset($this->data['links']))
   2557 		{
   2558 			$this->data['links'] = array();
   2559 			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
   2560 			{
   2561 				foreach ($links as $link)
   2562 				{
   2563 					if (isset($link['attribs']['']['href']))
   2564 					{
   2565 						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
   2566 						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
   2567 					}
   2568 				}
   2569 			}
   2570 			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
   2571 			{
   2572 				foreach ($links as $link)
   2573 				{
   2574 					if (isset($link['attribs']['']['href']))
   2575 					{
   2576 						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
   2577 						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
   2578 
   2579 					}
   2580 				}
   2581 			}
   2582 			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
   2583 			{
   2584 				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
   2585 			}
   2586 			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
   2587 			{
   2588 				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
   2589 			}
   2590 			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
   2591 			{
   2592 				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
   2593 			}
   2594 
   2595 			$keys = array_keys($this->data['links']);
   2596 			foreach ($keys as $key)
   2597 			{
   2598 				if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
   2599 				{
   2600 					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
   2601 					{
   2602 						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
   2603 						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
   2604 					}
   2605 					else
   2606 					{
   2607 						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
   2608 					}
   2609 				}
   2610 				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
   2611 				{
   2612 					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
   2613 				}
   2614 				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
   2615 			}
   2616 		}
   2617 
   2618 		if (isset($this->data['headers']['link']) &&
   2619 		    preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/',
   2620 		               $this->data['headers']['link'], $match))
   2621 		{
   2622 			return array($match[1]);
   2623 		}
   2624 		else if (isset($this->data['links'][$rel]))
   2625 		{
   2626 			return $this->data['links'][$rel];
   2627 		}
   2628 
   2629 		return null;
   2630 	}
   2631 
   2632 	public function get_all_discovered_feeds()
   2633 	{
   2634 		return $this->all_discovered_feeds;
   2635 	}
   2636 
   2637 	/**
   2638 	 * Get the content for the item
   2639 	 *
   2640 	 * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
   2641 	 * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
   2642 	 *
   2643 	 * @since 1.0 (previously called `get_feed_description()` since 0.8)
   2644 	 * @return string|null
   2645 	 */
   2646 	public function get_description()
   2647 	{
   2648 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
   2649 		{
   2650 			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
   2651 		}
   2652 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
   2653 		{
   2654 			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
   2655 		}
   2656 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
   2657 		{
   2658 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
   2659 		}
   2660 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
   2661 		{
   2662 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
   2663 		}
   2664 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
   2665 		{
   2666 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
   2667 		}
   2668 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
   2669 		{
   2670 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2671 		}
   2672 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
   2673 		{
   2674 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2675 		}
   2676 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
   2677 		{
   2678 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
   2679 		}
   2680 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
   2681 		{
   2682 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
   2683 		}
   2684 
   2685 		return null;
   2686 	}
   2687 
   2688 	/**
   2689 	 * Get the copyright info for the feed
   2690 	 *
   2691 	 * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
   2692 	 *
   2693 	 * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
   2694 	 * @return string|null
   2695 	 */
   2696 	public function get_copyright()
   2697 	{
   2698 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
   2699 		{
   2700 			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
   2701 		}
   2702 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
   2703 		{
   2704 			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
   2705 		}
   2706 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
   2707 		{
   2708 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2709 		}
   2710 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
   2711 		{
   2712 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2713 		}
   2714 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
   2715 		{
   2716 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2717 		}
   2718 
   2719 		return null;
   2720 	}
   2721 
   2722 	/**
   2723 	 * Get the language for the feed
   2724 	 *
   2725 	 * Uses `<language>`, `<dc:language>`, or @xml_lang
   2726 	 *
   2727 	 * @since 1.0 (previously called `get_feed_language()` since 0.8)
   2728 	 * @return string|null
   2729 	 */
   2730 	public function get_language()
   2731 	{
   2732 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
   2733 		{
   2734 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2735 		}
   2736 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
   2737 		{
   2738 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2739 		}
   2740 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
   2741 		{
   2742 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2743 		}
   2744 		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
   2745 		{
   2746 			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
   2747 		}
   2748 		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
   2749 		{
   2750 			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
   2751 		}
   2752 		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
   2753 		{
   2754 			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
   2755 		}
   2756 		elseif (isset($this->data['headers']['content-language']))
   2757 		{
   2758 			return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
   2759 		}
   2760 
   2761 		return null;
   2762 	}
   2763 
   2764 	/**
   2765 	 * Get the latitude coordinates for the item
   2766 	 *
   2767 	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
   2768 	 *
   2769 	 * Uses `<geo:lat>` or `<georss:point>`
   2770 	 *
   2771 	 * @since 1.0
   2772 	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
   2773 	 * @link http://www.georss.org/ GeoRSS
   2774 	 * @return string|null
   2775 	 */
   2776 	public function get_latitude()
   2777 	{
   2778 
   2779 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
   2780 		{
   2781 			return (float) $return[0]['data'];
   2782 		}
   2783 		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
   2784 		{
   2785 			return (float) $match[1];
   2786 		}
   2787 
   2788 		return null;
   2789 	}
   2790 
   2791 	/**
   2792 	 * Get the longitude coordinates for the feed
   2793 	 *
   2794 	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
   2795 	 *
   2796 	 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
   2797 	 *
   2798 	 * @since 1.0
   2799 	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
   2800 	 * @link http://www.georss.org/ GeoRSS
   2801 	 * @return string|null
   2802 	 */
   2803 	public function get_longitude()
   2804 	{
   2805 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
   2806 		{
   2807 			return (float) $return[0]['data'];
   2808 		}
   2809 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
   2810 		{
   2811 			return (float) $return[0]['data'];
   2812 		}
   2813 		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
   2814 		{
   2815 			return (float) $match[2];
   2816 		}
   2817 
   2818 		return null;
   2819 	}
   2820 
   2821 	/**
   2822 	 * Get the feed logo's title
   2823 	 *
   2824 	 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
   2825 	 *
   2826 	 * Uses `<image><title>` or `<image><dc:title>`
   2827 	 *
   2828 	 * @return string|null
   2829 	 */
   2830 	public function get_image_title()
   2831 	{
   2832 		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
   2833 		{
   2834 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2835 		}
   2836 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
   2837 		{
   2838 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2839 		}
   2840 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
   2841 		{
   2842 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2843 		}
   2844 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
   2845 		{
   2846 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2847 		}
   2848 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
   2849 		{
   2850 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
   2851 		}
   2852 
   2853 		return null;
   2854 	}
   2855 
   2856 	/**
   2857 	 * Get the feed logo's URL
   2858 	 *
   2859 	 * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
   2860 	 * have a "feed logo" URL. This points directly to the image itself.
   2861 	 *
   2862 	 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
   2863 	 * `<image><title>` or `<image><dc:title>`
   2864 	 *
   2865 	 * @return string|null
   2866 	 */
   2867 	public function get_image_url()
   2868 	{
   2869 		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
   2870 		{
   2871 			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
   2872 		}
   2873 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
   2874 		{
   2875 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2876 		}
   2877 		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
   2878 		{
   2879 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2880 		}
   2881 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
   2882 		{
   2883 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2884 		}
   2885 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
   2886 		{
   2887 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2888 		}
   2889 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
   2890 		{
   2891 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2892 		}
   2893 
   2894 		return null;
   2895 	}
   2896 
   2897 
   2898 	/**
   2899 	 * Get the feed logo's link
   2900 	 *
   2901 	 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
   2902 	 * points to a human-readable page that the image should link to.
   2903 	 *
   2904 	 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
   2905 	 * `<image><title>` or `<image><dc:title>`
   2906 	 *
   2907 	 * @return string|null
   2908 	 */
   2909 	public function get_image_link()
   2910 	{
   2911 		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
   2912 		{
   2913 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2914 		}
   2915 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
   2916 		{
   2917 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2918 		}
   2919 		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
   2920 		{
   2921 			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
   2922 		}
   2923 
   2924 		return null;
   2925 	}
   2926 
   2927 	/**
   2928 	 * Get the feed logo's link
   2929 	 *
   2930 	 * RSS 2.0 feeds are allowed to have a "feed logo" width.
   2931 	 *
   2932 	 * Uses `<image><width>` or defaults to 88.0 if no width is specified and
   2933 	 * the feed is an RSS 2.0 feed.
   2934 	 *
   2935 	 * @return int|float|null
   2936 	 */
   2937 	public function get_image_width()
   2938 	{
   2939 		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
   2940 		{
   2941 			return round($return[0]['data']);
   2942 		}
   2943 		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
   2944 		{
   2945 			return 88.0;
   2946 		}
   2947 
   2948 		return null;
   2949 	}
   2950 
   2951 	/**
   2952 	 * Get the feed logo's height
   2953 	 *
   2954 	 * RSS 2.0 feeds are allowed to have a "feed logo" height.
   2955 	 *
   2956 	 * Uses `<image><height>` or defaults to 31.0 if no height is specified and
   2957 	 * the feed is an RSS 2.0 feed.
   2958 	 *
   2959 	 * @return int|float|null
   2960 	 */
   2961 	public function get_image_height()
   2962 	{
   2963 		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
   2964 		{
   2965 			return round($return[0]['data']);
   2966 		}
   2967 		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
   2968 		{
   2969 			return 31.0;
   2970 		}
   2971 
   2972 		return null;
   2973 	}
   2974 
   2975 	/**
   2976 	 * Get the number of items in the feed
   2977 	 *
   2978 	 * This is well-suited for {@link http://php.net/for for()} loops with
   2979 	 * {@see get_item()}
   2980 	 *
   2981 	 * @param int $max Maximum value to return. 0 for no limit
   2982 	 * @return int Number of items in the feed
   2983 	 */
   2984 	public function get_item_quantity($max = 0)
   2985 	{
   2986 		$max = (int) $max;
   2987 		$qty = count($this->get_items());
   2988 		if ($max === 0)
   2989 		{
   2990 			return $qty;
   2991 		}
   2992 
   2993 		return ($qty > $max) ? $max : $qty;
   2994 	}
   2995 
   2996 	/**
   2997 	 * Get a single item from the feed
   2998 	 *
   2999 	 * This is better suited for {@link http://php.net/for for()} loops, whereas
   3000 	 * {@see get_items()} is better suited for
   3001 	 * {@link http://php.net/foreach foreach()} loops.
   3002 	 *
   3003 	 * @see get_item_quantity()
   3004 	 * @since Beta 2
   3005 	 * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1
   3006 	 * @return SimplePie_Item|null
   3007 	 */
   3008 	public function get_item($key = 0)
   3009 	{
   3010 		$items = $this->get_items();
   3011 		if (isset($items[$key]))
   3012 		{
   3013 			return $items[$key];
   3014 		}
   3015 
   3016 		return null;
   3017 	}
   3018 
   3019 	/**
   3020 	 * Get all items from the feed
   3021 	 *
   3022 	 * This is better suited for {@link http://php.net/for for()} loops, whereas
   3023 	 * {@see get_items()} is better suited for
   3024 	 * {@link http://php.net/foreach foreach()} loops.
   3025 	 *
   3026 	 * @see get_item_quantity
   3027 	 * @since Beta 2
   3028 	 * @param int $start Index to start at
   3029 	 * @param int $end Number of items to return. 0 for all items after `$start`
   3030 	 * @return SimplePie_Item[]|null List of {@see SimplePie_Item} objects
   3031 	 */
   3032 	public function get_items($start = 0, $end = 0)
   3033 	{
   3034 		if (!isset($this->data['items']))
   3035 		{
   3036 			if (!empty($this->multifeed_objects))
   3037 			{
   3038 				$this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
   3039 				if (empty($this->data['items']))
   3040 				{
   3041 					return array();
   3042 				}
   3043 				return $this->data['items'];
   3044 			}
   3045 			$this->data['items'] = array();
   3046 			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
   3047 			{
   3048 				$keys = array_keys($items);
   3049 				foreach ($keys as $key)
   3050 				{
   3051 					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
   3052 				}
   3053 			}
   3054 			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
   3055 			{
   3056 				$keys = array_keys($items);
   3057 				foreach ($keys as $key)
   3058 				{
   3059 					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
   3060 				}
   3061 			}
   3062 			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
   3063 			{
   3064 				$keys = array_keys($items);
   3065 				foreach ($keys as $key)
   3066 				{
   3067 					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
   3068 				}
   3069 			}
   3070 			if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
   3071 			{
   3072 				$keys = array_keys($items);
   3073 				foreach ($keys as $key)
   3074 				{
   3075 					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
   3076 				}
   3077 			}
   3078 			if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
   3079 			{
   3080 				$keys = array_keys($items);
   3081 				foreach ($keys as $key)
   3082 				{
   3083 					$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
   3084 				}
   3085 			}
   3086 		}
   3087 
   3088 		if (empty($this->data['items']))
   3089 		{
   3090 			return array();
   3091 		}
   3092 
   3093 		if ($this->order_by_date)
   3094 		{
   3095 			if (!isset($this->data['ordered_items']))
   3096 			{
   3097 				$this->data['ordered_items'] = $this->data['items'];
   3098 				usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
   3099 		 	}
   3100 			$items = $this->data['ordered_items'];
   3101 		}
   3102 		else
   3103 		{
   3104 			$items = $this->data['items'];
   3105 		}
   3106 		// Slice the data as desired
   3107 		if ($end === 0)
   3108 		{
   3109 			return array_slice($items, $start);
   3110 		}
   3111 
   3112 		return array_slice($items, $start, $end);
   3113 	}
   3114 
   3115 	/**
   3116 	 * Set the favicon handler
   3117 	 *
   3118 	 * @deprecated Use your own favicon handling instead
   3119 	 */
   3120 	public function set_favicon_handler($page = false, $qs = 'i')
   3121 	{
   3122 		$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
   3123 		trigger_error('Favicon handling has been removed, please use your own handling', $level);
   3124 		return false;
   3125 	}
   3126 
   3127 	/**
   3128 	 * Get the favicon for the current feed
   3129 	 *
   3130 	 * @deprecated Use your own favicon handling instead
   3131 	 */
   3132 	public function get_favicon()
   3133 	{
   3134 		$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
   3135 		trigger_error('Favicon handling has been removed, please use your own handling', $level);
   3136 
   3137 		if (($url = $this->get_link()) !== null)
   3138 		{
   3139 			return 'https://www.google.com/s2/favicons?domain=' . urlencode($url);
   3140 		}
   3141 
   3142 		return false;
   3143 	}
   3144 
   3145 	/**
   3146 	 * Magic method handler
   3147 	 *
   3148 	 * @param string $method Method name
   3149 	 * @param array $args Arguments to the method
   3150 	 * @return mixed
   3151 	 */
   3152 	public function __call($method, $args)
   3153 	{
   3154 		if (strpos($method, 'subscribe_') === 0)
   3155 		{
   3156 			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
   3157 			trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
   3158 			return '';
   3159 		}
   3160 		if ($method === 'enable_xml_dump')
   3161 		{
   3162 			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
   3163 			trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
   3164 			return false;
   3165 		}
   3166 
   3167 		$class = get_class($this);
   3168 		$trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
   3169 		$file = $trace[0]['file'];
   3170 		$line = $trace[0]['line'];
   3171 		trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
   3172 	}
   3173 
   3174 	/**
   3175 	 * Sorting callback for items
   3176 	 *
   3177 	 * @access private
   3178 	 * @param SimplePie $a
   3179 	 * @param SimplePie $b
   3180 	 * @return boolean
   3181 	 */
   3182 	public static function sort_items($a, $b)
   3183 	{
   3184 		$a_date = $a->get_date('U');
   3185 		$b_date = $b->get_date('U');
   3186 		if ($a_date && $b_date) {
   3187 			return $a_date > $b_date ? -1 : 1;
   3188 		}
   3189 		// Sort items without dates to the top.
   3190 		if ($a_date) {
   3191 			return 1;
   3192 		}
   3193 		if ($b_date) {
   3194 			return -1;
   3195 		}
   3196 		return 0;
   3197 	}
   3198 
   3199 	/**
   3200 	 * Merge items from several feeds into one
   3201 	 *
   3202 	 * If you're merging multiple feeds together, they need to all have dates
   3203 	 * for the items or else SimplePie will refuse to sort them.
   3204 	 *
   3205 	 * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
   3206 	 * @param array $urls List of SimplePie feed objects to merge
   3207 	 * @param int $start Starting item
   3208 	 * @param int $end Number of items to return
   3209 	 * @param int $limit Maximum number of items per feed
   3210 	 * @return array
   3211 	 */
   3212 	public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
   3213 	{
   3214 		if (is_array($urls) && sizeof($urls) > 0)
   3215 		{
   3216 			$items = array();
   3217 			foreach ($urls as $arg)
   3218 			{
   3219 				if ($arg instanceof SimplePie)
   3220 				{
   3221 					$items = array_merge($items, $arg->get_items(0, $limit));
   3222 				}
   3223 				else
   3224 				{
   3225 					trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
   3226 				}
   3227 			}
   3228 
   3229 			usort($items, array(get_class($urls[0]), 'sort_items'));
   3230 
   3231 			if ($end === 0)
   3232 			{
   3233 				return array_slice($items, $start);
   3234 			}
   3235 
   3236 			return array_slice($items, $start, $end);
   3237 		}
   3238 
   3239 		trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
   3240 		return array();
   3241 	}
   3242 
   3243 	/**
   3244 	 * Store PubSubHubbub links as headers
   3245 	 *
   3246 	 * There is no way to find PuSH links in the body of a microformats feed,
   3247 	 * so they are added to the headers when found, to be used later by get_links.
   3248 	 * @param SimplePie_File $file
   3249 	 * @param string $hub
   3250 	 * @param string $self
   3251 	 */
   3252 	private function store_links(&$file, $hub, $self) {
   3253 		if (isset($file->headers['link']['hub']) ||
   3254 			  (isset($file->headers['link']) &&
   3255 			   preg_match('/rel=hub/', $file->headers['link'])))
   3256 		{
   3257 			return;
   3258 		}
   3259 
   3260 		if ($hub)
   3261 		{
   3262 			if (isset($file->headers['link']))
   3263 			{
   3264 				if ($file->headers['link'] !== '')
   3265 				{
   3266 					$file->headers['link'] = ', ';
   3267 				}
   3268 			}
   3269 			else
   3270 			{
   3271 				$file->headers['link'] = '';
   3272 			}
   3273 			$file->headers['link'] .= '<'.$hub.'>; rel=hub';
   3274 			if ($self)
   3275 			{
   3276 				$file->headers['link'] .= ', <'.$self.'>; rel=self';
   3277 			}
   3278 		}
   3279 	}
   3280 }
   3281 endif;