Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

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