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