[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

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-2012, Ryan Parman, Geoffrey 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.3.1
  72   * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  73   * @author Ryan Parman
  74   * @author Geoffrey 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.3.1');
  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 object Instance of SimplePie_File to use as a feed
 485       * @see SimplePie::set_file()
 486       * @access private
 487       */
 488      public $file;
 489  
 490      /**
 491       * @var string Raw feed data
 492       * @see SimplePie::set_raw_data()
 493       * @access private
 494       */
 495      public $raw_data;
 496  
 497      /**
 498       * @var int Timeout for fetching remote files
 499       * @see SimplePie::set_timeout()
 500       * @access private
 501       */
 502      public $timeout = 10;
 503  
 504      /**
 505       * @var bool Forces fsockopen() to be used for remote files instead
 506       * of cURL, even if a new enough version is installed
 507       * @see SimplePie::force_fsockopen()
 508       * @access private
 509       */
 510      public $force_fsockopen = false;
 511  
 512      /**
 513       * @var bool Force the given data/URL to be treated as a feed no matter what
 514       * it appears like
 515       * @see SimplePie::force_feed()
 516       * @access private
 517       */
 518      public $force_feed = false;
 519  
 520      /**
 521       * @var bool Enable/Disable Caching
 522       * @see SimplePie::enable_cache()
 523       * @access private
 524       */
 525      public $cache = true;
 526  
 527      /**
 528       * @var int Cache duration (in seconds)
 529       * @see SimplePie::set_cache_duration()
 530       * @access private
 531       */
 532      public $cache_duration = 3600;
 533  
 534      /**
 535       * @var int Auto-discovery cache duration (in seconds)
 536       * @see SimplePie::set_autodiscovery_cache_duration()
 537       * @access private
 538       */
 539      public $autodiscovery_cache_duration = 604800; // 7 Days.
 540  
 541      /**
 542       * @var string Cache location (relative to executing script)
 543       * @see SimplePie::set_cache_location()
 544       * @access private
 545       */
 546      public $cache_location = './cache';
 547  
 548      /**
 549       * @var string Function that creates the cache filename
 550       * @see SimplePie::set_cache_name_function()
 551       * @access private
 552       */
 553      public $cache_name_function = 'md5';
 554  
 555      /**
 556       * @var bool Reorder feed by date descending
 557       * @see SimplePie::enable_order_by_date()
 558       * @access private
 559       */
 560      public $order_by_date = true;
 561  
 562      /**
 563       * @var mixed Force input encoding to be set to the follow value
 564       * (false, or anything type-cast to false, disables this feature)
 565       * @see SimplePie::set_input_encoding()
 566       * @access private
 567       */
 568      public $input_encoding = false;
 569  
 570      /**
 571       * @var int Feed Autodiscovery Level
 572       * @see SimplePie::set_autodiscovery_level()
 573       * @access private
 574       */
 575      public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
 576  
 577      /**
 578       * Class registry object
 579       *
 580       * @var SimplePie_Registry
 581       */
 582      public $registry;
 583  
 584      /**
 585       * @var int Maximum number of feeds to check with autodiscovery
 586       * @see SimplePie::set_max_checked_feeds()
 587       * @access private
 588       */
 589      public $max_checked_feeds = 10;
 590  
 591      /**
 592       * @var array All the feeds found during the autodiscovery process
 593       * @see SimplePie::get_all_discovered_feeds()
 594       * @access private
 595       */
 596      public $all_discovered_feeds = array();
 597  
 598      /**
 599       * @var string Web-accessible path to the handler_image.php file.
 600       * @see SimplePie::set_image_handler()
 601       * @access private
 602       */
 603      public $image_handler = '';
 604  
 605      /**
 606       * @var array Stores the URLs when multiple feeds are being initialized.
 607       * @see SimplePie::set_feed_url()
 608       * @access private
 609       */
 610      public $multifeed_url = array();
 611  
 612      /**
 613       * @var array Stores SimplePie objects when multiple feeds initialized.
 614       * @access private
 615       */
 616      public $multifeed_objects = array();
 617  
 618      /**
 619       * @var array Stores the get_object_vars() array for use with multifeeds.
 620       * @see SimplePie::set_feed_url()
 621       * @access private
 622       */
 623      public $config_settings = null;
 624  
 625      /**
 626       * @var integer Stores the number of items to return per-feed with multifeeds.
 627       * @see SimplePie::set_item_limit()
 628       * @access private
 629       */
 630      public $item_limit = 0;
 631  
 632      /**
 633       * @var array Stores the default attributes to be stripped by strip_attributes().
 634       * @see SimplePie::strip_attributes()
 635       * @access private
 636       */
 637      public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
 638  
 639      /**
 640       * @var array Stores the default tags to be stripped by strip_htmltags().
 641       * @see SimplePie::strip_htmltags()
 642       * @access private
 643       */
 644      public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
 645  
 646      /**
 647       * The SimplePie class contains feed level data and options
 648       *
 649       * To use SimplePie, create the SimplePie object with no parameters. You can
 650       * then set configuration options using the provided methods. After setting
 651       * them, you must initialise the feed using $feed->init(). At that point the
 652       * object's methods and properties will be available to you.
 653       *
 654       * Previously, it was possible to pass in the feed URL along with cache
 655       * options directly into the constructor. This has been removed as of 1.3 as
 656       * it caused a lot of confusion.
 657       *
 658       * @since 1.0 Preview Release
 659       */
 660  	public function __construct()
 661      {
 662          if (version_compare(PHP_VERSION, '5.2', '<'))
 663          {
 664              trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
 665              die();
 666          }
 667  
 668          // Other objects, instances created here so we can set options on them
 669          $this->sanitize = new SimplePie_Sanitize();
 670          $this->registry = new SimplePie_Registry();
 671  
 672          if (func_num_args() > 0)
 673          {
 674              $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
 675              trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
 676  
 677              $args = func_get_args();
 678              switch (count($args)) {
 679                  case 3:
 680                      $this->set_cache_duration($args[2]);
 681                  case 2:
 682                      $this->set_cache_location($args[1]);
 683                  case 1:
 684                      $this->set_feed_url($args[0]);
 685                      $this->init();
 686              }
 687          }
 688      }
 689  
 690      /**
 691       * Used for converting object to a string
 692       */
 693  	public function __toString()
 694      {
 695          return md5(serialize($this->data));
 696      }
 697  
 698      /**
 699       * Remove items that link back to this before destroying this object
 700       */
 701  	public function __destruct()
 702      {
 703          if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
 704          {
 705              if (!empty($this->data['items']))
 706              {
 707                  foreach ($this->data['items'] as $item)
 708                  {
 709                      $item->__destruct();
 710                  }
 711                  unset($item, $this->data['items']);
 712              }
 713              if (!empty($this->data['ordered_items']))
 714              {
 715                  foreach ($this->data['ordered_items'] as $item)
 716                  {
 717                      $item->__destruct();
 718                  }
 719                  unset($item, $this->data['ordered_items']);
 720              }
 721          }
 722      }
 723  
 724      /**
 725       * Force the given data/URL to be treated as a feed
 726       *
 727       * This tells SimplePie to ignore the content-type provided by the server.
 728       * Be careful when using this option, as it will also disable autodiscovery.
 729       *
 730       * @since 1.1
 731       * @param bool $enable Force the given data/URL to be treated as a feed
 732       */
 733  	public function force_feed($enable = false)
 734      {
 735          $this->force_feed = (bool) $enable;
 736      }
 737  
 738      /**
 739       * Set the URL of the feed you want to parse
 740       *
 741       * This allows you to enter the URL of the feed you want to parse, or the
 742       * website you want to try to use auto-discovery on. This takes priority
 743       * over any set raw data.
 744       *
 745       * You can set multiple feeds to mash together by passing an array instead
 746       * of a string for the $url. Remember that with each additional feed comes
 747       * additional processing and resources.
 748       *
 749       * @since 1.0 Preview Release
 750       * @see set_raw_data()
 751       * @param string|array $url This is the URL (or array of URLs) that you want to parse.
 752       */
 753  	public function set_feed_url($url)
 754      {
 755          $this->multifeed_url = array();
 756          if (is_array($url))
 757          {
 758              foreach ($url as $value)
 759              {
 760                  $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
 761              }
 762          }
 763          else
 764          {
 765              $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
 766          }
 767      }
 768  
 769      /**
 770       * Set an instance of {@see SimplePie_File} to use as a feed
 771       *
 772       * @param SimplePie_File &$file
 773       * @return bool True on success, false on failure
 774       */
 775  	public function set_file(&$file)
 776      {
 777          if ($file instanceof SimplePie_File)
 778          {
 779              $this->feed_url = $file->url;
 780              $this->file =& $file;
 781              return true;
 782          }
 783          return false;
 784      }
 785  
 786      /**
 787       * Set the raw XML data to parse
 788       *
 789       * Allows you to use a string of RSS/Atom data instead of a remote feed.
 790       *
 791       * If you have a feed available as a string in PHP, you can tell SimplePie
 792       * to parse that data string instead of a remote feed. Any set feed URL
 793       * takes precedence.
 794       *
 795       * @since 1.0 Beta 3
 796       * @param string $data RSS or Atom data as a string.
 797       * @see set_feed_url()
 798       */
 799  	public function set_raw_data($data)
 800      {
 801          $this->raw_data = $data;
 802      }
 803  
 804      /**
 805       * Set the the default timeout for fetching remote feeds
 806       *
 807       * This allows you to change the maximum time the feed's server to respond
 808       * and send the feed back.
 809       *
 810       * @since 1.0 Beta 3
 811       * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
 812       */
 813  	public function set_timeout($timeout = 10)
 814      {
 815          $this->timeout = (int) $timeout;
 816      }
 817  
 818      /**
 819       * Force SimplePie to use fsockopen() instead of cURL
 820       *
 821       * @since 1.0 Beta 3
 822       * @param bool $enable Force fsockopen() to be used
 823       */
 824  	public function force_fsockopen($enable = false)
 825      {
 826          $this->force_fsockopen = (bool) $enable;
 827      }
 828  
 829      /**
 830       * Enable/disable caching in SimplePie.
 831       *
 832       * This option allows you to disable caching all-together in SimplePie.
 833       * However, disabling the cache can lead to longer load times.
 834       *
 835       * @since 1.0 Preview Release
 836       * @param bool $enable Enable caching
 837       */
 838  	public function enable_cache($enable = true)
 839      {
 840          $this->cache = (bool) $enable;
 841      }
 842  
 843      /**
 844       * Set the length of time (in seconds) that the contents of a feed will be
 845       * cached
 846       *
 847       * @param int $seconds The feed content cache duration
 848       */
 849  	public function set_cache_duration($seconds = 3600)
 850      {
 851          $this->cache_duration = (int) $seconds;
 852      }
 853  
 854      /**
 855       * Set the length of time (in seconds) that the autodiscovered feed URL will
 856       * be cached
 857       *
 858       * @param int $seconds The autodiscovered feed URL cache duration.
 859       */
 860  	public function set_autodiscovery_cache_duration($seconds = 604800)
 861      {
 862          $this->autodiscovery_cache_duration = (int) $seconds;
 863      }
 864  
 865      /**
 866       * Set the file system location where the cached files should be stored
 867       *
 868       * @param string $location The file system location.
 869       */
 870  	public function set_cache_location($location = './cache')
 871      {
 872          $this->cache_location = (string) $location;
 873      }
 874  
 875      /**
 876       * Set whether feed items should be sorted into reverse chronological order
 877       *
 878       * @param bool $enable Sort as reverse chronological order.
 879       */
 880  	public function enable_order_by_date($enable = true)
 881      {
 882          $this->order_by_date = (bool) $enable;
 883      }
 884  
 885      /**
 886       * Set the character encoding used to parse the feed
 887       *
 888       * This overrides the encoding reported by the feed, however it will fall
 889       * back to the normal encoding detection if the override fails
 890       *
 891       * @param string $encoding Character encoding
 892       */
 893  	public function set_input_encoding($encoding = false)
 894      {
 895          if ($encoding)
 896          {
 897              $this->input_encoding = (string) $encoding;
 898          }
 899          else
 900          {
 901              $this->input_encoding = false;
 902          }
 903      }
 904  
 905      /**
 906       * Set how much feed autodiscovery to do
 907       *
 908       * @see SIMPLEPIE_LOCATOR_NONE
 909       * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
 910       * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
 911       * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
 912       * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
 913       * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
 914       * @see SIMPLEPIE_LOCATOR_ALL
 915       * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
 916       */
 917  	public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
 918      {
 919          $this->autodiscovery = (int) $level;
 920      }
 921  
 922      /**
 923       * Get the class registry
 924       *
 925       * Use this to override SimplePie's default classes
 926       * @see SimplePie_Registry
 927       * @return SimplePie_Registry
 928       */
 929      public function &get_registry()
 930      {
 931          return $this->registry;
 932      }
 933  
 934      /**#@+
 935       * Useful when you are overloading or extending SimplePie's default classes.
 936       *
 937       * @deprecated Use {@see get_registry()} instead
 938       * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
 939       * @param string $class Name of custom class
 940       * @return boolean True on success, false otherwise
 941       */
 942      /**
 943       * Set which class SimplePie uses for caching
 944       */
 945  	public function set_cache_class($class = 'SimplePie_Cache')
 946      {
 947          return $this->registry->register('Cache', $class, true);
 948      }
 949  
 950      /**
 951       * Set which class SimplePie uses for auto-discovery
 952       */
 953  	public function set_locator_class($class = 'SimplePie_Locator')
 954      {
 955          return $this->registry->register('Locator', $class, true);
 956      }
 957  
 958      /**
 959       * Set which class SimplePie uses for XML parsing
 960       */
 961  	public function set_parser_class($class = 'SimplePie_Parser')
 962      {
 963          return $this->registry->register('Parser', $class, true);
 964      }
 965  
 966      /**
 967       * Set which class SimplePie uses for remote file fetching
 968       */
 969  	public function set_file_class($class = 'SimplePie_File')
 970      {
 971          return $this->registry->register('File', $class, true);
 972      }
 973  
 974      /**
 975       * Set which class SimplePie uses for data sanitization
 976       */
 977  	public function set_sanitize_class($class = 'SimplePie_Sanitize')
 978      {
 979          return $this->registry->register('Sanitize', $class, true);
 980      }
 981  
 982      /**
 983       * Set which class SimplePie uses for handling feed items
 984       */
 985  	public function set_item_class($class = 'SimplePie_Item')
 986      {
 987          return $this->registry->register('Item', $class, true);
 988      }
 989  
 990      /**
 991       * Set which class SimplePie uses for handling author data
 992       */
 993  	public function set_author_class($class = 'SimplePie_Author')
 994      {
 995          return $this->registry->register('Author', $class, true);
 996      }
 997  
 998      /**
 999       * Set which class SimplePie uses for handling category data
1000       */
1001  	public function set_category_class($class = 'SimplePie_Category')
1002      {
1003          return $this->registry->register('Category', $class, true);
1004      }
1005  
1006      /**
1007       * Set which class SimplePie uses for feed enclosures
1008       */
1009  	public function set_enclosure_class($class = 'SimplePie_Enclosure')
1010      {
1011          return $this->registry->register('Enclosure', $class, true);
1012      }
1013  
1014      /**
1015       * Set which class SimplePie uses for `<media:text>` captions
1016       */
1017  	public function set_caption_class($class = 'SimplePie_Caption')
1018      {
1019          return $this->registry->register('Caption', $class, true);
1020      }
1021  
1022      /**
1023       * Set which class SimplePie uses for `<media:copyright>`
1024       */
1025  	public function set_copyright_class($class = 'SimplePie_Copyright')
1026      {
1027          return $this->registry->register('Copyright', $class, true);
1028      }
1029  
1030      /**
1031       * Set which class SimplePie uses for `<media:credit>`
1032       */
1033  	public function set_credit_class($class = 'SimplePie_Credit')
1034      {
1035          return $this->registry->register('Credit', $class, true);
1036      }
1037  
1038      /**
1039       * Set which class SimplePie uses for `<media:rating>`
1040       */
1041  	public function set_rating_class($class = 'SimplePie_Rating')
1042      {
1043          return $this->registry->register('Rating', $class, true);
1044      }
1045  
1046      /**
1047       * Set which class SimplePie uses for `<media:restriction>`
1048       */
1049  	public function set_restriction_class($class = 'SimplePie_Restriction')
1050      {
1051          return $this->registry->register('Restriction', $class, true);
1052      }
1053  
1054      /**
1055       * Set which class SimplePie uses for content-type sniffing
1056       */
1057  	public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1058      {
1059          return $this->registry->register('Content_Type_Sniffer', $class, true);
1060      }
1061  
1062      /**
1063       * Set which class SimplePie uses item sources
1064       */
1065  	public function set_source_class($class = 'SimplePie_Source')
1066      {
1067          return $this->registry->register('Source', $class, true);
1068      }
1069      /**#@-*/
1070  
1071      /**
1072       * Set the user agent string
1073       *
1074       * @param string $ua New user agent string.
1075       */
1076  	public function set_useragent($ua = SIMPLEPIE_USERAGENT)
1077      {
1078          $this->useragent = (string) $ua;
1079      }
1080  
1081      /**
1082       * Set callback function to create cache filename with
1083       *
1084       * @param mixed $function Callback function
1085       */
1086  	public function set_cache_name_function($function = 'md5')
1087      {
1088          if (is_callable($function))
1089          {
1090              $this->cache_name_function = $function;
1091          }
1092      }
1093  
1094      /**
1095       * Set options to make SP as fast as possible
1096       *
1097       * Forgoes a substantial amount of data sanitization in favor of speed. This
1098       * turns SimplePie into a dumb parser of feeds.
1099       *
1100       * @param bool $set Whether to set them or not
1101       */
1102  	public function set_stupidly_fast($set = false)
1103      {
1104          if ($set)
1105          {
1106              $this->enable_order_by_date(false);
1107              $this->remove_div(false);
1108              $this->strip_comments(false);
1109              $this->strip_htmltags(false);
1110              $this->strip_attributes(false);
1111              $this->set_image_handler(false);
1112          }
1113      }
1114  
1115      /**
1116       * Set maximum number of feeds to check with autodiscovery
1117       *
1118       * @param int $max Maximum number of feeds to check
1119       */
1120  	public function set_max_checked_feeds($max = 10)
1121      {
1122          $this->max_checked_feeds = (int) $max;
1123      }
1124  
1125  	public function remove_div($enable = true)
1126      {
1127          $this->sanitize->remove_div($enable);
1128      }
1129  
1130  	public function strip_htmltags($tags = '', $encode = null)
1131      {
1132          if ($tags === '')
1133          {
1134              $tags = $this->strip_htmltags;
1135          }
1136          $this->sanitize->strip_htmltags($tags);
1137          if ($encode !== null)
1138          {
1139              $this->sanitize->encode_instead_of_strip($tags);
1140          }
1141      }
1142  
1143  	public function encode_instead_of_strip($enable = true)
1144      {
1145          $this->sanitize->encode_instead_of_strip($enable);
1146      }
1147  
1148  	public function strip_attributes($attribs = '')
1149      {
1150          if ($attribs === '')
1151          {
1152              $attribs = $this->strip_attributes;
1153          }
1154          $this->sanitize->strip_attributes($attribs);
1155      }
1156  
1157      /**
1158       * Set the output encoding
1159       *
1160       * Allows you to override SimplePie's output to match that of your webpage.
1161       * This is useful for times when your webpages are not being served as
1162       * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and
1163       * is similar to {@see set_input_encoding()}.
1164       *
1165       * It should be noted, however, that not all character encodings can support
1166       * all characters.  If your page is being served as ISO-8859-1 and you try
1167       * to display a Japanese feed, you'll likely see garbled characters.
1168       * Because of this, it is highly recommended to ensure that your webpages
1169       * are served as UTF-8.
1170       *
1171       * The number of supported character encodings depends on whether your web
1172       * host supports {@link http://php.net/mbstring mbstring},
1173       * {@link http://php.net/iconv iconv}, or both. See
1174       * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
1175       * more information.
1176       *
1177       * @param string $encoding
1178       */
1179  	public function set_output_encoding($encoding = 'UTF-8')
1180      {
1181          $this->sanitize->set_output_encoding($encoding);
1182      }
1183  
1184  	public function strip_comments($strip = false)
1185      {
1186          $this->sanitize->strip_comments($strip);
1187      }
1188  
1189      /**
1190       * Set element/attribute key/value pairs of HTML attributes
1191       * containing URLs that need to be resolved relative to the feed
1192       *
1193       * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
1194       * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
1195       * |q|@cite
1196       *
1197       * @since 1.0
1198       * @param array|null $element_attribute Element/attribute key/value pairs, null for default
1199       */
1200  	public function set_url_replacements($element_attribute = null)
1201      {
1202          $this->sanitize->set_url_replacements($element_attribute);
1203      }
1204  
1205      /**
1206       * Set the handler to enable the display of cached images.
1207       *
1208       * @param str $page Web-accessible path to the handler_image.php file.
1209       * @param str $qs The query string that the value should be passed to.
1210       */
1211  	public function set_image_handler($page = false, $qs = 'i')
1212      {
1213          if ($page !== false)
1214          {
1215              $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1216          }
1217          else
1218          {
1219              $this->image_handler = '';
1220          }
1221      }
1222  
1223      /**
1224       * Set the limit for items returned per-feed with multifeeds
1225       *
1226       * @param integer $limit The maximum number of items to return.
1227       */
1228  	public function set_item_limit($limit = 0)
1229      {
1230          $this->item_limit = (int) $limit;
1231      }
1232  
1233      /**
1234       * Initialize the feed object
1235       *
1236       * This is what makes everything happen.  Period.  This is where all of the
1237       * configuration options get processed, feeds are fetched, cached, and
1238       * parsed, and all of that other good stuff.
1239       *
1240       * @return boolean True if successful, false otherwise
1241       */
1242  	public function init()
1243      {
1244          // Check absolute bare minimum requirements.
1245          if (!extension_loaded('xml') || !extension_loaded('pcre'))
1246          {
1247              return false;
1248          }
1249          // 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.
1250          elseif (!extension_loaded('xmlreader'))
1251          {
1252              static $xml_is_sane = null;
1253              if ($xml_is_sane === null)
1254              {
1255                  $parser_check = xml_parser_create();
1256                  xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1257                  xml_parser_free($parser_check);
1258                  $xml_is_sane = isset($values[0]['value']);
1259              }
1260              if (!$xml_is_sane)
1261              {
1262                  return false;
1263              }
1264          }
1265  
1266          if (method_exists($this->sanitize, 'set_registry'))
1267          {
1268              $this->sanitize->set_registry($this->registry);
1269          }
1270  
1271          // Pass whatever was set with config options over to the sanitizer.
1272          // Pass the classes in for legacy support; new classes should use the registry instead
1273          $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
1274          $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
1275  
1276          if (!empty($this->multifeed_url))
1277          {
1278              $i = 0;
1279              $success = 0;
1280              $this->multifeed_objects = array();
1281              $this->error = array();
1282              foreach ($this->multifeed_url as $url)
1283              {
1284                  $this->multifeed_objects[$i] = clone $this;
1285                  $this->multifeed_objects[$i]->set_feed_url($url);
1286                  $single_success = $this->multifeed_objects[$i]->init();
1287                  $success |= $single_success;
1288                  if (!$single_success)
1289                  {
1290                      $this->error[$i] = $this->multifeed_objects[$i]->error();
1291                  }
1292                  $i++;
1293              }
1294              return (bool) $success;
1295          }
1296          elseif ($this->feed_url === null && $this->raw_data === null)
1297          {
1298              return false;
1299          }
1300  
1301          $this->error = null;
1302          $this->data = array();
1303          $this->multifeed_objects = array();
1304          $cache = false;
1305  
1306          if ($this->feed_url !== null)
1307          {
1308              $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
1309  
1310              // Decide whether to enable caching
1311              if ($this->cache && $parsed_feed_url['scheme'] !== '')
1312              {
1313                  $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
1314              }
1315  
1316              // Fetch the data via SimplePie_File into $this->raw_data
1317              if (($fetched = $this->fetch_data($cache)) === true)
1318              {
1319                  return true;
1320              }
1321              elseif ($fetched === false) {
1322                  return false;
1323              }
1324  
1325              list($headers, $sniffed) = $fetched;
1326          }
1327  
1328          // Set up array of possible encodings
1329          $encodings = array();
1330  
1331          // First check to see if input has been overridden.
1332          if ($this->input_encoding !== false)
1333          {
1334              $encodings[] = $this->input_encoding;
1335          }
1336  
1337          $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1338          $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1339  
1340          // RFC 3023 (only applies to sniffed content)
1341          if (isset($sniffed))
1342          {
1343              if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1344              {
1345                  if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1346                  {
1347                      $encodings[] = strtoupper($charset[1]);
1348                  }
1349                  $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1350                  $encodings[] = 'UTF-8';
1351              }
1352              elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1353              {
1354                  if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1355                  {
1356                      $encodings[] = $charset[1];
1357                  }
1358                  $encodings[] = 'US-ASCII';
1359              }
1360              // Text MIME-type default
1361              elseif (substr($sniffed, 0, 5) === 'text/')
1362              {
1363                  $encodings[] = 'US-ASCII';
1364              }
1365          }
1366  
1367          // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1368          $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1369          $encodings[] = 'UTF-8';
1370          $encodings[] = 'ISO-8859-1';
1371  
1372          // There's no point in trying an encoding twice
1373          $encodings = array_unique($encodings);
1374  
1375          // Loop through each possible encoding, till we return something, or run out of possibilities
1376          foreach ($encodings as $encoding)
1377          {
1378              // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1379              if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
1380              {
1381                  // Create new parser
1382                  $parser = $this->registry->create('Parser');
1383  
1384                  // If it's parsed fine
1385                  if ($parser->parse($utf8_data, 'UTF-8'))
1386                  {
1387                      $this->data = $parser->get_data();
1388                      if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
1389                      {
1390                          $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1391                          $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1392                          return false;
1393                      }
1394  
1395                      if (isset($headers))
1396                      {
1397                          $this->data['headers'] = $headers;
1398                      }
1399                      $this->data['build'] = SIMPLEPIE_BUILD;
1400  
1401                      // Cache the file if caching is enabled
1402                      if ($cache && !$cache->save($this))
1403                      {
1404                          trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1405                      }
1406                      return true;
1407                  }
1408              }
1409          }
1410  
1411          if (isset($parser))
1412          {
1413              // We have an error, just set SimplePie_Misc::error to it and quit
1414              $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1415          }
1416          else
1417          {
1418              $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1419          }
1420  
1421          $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1422  
1423          return false;
1424      }
1425  
1426      /**
1427       * Fetch the data via SimplePie_File
1428       *
1429       * If the data is already cached, attempt to fetch it from there instead
1430       * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
1431       * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
1432       */
1433  	protected function fetch_data(&$cache)
1434      {
1435          // If it's enabled, use the cache
1436          if ($cache)
1437          {
1438              // Load the Cache
1439              $this->data = $cache->load();
1440              if (!empty($this->data))
1441              {
1442                  // If the cache is for an outdated build of SimplePie
1443                  if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1444                  {
1445                      $cache->unlink();
1446                      $this->data = array();
1447                  }
1448                  // If we've hit a collision just rerun it with caching disabled
1449                  elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1450                  {
1451                      $cache = false;
1452                      $this->data = array();
1453                  }
1454                  // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1455                  elseif (isset($this->data['feed_url']))
1456                  {
1457                      // If the autodiscovery cache is still valid use it.
1458                      if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1459                      {
1460                          // Do not need to do feed autodiscovery yet.
1461                          if ($this->data['feed_url'] !== $this->data['url'])
1462                          {
1463                              $this->set_feed_url($this->data['feed_url']);
1464                              return $this->init();
1465                          }
1466  
1467                          $cache->unlink();
1468                          $this->data = array();
1469                      }
1470                  }
1471                  // Check if the cache has been updated
1472                  elseif ($cache->mtime() + $this->cache_duration < time())
1473                  {
1474                      // If we have last-modified and/or etag set
1475                      if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1476                      {
1477                          $headers = array(
1478                              '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',
1479                          );
1480                          if (isset($this->data['headers']['last-modified']))
1481                          {
1482                              $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1483                          }
1484                          if (isset($this->data['headers']['etag']))
1485                          {
1486                              $headers['if-none-match'] = $this->data['headers']['etag'];
1487                          }
1488  
1489                          $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
1490  
1491                          if ($file->success)
1492                          {
1493                              if ($file->status_code === 304)
1494                              {
1495                                  $cache->touch();
1496                                  return true;
1497                              }
1498                          }
1499                          else
1500                          {
1501                              unset($file);
1502                          }
1503                      }
1504                  }
1505                  // If the cache is still valid, just return true
1506                  else
1507                  {
1508                      $this->raw_data = false;
1509                      return true;
1510                  }
1511              }
1512              // If the cache is empty, delete it
1513              else
1514              {
1515                  $cache->unlink();
1516                  $this->data = array();
1517              }
1518          }
1519          // 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.
1520          if (!isset($file))
1521          {
1522              if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
1523              {
1524                  $file =& $this->file;
1525              }
1526              else
1527              {
1528                  $headers = array(
1529                      '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',
1530                  );
1531                  $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
1532              }
1533          }
1534          // If the file connection has an error, set SimplePie::error to that and quit
1535          if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1536          {
1537              $this->error = $file->error;
1538              return !empty($this->data);
1539          }
1540  
1541          if (!$this->force_feed)
1542          {
1543              // Check if the supplied URL is a feed, if it isn't, look for it.
1544              $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
1545  
1546              if (!$locate->is_feed($file))
1547              {
1548                  // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1549                  unset($file);
1550                  try
1551                  {
1552                      if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
1553                      {
1554                          $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1555                          $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1556                          return false;
1557                      }
1558                  }
1559                  catch (SimplePie_Exception $e)
1560                  {
1561                      // This is usually because DOMDocument doesn't exist
1562                      $this->error = $e->getMessage();
1563                      $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
1564                      return false;
1565                  }
1566                  if ($cache)
1567                  {
1568                      $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1569                      if (!$cache->save($this))
1570                      {
1571                          trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1572                      }
1573                      $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
1574                  }
1575                  $this->feed_url = $file->url;
1576              }
1577              $locate = null;
1578          }
1579  
1580          $this->raw_data = $file->body;
1581  
1582          $headers = $file->headers;
1583          $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
1584          $sniffed = $sniffer->get_type();
1585  
1586          return array($headers, $sniffed);
1587      }
1588  
1589      /**
1590       * Get the error message for the occurred error.
1591       *
1592       * @return string|array Error message, or array of messages for multifeeds
1593       */
1594  	public function error()
1595      {
1596          return $this->error;
1597      }
1598  
1599      /**
1600       * Get the raw XML
1601       *
1602       * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
1603       * the data instead of printing it.
1604       *
1605       * @return string|boolean Raw XML data, false if the cache is used
1606       */
1607  	public function get_raw_data()
1608      {
1609          return $this->raw_data;
1610      }
1611  
1612      /**
1613       * Get the character encoding used for output
1614       *
1615       * @since Preview Release
1616       * @return string
1617       */
1618  	public function get_encoding()
1619      {
1620          return $this->sanitize->output_encoding;
1621      }
1622  
1623      /**
1624       * Send the content-type header with correct encoding
1625       *
1626       * This method ensures that the SimplePie-enabled page is being served with
1627       * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
1628       * and character encoding HTTP headers (character encoding determined by the
1629       * {@see set_output_encoding} config option).
1630       *
1631       * This won't work properly if any content or whitespace has already been
1632       * sent to the browser, because it relies on PHP's
1633       * {@link http://php.net/header header()} function, and these are the
1634       * circumstances under which the function works.
1635       *
1636       * Because it's setting these settings for the entire page (as is the nature
1637       * of HTTP headers), this should only be used once per page (again, at the
1638       * top).
1639       *
1640       * @param string $mime MIME type to serve the page as
1641       */
1642  	public function handle_content_type($mime = 'text/html')
1643      {
1644          if (!headers_sent())
1645          {
1646              $header = "Content-type: $mime;";
1647              if ($this->get_encoding())
1648              {
1649                  $header .= ' charset=' . $this->get_encoding();
1650              }
1651              else
1652              {
1653                  $header .= ' charset=UTF-8';
1654              }
1655              header($header);
1656          }
1657      }
1658  
1659      /**
1660       * Get the type of the feed
1661       *
1662       * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
1663       * using {@link http://php.net/language.operators.bitwise bitwise operators}
1664       *
1665       * @since 0.8 (usage changed to using constants in 1.0)
1666       * @see SIMPLEPIE_TYPE_NONE Unknown.
1667       * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
1668       * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
1669       * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
1670       * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
1671       * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
1672       * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
1673       * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
1674       * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
1675       * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
1676       * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
1677       * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
1678       * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
1679       * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
1680       * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
1681       * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
1682       * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
1683       * @return int SIMPLEPIE_TYPE_* constant
1684       */
1685  	public function get_type()
1686      {
1687          if (!isset($this->data['type']))
1688          {
1689              $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1690              if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1691              {
1692                  $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1693              }
1694              elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1695              {
1696                  $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1697              }
1698              elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1699              {
1700                  if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1701                  || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1702                  || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1703                  || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1704                  {
1705                      $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1706                  }
1707                  if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1708                  || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1709                  || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1710                  || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1711                  {
1712                      $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1713                  }
1714              }
1715              elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1716              {
1717                  $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1718                  if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1719                  {
1720                      switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1721                      {
1722                          case '0.91':
1723                              $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1724                              if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1725                              {
1726                                  switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1727                                  {
1728                                      case '0':
1729                                          $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1730                                          break;
1731  
1732                                      case '24':
1733                                          $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1734                                          break;
1735                                  }
1736                              }
1737                              break;
1738  
1739                          case '0.92':
1740                              $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1741                              break;
1742  
1743                          case '0.93':
1744                              $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1745                              break;
1746  
1747                          case '0.94':
1748                              $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1749                              break;
1750  
1751                          case '2.0':
1752                              $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1753                              break;
1754                      }
1755                  }
1756              }
1757              else
1758              {
1759                  $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1760              }
1761          }
1762          return $this->data['type'];
1763      }
1764  
1765      /**
1766       * Get the URL for the feed
1767       *
1768       * May or may not be different from the URL passed to {@see set_feed_url()},
1769       * depending on whether auto-discovery was used.
1770       *
1771       * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
1772       * @todo If we have a perm redirect we should return the new URL
1773       * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1774       * @todo Also, |atom:link|@rel=self
1775       * @return string|null
1776       */
1777  	public function subscribe_url()
1778      {
1779          if ($this->feed_url !== null)
1780          {
1781              return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1782          }
1783          else
1784          {
1785              return null;
1786          }
1787      }
1788  
1789      /**
1790       * Get data for an feed-level element
1791       *
1792       * This method allows you to get access to ANY element/attribute that is a
1793       * sub-element of the opening feed tag.
1794       *
1795       * The return value is an indexed array of elements matching the given
1796       * namespace and tag name. Each element has `attribs`, `data` and `child`
1797       * subkeys. For `attribs` and `child`, these contain namespace subkeys.
1798       * `attribs` then has one level of associative name => value data (where
1799       * `value` is a string) after the namespace. `child` has tag-indexed keys
1800       * after the namespace, each member of which is an indexed array matching
1801       * this same format.
1802       *
1803       * For example:
1804       * <pre>
1805       * // This is probably a bad example because we already support
1806       * // <media:content> natively, but it shows you how to parse through
1807       * // the nodes.
1808       * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
1809       * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
1810       * $file = $content[0]['attribs']['']['url'];
1811       * echo $file;
1812       * </pre>
1813       *
1814       * @since 1.0
1815       * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1816       * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1817       * @param string $tag Tag name
1818       * @return array
1819       */
1820  	public function get_feed_tags($namespace, $tag)
1821      {
1822          $type = $this->get_type();
1823          if ($type & SIMPLEPIE_TYPE_ATOM_10)
1824          {
1825              if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1826              {
1827                  return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1828              }
1829          }
1830          if ($type & SIMPLEPIE_TYPE_ATOM_03)
1831          {
1832              if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1833              {
1834                  return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1835              }
1836          }
1837          if ($type & SIMPLEPIE_TYPE_RSS_RDF)
1838          {
1839              if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1840              {
1841                  return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
1842              }
1843          }
1844          if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1845          {
1846              if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
1847              {
1848                  return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
1849              }
1850          }
1851          return null;
1852      }
1853  
1854      /**
1855       * Get data for an channel-level element
1856       *
1857       * This method allows you to get access to ANY element/attribute in the
1858       * channel/header section of the feed.
1859       *
1860       * See {@see SimplePie::get_feed_tags()} for a description of the return value
1861       *
1862       * @since 1.0
1863       * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1864       * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1865       * @param string $tag Tag name
1866       * @return array
1867       */
1868  	public function get_channel_tags($namespace, $tag)
1869      {
1870          $type = $this->get_type();
1871          if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
1872          {
1873              if ($return = $this->get_feed_tags($namespace, $tag))
1874              {
1875                  return $return;
1876              }
1877          }
1878          if ($type & SIMPLEPIE_TYPE_RSS_10)
1879          {
1880              if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
1881              {
1882                  if (isset($channel[0]['child'][$namespace][$tag]))
1883                  {
1884                      return $channel[0]['child'][$namespace][$tag];
1885                  }
1886              }
1887          }
1888          if ($type & SIMPLEPIE_TYPE_RSS_090)
1889          {
1890              if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
1891              {
1892                  if (isset($channel[0]['child'][$namespace][$tag]))
1893                  {
1894                      return $channel[0]['child'][$namespace][$tag];
1895                  }
1896              }
1897          }
1898          if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1899          {
1900              if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
1901              {
1902                  if (isset($channel[0]['child'][$namespace][$tag]))
1903                  {
1904                      return $channel[0]['child'][$namespace][$tag];
1905                  }
1906              }
1907          }
1908          return null;
1909      }
1910  
1911      /**
1912       * Get data for an channel-level element
1913       *
1914       * This method allows you to get access to ANY element/attribute in the
1915       * image/logo section of the feed.
1916       *
1917       * See {@see SimplePie::get_feed_tags()} for a description of the return value
1918       *
1919       * @since 1.0
1920       * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1921       * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1922       * @param string $tag Tag name
1923       * @return array
1924       */
1925  	public function get_image_tags($namespace, $tag)
1926      {
1927          $type = $this->get_type();
1928          if ($type & SIMPLEPIE_TYPE_RSS_10)
1929          {
1930              if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
1931              {
1932                  if (isset($image[0]['child'][$namespace][$tag]))
1933                  {
1934                      return $image[0]['child'][$namespace][$tag];
1935                  }
1936              }
1937          }
1938          if ($type & SIMPLEPIE_TYPE_RSS_090)
1939          {
1940              if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
1941              {
1942                  if (isset($image[0]['child'][$namespace][$tag]))
1943                  {
1944                      return $image[0]['child'][$namespace][$tag];
1945                  }
1946              }
1947          }
1948          if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1949          {
1950              if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
1951              {
1952                  if (isset($image[0]['child'][$namespace][$tag]))
1953                  {
1954                      return $image[0]['child'][$namespace][$tag];
1955                  }
1956              }
1957          }
1958          return null;
1959      }
1960  
1961      /**
1962       * Get the base URL value from the feed
1963       *
1964       * Uses `<xml:base>` if available, otherwise uses the first link in the
1965       * feed, or failing that, the URL of the feed itself.
1966       *
1967       * @see get_link
1968       * @see subscribe_url
1969       *
1970       * @param array $element
1971       * @return string
1972       */
1973  	public function get_base($element = array())
1974      {
1975          if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
1976          {
1977              return $element['xml_base'];
1978          }
1979          elseif ($this->get_link() !== null)
1980          {
1981              return $this->get_link();
1982          }
1983          else
1984          {
1985              return $this->subscribe_url();
1986          }
1987      }
1988  
1989      /**
1990       * Sanitize feed data
1991       *
1992       * @access private
1993       * @see SimplePie_Sanitize::sanitize()
1994       * @param string $data Data to sanitize
1995       * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
1996       * @param string $base Base URL to resolve URLs against
1997       * @return string Sanitized data
1998       */
1999  	public function sanitize($data, $type, $base = '')
2000      {
2001          return $this->sanitize->sanitize($data, $type, $base);
2002      }
2003  
2004      /**
2005       * Get the title of the feed
2006       *
2007       * Uses `<atom:title>`, `<title>` or `<dc:title>`
2008       *
2009       * @since 1.0 (previously called `get_feed_title` since 0.8)
2010       * @return string|null
2011       */
2012  	public function get_title()
2013      {
2014          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2015          {
2016              return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2017          }
2018          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2019          {
2020              return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2021          }
2022          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2023          {
2024              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2025          }
2026          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2027          {
2028              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2029          }
2030          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2031          {
2032              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2033          }
2034          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2035          {
2036              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2037          }
2038          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2039          {
2040              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2041          }
2042          else
2043          {
2044              return null;
2045          }
2046      }
2047  
2048      /**
2049       * Get a category for the feed
2050       *
2051       * @since Unknown
2052       * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
2053       * @return SimplePie_Category|null
2054       */
2055  	public function get_category($key = 0)
2056      {
2057          $categories = $this->get_categories();
2058          if (isset($categories[$key]))
2059          {
2060              return $categories[$key];
2061          }
2062          else
2063          {
2064              return null;
2065          }
2066      }
2067  
2068      /**
2069       * Get all categories for the feed
2070       *
2071       * Uses `<atom:category>`, `<category>` or `<dc:subject>`
2072       *
2073       * @since Unknown
2074       * @return array|null List of {@see SimplePie_Category} objects
2075       */
2076  	public function get_categories()
2077      {
2078          $categories = array();
2079  
2080          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2081          {
2082              $term = null;
2083              $scheme = null;
2084              $label = null;
2085              if (isset($category['attribs']['']['term']))
2086              {
2087                  $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2088              }
2089              if (isset($category['attribs']['']['scheme']))
2090              {
2091                  $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2092              }
2093              if (isset($category['attribs']['']['label']))
2094              {
2095                  $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2096              }
2097              $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
2098          }
2099          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2100          {
2101              // This is really the label, but keep this as the term also for BC.
2102              // Label will also work on retrieving because that falls back to term.
2103              $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2104              if (isset($category['attribs']['']['domain']))
2105              {
2106                  $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2107              }
2108              else
2109              {
2110                  $scheme = null;
2111              }
2112              $categories[] = $this->registry->create('Category', array($term, $scheme, null));
2113          }
2114          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2115          {
2116              $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2117          }
2118          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2119          {
2120              $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2121          }
2122  
2123          if (!empty($categories))
2124          {
2125              return array_unique($categories);
2126          }
2127          else
2128          {
2129              return null;
2130          }
2131      }
2132  
2133      /**
2134       * Get an author for the feed
2135       *
2136       * @since 1.1
2137       * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
2138       * @return SimplePie_Author|null
2139       */
2140  	public function get_author($key = 0)
2141      {
2142          $authors = $this->get_authors();
2143          if (isset($authors[$key]))
2144          {
2145              return $authors[$key];
2146          }
2147          else
2148          {
2149              return null;
2150          }
2151      }
2152  
2153      /**
2154       * Get all authors for the feed
2155       *
2156       * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
2157       *
2158       * @since 1.1
2159       * @return array|null List of {@see SimplePie_Author} objects
2160       */
2161  	public function get_authors()
2162      {
2163          $authors = array();
2164          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2165          {
2166              $name = null;
2167              $uri = null;
2168              $email = null;
2169              if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2170              {
2171                  $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2172              }
2173              if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2174              {
2175                  $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]));
2176              }
2177              if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2178              {
2179                  $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2180              }
2181              if ($name !== null || $email !== null || $uri !== null)
2182              {
2183                  $authors[] = $this->registry->create('Author', array($name, $uri, $email));
2184              }
2185          }
2186          if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2187          {
2188              $name = null;
2189              $url = null;
2190              $email = null;
2191              if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2192              {
2193                  $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2194              }
2195              if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2196              {
2197                  $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]));
2198              }
2199              if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2200              {
2201                  $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2202              }
2203              if ($name !== null || $email !== null || $url !== null)
2204              {
2205                  $authors[] = $this->registry->create('Author', array($name, $url, $email));
2206              }
2207          }
2208          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2209          {
2210              $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2211          }
2212          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2213          {
2214              $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2215          }
2216          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2217          {
2218              $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2219          }
2220  
2221          if (!empty($authors))
2222          {
2223              return array_unique($authors);
2224          }
2225          else
2226          {
2227              return null;
2228          }
2229      }
2230  
2231      /**
2232       * Get a contributor for the feed
2233       *
2234       * @since 1.1
2235       * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
2236       * @return SimplePie_Author|null
2237       */
2238  	public function get_contributor($key = 0)
2239      {
2240          $contributors = $this->get_contributors();
2241          if (isset($contributors[$key]))
2242          {
2243              return $contributors[$key];
2244          }
2245          else
2246          {
2247              return null;
2248          }
2249      }
2250  
2251      /**
2252       * Get all contributors for the feed
2253       *
2254       * Uses `<atom:contributor>`
2255       *
2256       * @since 1.1
2257       * @return array|null List of {@see SimplePie_Author} objects
2258       */
2259  	public function get_contributors()
2260      {
2261          $contributors = array();
2262          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2263          {
2264              $name = null;
2265              $uri = null;
2266              $email = null;
2267              if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2268              {
2269                  $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2270              }
2271              if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2272              {
2273                  $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]));
2274              }
2275              if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2276              {
2277                  $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2278              }
2279              if ($name !== null || $email !== null || $uri !== null)
2280              {
2281                  $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
2282              }
2283          }
2284          foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2285          {
2286              $name = null;
2287              $url = null;
2288              $email = null;
2289              if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2290              {
2291                  $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2292              }
2293              if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2294              {
2295                  $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]));
2296              }
2297              if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2298              {
2299                  $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2300              }
2301              if ($name !== null || $email !== null || $url !== null)
2302              {
2303                  $contributors[] = $this->registry->create('Author', array($name, $url, $email));
2304              }
2305          }
2306  
2307          if (!empty($contributors))
2308          {
2309              return array_unique($contributors);
2310          }
2311          else
2312          {
2313              return null;
2314          }
2315      }
2316  
2317      /**
2318       * Get a single link for the feed
2319       *
2320       * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2321       * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
2322       * @param string $rel The relationship of the link to return
2323       * @return string|null Link URL
2324       */
2325  	public function get_link($key = 0, $rel = 'alternate')
2326      {
2327          $links = $this->get_links($rel);
2328          if (isset($links[$key]))
2329          {
2330              return $links[$key];
2331          }
2332          else
2333          {
2334              return null;
2335          }
2336      }
2337  
2338      /**
2339       * Get the permalink for the item
2340       *
2341       * Returns the first link available with a relationship of "alternate".
2342       * Identical to {@see get_link()} with key 0
2343       *
2344       * @see get_link
2345       * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2346       * @internal Added for parity between the parent-level and the item/entry-level.
2347       * @return string|null Link URL
2348       */
2349  	public function get_permalink()
2350      {
2351          return $this->get_link(0);
2352      }
2353  
2354      /**
2355       * Get all links for the feed
2356       *
2357       * Uses `<atom:link>` or `<link>`
2358       *
2359       * @since Beta 2
2360       * @param string $rel The relationship of links to return
2361       * @return array|null Links found for the feed (strings)
2362       */
2363  	public function get_links($rel = 'alternate')
2364      {
2365          if (!isset($this->data['links']))
2366          {
2367              $this->data['links'] = array();
2368              if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2369              {
2370                  foreach ($links as $link)
2371                  {
2372                      if (isset($link['attribs']['']['href']))
2373                      {
2374                          $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2375                          $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2376                      }
2377                  }
2378              }
2379              if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2380              {
2381                  foreach ($links as $link)
2382                  {
2383                      if (isset($link['attribs']['']['href']))
2384                      {
2385                          $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2386                          $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2387  
2388                      }
2389                  }
2390              }
2391              if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2392              {
2393                  $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2394              }
2395              if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2396              {
2397                  $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2398              }
2399              if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2400              {
2401                  $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2402              }
2403  
2404              $keys = array_keys($this->data['links']);
2405              foreach ($keys as $key)
2406              {
2407                  if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
2408                  {
2409                      if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2410                      {
2411                          $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2412                          $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2413                      }
2414                      else
2415                      {
2416                          $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2417                      }
2418                  }
2419                  elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2420                  {
2421                      $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2422                  }
2423                  $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2424              }
2425          }
2426  
2427          if (isset($this->data['links'][$rel]))
2428          {
2429              return $this->data['links'][$rel];
2430          }
2431          else
2432          {
2433              return null;
2434          }
2435      }
2436  
2437  	public function get_all_discovered_feeds()
2438      {
2439          return $this->all_discovered_feeds;
2440      }
2441  
2442      /**
2443       * Get the content for the item
2444       *
2445       * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
2446       * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
2447       *
2448       * @since 1.0 (previously called `get_feed_description()` since 0.8)
2449       * @return string|null
2450       */
2451  	public function get_description()
2452      {
2453          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2454          {
2455              return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2456          }
2457          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2458          {
2459              return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2460          }
2461          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2462          {
2463              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2464          }
2465          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2466          {
2467              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2468          }
2469          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2470          {
2471              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2472          }
2473          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2474          {
2475              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2476          }
2477          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2478          {
2479              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2480          }
2481          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2482          {
2483              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2484          }
2485          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2486          {
2487              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2488          }
2489          else
2490          {
2491              return null;
2492          }
2493      }
2494  
2495      /**
2496       * Get the copyright info for the feed
2497       *
2498       * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
2499       *
2500       * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
2501       * @return string|null
2502       */
2503  	public function get_copyright()
2504      {
2505          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2506          {
2507              return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2508          }
2509          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2510          {
2511              return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2512          }
2513          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2514          {
2515              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2516          }
2517          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2518          {
2519              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2520          }
2521          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2522          {
2523              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2524          }
2525          else
2526          {
2527              return null;
2528          }
2529      }
2530  
2531      /**
2532       * Get the language for the feed
2533       *
2534       * Uses `<language>`, `<dc:language>`, or @xml_lang
2535       *
2536       * @since 1.0 (previously called `get_feed_language()` since 0.8)
2537       * @return string|null
2538       */
2539  	public function get_language()
2540      {
2541          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2542          {
2543              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2544          }
2545          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2546          {
2547              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2548          }
2549          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2550          {
2551              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2552          }
2553          elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2554          {
2555              return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2556          }
2557          elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2558          {
2559              return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2560          }
2561          elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2562          {
2563              return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2564          }
2565          elseif (isset($this->data['headers']['content-language']))
2566          {
2567              return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2568          }
2569          else
2570          {
2571              return null;
2572          }
2573      }
2574  
2575      /**
2576       * Get the latitude coordinates for the item
2577       *
2578       * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2579       *
2580       * Uses `<geo:lat>` or `<georss:point>`
2581       *
2582       * @since 1.0
2583       * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2584       * @link http://www.georss.org/ GeoRSS
2585       * @return string|null
2586       */
2587  	public function get_latitude()
2588      {
2589  
2590          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2591          {
2592              return (float) $return[0]['data'];
2593          }
2594          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))
2595          {
2596              return (float) $match[1];
2597          }
2598          else
2599          {
2600              return null;
2601          }
2602      }
2603  
2604      /**
2605       * Get the longitude coordinates for the feed
2606       *
2607       * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2608       *
2609       * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2610       *
2611       * @since 1.0
2612       * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2613       * @link http://www.georss.org/ GeoRSS
2614       * @return string|null
2615       */
2616  	public function get_longitude()
2617      {
2618          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2619          {
2620              return (float) $return[0]['data'];
2621          }
2622          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2623          {
2624              return (float) $return[0]['data'];
2625          }
2626          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))
2627          {
2628              return (float) $match[2];
2629          }
2630          else
2631          {
2632              return null;
2633          }
2634      }
2635  
2636      /**
2637       * Get the feed logo's title
2638       *
2639       * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
2640       *
2641       * Uses `<image><title>` or `<image><dc:title>`
2642       *
2643       * @return string|null
2644       */
2645  	public function get_image_title()
2646      {
2647          if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2648          {
2649              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2650          }
2651          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2652          {
2653              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2654          }
2655          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2656          {
2657              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2658          }
2659          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2660          {
2661              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2662          }
2663          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2664          {
2665              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2666          }
2667          else
2668          {
2669              return null;
2670          }
2671      }
2672  
2673      /**
2674       * Get the feed logo's URL
2675       *
2676       * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
2677       * have a "feed logo" URL. This points directly to the image itself.
2678       *
2679       * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2680       * `<image><title>` or `<image><dc:title>`
2681       *
2682       * @return string|null
2683       */
2684  	public function get_image_url()
2685      {
2686          if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2687          {
2688              return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2689          }
2690          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2691          {
2692              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2693          }
2694          elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2695          {
2696              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2697          }
2698          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2699          {
2700              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2701          }
2702          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2703          {
2704              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2705          }
2706          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2707          {
2708              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2709          }
2710          else
2711          {
2712              return null;
2713          }
2714      }
2715  
2716  
2717      /**
2718       * Get the feed logo's link
2719       *
2720       * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
2721       * points to a human-readable page that the image should link to.
2722       *
2723       * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2724       * `<image><title>` or `<image><dc:title>`
2725       *
2726       * @return string|null
2727       */
2728  	public function get_image_link()
2729      {
2730          if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2731          {
2732              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2733          }
2734          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2735          {
2736              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2737          }
2738          elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2739          {
2740              return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2741          }
2742          else
2743          {
2744              return null;
2745          }
2746      }
2747  
2748      /**
2749       * Get the feed logo's link
2750       *
2751       * RSS 2.0 feeds are allowed to have a "feed logo" width.
2752       *
2753       * Uses `<image><width>` or defaults to 88.0 if no width is specified and
2754       * the feed is an RSS 2.0 feed.
2755       *
2756       * @return int|float|null
2757       */
2758  	public function get_image_width()
2759      {
2760          if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2761          {
2762              return round($return[0]['data']);
2763          }
2764          elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2765          {
2766              return 88.0;
2767          }
2768          else
2769          {
2770              return null;
2771          }
2772      }
2773  
2774      /**
2775       * Get the feed logo's height
2776       *
2777       * RSS 2.0 feeds are allowed to have a "feed logo" height.
2778       *
2779       * Uses `<image><height>` or defaults to 31.0 if no height is specified and
2780       * the feed is an RSS 2.0 feed.
2781       *
2782       * @return int|float|null
2783       */
2784  	public function get_image_height()
2785      {
2786          if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2787          {
2788              return round($return[0]['data']);
2789          }
2790          elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2791          {
2792              return 31.0;
2793          }
2794          else
2795          {
2796              return null;
2797          }
2798      }
2799  
2800      /**
2801       * Get the number of items in the feed
2802       *
2803       * This is well-suited for {@link http://php.net/for for()} loops with
2804       * {@see get_item()}
2805       *
2806       * @param int $max Maximum value to return. 0 for no limit
2807       * @return int Number of items in the feed
2808       */
2809  	public function get_item_quantity($max = 0)
2810      {
2811          $max = (int) $max;
2812          $qty = count($this->get_items());
2813          if ($max === 0)
2814          {
2815              return $qty;
2816          }
2817          else
2818          {
2819              return ($qty > $max) ? $max : $qty;
2820          }
2821      }
2822  
2823      /**
2824       * Get a single item from the feed
2825       *
2826       * This is better suited for {@link http://php.net/for for()} loops, whereas
2827       * {@see get_items()} is better suited for
2828       * {@link http://php.net/foreach foreach()} loops.
2829       *
2830       * @see get_item_quantity()
2831       * @since Beta 2
2832       * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1
2833       * @return SimplePie_Item|null
2834       */
2835  	public function get_item($key = 0)
2836      {
2837          $items = $this->get_items();
2838          if (isset($items[$key]))
2839          {
2840              return $items[$key];
2841          }
2842          else
2843          {
2844              return null;
2845          }
2846      }
2847  
2848      /**
2849       * Get all items from the feed
2850       *
2851       * This is better suited for {@link http://php.net/for for()} loops, whereas
2852       * {@see get_items()} is better suited for
2853       * {@link http://php.net/foreach foreach()} loops.
2854       *
2855       * @see get_item_quantity
2856       * @since Beta 2
2857       * @param int $start Index to start at
2858       * @param int $end Number of items to return. 0 for all items after `$start`
2859       * @return array|null List of {@see SimplePie_Item} objects
2860       */
2861  	public function get_items($start = 0, $end = 0)
2862      {
2863          if (!isset($this->data['items']))
2864          {
2865              if (!empty($this->multifeed_objects))
2866              {
2867                  $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2868              }
2869              else
2870              {
2871                  $this->data['items'] = array();
2872                  if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2873                  {
2874                      $keys = array_keys($items);
2875                      foreach ($keys as $key)
2876                      {
2877                          $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2878                      }
2879                  }
2880                  if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2881                  {
2882                      $keys = array_keys($items);
2883                      foreach ($keys as $key)
2884                      {
2885                          $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2886                      }
2887                  }
2888                  if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2889                  {
2890                      $keys = array_keys($items);
2891                      foreach ($keys as $key)
2892                      {
2893                          $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2894                      }
2895                  }
2896                  if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2897                  {
2898                      $keys = array_keys($items);
2899                      foreach ($keys as $key)
2900                      {
2901                          $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2902                      }
2903                  }
2904                  if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2905                  {
2906                      $keys = array_keys($items);
2907                      foreach ($keys as $key)
2908                      {
2909                          $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2910                      }
2911                  }
2912              }
2913          }
2914  
2915          if (!empty($this->data['items']))
2916          {
2917              // If we want to order it by date, check if all items have a date, and then sort it
2918              if ($this->order_by_date && empty($this->multifeed_objects))
2919              {
2920                  if (!isset($this->data['ordered_items']))
2921                  {
2922                      $do_sort = true;
2923                      foreach ($this->data['items'] as $item)
2924                      {
2925                          if (!$item->get_date('U'))
2926                          {
2927                              $do_sort = false;
2928                              break;
2929                          }
2930                      }
2931                      $item = null;
2932                      $this->data['ordered_items'] = $this->data['items'];
2933                      if ($do_sort)
2934                      {
2935                          usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
2936                      }
2937                  }
2938                  $items = $this->data['ordered_items'];
2939              }
2940              else
2941              {
2942                  $items = $this->data['items'];
2943              }
2944  
2945              // Slice the data as desired
2946              if ($end === 0)
2947              {
2948                  return array_slice($items, $start);
2949              }
2950              else
2951              {
2952                  return array_slice($items, $start, $end);
2953              }
2954          }
2955          else
2956          {
2957              return array();
2958          }
2959      }
2960  
2961      /**
2962       * Set the favicon handler
2963       *
2964       * @deprecated Use your own favicon handling instead
2965       */
2966  	public function set_favicon_handler($page = false, $qs = 'i')
2967      {
2968          $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
2969          trigger_error('Favicon handling has been removed, please use your own handling', $level);
2970          return false;
2971      }
2972  
2973      /**
2974       * Get the favicon for the current feed
2975       *
2976       * @deprecated Use your own favicon handling instead
2977       */
2978  	public function get_favicon()
2979      {
2980          $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
2981          trigger_error('Favicon handling has been removed, please use your own handling', $level);
2982  
2983          if (($url = $this->get_link()) !== null)
2984          {
2985              return 'http://g.etfv.co/' . urlencode($url);
2986          }
2987  
2988          return false;
2989      }
2990  
2991      /**
2992       * Magic method handler
2993       *
2994       * @param string $method Method name
2995       * @param array $args Arguments to the method
2996       * @return mixed
2997       */
2998  	public function __call($method, $args)
2999      {
3000          if (strpos($method, 'subscribe_') === 0)
3001          {
3002              $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3003              trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
3004              return '';
3005          }
3006          if ($method === 'enable_xml_dump')
3007          {
3008              $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3009              trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
3010              return false;
3011          }
3012  
3013          $class = get_class($this);
3014          $trace = debug_backtrace();
3015          $file = $trace[0]['file'];
3016          $line = $trace[0]['line'];
3017          trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
3018      }
3019  
3020      /**
3021       * Sorting callback for items
3022       *
3023       * @access private
3024       * @param SimplePie $a
3025       * @param SimplePie $b
3026       * @return boolean
3027       */
3028  	public static function sort_items($a, $b)
3029      {
3030          return $a->get_date('U') <= $b->get_date('U');
3031      }
3032  
3033      /**
3034       * Merge items from several feeds into one
3035       *
3036       * If you're merging multiple feeds together, they need to all have dates
3037       * for the items or else SimplePie will refuse to sort them.
3038       *
3039       * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
3040       * @param array $urls List of SimplePie feed objects to merge
3041       * @param int $start Starting item
3042       * @param int $end Number of items to return
3043       * @param int $limit Maximum number of items per feed
3044       * @return array
3045       */
3046  	public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3047      {
3048          if (is_array($urls) && sizeof($urls) > 0)
3049          {
3050              $items = array();
3051              foreach ($urls as $arg)
3052              {
3053                  if ($arg instanceof SimplePie)
3054                  {
3055                      $items = array_merge($items, $arg->get_items(0, $limit));
3056                  }
3057                  else
3058                  {
3059                      trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3060                  }
3061              }
3062  
3063              $do_sort = true;
3064              foreach ($items as $item)
3065              {
3066                  if (!$item->get_date('U'))
3067                  {
3068                      $do_sort = false;
3069                      break;
3070                  }
3071              }
3072              $item = null;
3073              if ($do_sort)
3074              {
3075                  usort($items, array(get_class($urls[0]), 'sort_items'));
3076              }
3077  
3078              if ($end === 0)
3079              {
3080                  return array_slice($items, $start);
3081              }
3082              else
3083              {
3084                  return array_slice($items, $start, $end);
3085              }
3086          }
3087          else
3088          {
3089              trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3090              return array();
3091          }
3092      }
3093  }
3094  endif;


Generated: Tue Oct 22 08:20:01 2019 Cross-referenced by PHPXref 0.7