Overview

Packages

  • None
  • SimplePie

Classes

  • SimplePie
  • SimplePie_Author
  • SimplePie_Autoloader
  • SimplePie_Cache
  • SimplePie_Cache_DB
  • SimplePie_Cache_File
  • SimplePie_Cache_Memcache
  • SimplePie_Cache_MySQL
  • SimplePie_Caption
  • SimplePie_Category
  • SimplePie_Content_Type_Sniffer
  • SimplePie_Copyright
  • SimplePie_Core
  • SimplePie_Credit
  • SimplePie_Decode_HTML_Entities
  • SimplePie_Enclosure
  • SimplePie_File
  • SimplePie_gzdecode
  • SimplePie_HTTP_Parser
  • SimplePie_IRI
  • SimplePie_Item
  • SimplePie_Locator
  • SimplePie_Misc
  • SimplePie_Net_IPv6
  • SimplePie_Parse_Date
  • SimplePie_Parser
  • SimplePie_Rating
  • SimplePie_Registry
  • SimplePie_Restriction
  • SimplePie_Sanitize
  • SimplePie_Source
  • SimplePie_XML_Declaration_Parser

Interfaces

  • SimplePie_Cache_Base
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
   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-2012, Ryan Parman, Geoffrey 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.3-dev
  37:  * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  38:  * @author Ryan Parman
  39:  * @author Geoffrey 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.3-dev');
  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:  * Whether we're running on PHP5
 377:  */
 378: define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
 379: 
 380: /**
 381:  * No file source
 382:  */
 383: define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
 384: 
 385: /**
 386:  * Remote file source
 387:  */
 388: define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
 389: 
 390: /**
 391:  * Local file source
 392:  */
 393: define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
 394: 
 395: /**
 396:  * fsockopen() file source
 397:  */
 398: define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
 399: 
 400: /**
 401:  * cURL file source
 402:  */
 403: define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
 404: 
 405: /**
 406:  * file_get_contents() file source
 407:  */
 408: define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
 409: 
 410: 
 411: 
 412: /**
 413:  * SimplePie
 414:  *
 415:  * @package SimplePie
 416:  */
 417: class SimplePie_Core
 418: {
 419:     /**
 420:      * @var array Raw data
 421:      * @access private
 422:      */
 423:     public $data = array();
 424: 
 425:     /**
 426:      * @var mixed Error string
 427:      * @access private
 428:      */
 429:     public $error;
 430: 
 431:     /**
 432:      * @var object Instance of SimplePie_Sanitize (or other class)
 433:      * @see SimplePie::set_sanitize_class()
 434:      * @access private
 435:      */
 436:     public $sanitize;
 437: 
 438:     /**
 439:      * @var string SimplePie Useragent
 440:      * @see SimplePie::set_useragent()
 441:      * @access private
 442:      */
 443:     public $useragent = SIMPLEPIE_USERAGENT;
 444: 
 445:     /**
 446:      * @var string Feed URL
 447:      * @see SimplePie::set_feed_url()
 448:      * @access private
 449:      */
 450:     public $feed_url;
 451: 
 452:     /**
 453:      * @var object Instance of SimplePie_File to use as a feed
 454:      * @see SimplePie::set_file()
 455:      * @access private
 456:      */
 457:     public $file;
 458: 
 459:     /**
 460:      * @var string Raw feed data
 461:      * @see SimplePie::set_raw_data()
 462:      * @access private
 463:      */
 464:     public $raw_data;
 465: 
 466:     /**
 467:      * @var int Timeout for fetching remote files
 468:      * @see SimplePie::set_timeout()
 469:      * @access private
 470:      */
 471:     public $timeout = 10;
 472: 
 473:     /**
 474:      * @var bool Forces fsockopen() to be used for remote files instead
 475:      * of cURL, even if a new enough version is installed
 476:      * @see SimplePie::force_fsockopen()
 477:      * @access private
 478:      */
 479:     public $force_fsockopen = false;
 480: 
 481:     /**
 482:      * @var bool Force the given data/URL to be treated as a feed no matter what
 483:      * it appears like
 484:      * @see SimplePie::force_feed()
 485:      * @access private
 486:      */
 487:     public $force_feed = false;
 488: 
 489:     /**
 490:      * @var bool Enable/Disable XML dump
 491:      * @see SimplePie::enable_xml_dump()
 492:      * @access private
 493:      */
 494:     public $xml_dump = false;
 495: 
 496:     /**
 497:      * @var bool Enable/Disable Caching
 498:      * @see SimplePie::enable_cache()
 499:      * @access private
 500:      */
 501:     public $cache = true;
 502: 
 503:     /**
 504:      * @var int Cache duration (in seconds)
 505:      * @see SimplePie::set_cache_duration()
 506:      * @access private
 507:      */
 508:     public $cache_duration = 3600;
 509: 
 510:     /**
 511:      * @var int Auto-discovery cache duration (in seconds)
 512:      * @see SimplePie::set_autodiscovery_cache_duration()
 513:      * @access private
 514:      */
 515:     public $autodiscovery_cache_duration = 604800; // 7 Days.
 516: 
 517:     /**
 518:      * @var string Cache location (relative to executing script)
 519:      * @see SimplePie::set_cache_location()
 520:      * @access private
 521:      */
 522:     public $cache_location = './cache';
 523: 
 524:     /**
 525:      * @var string Function that creates the cache filename
 526:      * @see SimplePie::set_cache_name_function()
 527:      * @access private
 528:      */
 529:     public $cache_name_function = 'md5';
 530: 
 531:     /**
 532:      * @var bool Reorder feed by date descending
 533:      * @see SimplePie::enable_order_by_date()
 534:      * @access private
 535:      */
 536:     public $order_by_date = true;
 537: 
 538:     /**
 539:      * @var mixed Force input encoding to be set to the follow value
 540:      * (false, or anything type-cast to false, disables this feature)
 541:      * @see SimplePie::set_input_encoding()
 542:      * @access private
 543:      */
 544:     public $input_encoding = false;
 545: 
 546:     /**
 547:      * @var int Feed Autodiscovery Level
 548:      * @see SimplePie::set_autodiscovery_level()
 549:      * @access private
 550:      */
 551:     public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
 552: 
 553:     public $registry;
 554: 
 555:     /**
 556:      * @var int Maximum number of feeds to check with autodiscovery
 557:      * @see SimplePie::set_max_checked_feeds()
 558:      * @access private
 559:      */
 560:     public $max_checked_feeds = 10;
 561: 
 562:     /**
 563:      * @var array All the feeds found during the autodiscovery process
 564:      * @see SimplePie::get_all_discovered_feeds()
 565:      * @access private
 566:      */
 567:     public $all_discovered_feeds = array();
 568: 
 569:     /**
 570:      * @var string Web-accessible path to the handler_image.php file.
 571:      * @see SimplePie::set_image_handler()
 572:      * @access private
 573:      */
 574:     public $image_handler = '';
 575: 
 576:     /**
 577:      * @var array Stores the URLs when multiple feeds are being initialized.
 578:      * @see SimplePie::set_feed_url()
 579:      * @access private
 580:      */
 581:     public $multifeed_url = array();
 582: 
 583:     /**
 584:      * @var array Stores SimplePie objects when multiple feeds initialized.
 585:      * @access private
 586:      */
 587:     public $multifeed_objects = array();
 588: 
 589:     /**
 590:      * @var array Stores the get_object_vars() array for use with multifeeds.
 591:      * @see SimplePie::set_feed_url()
 592:      * @access private
 593:      */
 594:     public $config_settings = null;
 595: 
 596:     /**
 597:      * @var integer Stores the number of items to return per-feed with multifeeds.
 598:      * @see SimplePie::set_item_limit()
 599:      * @access private
 600:      */
 601:     public $item_limit = 0;
 602: 
 603:     /**
 604:      * @var array Stores the default attributes to be stripped by strip_attributes().
 605:      * @see SimplePie::strip_attributes()
 606:      * @access private
 607:      */
 608:     public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
 609: 
 610:     /**
 611:      * @var array Stores the default tags to be stripped by strip_htmltags().
 612:      * @see SimplePie::strip_htmltags()
 613:      * @access private
 614:      */
 615:     public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
 616: 
 617:     /**
 618:      * The SimplePie class contains feed level data and options
 619:      *
 620:      * There are two ways that you can create a new SimplePie object. The first
 621:      * is by passing a feed URL as a parameter to the SimplePie constructor
 622:      * (as well as optionally setting the cache location and cache expiry). This
 623:      * will initialise the whole feed with all of the default settings, and you
 624:      * can begin accessing methods and properties immediately.
 625:      *
 626:      * The second way is to create the SimplePie object with no parameters
 627:      * at all. This will enable you to set configuration options. After setting
 628:      * them, you must initialise the feed using $feed->init(). At that point the
 629:      * object's methods and properties will be available to you. This format is
 630:      * what is used throughout this documentation.
 631:      *
 632:      * @access public
 633:      * @since 1.0 Preview Release
 634:      */
 635:     public function __construct()
 636:     {
 637:         if (version_compare(PHP_VERSION, '5.0', '<'))
 638:         {
 639:             trigger_error('PHP 4.x is no longer supported. Please upgrade to PHP 5.2 or newer.');
 640:             die();
 641:         }
 642: 
 643:         // Other objects, instances created here so we can set options on them
 644:         $this->sanitize = new SimplePie_Sanitize();
 645:         $this->registry = new SimplePie_Registry();
 646: 
 647:         if (func_num_args() > 0)
 648:         {
 649:             trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.');
 650:         }
 651:     }
 652: 
 653:     /**
 654:      * Used for converting object to a string
 655:      */
 656:     public function __toString()
 657:     {
 658:         return md5(serialize($this->data));
 659:     }
 660: 
 661:     /**
 662:      * Remove items that link back to this before destroying this object
 663:      */
 664:     public function __destruct()
 665:     {
 666:         if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
 667:         {
 668:             if (!empty($this->data['items']))
 669:             {
 670:                 foreach ($this->data['items'] as $item)
 671:                 {
 672:                     $item->__destruct();
 673:                 }
 674:                 unset($item, $this->data['items']);
 675:             }
 676:             if (!empty($this->data['ordered_items']))
 677:             {
 678:                 foreach ($this->data['ordered_items'] as $item)
 679:                 {
 680:                     $item->__destruct();
 681:                 }
 682:                 unset($item, $this->data['ordered_items']);
 683:             }
 684:         }
 685:     }
 686: 
 687:     /**
 688:      * Force the given data/URL to be treated as a feed no matter what it
 689:      * appears like
 690:      *
 691:      * @access public
 692:      * @since 1.1
 693:      * @param bool $enable Force the given data/URL to be treated as a feed
 694:      */
 695:     public function force_feed($enable = false)
 696:     {
 697:         $this->force_feed = (bool) $enable;
 698:     }
 699: 
 700:     /**
 701:      * This is the URL of the feed you want to parse.
 702:      *
 703:      * This allows you to enter the URL of the feed you want to parse, or the
 704:      * website you want to try to use auto-discovery on. This takes priority
 705:      * over any set raw data.
 706:      *
 707:      * You can set multiple feeds to mash together by passing an array instead
 708:      * of a string for the $url. Remember that with each additional feed comes
 709:      * additional processing and resources.
 710:      *
 711:      * @access public
 712:      * @since 1.0 Preview Release
 713:      * @param mixed $url This is the URL (or array of URLs) that you want to parse.
 714:      * @see SimplePie::set_raw_data()
 715:      */
 716:     public function set_feed_url($url)
 717:     {
 718:         $this->multifeed_url = array();
 719:         if (is_array($url))
 720:         {
 721:             foreach ($url as $value)
 722:             {
 723:                 $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
 724:             }
 725:         }
 726:         else
 727:         {
 728:             $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
 729:         }
 730:     }
 731: 
 732:     /**
 733:      * Provides an instance of SimplePie_File to use as a feed
 734:      *
 735:      * @access public
 736:      * @param object &$file Instance of SimplePie_File (or subclass)
 737:      * @return bool True on success, false on failure
 738:      */
 739:     public function set_file(&$file)
 740:     {
 741:         if ($file instanceof SimplePie_File)
 742:         {
 743:             $this->feed_url = $file->url;
 744:             $this->file =& $file;
 745:             return true;
 746:         }
 747:         return false;
 748:     }
 749: 
 750:     /**
 751:      * Allows you to use a string of RSS/Atom data instead of a remote feed.
 752:      *
 753:      * If you have a feed available as a string in PHP, you can tell SimplePie
 754:      * to parse that data string instead of a remote feed. Any set feed URL
 755:      * takes precedence.
 756:      *
 757:      * @access public
 758:      * @since 1.0 Beta 3
 759:      * @param string $data RSS or Atom data as a string.
 760:      * @see SimplePie::set_feed_url()
 761:      */
 762:     public function set_raw_data($data)
 763:     {
 764:         $this->raw_data = $data;
 765:     }
 766: 
 767:     /**
 768:      * Allows you to override the default timeout for fetching remote feeds.
 769:      *
 770:      * This allows you to change the maximum time the feed's server to respond
 771:      * and send the feed back.
 772:      *
 773:      * @access public
 774:      * @since 1.0 Beta 3
 775:      * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
 776:      */
 777:     public function set_timeout($timeout = 10)
 778:     {
 779:         $this->timeout = (int) $timeout;
 780:     }
 781: 
 782:     /**
 783:      * Forces SimplePie to use fsockopen() instead of the preferred cURL
 784:      * functions.
 785:      *
 786:      * @access public
 787:      * @since 1.0 Beta 3
 788:      * @param bool $enable Force fsockopen() to be used
 789:      */
 790:     public function force_fsockopen($enable = false)
 791:     {
 792:         $this->force_fsockopen = (bool) $enable;
 793:     }
 794: 
 795:     /**
 796:      * Enables/disables caching in SimplePie.
 797:      *
 798:      * This option allows you to disable caching all-together in SimplePie.
 799:      * However, disabling the cache can lead to longer load times.
 800:      *
 801:      * @access public
 802:      * @since 1.0 Preview Release
 803:      * @param bool $enable Enable caching
 804:      */
 805:     public function enable_cache($enable = true)
 806:     {
 807:         $this->cache = (bool) $enable;
 808:     }
 809: 
 810:     /**
 811:      * Set the length of time (in seconds) that the contents of a feed
 812:      * will be cached.
 813:      *
 814:      * @access public
 815:      * @param int $seconds The feed content cache duration.
 816:      */
 817:     public function set_cache_duration($seconds = 3600)
 818:     {
 819:         $this->cache_duration = (int) $seconds;
 820:     }
 821: 
 822:     /**
 823:      * Set the length of time (in seconds) that the autodiscovered feed
 824:      * URL will be cached.
 825:      *
 826:      * @access public
 827:      * @param int $seconds The autodiscovered feed URL cache duration.
 828:      */
 829:     public function set_autodiscovery_cache_duration($seconds = 604800)
 830:     {
 831:         $this->autodiscovery_cache_duration = (int) $seconds;
 832:     }
 833: 
 834:     /**
 835:      * Set the file system location where the cached files should be stored.
 836:      *
 837:      * @access public
 838:      * @param string $location The file system location.
 839:      */
 840:     public function set_cache_location($location = './cache')
 841:     {
 842:         $this->cache_location = (string) $location;
 843:     }
 844: 
 845:     /**
 846:      * Determines whether feed items should be sorted into reverse chronological order.
 847:      *
 848:      * @access public
 849:      * @param bool $enable Sort as reverse chronological order.
 850:      */
 851:     public function enable_order_by_date($enable = true)
 852:     {
 853:         $this->order_by_date = (bool) $enable;
 854:     }
 855: 
 856:     /**
 857:      * Allows you to override the character encoding reported by the feed.
 858:      *
 859:      * @access public
 860:      * @param string $encoding Character encoding.
 861:      */
 862:     public function set_input_encoding($encoding = false)
 863:     {
 864:         if ($encoding)
 865:         {
 866:             $this->input_encoding = (string) $encoding;
 867:         }
 868:         else
 869:         {
 870:             $this->input_encoding = false;
 871:         }
 872:     }
 873: 
 874:     /**
 875:      * Set how much feed autodiscovery to do
 876:      *
 877:      * @access public
 878:      * @see SIMPLEPIE_LOCATOR_NONE
 879:      * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
 880:      * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
 881:      * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
 882:      * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
 883:      * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
 884:      * @see SIMPLEPIE_LOCATOR_ALL
 885:      * @param int $level Feed Autodiscovery Level (level can be a
 886:      * combination of the above constants, see bitwise OR operator)
 887:      */
 888:     public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
 889:     {
 890:         $this->autodiscovery = (int) $level;
 891:     }
 892: 
 893:     /**
 894:      * Get the class registry
 895:      *
 896:      * Use this to override SimplePie's default classes
 897:      * @see SimplePie_Registry
 898:      * @return SimplePie_Registry
 899:      */
 900:     public function &get_registry()
 901:     {
 902:         return $this->registry;
 903:     }
 904: 
 905:     /**#@+
 906:      * Useful when you are overloading or extending SimplePie's default classes.
 907:      *
 908:      * @deprecated Use {@see get_registry()} instead
 909:      * @param string $class Name of custom class.
 910:      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
 911:      */
 912:     /**
 913:      * Allows you to change which class SimplePie uses for caching.
 914:      */
 915:     public function set_cache_class($class = 'SimplePie_Cache')
 916:     {
 917:         return $this->registry->register('Cache', $class, true);
 918:     }
 919: 
 920:     /**
 921:      * Allows you to change which class SimplePie uses for auto-discovery.
 922:      */
 923:     public function set_locator_class($class = 'SimplePie_Locator')
 924:     {
 925:         return $this->registry->register('Locator', $class, true);
 926:     }
 927: 
 928:     /**
 929:      * Allows you to change which class SimplePie uses for XML parsing.
 930:      */
 931:     public function set_parser_class($class = 'SimplePie_Parser')
 932:     {
 933:         return $this->registry->register('Parser', $class, true);
 934:     }
 935: 
 936:     /**
 937:      * Allows you to change which class SimplePie uses for remote file fetching.
 938:      */
 939:     public function set_file_class($class = 'SimplePie_File')
 940:     {
 941:         return $this->registry->register('File', $class, true);
 942:     }
 943: 
 944:     /**
 945:      * Allows you to change which class SimplePie uses for data sanitization.
 946:      */
 947:     public function set_sanitize_class($class = 'SimplePie_Sanitize')
 948:     {
 949:         return $this->registry->register('Sanitize', $class, true);
 950:     }
 951: 
 952:     /**
 953:      * Allows you to change which class SimplePie uses for handling feed items.
 954:      */
 955:     public function set_item_class($class = 'SimplePie_Item')
 956:     {
 957:         return $this->registry->register('Item', $class, true);
 958:     }
 959: 
 960:     /**
 961:      * Allows you to change which class SimplePie uses for handling author data.
 962:      */
 963:     public function set_author_class($class = 'SimplePie_Author')
 964:     {
 965:         return $this->registry->register('Author', $class, true);
 966:     }
 967: 
 968:     /**
 969:      * Allows you to change which class SimplePie uses for handling category data.
 970:      */
 971:     public function set_category_class($class = 'SimplePie_Category')
 972:     {
 973:         return $this->registry->register('Category', $class, true);
 974:     }
 975: 
 976:     /**
 977:      * Allows you to change which class SimplePie uses for feed enclosures.
 978:      */
 979:     public function set_enclosure_class($class = 'SimplePie_Enclosure')
 980:     {
 981:         return $this->registry->register('Enclosure', $class, true);
 982:     }
 983: 
 984:     /**
 985:      * Allows you to change which class SimplePie uses for <media:text> captions
 986:      */
 987:     public function set_caption_class($class = 'SimplePie_Caption')
 988:     {
 989:         return $this->registry->register('Caption', $class, true);
 990:     }
 991: 
 992:     /**
 993:      * Allows you to change which class SimplePie uses for <media:copyright>
 994:      */
 995:     public function set_copyright_class($class = 'SimplePie_Copyright')
 996:     {
 997:         return $this->registry->register('Copyright', $class, true);
 998:     }
 999: 
1000:     /**
1001:      * Allows you to change which class SimplePie uses for <media:credit>
1002:      */
1003:     public function set_credit_class($class = 'SimplePie_Credit')
1004:     {
1005:         return $this->registry->register('Credit', $class, true);
1006:     }
1007: 
1008:     /**
1009:      * Allows you to change which class SimplePie uses for <media:rating>
1010:      */
1011:     public function set_rating_class($class = 'SimplePie_Rating')
1012:     {
1013:         return $this->registry->register('Rating', $class, true);
1014:     }
1015: 
1016:     /**
1017:      * Allows you to change which class SimplePie uses for <media:restriction>
1018:      */
1019:     public function set_restriction_class($class = 'SimplePie_Restriction')
1020:     {
1021:         return $this->registry->register('Restriction', $class, true);
1022:     }
1023: 
1024:     /**
1025:      * Allows you to change which class SimplePie uses for content-type sniffing.
1026:      */
1027:     public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1028:     {
1029:         return $this->registry->register('Content_Type_Sniffer', $class, true);
1030:     }
1031: 
1032:     /**
1033:      * Allows you to change which class SimplePie uses item sources.
1034:      */
1035:     public function set_source_class($class = 'SimplePie_Source')
1036:     {
1037:         return $this->registry->register('Source', $class, true);
1038:     }
1039:     /**#@-*/
1040: 
1041:     /**
1042:      * Allows you to override the default user agent string.
1043:      *
1044:      * @access public
1045:      * @param string $ua New user agent string.
1046:      */
1047:     public function set_useragent($ua = SIMPLEPIE_USERAGENT)
1048:     {
1049:         $this->useragent = (string) $ua;
1050:     }
1051: 
1052:     /**
1053:      * Set callback function to create cache filename with
1054:      *
1055:      * @access public
1056:      * @param mixed $function Callback function
1057:      */
1058:     public function set_cache_name_function($function = 'md5')
1059:     {
1060:         if (is_callable($function))
1061:         {
1062:             $this->cache_name_function = $function;
1063:         }
1064:     }
1065: 
1066:     /**
1067:      * Set options to make SP as fast as possible.  Forgoes a
1068:      * substantial amount of data sanitization in favor of speed.
1069:      *
1070:      * @access public
1071:      * @param bool $set Whether to set them or not
1072:      */
1073:     public function set_stupidly_fast($set = false)
1074:     {
1075:         if ($set)
1076:         {
1077:             $this->enable_order_by_date(false);
1078:             $this->remove_div(false);
1079:             $this->strip_comments(false);
1080:             $this->strip_htmltags(false);
1081:             $this->strip_attributes(false);
1082:             $this->set_image_handler(false);
1083:         }
1084:     }
1085: 
1086:     /**
1087:      * Set maximum number of feeds to check with autodiscovery
1088:      *
1089:      * @access public
1090:      * @param int $max Maximum number of feeds to check
1091:      */
1092:     public function set_max_checked_feeds($max = 10)
1093:     {
1094:         $this->max_checked_feeds = (int) $max;
1095:     }
1096: 
1097:     public function remove_div($enable = true)
1098:     {
1099:         $this->sanitize->remove_div($enable);
1100:     }
1101: 
1102:     public function strip_htmltags($tags = '', $encode = null)
1103:     {
1104:         if ($tags === '')
1105:         {
1106:             $tags = $this->strip_htmltags;
1107:         }
1108:         $this->sanitize->strip_htmltags($tags);
1109:         if ($encode !== null)
1110:         {
1111:             $this->sanitize->encode_instead_of_strip($tags);
1112:         }
1113:     }
1114: 
1115:     public function encode_instead_of_strip($enable = true)
1116:     {
1117:         $this->sanitize->encode_instead_of_strip($enable);
1118:     }
1119: 
1120:     public function strip_attributes($attribs = '')
1121:     {
1122:         if ($attribs === '')
1123:         {
1124:             $attribs = $this->strip_attributes;
1125:         }
1126:         $this->sanitize->strip_attributes($attribs);
1127:     }
1128: 
1129:     public function set_output_encoding($encoding = 'UTF-8')
1130:     {
1131:         $this->sanitize->set_output_encoding($encoding);
1132:     }
1133: 
1134:     public function strip_comments($strip = false)
1135:     {
1136:         $this->sanitize->strip_comments($strip);
1137:     }
1138: 
1139:     /**
1140:      * Set element/attribute key/value pairs of HTML attributes
1141:      * containing URLs that need to be resolved relative to the feed
1142:      *
1143:      * @access public
1144:      * @since 1.0
1145:      * @param array $element_attribute Element/attribute key/value pairs
1146:      */
1147:     public function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1148:     {
1149:         $this->sanitize->set_url_replacements($element_attribute);
1150:     }
1151: 
1152:     /**
1153:      * Set the handler to enable the display of cached images.
1154:      *
1155:      * @access public
1156:      * @param str $page Web-accessible path to the handler_image.php file.
1157:      * @param str $qs The query string that the value should be passed to.
1158:      */
1159:     public function set_image_handler($page = false, $qs = 'i')
1160:     {
1161:         if ($page !== false)
1162:         {
1163:             $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1164:         }
1165:         else
1166:         {
1167:             $this->image_handler = '';
1168:         }
1169:     }
1170: 
1171:     /**
1172:      * Set the limit for items returned per-feed with multifeeds.
1173:      *
1174:      * @access public
1175:      * @param integer $limit The maximum number of items to return.
1176:      */
1177:     public function set_item_limit($limit = 0)
1178:     {
1179:         $this->item_limit = (int) $limit;
1180:     }
1181: 
1182:     public function init()
1183:     {
1184:         // Check absolute bare minimum requirements.
1185:         if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1186:         {
1187:             return false;
1188:         }
1189:         // 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.
1190:         elseif (!extension_loaded('xmlreader'))
1191:         {
1192:             static $xml_is_sane = null;
1193:             if ($xml_is_sane === null)
1194:             {
1195:                 $parser_check = xml_parser_create();
1196:                 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1197:                 xml_parser_free($parser_check);
1198:                 $xml_is_sane = isset($values[0]['value']);
1199:             }
1200:             if (!$xml_is_sane)
1201:             {
1202:                 return false;
1203:             }
1204:         }
1205: 
1206:         if (method_exists($this->sanitize, 'set_registry'))
1207:         {
1208:             $this->sanitize->set_registry($this->registry);
1209:         }
1210: 
1211:         // Pass whatever was set with config options over to the sanitizer.
1212:         // Pass the classes in for legacy support; new classes should use the registry instead
1213:         $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
1214:         $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
1215: 
1216:         if (!empty($this->multifeed_url))
1217:         {
1218:             $i = 0;
1219:             $success = 0;
1220:             $this->multifeed_objects = array();
1221:             foreach ($this->multifeed_url as $url)
1222:             {
1223:                 $this->multifeed_objects[$i] = clone $this;
1224:                 $this->multifeed_objects[$i]->set_feed_url($url);
1225:                 $success |= $this->multifeed_objects[$i]->init();
1226:                 $i++;
1227:             }
1228:             return (bool) $success;
1229:         }
1230:         elseif ($this->feed_url === null && $this->raw_data === null)
1231:         {
1232:             return false;
1233:         }
1234: 
1235:         $this->error = null;
1236:         $this->data = array();
1237:         $this->multifeed_objects = array();
1238:         $cache = false;
1239: 
1240:         if ($this->feed_url !== null)
1241:         {
1242:             $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
1243:             // Decide whether to enable caching
1244:             if ($this->cache && $parsed_feed_url['scheme'] !== '')
1245:             {
1246:                 $cache = $this->registry->call('Cache', 'create', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
1247:             }
1248:             // If it's enabled and we don't want an XML dump, use the cache
1249:             if ($cache && !$this->xml_dump)
1250:             {
1251:                 // Load the Cache
1252:                 $this->data = $cache->load();
1253:                 if (!empty($this->data))
1254:                 {
1255:                     // If the cache is for an outdated build of SimplePie
1256:                     if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1257:                     {
1258:                         $cache->unlink();
1259:                         $this->data = array();
1260:                     }
1261:                     // If we've hit a collision just rerun it with caching disabled
1262:                     elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1263:                     {
1264:                         $cache = false;
1265:                         $this->data = array();
1266:                     }
1267:                     // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1268:                     elseif (isset($this->data['feed_url']))
1269:                     {
1270:                         // If the autodiscovery cache is still valid use it.
1271:                         if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1272:                         {
1273:                             // Do not need to do feed autodiscovery yet.
1274:                             if ($this->data['feed_url'] !== $this->data['url']) {
1275:                                 $this->set_feed_url($this->data['feed_url']);
1276:                                 return $this->init();
1277:                             }
1278: 
1279:                             $cache->unlink();
1280:                             $this->data = array();
1281:                         }
1282:                     }
1283:                     // Check if the cache has been updated
1284:                     elseif ($cache->mtime() + $this->cache_duration < time())
1285:                     {
1286:                         // If we have last-modified and/or etag set
1287:                         if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1288:                         {
1289:                             $headers = array(
1290:                                 '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',
1291:                             );
1292:                             if (isset($this->data['headers']['last-modified']))
1293:                             {
1294:                                 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1295:                             }
1296:                             if (isset($this->data['headers']['etag']))
1297:                             {
1298:                                 $headers['if-none-match'] = $this->data['headers']['etag'];
1299:                             }
1300: 
1301:                             $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
1302: 
1303:                             if ($file->success)
1304:                             {
1305:                                 if ($file->status_code === 304)
1306:                                 {
1307:                                     $cache->touch();
1308:                                     return true;
1309:                                 }
1310: 
1311:                                 $headers = $file->headers;
1312:                             }
1313:                             else
1314:                             {
1315:                                 unset($file);
1316:                             }
1317:                         }
1318:                     }
1319:                     // If the cache is still valid, just return true
1320:                     else
1321:                     {
1322:                         $this->raw_data = false;
1323:                         return true;
1324:                     }
1325:                 }
1326:                 // If the cache is empty, delete it
1327:                 else
1328:                 {
1329:                     $cache->unlink();
1330:                     $this->data = array();
1331:                 }
1332:             }
1333:             // 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.
1334:             if (!isset($file))
1335:             {
1336:                 if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
1337:                 {
1338:                     $file =& $this->file;
1339:                 }
1340:                 else
1341:                 {
1342:                     $headers = array(
1343:                         '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',
1344:                     );
1345:                     $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
1346:                 }
1347:             }
1348:             // If the file connection has an error, set SimplePie::error to that and quit
1349:             if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1350:             {
1351:                 $this->error = $file->error;
1352:                 return !empty($this->data);
1353:             }
1354: 
1355:             if (!$this->force_feed)
1356:             {
1357:                 // Check if the supplied URL is a feed, if it isn't, look for it.
1358:                 $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
1359: 
1360:                 if (!$locate->is_feed($file))
1361:                 {
1362:                     // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1363:                     unset($file);
1364:                     if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
1365:                     {
1366:                         $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1367:                         $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1368:                         return false;
1369:                     }
1370:                     if ($cache)
1371:                     {
1372:                         $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1373:                         if (!$cache->save($this))
1374:                         {
1375:                             trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1376:                         }
1377:                         $cache = $this->registry->call('Cache', 'create', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
1378:                     }
1379:                     $this->feed_url = $file->url;
1380:                 }
1381:                 $locate = null;
1382:             }
1383: 
1384:             $headers = $file->headers;
1385:             $data = $file->body;
1386:             $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
1387:             $sniffed = $sniffer->get_type();
1388:         }
1389:         else
1390:         {
1391:             $data = $this->raw_data;
1392:         }
1393: 
1394:         // This is exposed via get_raw_data()
1395:         $this->raw_data = $data;
1396: 
1397:         // Set up array of possible encodings
1398:         $encodings = array();
1399: 
1400:         // First check to see if input has been overridden.
1401:         if ($this->input_encoding !== false)
1402:         {
1403:             $encodings[] = $this->input_encoding;
1404:         }
1405: 
1406:         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1407:         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1408: 
1409:         // RFC 3023 (only applies to sniffed content)
1410:         if (isset($sniffed))
1411:         {
1412:             if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1413:             {
1414:                 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1415:                 {
1416:                     $encodings[] = strtoupper($charset[1]);
1417:                 }
1418:                 $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($data, &$this->registry)));
1419:                 $encodings[] = 'UTF-8';
1420:             }
1421:             elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1422:             {
1423:                 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1424:                 {
1425:                     $encodings[] = $charset[1];
1426:                 }
1427:                 $encodings[] = 'US-ASCII';
1428:             }
1429:             // Text MIME-type default
1430:             elseif (substr($sniffed, 0, 5) === 'text/')
1431:             {
1432:                 $encodings[] = 'US-ASCII';
1433:             }
1434:         }
1435: 
1436:         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1437:         $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($data, &$this->registry)));
1438:         $encodings[] = 'UTF-8';
1439:         $encodings[] = 'ISO-8859-1';
1440: 
1441:         // There's no point in trying an encoding twice
1442:         $encodings = array_unique($encodings);
1443: 
1444:         // If we want the XML, just output that with the most likely encoding and quit
1445:         if ($this->xml_dump)
1446:         {
1447:             header('Content-type: text/xml; charset=' . $encodings[0]);
1448:             echo $data;
1449:             exit;
1450:         }
1451: 
1452:         // Loop through each possible encoding, till we return something, or run out of possibilities
1453:         foreach ($encodings as $encoding)
1454:         {
1455:             // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1456:             if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($data, $encoding, 'UTF-8')))
1457:             {
1458:                 // Create new parser
1459:                 $parser = $this->registry->create('Parser');
1460: 
1461:                 // If it's parsed fine
1462:                 if ($parser->parse($utf8_data, 'UTF-8'))
1463:                 {
1464:                     $this->data = $parser->get_data();
1465:                     if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
1466:                     {
1467:                         $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1468:                         $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1469:                         return false;
1470:                     }
1471: 
1472:                     if (isset($headers))
1473:                     {
1474:                         $this->data['headers'] = $headers;
1475:                     }
1476:                     $this->data['build'] = SIMPLEPIE_BUILD;
1477: 
1478:                     // Cache the file if caching is enabled
1479:                     if ($cache && !$cache->save($this))
1480:                     {
1481:                         trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1482:                     }
1483:                     return true;
1484:                 }
1485:             }
1486:         }
1487: 
1488:         if (isset($parser))
1489:         {
1490:             // We have an error, just set SimplePie_Misc::error to it and quit
1491:             $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1492:         }
1493:         else
1494:         {
1495:             $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1496:         }
1497: 
1498:         $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1499: 
1500:         return false;
1501:     }
1502: 
1503:     /**
1504:      * Return the error message for the occured error
1505:      *
1506:      * @access public
1507:      * @return string Error message
1508:      */
1509:     public function error()
1510:     {
1511:         return $this->error;
1512:     }
1513: 
1514:     /**
1515:      * Return the raw XML
1516:      *
1517:      * This is the same as setting `$xml_dump = true;`, but returns
1518:      * the data instead of printing it.
1519:      *
1520:      * @return string|boolean Raw XML data, false if the cache is used
1521:      */
1522:     public function get_raw_data()
1523:     {
1524:         return $this->raw_data;
1525:     }
1526: 
1527:     public function get_encoding()
1528:     {
1529:         return $this->sanitize->output_encoding;
1530:     }
1531: 
1532:     public function handle_content_type($mime = 'text/html')
1533:     {
1534:         if (!headers_sent())
1535:         {
1536:             $header = "Content-type: $mime;";
1537:             if ($this->get_encoding())
1538:             {
1539:                 $header .= ' charset=' . $this->get_encoding();
1540:             }
1541:             else
1542:             {
1543:                 $header .= ' charset=UTF-8';
1544:             }
1545:             header($header);
1546:         }
1547:     }
1548: 
1549:     public function get_type()
1550:     {
1551:         if (!isset($this->data['type']))
1552:         {
1553:             $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1554:             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1555:             {
1556:                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1557:             }
1558:             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1559:             {
1560:                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1561:             }
1562:             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1563:             {
1564:                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1565:                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1566:                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1567:                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1568:                 {
1569:                     $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1570:                 }
1571:                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1572:                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1573:                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1574:                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1575:                 {
1576:                     $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1577:                 }
1578:             }
1579:             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1580:             {
1581:                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1582:                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1583:                 {
1584:                     switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1585:                     {
1586:                         case '0.91':
1587:                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1588:                             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1589:                             {
1590:                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1591:                                 {
1592:                                     case '0':
1593:                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1594:                                         break;
1595: 
1596:                                     case '24':
1597:                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1598:                                         break;
1599:                                 }
1600:                             }
1601:                             break;
1602: 
1603:                         case '0.92':
1604:                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1605:                             break;
1606: 
1607:                         case '0.93':
1608:                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1609:                             break;
1610: 
1611:                         case '0.94':
1612:                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1613:                             break;
1614: 
1615:                         case '2.0':
1616:                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1617:                             break;
1618:                     }
1619:                 }
1620:             }
1621:             else
1622:             {
1623:                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1624:             }
1625:         }
1626:         return $this->data['type'];
1627:     }
1628: 
1629:     /**
1630:      * @todo If we have a perm redirect we should return the new URL
1631:      * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1632:      * @todo Also, |atom:link|@rel=self
1633:      */
1634:     public function subscribe_url()
1635:     {
1636:         if ($this->feed_url !== null)
1637:         {
1638:             return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1639:         }
1640:         else
1641:         {
1642:             return null;
1643:         }
1644:     }
1645: 
1646:     public function get_feed_tags($namespace, $tag)
1647:     {
1648:         $type = $this->get_type();
1649:         if ($type & SIMPLEPIE_TYPE_ATOM_10)
1650:         {
1651:             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1652:             {
1653:                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1654:             }
1655:         }
1656:         if ($type & SIMPLEPIE_TYPE_ATOM_03)
1657:         {
1658:             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1659:             {
1660:                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1661:             }
1662:         }
1663:         if ($type & SIMPLEPIE_TYPE_RSS_RDF)
1664:         {
1665:             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1666:             {
1667:                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
1668:             }
1669:         }
1670:         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1671:         {
1672:             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
1673:             {
1674:                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
1675:             }
1676:         }
1677:         return null;
1678:     }
1679: 
1680:     public function get_channel_tags($namespace, $tag)
1681:     {
1682:         $type = $this->get_type();
1683:         if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
1684:         {
1685:             if ($return = $this->get_feed_tags($namespace, $tag))
1686:             {
1687:                 return $return;
1688:             }
1689:         }
1690:         if ($type & SIMPLEPIE_TYPE_RSS_10)
1691:         {
1692:             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
1693:             {
1694:                 if (isset($channel[0]['child'][$namespace][$tag]))
1695:                 {
1696:                     return $channel[0]['child'][$namespace][$tag];
1697:                 }
1698:             }
1699:         }
1700:         if ($type & SIMPLEPIE_TYPE_RSS_090)
1701:         {
1702:             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
1703:             {
1704:                 if (isset($channel[0]['child'][$namespace][$tag]))
1705:                 {
1706:                     return $channel[0]['child'][$namespace][$tag];
1707:                 }
1708:             }
1709:         }
1710:         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1711:         {
1712:             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
1713:             {
1714:                 if (isset($channel[0]['child'][$namespace][$tag]))
1715:                 {
1716:                     return $channel[0]['child'][$namespace][$tag];
1717:                 }
1718:             }
1719:         }
1720:         return null;
1721:     }
1722: 
1723:     public function get_image_tags($namespace, $tag)
1724:     {
1725:         $type = $this->get_type();
1726:         if ($type & SIMPLEPIE_TYPE_RSS_10)
1727:         {
1728:             if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
1729:             {
1730:                 if (isset($image[0]['child'][$namespace][$tag]))
1731:                 {
1732:                     return $image[0]['child'][$namespace][$tag];
1733:                 }
1734:             }
1735:         }
1736:         if ($type & SIMPLEPIE_TYPE_RSS_090)
1737:         {
1738:             if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
1739:             {
1740:                 if (isset($image[0]['child'][$namespace][$tag]))
1741:                 {
1742:                     return $image[0]['child'][$namespace][$tag];
1743:                 }
1744:             }
1745:         }
1746:         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1747:         {
1748:             if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
1749:             {
1750:                 if (isset($image[0]['child'][$namespace][$tag]))
1751:                 {
1752:                     return $image[0]['child'][$namespace][$tag];
1753:                 }
1754:             }
1755:         }
1756:         return null;
1757:     }
1758: 
1759:     public function get_base($element = array())
1760:     {
1761:         if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
1762:         {
1763:             return $element['xml_base'];
1764:         }
1765:         elseif ($this->get_link() !== null)
1766:         {
1767:             return $this->get_link();
1768:         }
1769:         else
1770:         {
1771:             return $this->subscribe_url();
1772:         }
1773:     }
1774: 
1775:     public function sanitize($data, $type, $base = '')
1776:     {
1777:         return $this->sanitize->sanitize($data, $type, $base);
1778:     }
1779: 
1780:     public function get_title()
1781:     {
1782:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
1783:         {
1784:             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
1785:         }
1786:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
1787:         {
1788:             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
1789:         }
1790:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
1791:         {
1792:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
1793:         }
1794:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
1795:         {
1796:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
1797:         }
1798:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
1799:         {
1800:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
1801:         }
1802:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
1803:         {
1804:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1805:         }
1806:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
1807:         {
1808:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1809:         }
1810:         else
1811:         {
1812:             return null;
1813:         }
1814:     }
1815: 
1816:     public function get_category($key = 0)
1817:     {
1818:         $categories = $this->get_categories();
1819:         if (isset($categories[$key]))
1820:         {
1821:             return $categories[$key];
1822:         }
1823:         else
1824:         {
1825:             return null;
1826:         }
1827:     }
1828: 
1829:     public function get_categories()
1830:     {
1831:         $categories = array();
1832: 
1833:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
1834:         {
1835:             $term = null;
1836:             $scheme = null;
1837:             $label = null;
1838:             if (isset($category['attribs']['']['term']))
1839:             {
1840:                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
1841:             }
1842:             if (isset($category['attribs']['']['scheme']))
1843:             {
1844:                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
1845:             }
1846:             if (isset($category['attribs']['']['label']))
1847:             {
1848:                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
1849:             }
1850:             $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
1851:         }
1852:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
1853:         {
1854:             // This is really the label, but keep this as the term also for BC.
1855:             // Label will also work on retrieving because that falls back to term.
1856:             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1857:             if (isset($category['attribs']['']['domain']))
1858:             {
1859:                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
1860:             }
1861:             else
1862:             {
1863:                 $scheme = null;
1864:             }
1865:             $categories[] = $this->registry->create('Category', array($term, $scheme, null));
1866:         }
1867:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
1868:         {
1869:             $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
1870:         }
1871:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
1872:         {
1873:             $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
1874:         }
1875: 
1876:         if (!empty($categories))
1877:         {
1878:             return $this->registry->call('Misc', 'array_unique', array($categories));
1879:         }
1880:         else
1881:         {
1882:             return null;
1883:         }
1884:     }
1885: 
1886:     public function get_author($key = 0)
1887:     {
1888:         $authors = $this->get_authors();
1889:         if (isset($authors[$key]))
1890:         {
1891:             return $authors[$key];
1892:         }
1893:         else
1894:         {
1895:             return null;
1896:         }
1897:     }
1898: 
1899:     public function get_authors()
1900:     {
1901:         $authors = array();
1902:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
1903:         {
1904:             $name = null;
1905:             $uri = null;
1906:             $email = null;
1907:             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
1908:             {
1909:                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1910:             }
1911:             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
1912:             {
1913:                 $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]));
1914:             }
1915:             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
1916:             {
1917:                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1918:             }
1919:             if ($name !== null || $email !== null || $uri !== null)
1920:             {
1921:                 $authors[] = $this->registry->create('Author', array($name, $uri, $email));
1922:             }
1923:         }
1924:         if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
1925:         {
1926:             $name = null;
1927:             $url = null;
1928:             $email = null;
1929:             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
1930:             {
1931:                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1932:             }
1933:             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
1934:             {
1935:                 $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]));
1936:             }
1937:             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
1938:             {
1939:                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1940:             }
1941:             if ($name !== null || $email !== null || $url !== null)
1942:             {
1943:                 $authors[] = $this->registry->create('Author', array($name, $url, $email));
1944:             }
1945:         }
1946:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
1947:         {
1948:             $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
1949:         }
1950:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
1951:         {
1952:             $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
1953:         }
1954:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
1955:         {
1956:             $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
1957:         }
1958: 
1959:         if (!empty($authors))
1960:         {
1961:             return $this->registry->call('Misc', 'array_unique', array($authors));
1962:         }
1963:         else
1964:         {
1965:             return null;
1966:         }
1967:     }
1968: 
1969:     public function get_contributor($key = 0)
1970:     {
1971:         $contributors = $this->get_contributors();
1972:         if (isset($contributors[$key]))
1973:         {
1974:             return $contributors[$key];
1975:         }
1976:         else
1977:         {
1978:             return null;
1979:         }
1980:     }
1981: 
1982:     public function get_contributors()
1983:     {
1984:         $contributors = array();
1985:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
1986:         {
1987:             $name = null;
1988:             $uri = null;
1989:             $email = null;
1990:             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
1991:             {
1992:                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
1993:             }
1994:             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
1995:             {
1996:                 $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]));
1997:             }
1998:             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
1999:             {
2000:                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2001:             }
2002:             if ($name !== null || $email !== null || $uri !== null)
2003:             {
2004:                 $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
2005:             }
2006:         }
2007:         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2008:         {
2009:             $name = null;
2010:             $url = null;
2011:             $email = null;
2012:             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2013:             {
2014:                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2015:             }
2016:             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2017:             {
2018:                 $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]));
2019:             }
2020:             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2021:             {
2022:                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2023:             }
2024:             if ($name !== null || $email !== null || $url !== null)
2025:             {
2026:                 $contributors[] = $this->registry->create('Author', array($name, $url, $email));
2027:             }
2028:         }
2029: 
2030:         if (!empty($contributors))
2031:         {
2032:             return $this->registry->call('Misc', 'array_unique', array($contributors));
2033:         }
2034:         else
2035:         {
2036:             return null;
2037:         }
2038:     }
2039: 
2040:     public function get_link($key = 0, $rel = 'alternate')
2041:     {
2042:         $links = $this->get_links($rel);
2043:         if (isset($links[$key]))
2044:         {
2045:             return $links[$key];
2046:         }
2047:         else
2048:         {
2049:             return null;
2050:         }
2051:     }
2052: 
2053:     /**
2054:      * Added for parity between the parent-level and the item/entry-level.
2055:      */
2056:     public function get_permalink()
2057:     {
2058:         return $this->get_link(0);
2059:     }
2060: 
2061:     public function get_links($rel = 'alternate')
2062:     {
2063:         if (!isset($this->data['links']))
2064:         {
2065:             $this->data['links'] = array();
2066:             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2067:             {
2068:                 foreach ($links as $link)
2069:                 {
2070:                     if (isset($link['attribs']['']['href']))
2071:                     {
2072:                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2073:                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2074:                     }
2075:                 }
2076:             }
2077:             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2078:             {
2079:                 foreach ($links as $link)
2080:                 {
2081:                     if (isset($link['attribs']['']['href']))
2082:                     {
2083:                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2084:                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2085: 
2086:                     }
2087:                 }
2088:             }
2089:             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2090:             {
2091:                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2092:             }
2093:             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2094:             {
2095:                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2096:             }
2097:             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2098:             {
2099:                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2100:             }
2101: 
2102:             $keys = array_keys($this->data['links']);
2103:             foreach ($keys as $key)
2104:             {
2105:                 if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
2106:                 {
2107:                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2108:                     {
2109:                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2110:                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2111:                     }
2112:                     else
2113:                     {
2114:                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2115:                     }
2116:                 }
2117:                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2118:                 {
2119:                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2120:                 }
2121:                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2122:             }
2123:         }
2124: 
2125:         if (isset($this->data['links'][$rel]))
2126:         {
2127:             return $this->data['links'][$rel];
2128:         }
2129:         else
2130:         {
2131:             return null;
2132:         }
2133:     }
2134: 
2135:     public function get_all_discovered_feeds()
2136:     {
2137:         return $this->all_discovered_feeds;
2138:     }
2139: 
2140:     public function get_description()
2141:     {
2142:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2143:         {
2144:             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2145:         }
2146:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2147:         {
2148:             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2149:         }
2150:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2151:         {
2152:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2153:         }
2154:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2155:         {
2156:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2157:         }
2158:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2159:         {
2160:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2161:         }
2162:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2163:         {
2164:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2165:         }
2166:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2167:         {
2168:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2169:         }
2170:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2171:         {
2172:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2173:         }
2174:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2175:         {
2176:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2177:         }
2178:         else
2179:         {
2180:             return null;
2181:         }
2182:     }
2183: 
2184:     public function get_copyright()
2185:     {
2186:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2187:         {
2188:             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2189:         }
2190:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2191:         {
2192:             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2193:         }
2194:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2195:         {
2196:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2197:         }
2198:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2199:         {
2200:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2201:         }
2202:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2203:         {
2204:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2205:         }
2206:         else
2207:         {
2208:             return null;
2209:         }
2210:     }
2211: 
2212:     public function get_language()
2213:     {
2214:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2215:         {
2216:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2217:         }
2218:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2219:         {
2220:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2221:         }
2222:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2223:         {
2224:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2225:         }
2226:         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2227:         {
2228:             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2229:         }
2230:         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2231:         {
2232:             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2233:         }
2234:         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2235:         {
2236:             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2237:         }
2238:         elseif (isset($this->data['headers']['content-language']))
2239:         {
2240:             return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2241:         }
2242:         else
2243:         {
2244:             return null;
2245:         }
2246:     }
2247: 
2248:     public function get_latitude()
2249:     {
2250: 
2251:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2252:         {
2253:             return (float) $return[0]['data'];
2254:         }
2255:         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))
2256:         {
2257:             return (float) $match[1];
2258:         }
2259:         else
2260:         {
2261:             return null;
2262:         }
2263:     }
2264: 
2265:     public function get_longitude()
2266:     {
2267:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2268:         {
2269:             return (float) $return[0]['data'];
2270:         }
2271:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2272:         {
2273:             return (float) $return[0]['data'];
2274:         }
2275:         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))
2276:         {
2277:             return (float) $match[2];
2278:         }
2279:         else
2280:         {
2281:             return null;
2282:         }
2283:     }
2284: 
2285:     public function get_image_title()
2286:     {
2287:         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2288:         {
2289:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2290:         }
2291:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2292:         {
2293:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2294:         }
2295:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2296:         {
2297:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2298:         }
2299:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2300:         {
2301:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2302:         }
2303:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2304:         {
2305:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2306:         }
2307:         else
2308:         {
2309:             return null;
2310:         }
2311:     }
2312: 
2313:     public function get_image_url()
2314:     {
2315:         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2316:         {
2317:             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2318:         }
2319:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2320:         {
2321:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2322:         }
2323:         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2324:         {
2325:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2326:         }
2327:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2328:         {
2329:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2330:         }
2331:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2332:         {
2333:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2334:         }
2335:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2336:         {
2337:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2338:         }
2339:         else
2340:         {
2341:             return null;
2342:         }
2343:     }
2344: 
2345:     public function get_image_link()
2346:     {
2347:         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2348:         {
2349:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2350:         }
2351:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2352:         {
2353:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2354:         }
2355:         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2356:         {
2357:             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2358:         }
2359:         else
2360:         {
2361:             return null;
2362:         }
2363:     }
2364: 
2365:     public function get_image_width()
2366:     {
2367:         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2368:         {
2369:             return round($return[0]['data']);
2370:         }
2371:         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2372:         {
2373:             return 88.0;
2374:         }
2375:         else
2376:         {
2377:             return null;
2378:         }
2379:     }
2380: 
2381:     public function get_image_height()
2382:     {
2383:         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2384:         {
2385:             return round($return[0]['data']);
2386:         }
2387:         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2388:         {
2389:             return 31.0;
2390:         }
2391:         else
2392:         {
2393:             return null;
2394:         }
2395:     }
2396: 
2397:     public function get_item_quantity($max = 0)
2398:     {
2399:         $max = (int) $max;
2400:         $qty = count($this->get_items());
2401:         if ($max === 0)
2402:         {
2403:             return $qty;
2404:         }
2405:         else
2406:         {
2407:             return ($qty > $max) ? $max : $qty;
2408:         }
2409:     }
2410: 
2411:     public function get_item($key = 0)
2412:     {
2413:         $items = $this->get_items();
2414:         if (isset($items[$key]))
2415:         {
2416:             return $items[$key];
2417:         }
2418:         else
2419:         {
2420:             return null;
2421:         }
2422:     }
2423: 
2424:     public function get_items($start = 0, $end = 0)
2425:     {
2426:         if (!isset($this->data['items']))
2427:         {
2428:             if (!empty($this->multifeed_objects))
2429:             {
2430:                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2431:             }
2432:             else
2433:             {
2434:                 $this->data['items'] = array();
2435:                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2436:                 {
2437:                     $keys = array_keys($items);
2438:                     foreach ($keys as $key)
2439:                     {
2440:                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2441:                     }
2442:                 }
2443:                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2444:                 {
2445:                     $keys = array_keys($items);
2446:                     foreach ($keys as $key)
2447:                     {
2448:                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2449:                     }
2450:                 }
2451:                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2452:                 {
2453:                     $keys = array_keys($items);
2454:                     foreach ($keys as $key)
2455:                     {
2456:                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2457:                     }
2458:                 }
2459:                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2460:                 {
2461:                     $keys = array_keys($items);
2462:                     foreach ($keys as $key)
2463:                     {
2464:                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2465:                     }
2466:                 }
2467:                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2468:                 {
2469:                     $keys = array_keys($items);
2470:                     foreach ($keys as $key)
2471:                     {
2472:                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2473:                     }
2474:                 }
2475:             }
2476:         }
2477: 
2478:         if (!empty($this->data['items']))
2479:         {
2480:             // If we want to order it by date, check if all items have a date, and then sort it
2481:             if ($this->order_by_date && empty($this->multifeed_objects))
2482:             {
2483:                 if (!isset($this->data['ordered_items']))
2484:                 {
2485:                     $do_sort = true;
2486:                     foreach ($this->data['items'] as $item)
2487:                     {
2488:                         if (!$item->get_date('U'))
2489:                         {
2490:                             $do_sort = false;
2491:                             break;
2492:                         }
2493:                     }
2494:                     $item = null;
2495:                     $this->data['ordered_items'] = $this->data['items'];
2496:                     if ($do_sort)
2497:                     {
2498:                         usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
2499:                     }
2500:                 }
2501:                 $items = $this->data['ordered_items'];
2502:             }
2503:             else
2504:             {
2505:                 $items = $this->data['items'];
2506:             }
2507: 
2508:             // Slice the data as desired
2509:             if ($end === 0)
2510:             {
2511:                 return array_slice($items, $start);
2512:             }
2513:             else
2514:             {
2515:                 return array_slice($items, $start, $end);
2516:             }
2517:         }
2518:         else
2519:         {
2520:             return array();
2521:         }
2522:     }
2523: 
2524:     public static function sort_items($a, $b)
2525:     {
2526:         return $a->get_date('U') <= $b->get_date('U');
2527:     }
2528: 
2529:     public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
2530:     {
2531:         if (is_array($urls) && sizeof($urls) > 0)
2532:         {
2533:             $items = array();
2534:             foreach ($urls as $arg)
2535:             {
2536:                 if ($arg instanceof SimplePie)
2537:                 {
2538:                     $items = array_merge($items, $arg->get_items(0, $limit));
2539:                 }
2540:                 else
2541:                 {
2542:                     trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
2543:                 }
2544:             }
2545: 
2546:             $do_sort = true;
2547:             foreach ($items as $item)
2548:             {
2549:                 if (!$item->get_date('U'))
2550:                 {
2551:                     $do_sort = false;
2552:                     break;
2553:                 }
2554:             }
2555:             $item = null;
2556:             if ($do_sort)
2557:             {
2558:                 usort($items, array('SimplePie', 'sort_items'));
2559:             }
2560: 
2561:             if ($end === 0)
2562:             {
2563:                 return array_slice($items, $start);
2564:             }
2565:             else
2566:             {
2567:                 return array_slice($items, $start, $end);
2568:             }
2569:         }
2570:         else
2571:         {
2572:             trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
2573:             return array();
2574:         }
2575:     }
2576: }
2577: 
SimplePie Documentation API documentation generated by ApiGen 2.4.0