[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-simplepie.php (source)

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


Generated : Sun Oct 25 08:20:01 2020 Cross-referenced by PHPXref