| [ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 if ( !class_exists( 'SimplePie' ) ) : 3 /** 4 * SimplePie 5 * 6 * A PHP-Based RSS and Atom Feed Framework. 7 * Takes the hard work out of managing a complete RSS/Atom solution. 8 * 9 * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without modification, are 13 * permitted provided that the following conditions are met: 14 * 15 * * Redistributions of source code must retain the above copyright notice, this list of 16 * conditions and the following disclaimer. 17 * 18 * * Redistributions in binary form must reproduce the above copyright notice, this list 19 * of conditions and the following disclaimer in the documentation and/or other materials 20 * provided with the distribution. 21 * 22 * * Neither the name of the SimplePie Team nor the names of its contributors may be used 23 * to endorse or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 29 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 * 36 * @package SimplePie 37 * @version 1.2 38 * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon 39 * @author Ryan Parman 40 * @author Geoffrey Sneddon 41 * @link http://simplepie.org/ SimplePie 42 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums 43 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 44 * @todo phpDoc comments 45 */ 46 47 /** 48 * SimplePie Name 49 */ 50 define('SIMPLEPIE_NAME', 'SimplePie'); 51 52 /** 53 * SimplePie Version 54 */ 55 define('SIMPLEPIE_VERSION', '1.2'); 56 57 /** 58 * SimplePie Build 59 */ 60 define('SIMPLEPIE_BUILD', '20090627192103'); 61 62 /** 63 * SimplePie Website URL 64 */ 65 define('SIMPLEPIE_URL', 'http://simplepie.org'); 66 67 /** 68 * SimplePie Useragent 69 * @see SimplePie::set_useragent() 70 */ 71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD); 72 73 /** 74 * SimplePie Linkback 75 */ 76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>'); 77 78 /** 79 * No Autodiscovery 80 * @see SimplePie::set_autodiscovery_level() 81 */ 82 define('SIMPLEPIE_LOCATOR_NONE', 0); 83 84 /** 85 * Feed Link Element Autodiscovery 86 * @see SimplePie::set_autodiscovery_level() 87 */ 88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1); 89 90 /** 91 * Local Feed Extension Autodiscovery 92 * @see SimplePie::set_autodiscovery_level() 93 */ 94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2); 95 96 /** 97 * Local Feed Body Autodiscovery 98 * @see SimplePie::set_autodiscovery_level() 99 */ 100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4); 101 102 /** 103 * Remote Feed Extension Autodiscovery 104 * @see SimplePie::set_autodiscovery_level() 105 */ 106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8); 107 108 /** 109 * Remote Feed Body Autodiscovery 110 * @see SimplePie::set_autodiscovery_level() 111 */ 112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16); 113 114 /** 115 * All Feed Autodiscovery 116 * @see SimplePie::set_autodiscovery_level() 117 */ 118 define('SIMPLEPIE_LOCATOR_ALL', 31); 119 120 /** 121 * No known feed type 122 */ 123 define('SIMPLEPIE_TYPE_NONE', 0); 124 125 /** 126 * RSS 0.90 127 */ 128 define('SIMPLEPIE_TYPE_RSS_090', 1); 129 130 /** 131 * RSS 0.91 (Netscape) 132 */ 133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2); 134 135 /** 136 * RSS 0.91 (Userland) 137 */ 138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4); 139 140 /** 141 * RSS 0.91 (both Netscape and Userland) 142 */ 143 define('SIMPLEPIE_TYPE_RSS_091', 6); 144 145 /** 146 * RSS 0.92 147 */ 148 define('SIMPLEPIE_TYPE_RSS_092', 8); 149 150 /** 151 * RSS 0.93 152 */ 153 define('SIMPLEPIE_TYPE_RSS_093', 16); 154 155 /** 156 * RSS 0.94 157 */ 158 define('SIMPLEPIE_TYPE_RSS_094', 32); 159 160 /** 161 * RSS 1.0 162 */ 163 define('SIMPLEPIE_TYPE_RSS_10', 64); 164 165 /** 166 * RSS 2.0 167 */ 168 define('SIMPLEPIE_TYPE_RSS_20', 128); 169 170 /** 171 * RDF-based RSS 172 */ 173 define('SIMPLEPIE_TYPE_RSS_RDF', 65); 174 175 /** 176 * Non-RDF-based RSS (truly intended as syndication format) 177 */ 178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190); 179 180 /** 181 * All RSS 182 */ 183 define('SIMPLEPIE_TYPE_RSS_ALL', 255); 184 185 /** 186 * Atom 0.3 187 */ 188 define('SIMPLEPIE_TYPE_ATOM_03', 256); 189 190 /** 191 * Atom 1.0 192 */ 193 define('SIMPLEPIE_TYPE_ATOM_10', 512); 194 195 /** 196 * All Atom 197 */ 198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768); 199 200 /** 201 * All feed types 202 */ 203 define('SIMPLEPIE_TYPE_ALL', 1023); 204 205 /** 206 * No construct 207 */ 208 define('SIMPLEPIE_CONSTRUCT_NONE', 0); 209 210 /** 211 * Text construct 212 */ 213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1); 214 215 /** 216 * HTML construct 217 */ 218 define('SIMPLEPIE_CONSTRUCT_HTML', 2); 219 220 /** 221 * XHTML construct 222 */ 223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4); 224 225 /** 226 * base64-encoded construct 227 */ 228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8); 229 230 /** 231 * IRI construct 232 */ 233 define('SIMPLEPIE_CONSTRUCT_IRI', 16); 234 235 /** 236 * A construct that might be HTML 237 */ 238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32); 239 240 /** 241 * All constructs 242 */ 243 define('SIMPLEPIE_CONSTRUCT_ALL', 63); 244 245 /** 246 * Don't change case 247 */ 248 define('SIMPLEPIE_SAME_CASE', 1); 249 250 /** 251 * Change to lowercase 252 */ 253 define('SIMPLEPIE_LOWERCASE', 2); 254 255 /** 256 * Change to uppercase 257 */ 258 define('SIMPLEPIE_UPPERCASE', 4); 259 260 /** 261 * PCRE for HTML attributes 262 */ 263 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]*'); 264 265 /** 266 * PCRE for XML attributes 267 */ 268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*'); 269 270 /** 271 * XML Namespace 272 */ 273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace'); 274 275 /** 276 * Atom 1.0 Namespace 277 */ 278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom'); 279 280 /** 281 * Atom 0.3 Namespace 282 */ 283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#'); 284 285 /** 286 * RDF Namespace 287 */ 288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); 289 290 /** 291 * RSS 0.90 Namespace 292 */ 293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/'); 294 295 /** 296 * RSS 1.0 Namespace 297 */ 298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/'); 299 300 /** 301 * RSS 1.0 Content Module Namespace 302 */ 303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/'); 304 305 /** 306 * RSS 2.0 Namespace 307 * (Stupid, I know, but I'm certain it will confuse people less with support.) 308 */ 309 define('SIMPLEPIE_NAMESPACE_RSS_20', ''); 310 311 /** 312 * DC 1.0 Namespace 313 */ 314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/'); 315 316 /** 317 * DC 1.1 Namespace 318 */ 319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/'); 320 321 /** 322 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace 323 */ 324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#'); 325 326 /** 327 * GeoRSS Namespace 328 */ 329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss'); 330 331 /** 332 * Media RSS Namespace 333 */ 334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/'); 335 336 /** 337 * Wrong Media RSS Namespace 338 */ 339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss'); 340 341 /** 342 * iTunes RSS Namespace 343 */ 344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd'); 345 346 /** 347 * XHTML Namespace 348 */ 349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml'); 350 351 /** 352 * IANA Link Relations Registry 353 */ 354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/'); 355 356 /** 357 * Whether we're running on PHP5 358 */ 359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>=')); 360 361 /** 362 * No file source 363 */ 364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0); 365 366 /** 367 * Remote file source 368 */ 369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1); 370 371 /** 372 * Local file source 373 */ 374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2); 375 376 /** 377 * fsockopen() file source 378 */ 379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4); 380 381 /** 382 * cURL file source 383 */ 384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8); 385 386 /** 387 * file_get_contents() file source 388 */ 389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16); 390 391 /** 392 * SimplePie 393 * 394 * @package SimplePie 395 */ 396 class SimplePie 397 { 398 /** 399 * @var array Raw data 400 * @access private 401 */ 402 var $data = array(); 403 404 /** 405 * @var mixed Error string 406 * @access private 407 */ 408 var $error; 409 410 /** 411 * @var object Instance of SimplePie_Sanitize (or other class) 412 * @see SimplePie::set_sanitize_class() 413 * @access private 414 */ 415 var $sanitize; 416 417 /** 418 * @var string SimplePie Useragent 419 * @see SimplePie::set_useragent() 420 * @access private 421 */ 422 var $useragent = SIMPLEPIE_USERAGENT; 423 424 /** 425 * @var string Feed URL 426 * @see SimplePie::set_feed_url() 427 * @access private 428 */ 429 var $feed_url; 430 431 /** 432 * @var object Instance of SimplePie_File to use as a feed 433 * @see SimplePie::set_file() 434 * @access private 435 */ 436 var $file; 437 438 /** 439 * @var string Raw feed data 440 * @see SimplePie::set_raw_data() 441 * @access private 442 */ 443 var $raw_data; 444 445 /** 446 * @var int Timeout for fetching remote files 447 * @see SimplePie::set_timeout() 448 * @access private 449 */ 450 var $timeout = 10; 451 452 /** 453 * @var bool Forces fsockopen() to be used for remote files instead 454 * of cURL, even if a new enough version is installed 455 * @see SimplePie::force_fsockopen() 456 * @access private 457 */ 458 var $force_fsockopen = false; 459 460 /** 461 * @var bool Force the given data/URL to be treated as a feed no matter what 462 * it appears like 463 * @see SimplePie::force_feed() 464 * @access private 465 */ 466 var $force_feed = false; 467 468 /** 469 * @var bool Enable/Disable XML dump 470 * @see SimplePie::enable_xml_dump() 471 * @access private 472 */ 473 var $xml_dump = false; 474 475 /** 476 * @var bool Enable/Disable Caching 477 * @see SimplePie::enable_cache() 478 * @access private 479 */ 480 var $cache = true; 481 482 /** 483 * @var int Cache duration (in seconds) 484 * @see SimplePie::set_cache_duration() 485 * @access private 486 */ 487 var $cache_duration = 3600; 488 489 /** 490 * @var int Auto-discovery cache duration (in seconds) 491 * @see SimplePie::set_autodiscovery_cache_duration() 492 * @access private 493 */ 494 var $autodiscovery_cache_duration = 604800; // 7 Days. 495 496 /** 497 * @var string Cache location (relative to executing script) 498 * @see SimplePie::set_cache_location() 499 * @access private 500 */ 501 var $cache_location = './cache'; 502 503 /** 504 * @var string Function that creates the cache filename 505 * @see SimplePie::set_cache_name_function() 506 * @access private 507 */ 508 var $cache_name_function = 'md5'; 509 510 /** 511 * @var bool Reorder feed by date descending 512 * @see SimplePie::enable_order_by_date() 513 * @access private 514 */ 515 var $order_by_date = true; 516 517 /** 518 * @var mixed Force input encoding to be set to the follow value 519 * (false, or anything type-cast to false, disables this feature) 520 * @see SimplePie::set_input_encoding() 521 * @access private 522 */ 523 var $input_encoding = false; 524 525 /** 526 * @var int Feed Autodiscovery Level 527 * @see SimplePie::set_autodiscovery_level() 528 * @access private 529 */ 530 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL; 531 532 /** 533 * @var string Class used for caching feeds 534 * @see SimplePie::set_cache_class() 535 * @access private 536 */ 537 var $cache_class = 'SimplePie_Cache'; 538 539 /** 540 * @var string Class used for locating feeds 541 * @see SimplePie::set_locator_class() 542 * @access private 543 */ 544 var $locator_class = 'SimplePie_Locator'; 545 546 /** 547 * @var string Class used for parsing feeds 548 * @see SimplePie::set_parser_class() 549 * @access private 550 */ 551 var $parser_class = 'SimplePie_Parser'; 552 553 /** 554 * @var string Class used for fetching feeds 555 * @see SimplePie::set_file_class() 556 * @access private 557 */ 558 var $file_class = 'SimplePie_File'; 559 560 /** 561 * @var string Class used for items 562 * @see SimplePie::set_item_class() 563 * @access private 564 */ 565 var $item_class = 'SimplePie_Item'; 566 567 /** 568 * @var string Class used for authors 569 * @see SimplePie::set_author_class() 570 * @access private 571 */ 572 var $author_class = 'SimplePie_Author'; 573 574 /** 575 * @var string Class used for categories 576 * @see SimplePie::set_category_class() 577 * @access private 578 */ 579 var $category_class = 'SimplePie_Category'; 580 581 /** 582 * @var string Class used for enclosures 583 * @see SimplePie::set_enclosures_class() 584 * @access private 585 */ 586 var $enclosure_class = 'SimplePie_Enclosure'; 587 588 /** 589 * @var string Class used for Media RSS <media:text> captions 590 * @see SimplePie::set_caption_class() 591 * @access private 592 */ 593 var $caption_class = 'SimplePie_Caption'; 594 595 /** 596 * @var string Class used for Media RSS <media:copyright> 597 * @see SimplePie::set_copyright_class() 598 * @access private 599 */ 600 var $copyright_class = 'SimplePie_Copyright'; 601 602 /** 603 * @var string Class used for Media RSS <media:credit> 604 * @see SimplePie::set_credit_class() 605 * @access private 606 */ 607 var $credit_class = 'SimplePie_Credit'; 608 609 /** 610 * @var string Class used for Media RSS <media:rating> 611 * @see SimplePie::set_rating_class() 612 * @access private 613 */ 614 var $rating_class = 'SimplePie_Rating'; 615 616 /** 617 * @var string Class used for Media RSS <media:restriction> 618 * @see SimplePie::set_restriction_class() 619 * @access private 620 */ 621 var $restriction_class = 'SimplePie_Restriction'; 622 623 /** 624 * @var string Class used for content-type sniffing 625 * @see SimplePie::set_content_type_sniffer_class() 626 * @access private 627 */ 628 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer'; 629 630 /** 631 * @var string Class used for item sources. 632 * @see SimplePie::set_source_class() 633 * @access private 634 */ 635 var $source_class = 'SimplePie_Source'; 636 637 /** 638 * @var mixed Set javascript query string parameter (false, or 639 * anything type-cast to false, disables this feature) 640 * @see SimplePie::set_javascript() 641 * @access private 642 */ 643 var $javascript = 'js'; 644 645 /** 646 * @var int Maximum number of feeds to check with autodiscovery 647 * @see SimplePie::set_max_checked_feeds() 648 * @access private 649 */ 650 var $max_checked_feeds = 10; 651 652 /** 653 * @var array All the feeds found during the autodiscovery process 654 * @see SimplePie::get_all_discovered_feeds() 655 * @access private 656 */ 657 var $all_discovered_feeds = array(); 658 659 /** 660 * @var string Web-accessible path to the handler_favicon.php file. 661 * @see SimplePie::set_favicon_handler() 662 * @access private 663 */ 664 var $favicon_handler = ''; 665 666 /** 667 * @var string Web-accessible path to the handler_image.php file. 668 * @see SimplePie::set_image_handler() 669 * @access private 670 */ 671 var $image_handler = ''; 672 673 /** 674 * @var array Stores the URLs when multiple feeds are being initialized. 675 * @see SimplePie::set_feed_url() 676 * @access private 677 */ 678 var $multifeed_url = array(); 679 680 /** 681 * @var array Stores SimplePie objects when multiple feeds initialized. 682 * @access private 683 */ 684 var $multifeed_objects = array(); 685 686 /** 687 * @var array Stores the get_object_vars() array for use with multifeeds. 688 * @see SimplePie::set_feed_url() 689 * @access private 690 */ 691 var $config_settings = null; 692 693 /** 694 * @var integer Stores the number of items to return per-feed with multifeeds. 695 * @see SimplePie::set_item_limit() 696 * @access private 697 */ 698 var $item_limit = 0; 699 700 /** 701 * @var array Stores the default attributes to be stripped by strip_attributes(). 702 * @see SimplePie::strip_attributes() 703 * @access private 704 */ 705 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); 706 707 /** 708 * @var array Stores the default tags to be stripped by strip_htmltags(). 709 * @see SimplePie::strip_htmltags() 710 * @access private 711 */ 712 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); 713 714 /** 715 * The SimplePie class contains feed level data and options 716 * 717 * There are two ways that you can create a new SimplePie object. The first 718 * is by passing a feed URL as a parameter to the SimplePie constructor 719 * (as well as optionally setting the cache location and cache expiry). This 720 * will initialise the whole feed with all of the default settings, and you 721 * can begin accessing methods and properties immediately. 722 * 723 * The second way is to create the SimplePie object with no parameters 724 * at all. This will enable you to set configuration options. After setting 725 * them, you must initialise the feed using $feed->init(). At that point the 726 * object's methods and properties will be available to you. This format is 727 * what is used throughout this documentation. 728 * 729 * @access public 730 * @since 1.0 Preview Release 731 * @param string $feed_url This is the URL you want to parse. 732 * @param string $cache_location This is where you want the cache to be stored. 733 * @param int $cache_duration This is the number of seconds that you want to store the cache file for. 734 */ 735 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null) 736 { 737 // Other objects, instances created here so we can set options on them 738 $this->sanitize =& new SimplePie_Sanitize; 739 740 // Set options if they're passed to the constructor 741 if ($cache_location !== null) 742 { 743 $this->set_cache_location($cache_location); 744 } 745 746 if ($cache_duration !== null) 747 { 748 $this->set_cache_duration($cache_duration); 749 } 750 751 // Only init the script if we're passed a feed URL 752 if ($feed_url !== null) 753 { 754 $this->set_feed_url($feed_url); 755 $this->init(); 756 } 757 } 758 759 /** 760 * Used for converting object to a string 761 */ 762 function __toString() 763 { 764 return md5(serialize($this->data)); 765 } 766 767 /** 768 * Remove items that link back to this before destroying this object 769 */ 770 function __destruct() 771 { 772 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) 773 { 774 if (!empty($this->data['items'])) 775 { 776 foreach ($this->data['items'] as $item) 777 { 778 $item->__destruct(); 779 } 780 unset($item, $this->data['items']); 781 } 782 if (!empty($this->data['ordered_items'])) 783 { 784 foreach ($this->data['ordered_items'] as $item) 785 { 786 $item->__destruct(); 787 } 788 unset($item, $this->data['ordered_items']); 789 } 790 } 791 } 792 793 /** 794 * Force the given data/URL to be treated as a feed no matter what it 795 * appears like 796 * 797 * @access public 798 * @since 1.1 799 * @param bool $enable Force the given data/URL to be treated as a feed 800 */ 801 function force_feed($enable = false) 802 { 803 $this->force_feed = (bool) $enable; 804 } 805 806 /** 807 * This is the URL of the feed you want to parse. 808 * 809 * This allows you to enter the URL of the feed you want to parse, or the 810 * website you want to try to use auto-discovery on. This takes priority 811 * over any set raw data. 812 * 813 * You can set multiple feeds to mash together by passing an array instead 814 * of a string for the $url. Remember that with each additional feed comes 815 * additional processing and resources. 816 * 817 * @access public 818 * @since 1.0 Preview Release 819 * @param mixed $url This is the URL (or array of URLs) that you want to parse. 820 * @see SimplePie::set_raw_data() 821 */ 822 function set_feed_url($url) 823 { 824 if (is_array($url)) 825 { 826 $this->multifeed_url = array(); 827 foreach ($url as $value) 828 { 829 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1); 830 } 831 } 832 else 833 { 834 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1); 835 } 836 } 837 838 /** 839 * Provides an instance of SimplePie_File to use as a feed 840 * 841 * @access public 842 * @param object &$file Instance of SimplePie_File (or subclass) 843 * @return bool True on success, false on failure 844 */ 845 function set_file(&$file) 846 { 847 if (is_a($file, 'SimplePie_File')) 848 { 849 $this->feed_url = $file->url; 850 $this->file =& $file; 851 return true; 852 } 853 return false; 854 } 855 856 /** 857 * Allows you to use a string of RSS/Atom data instead of a remote feed. 858 * 859 * If you have a feed available as a string in PHP, you can tell SimplePie 860 * to parse that data string instead of a remote feed. Any set feed URL 861 * takes precedence. 862 * 863 * @access public 864 * @since 1.0 Beta 3 865 * @param string $data RSS or Atom data as a string. 866 * @see SimplePie::set_feed_url() 867 */ 868 function set_raw_data($data) 869 { 870 $this->raw_data = $data; 871 } 872 873 /** 874 * Allows you to override the default timeout for fetching remote feeds. 875 * 876 * This allows you to change the maximum time the feed's server to respond 877 * and send the feed back. 878 * 879 * @access public 880 * @since 1.0 Beta 3 881 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed. 882 */ 883 function set_timeout($timeout = 10) 884 { 885 $this->timeout = (int) $timeout; 886 } 887 888 /** 889 * Forces SimplePie to use fsockopen() instead of the preferred cURL 890 * functions. 891 * 892 * @access public 893 * @since 1.0 Beta 3 894 * @param bool $enable Force fsockopen() to be used 895 */ 896 function force_fsockopen($enable = false) 897 { 898 $this->force_fsockopen = (bool) $enable; 899 } 900 901 /** 902 * Outputs the raw XML content of the feed, after it has gone through 903 * SimplePie's filters. 904 * 905 * Used only for debugging, this function will output the XML content as 906 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up 907 * before trying to parse it. Many parts of the feed are re-written in 908 * memory, and in the end, you have a parsable feed. XML dump shows you the 909 * actual XML that SimplePie tries to parse, which may or may not be very 910 * different from the original feed. 911 * 912 * @access public 913 * @since 1.0 Preview Release 914 * @param bool $enable Enable XML dump 915 */ 916 function enable_xml_dump($enable = false) 917 { 918 $this->xml_dump = (bool) $enable; 919 } 920 921 /** 922 * Enables/disables caching in SimplePie. 923 * 924 * This option allows you to disable caching all-together in SimplePie. 925 * However, disabling the cache can lead to longer load times. 926 * 927 * @access public 928 * @since 1.0 Preview Release 929 * @param bool $enable Enable caching 930 */ 931 function enable_cache($enable = true) 932 { 933 $this->cache = (bool) $enable; 934 } 935 936 /** 937 * Set the length of time (in seconds) that the contents of a feed 938 * will be cached. 939 * 940 * @access public 941 * @param int $seconds The feed content cache duration. 942 */ 943 function set_cache_duration($seconds = 3600) 944 { 945 $this->cache_duration = (int) $seconds; 946 } 947 948 /** 949 * Set the length of time (in seconds) that the autodiscovered feed 950 * URL will be cached. 951 * 952 * @access public 953 * @param int $seconds The autodiscovered feed URL cache duration. 954 */ 955 function set_autodiscovery_cache_duration($seconds = 604800) 956 { 957 $this->autodiscovery_cache_duration = (int) $seconds; 958 } 959 960 /** 961 * Set the file system location where the cached files should be stored. 962 * 963 * @access public 964 * @param string $location The file system location. 965 */ 966 function set_cache_location($location = './cache') 967 { 968 $this->cache_location = (string) $location; 969 } 970 971 /** 972 * Determines whether feed items should be sorted into reverse chronological order. 973 * 974 * @access public 975 * @param bool $enable Sort as reverse chronological order. 976 */ 977 function enable_order_by_date($enable = true) 978 { 979 $this->order_by_date = (bool) $enable; 980 } 981 982 /** 983 * Allows you to override the character encoding reported by the feed. 984 * 985 * @access public 986 * @param string $encoding Character encoding. 987 */ 988 function set_input_encoding($encoding = false) 989 { 990 if ($encoding) 991 { 992 $this->input_encoding = (string) $encoding; 993 } 994 else 995 { 996 $this->input_encoding = false; 997 } 998 } 999 1000 /** 1001 * Set how much feed autodiscovery to do 1002 * 1003 * @access public 1004 * @see SIMPLEPIE_LOCATOR_NONE 1005 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY 1006 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION 1007 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY 1008 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION 1009 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY 1010 * @see SIMPLEPIE_LOCATOR_ALL 1011 * @param int $level Feed Autodiscovery Level (level can be a 1012 * combination of the above constants, see bitwise OR operator) 1013 */ 1014 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL) 1015 { 1016 $this->autodiscovery = (int) $level; 1017 } 1018 1019 /** 1020 * Allows you to change which class SimplePie uses for caching. 1021 * Useful when you are overloading or extending SimplePie's default classes. 1022 * 1023 * @access public 1024 * @param string $class Name of custom class. 1025 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1026 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1027 */ 1028 function set_cache_class($class = 'SimplePie_Cache') 1029 { 1030 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache')) 1031 { 1032 $this->cache_class = $class; 1033 return true; 1034 } 1035 return false; 1036 } 1037 1038 /** 1039 * Allows you to change which class SimplePie uses for auto-discovery. 1040 * Useful when you are overloading or extending SimplePie's default classes. 1041 * 1042 * @access public 1043 * @param string $class Name of custom class. 1044 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1045 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1046 */ 1047 function set_locator_class($class = 'SimplePie_Locator') 1048 { 1049 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator')) 1050 { 1051 $this->locator_class = $class; 1052 return true; 1053 } 1054 return false; 1055 } 1056 1057 /** 1058 * Allows you to change which class SimplePie uses for XML parsing. 1059 * Useful when you are overloading or extending SimplePie's default classes. 1060 * 1061 * @access public 1062 * @param string $class Name of custom class. 1063 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1064 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1065 */ 1066 function set_parser_class($class = 'SimplePie_Parser') 1067 { 1068 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser')) 1069 { 1070 $this->parser_class = $class; 1071 return true; 1072 } 1073 return false; 1074 } 1075 1076 /** 1077 * Allows you to change which class SimplePie uses for remote file fetching. 1078 * Useful when you are overloading or extending SimplePie's default classes. 1079 * 1080 * @access public 1081 * @param string $class Name of custom class. 1082 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1083 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1084 */ 1085 function set_file_class($class = 'SimplePie_File') 1086 { 1087 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File')) 1088 { 1089 $this->file_class = $class; 1090 return true; 1091 } 1092 return false; 1093 } 1094 1095 /** 1096 * Allows you to change which class SimplePie uses for data sanitization. 1097 * Useful when you are overloading or extending SimplePie's default classes. 1098 * 1099 * @access public 1100 * @param string $class Name of custom class. 1101 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1102 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1103 */ 1104 function set_sanitize_class($class = 'SimplePie_Sanitize') 1105 { 1106 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize')) 1107 { 1108 $this->sanitize =& new $class; 1109 return true; 1110 } 1111 return false; 1112 } 1113 1114 /** 1115 * Allows you to change which class SimplePie uses for handling feed items. 1116 * Useful when you are overloading or extending SimplePie's default classes. 1117 * 1118 * @access public 1119 * @param string $class Name of custom class. 1120 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1121 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1122 */ 1123 function set_item_class($class = 'SimplePie_Item') 1124 { 1125 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item')) 1126 { 1127 $this->item_class = $class; 1128 return true; 1129 } 1130 return false; 1131 } 1132 1133 /** 1134 * Allows you to change which class SimplePie uses for handling author data. 1135 * Useful when you are overloading or extending SimplePie's default classes. 1136 * 1137 * @access public 1138 * @param string $class Name of custom class. 1139 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1140 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1141 */ 1142 function set_author_class($class = 'SimplePie_Author') 1143 { 1144 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author')) 1145 { 1146 $this->author_class = $class; 1147 return true; 1148 } 1149 return false; 1150 } 1151 1152 /** 1153 * Allows you to change which class SimplePie uses for handling category data. 1154 * Useful when you are overloading or extending SimplePie's default classes. 1155 * 1156 * @access public 1157 * @param string $class Name of custom class. 1158 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1159 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1160 */ 1161 function set_category_class($class = 'SimplePie_Category') 1162 { 1163 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category')) 1164 { 1165 $this->category_class = $class; 1166 return true; 1167 } 1168 return false; 1169 } 1170 1171 /** 1172 * Allows you to change which class SimplePie uses for feed enclosures. 1173 * Useful when you are overloading or extending SimplePie's default classes. 1174 * 1175 * @access public 1176 * @param string $class Name of custom class. 1177 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1178 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1179 */ 1180 function set_enclosure_class($class = 'SimplePie_Enclosure') 1181 { 1182 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure')) 1183 { 1184 $this->enclosure_class = $class; 1185 return true; 1186 } 1187 return false; 1188 } 1189 1190 /** 1191 * Allows you to change which class SimplePie uses for <media:text> captions 1192 * Useful when you are overloading or extending SimplePie's default classes. 1193 * 1194 * @access public 1195 * @param string $class Name of custom class. 1196 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1197 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1198 */ 1199 function set_caption_class($class = 'SimplePie_Caption') 1200 { 1201 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption')) 1202 { 1203 $this->caption_class = $class; 1204 return true; 1205 } 1206 return false; 1207 } 1208 1209 /** 1210 * Allows you to change which class SimplePie uses for <media:copyright> 1211 * Useful when you are overloading or extending SimplePie's default classes. 1212 * 1213 * @access public 1214 * @param string $class Name of custom class. 1215 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1216 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1217 */ 1218 function set_copyright_class($class = 'SimplePie_Copyright') 1219 { 1220 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright')) 1221 { 1222 $this->copyright_class = $class; 1223 return true; 1224 } 1225 return false; 1226 } 1227 1228 /** 1229 * Allows you to change which class SimplePie uses for <media:credit> 1230 * Useful when you are overloading or extending SimplePie's default classes. 1231 * 1232 * @access public 1233 * @param string $class Name of custom class. 1234 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1235 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1236 */ 1237 function set_credit_class($class = 'SimplePie_Credit') 1238 { 1239 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit')) 1240 { 1241 $this->credit_class = $class; 1242 return true; 1243 } 1244 return false; 1245 } 1246 1247 /** 1248 * Allows you to change which class SimplePie uses for <media:rating> 1249 * Useful when you are overloading or extending SimplePie's default classes. 1250 * 1251 * @access public 1252 * @param string $class Name of custom class. 1253 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1254 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1255 */ 1256 function set_rating_class($class = 'SimplePie_Rating') 1257 { 1258 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating')) 1259 { 1260 $this->rating_class = $class; 1261 return true; 1262 } 1263 return false; 1264 } 1265 1266 /** 1267 * Allows you to change which class SimplePie uses for <media:restriction> 1268 * Useful when you are overloading or extending SimplePie's default classes. 1269 * 1270 * @access public 1271 * @param string $class Name of custom class. 1272 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1273 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1274 */ 1275 function set_restriction_class($class = 'SimplePie_Restriction') 1276 { 1277 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction')) 1278 { 1279 $this->restriction_class = $class; 1280 return true; 1281 } 1282 return false; 1283 } 1284 1285 /** 1286 * Allows you to change which class SimplePie uses for content-type sniffing. 1287 * Useful when you are overloading or extending SimplePie's default classes. 1288 * 1289 * @access public 1290 * @param string $class Name of custom class. 1291 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1292 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1293 */ 1294 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer') 1295 { 1296 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer')) 1297 { 1298 $this->content_type_sniffer_class = $class; 1299 return true; 1300 } 1301 return false; 1302 } 1303 1304 /** 1305 * Allows you to change which class SimplePie uses item sources. 1306 * Useful when you are overloading or extending SimplePie's default classes. 1307 * 1308 * @access public 1309 * @param string $class Name of custom class. 1310 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation 1311 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation 1312 */ 1313 function set_source_class($class = 'SimplePie_Source') 1314 { 1315 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source')) 1316 { 1317 $this->source_class = $class; 1318 return true; 1319 } 1320 return false; 1321 } 1322 1323 /** 1324 * Allows you to override the default user agent string. 1325 * 1326 * @access public 1327 * @param string $ua New user agent string. 1328 */ 1329 function set_useragent($ua = SIMPLEPIE_USERAGENT) 1330 { 1331 $this->useragent = (string) $ua; 1332 } 1333 1334 /** 1335 * Set callback function to create cache filename with 1336 * 1337 * @access public 1338 * @param mixed $function Callback function 1339 */ 1340 function set_cache_name_function($function = 'md5') 1341 { 1342 if (is_callable($function)) 1343 { 1344 $this->cache_name_function = $function; 1345 } 1346 } 1347 1348 /** 1349 * Set javascript query string parameter 1350 * 1351 * @access public 1352 * @param mixed $get Javascript query string parameter 1353 */ 1354 function set_javascript($get = 'js') 1355 { 1356 if ($get) 1357 { 1358 $this->javascript = (string) $get; 1359 } 1360 else 1361 { 1362 $this->javascript = false; 1363 } 1364 } 1365 1366 /** 1367 * Set options to make SP as fast as possible. Forgoes a 1368 * substantial amount of data sanitization in favor of speed. 1369 * 1370 * @access public 1371 * @param bool $set Whether to set them or not 1372 */ 1373 function set_stupidly_fast($set = false) 1374 { 1375 if ($set) 1376 { 1377 $this->enable_order_by_date(false); 1378 $this->remove_div(false); 1379 $this->strip_comments(false); 1380 $this->strip_htmltags(false); 1381 $this->strip_attributes(false); 1382 $this->set_image_handler(false); 1383 } 1384 } 1385 1386 /** 1387 * Set maximum number of feeds to check with autodiscovery 1388 * 1389 * @access public 1390 * @param int $max Maximum number of feeds to check 1391 */ 1392 function set_max_checked_feeds($max = 10) 1393 { 1394 $this->max_checked_feeds = (int) $max; 1395 } 1396 1397 function remove_div($enable = true) 1398 { 1399 $this->sanitize->remove_div($enable); 1400 } 1401 1402 function strip_htmltags($tags = '', $encode = null) 1403 { 1404 if ($tags === '') 1405 { 1406 $tags = $this->strip_htmltags; 1407 } 1408 $this->sanitize->strip_htmltags($tags); 1409 if ($encode !== null) 1410 { 1411 $this->sanitize->encode_instead_of_strip($tags); 1412 } 1413 } 1414 1415 function encode_instead_of_strip($enable = true) 1416 { 1417 $this->sanitize->encode_instead_of_strip($enable); 1418 } 1419 1420 function strip_attributes($attribs = '') 1421 { 1422 if ($attribs === '') 1423 { 1424 $attribs = $this->strip_attributes; 1425 } 1426 $this->sanitize->strip_attributes($attribs); 1427 } 1428 1429 function set_output_encoding($encoding = 'UTF-8') 1430 { 1431 $this->sanitize->set_output_encoding($encoding); 1432 } 1433 1434 function strip_comments($strip = false) 1435 { 1436 $this->sanitize->strip_comments($strip); 1437 } 1438 1439 /** 1440 * Set element/attribute key/value pairs of HTML attributes 1441 * containing URLs that need to be resolved relative to the feed 1442 * 1443 * @access public 1444 * @since 1.0 1445 * @param array $element_attribute Element/attribute key/value pairs 1446 */ 1447 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')) 1448 { 1449 $this->sanitize->set_url_replacements($element_attribute); 1450 } 1451 1452 /** 1453 * Set the handler to enable the display of cached favicons. 1454 * 1455 * @access public 1456 * @param str $page Web-accessible path to the handler_favicon.php file. 1457 * @param str $qs The query string that the value should be passed to. 1458 */ 1459 function set_favicon_handler($page = false, $qs = 'i') 1460 { 1461 if ($page !== false) 1462 { 1463 $this->favicon_handler = $page . '?' . $qs . '='; 1464 } 1465 else 1466 { 1467 $this->favicon_handler = ''; 1468 } 1469 } 1470 1471 /** 1472 * Set the handler to enable the display of cached images. 1473 * 1474 * @access public 1475 * @param str $page Web-accessible path to the handler_image.php file. 1476 * @param str $qs The query string that the value should be passed to. 1477 */ 1478 function set_image_handler($page = false, $qs = 'i') 1479 { 1480 if ($page !== false) 1481 { 1482 $this->sanitize->set_image_handler($page . '?' . $qs . '='); 1483 } 1484 else 1485 { 1486 $this->image_handler = ''; 1487 } 1488 } 1489 1490 /** 1491 * Set the limit for items returned per-feed with multifeeds. 1492 * 1493 * @access public 1494 * @param integer $limit The maximum number of items to return. 1495 */ 1496 function set_item_limit($limit = 0) 1497 { 1498 $this->item_limit = (int) $limit; 1499 } 1500 1501 function init() 1502 { 1503 // Check absolute bare minimum requirements. 1504 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre')) 1505 { 1506 return false; 1507 } 1508 // 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. 1509 elseif (!extension_loaded('xmlreader')) 1510 { 1511 static $xml_is_sane = null; 1512 if ($xml_is_sane === null) 1513 { 1514 $parser_check = xml_parser_create(); 1515 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values); 1516 xml_parser_free($parser_check); 1517 $xml_is_sane = isset($values[0]['value']); 1518 } 1519 if (!$xml_is_sane) 1520 { 1521 return false; 1522 } 1523 } 1524 1525 if (isset($_GET[$this->javascript])) 1526 { 1527 SimplePie_Misc::output_javascript(); 1528 exit; 1529 } 1530 1531 // Pass whatever was set with config options over to the sanitizer. 1532 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class); 1533 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen); 1534 1535 if ($this->feed_url !== null || $this->raw_data !== null) 1536 { 1537 $this->data = array(); 1538 $this->multifeed_objects = array(); 1539 $cache = false; 1540 1541 if ($this->feed_url !== null) 1542 { 1543 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url); 1544 // Decide whether to enable caching 1545 if ($this->cache && $parsed_feed_url['scheme'] !== '') 1546 { 1547 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'); 1548 } 1549 // If it's enabled and we don't want an XML dump, use the cache 1550 if ($cache && !$this->xml_dump) 1551 { 1552 // Load the Cache 1553 $this->data = $cache->load(); 1554 if (!empty($this->data)) 1555 { 1556 // If the cache is for an outdated build of SimplePie 1557 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD) 1558 { 1559 $cache->unlink(); 1560 $this->data = array(); 1561 } 1562 // If we've hit a collision just rerun it with caching disabled 1563 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) 1564 { 1565 $cache = false; 1566 $this->data = array(); 1567 } 1568 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL. 1569 elseif (isset($this->data['feed_url'])) 1570 { 1571 // If the autodiscovery cache is still valid use it. 1572 if ($cache->mtime() + $this->autodiscovery_cache_duration > time()) 1573 { 1574 // Do not need to do feed autodiscovery yet. 1575 if ($this->data['feed_url'] === $this->data['url']) 1576 { 1577 $cache->unlink(); 1578 $this->data = array(); 1579 } 1580 else 1581 { 1582 $this->set_feed_url($this->data['feed_url']); 1583 return $this->init(); 1584 } 1585 } 1586 } 1587 // Check if the cache has been updated 1588 elseif ($cache->mtime() + $this->cache_duration < time()) 1589 { 1590 // If we have last-modified and/or etag set 1591 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) 1592 { 1593 $headers = array(); 1594 if (isset($this->data['headers']['last-modified'])) 1595 { 1596 $headers['if-modified-since'] = $this->data['headers']['last-modified']; 1597 } 1598 if (isset($this->data['headers']['etag'])) 1599 { 1600 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"'; 1601 } 1602 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen); 1603 if ($file->success) 1604 { 1605 if ($file->status_code === 304) 1606 { 1607 $cache->touch(); 1608 return true; 1609 } 1610 else 1611 { 1612 $headers = $file->headers; 1613 } 1614 } 1615 else 1616 { 1617 unset($file); 1618 } 1619 } 1620 } 1621 // If the cache is still valid, just return true 1622 else 1623 { 1624 return true; 1625 } 1626 } 1627 // If the cache is empty, delete it 1628 else 1629 { 1630 $cache->unlink(); 1631 $this->data = array(); 1632 } 1633 } 1634 // 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. 1635 if (!isset($file)) 1636 { 1637 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url) 1638 { 1639 $file =& $this->file; 1640 } 1641 else 1642 { 1643 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen); 1644 } 1645 } 1646 // If the file connection has an error, set SimplePie::error to that and quit 1647 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) 1648 { 1649 $this->error = $file->error; 1650 if (!empty($this->data)) 1651 { 1652 return true; 1653 } 1654 else 1655 { 1656 return false; 1657 } 1658 } 1659 1660 if (!$this->force_feed) 1661 { 1662 // Check if the supplied URL is a feed, if it isn't, look for it. 1663 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class); 1664 if (!$locate->is_feed($file)) 1665 { 1666 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched 1667 unset($file); 1668 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)) 1669 { 1670 if ($cache) 1671 { 1672 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD); 1673 if (!$cache->save($this)) 1674 { 1675 trigger_error("$this->cache_location is not writeable", E_USER_WARNING); 1676 } 1677 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'); 1678 } 1679 $this->feed_url = $file->url; 1680 } 1681 else 1682 { 1683 $this->error = "A feed could not be found at $this->feed_url"; 1684 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__); 1685 return false; 1686 } 1687 } 1688 $locate = null; 1689 } 1690 1691 $headers = $file->headers; 1692 $data = $file->body; 1693 $sniffer =& new $this->content_type_sniffer_class($file); 1694 $sniffed = $sniffer->get_type(); 1695 } 1696 else 1697 { 1698 $data = $this->raw_data; 1699 } 1700 1701 // Set up array of possible encodings 1702 $encodings = array(); 1703 1704 // First check to see if input has been overridden. 1705 if ($this->input_encoding !== false) 1706 { 1707 $encodings[] = $this->input_encoding; 1708 } 1709 1710 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity'); 1711 $text_types = array('text/xml', 'text/xml-external-parsed-entity'); 1712 1713 // RFC 3023 (only applies to sniffed content) 1714 if (isset($sniffed)) 1715 { 1716 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml') 1717 { 1718 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) 1719 { 1720 $encodings[] = strtoupper($charset[1]); 1721 } 1722 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data)); 1723 $encodings[] = 'UTF-8'; 1724 } 1725 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml') 1726 { 1727 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) 1728 { 1729 $encodings[] = $charset[1]; 1730 } 1731 $encodings[] = 'US-ASCII'; 1732 } 1733 // Text MIME-type default 1734 elseif (substr($sniffed, 0, 5) === 'text/') 1735 { 1736 $encodings[] = 'US-ASCII'; 1737 } 1738 } 1739 1740 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1 1741 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data)); 1742 $encodings[] = 'UTF-8'; 1743 $encodings[] = 'ISO-8859-1'; 1744 1745 // There's no point in trying an encoding twice 1746 $encodings = array_unique($encodings); 1747 1748 // If we want the XML, just output that with the most likely encoding and quit 1749 if ($this->xml_dump) 1750 { 1751 header('Content-type: text/xml; charset=' . $encodings[0]); 1752 echo $data; 1753 exit; 1754 } 1755 1756 // Loop through each possible encoding, till we return something, or run out of possibilities 1757 foreach ($encodings as $encoding) 1758 { 1759 // Change the encoding to UTF-8 (as we always use UTF-8 internally) 1760 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8')) 1761 { 1762 // Create new parser 1763 $parser =& new $this->parser_class(); 1764 1765 // If it's parsed fine 1766 if ($parser->parse($utf8_data, 'UTF-8')) 1767 { 1768 $this->data = $parser->get_data(); 1769 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE) 1770 { 1771 if (isset($headers)) 1772 { 1773 $this->data['headers'] = $headers; 1774 } 1775 $this->data['build'] = SIMPLEPIE_BUILD; 1776 1777 // Cache the file if caching is enabled 1778 if ($cache && !$cache->save($this)) 1779 { 1780 trigger_error("$cache->name is not writeable", E_USER_WARNING); 1781 } 1782 return true; 1783 } 1784 else 1785 { 1786 $this->error = "A feed could not be found at $this->feed_url"; 1787 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__); 1788 return false; 1789 } 1790 } 1791 } 1792 } 1793 if(isset($parser)) 1794 { 1795 // We have an error, just set SimplePie_Misc::error to it and quit 1796 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column()); 1797 } 1798 else 1799 { 1800 $this->error = 'The data could not be converted to UTF-8'; 1801 } 1802 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__); 1803 return false; 1804 } 1805 elseif (!empty($this->multifeed_url)) 1806 { 1807 $i = 0; 1808 $success = 0; 1809 $this->multifeed_objects = array(); 1810 foreach ($this->multifeed_url as $url) 1811 { 1812 if (SIMPLEPIE_PHP5) 1813 { 1814 // This keyword needs to defy coding standards for PHP4 compatibility 1815 $this->multifeed_objects[$i] = clone($this); 1816 } 1817 else 1818 { 1819 $this->multifeed_objects[$i] = $this; 1820 } 1821 $this->multifeed_objects[$i]->set_feed_url($url); 1822 $success |= $this->multifeed_objects[$i]->init(); 1823 $i++; 1824 } 1825 return (bool) $success; 1826 } 1827 else 1828 { 1829 return false; 1830 } 1831 } 1832 1833 /** 1834 * Return the error message for the occurred error 1835 * 1836 * @access public 1837 * @return string Error message 1838 */ 1839 function error() 1840 { 1841 return $this->error; 1842 } 1843 1844 function get_encoding() 1845 { 1846 return $this->sanitize->output_encoding; 1847 } 1848 1849 function handle_content_type($mime = 'text/html') 1850 { 1851 if (!headers_sent()) 1852 { 1853 $header = "Content-type: $mime;"; 1854 if ($this->get_encoding()) 1855 { 1856 $header .= ' charset=' . $this->get_encoding(); 1857 } 1858 else 1859 { 1860 $header .= ' charset=UTF-8'; 1861 } 1862 header($header); 1863 } 1864 } 1865 1866 function get_type() 1867 { 1868 if (!isset($this->data['type'])) 1869 { 1870 $this->data['type'] = SIMPLEPIE_TYPE_ALL; 1871 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'])) 1872 { 1873 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10; 1874 } 1875 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'])) 1876 { 1877 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03; 1878 } 1879 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'])) 1880 { 1881 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel']) 1882 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image']) 1883 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']) 1884 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput'])) 1885 { 1886 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10; 1887 } 1888 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel']) 1889 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image']) 1890 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']) 1891 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput'])) 1892 { 1893 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090; 1894 } 1895 } 1896 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'])) 1897 { 1898 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL; 1899 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) 1900 { 1901 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) 1902 { 1903 case '0.91': 1904 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091; 1905 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) 1906 { 1907 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) 1908 { 1909 case '0': 1910 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE; 1911 break; 1912 1913 case '24': 1914 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND; 1915 break; 1916 } 1917 } 1918 break; 1919 1920 case '0.92': 1921 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092; 1922 break; 1923 1924 case '0.93': 1925 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093; 1926 break; 1927 1928 case '0.94': 1929 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094; 1930 break; 1931 1932 case '2.0': 1933 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20; 1934 break; 1935 } 1936 } 1937 } 1938 else 1939 { 1940 $this->data['type'] = SIMPLEPIE_TYPE_NONE; 1941 } 1942 } 1943 return $this->data['type']; 1944 } 1945 1946 /** 1947 * Returns the URL for the favicon of the feed's website. 1948 * 1949 * @todo Cache atom:icon 1950 * @access public 1951 * @since 1.0 1952 */ 1953 function get_favicon() 1954 { 1955 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) 1956 { 1957 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); 1958 } 1959 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url)) 1960 { 1961 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url); 1962 1963 if ($this->cache && $this->favicon_handler) 1964 { 1965 $favicon_filename = call_user_func($this->cache_name_function, $favicon); 1966 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi'); 1967 1968 if ($cache->load()) 1969 { 1970 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI); 1971 } 1972 else 1973 { 1974 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen); 1975 1976 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0) 1977 { 1978 $sniffer =& new $this->content_type_sniffer_class($file); 1979 if (substr($sniffer->get_type(), 0, 6) === 'image/') 1980 { 1981 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body))) 1982 { 1983 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI); 1984 } 1985 else 1986 { 1987 trigger_error("$cache->name is not writeable", E_USER_WARNING); 1988 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI); 1989 } 1990 } 1991 // not an image 1992 else 1993 { 1994 return false; 1995 } 1996 } 1997 } 1998 } 1999 else 2000 { 2001 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI); 2002 } 2003 } 2004 return false; 2005 } 2006 2007 /** 2008 * @todo If we have a perm redirect we should return the new URL 2009 * @todo When we make the above change, let's support <itunes:new-feed-url> as well 2010 * @todo Also, |atom:link|@rel=self 2011 */ 2012 function subscribe_url() 2013 { 2014 if ($this->feed_url !== null) 2015 { 2016 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI); 2017 } 2018 else 2019 { 2020 return null; 2021 } 2022 } 2023 2024 function subscribe_feed() 2025 { 2026 if ($this->feed_url !== null) 2027 { 2028 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI); 2029 } 2030 else 2031 { 2032 return null; 2033 } 2034 } 2035 2036 function subscribe_outlook() 2037 { 2038 if ($this->feed_url !== null) 2039 { 2040 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI); 2041 } 2042 else 2043 { 2044 return null; 2045 } 2046 } 2047 2048 function subscribe_podcast() 2049 { 2050 if ($this->feed_url !== null) 2051 { 2052 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI); 2053 } 2054 else 2055 { 2056 return null; 2057 } 2058 } 2059 2060 function subscribe_itunes() 2061 { 2062 if ($this->feed_url !== null) 2063 { 2064 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI); 2065 } 2066 else 2067 { 2068 return null; 2069 } 2070 } 2071 2072 /** 2073 * Creates the subscribe_* methods' return data 2074 * 2075 * @access private 2076 * @param string $feed_url String to prefix to the feed URL 2077 * @param string $site_url String to prefix to the site URL (and 2078 * suffix to the feed URL) 2079 * @return mixed URL if feed exists, false otherwise 2080 */ 2081 function subscribe_service($feed_url, $site_url = null) 2082 { 2083 if ($this->subscribe_url()) 2084 { 2085 $return = $feed_url . rawurlencode($this->feed_url); 2086 if ($site_url !== null && $this->get_link() !== null) 2087 { 2088 $return .= $site_url . rawurlencode($this->get_link()); 2089 } 2090 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI); 2091 } 2092 else 2093 { 2094 return null; 2095 } 2096 } 2097 2098 function subscribe_aol() 2099 { 2100 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url='); 2101 } 2102 2103 function subscribe_bloglines() 2104 { 2105 return $this->subscribe_service('http://www.bloglines.com/sub/'); 2106 } 2107 2108 function subscribe_eskobo() 2109 { 2110 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage='); 2111 } 2112 2113 function subscribe_feedfeeds() 2114 { 2115 return $this->subscribe_service('http://www.feedfeeds.com/add?feed='); 2116 } 2117 2118 function subscribe_feedster() 2119 { 2120 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl='); 2121 } 2122 2123 function subscribe_google() 2124 { 2125 return $this->subscribe_service('http://fusion.google.com/add?feedurl='); 2126 } 2127 2128 function subscribe_gritwire() 2129 { 2130 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl='); 2131 } 2132 2133 function subscribe_msn() 2134 { 2135 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru='); 2136 } 2137 2138 function subscribe_netvibes() 2139 { 2140 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url='); 2141 } 2142 2143 function subscribe_newsburst() 2144 { 2145 return $this->subscribe_service('http://www.newsburst.com/Source/?add='); 2146 } 2147 2148 function subscribe_newsgator() 2149 { 2150 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url='); 2151 } 2152 2153 function subscribe_odeo() 2154 { 2155 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed='); 2156 } 2157 2158 function subscribe_podnova() 2159 { 2160 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url='); 2161 } 2162 2163 function subscribe_rojo() 2164 { 2165 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource='); 2166 } 2167 2168 function subscribe_yahoo() 2169 { 2170 return $this->subscribe_service('http://add.my.yahoo.com/rss?url='); 2171 } 2172 2173 function get_feed_tags($namespace, $tag) 2174 { 2175 $type = $this->get_type(); 2176 if ($type & SIMPLEPIE_TYPE_ATOM_10) 2177 { 2178 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag])) 2179 { 2180 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]; 2181 } 2182 } 2183 if ($type & SIMPLEPIE_TYPE_ATOM_03) 2184 { 2185 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag])) 2186 { 2187 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]; 2188 } 2189 } 2190 if ($type & SIMPLEPIE_TYPE_RSS_RDF) 2191 { 2192 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag])) 2193 { 2194 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]; 2195 } 2196 } 2197 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION) 2198 { 2199 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag])) 2200 { 2201 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]; 2202 } 2203 } 2204 return null; 2205 } 2206 2207 function get_channel_tags($namespace, $tag) 2208 { 2209 $type = $this->get_type(); 2210 if ($type & SIMPLEPIE_TYPE_ATOM_ALL) 2211 { 2212 if ($return = $this->get_feed_tags($namespace, $tag)) 2213 { 2214 return $return; 2215 } 2216 } 2217 if ($type & SIMPLEPIE_TYPE_RSS_10) 2218 { 2219 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel')) 2220 { 2221 if (isset($channel[0]['child'][$namespace][$tag])) 2222 { 2223 return $channel[0]['child'][$namespace][$tag]; 2224 } 2225 } 2226 } 2227 if ($type & SIMPLEPIE_TYPE_RSS_090) 2228 { 2229 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel')) 2230 { 2231 if (isset($channel[0]['child'][$namespace][$tag])) 2232 { 2233 return $channel[0]['child'][$namespace][$tag]; 2234 } 2235 } 2236 } 2237 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION) 2238 { 2239 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel')) 2240 { 2241 if (isset($channel[0]['child'][$namespace][$tag])) 2242 { 2243 return $channel[0]['child'][$namespace][$tag]; 2244 } 2245 } 2246 } 2247 return null; 2248 } 2249 2250 function get_image_tags($namespace, $tag) 2251 { 2252 $type = $this->get_type(); 2253 if ($type & SIMPLEPIE_TYPE_RSS_10) 2254 { 2255 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image')) 2256 { 2257 if (isset($image[0]['child'][$namespace][$tag])) 2258 { 2259 return $image[0]['child'][$namespace][$tag]; 2260 } 2261 } 2262 } 2263 if ($type & SIMPLEPIE_TYPE_RSS_090) 2264 { 2265 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image')) 2266 { 2267 if (isset($image[0]['child'][$namespace][$tag])) 2268 { 2269 return $image[0]['child'][$namespace][$tag]; 2270 } 2271 } 2272 } 2273 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION) 2274 { 2275 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image')) 2276 { 2277 if (isset($image[0]['child'][$namespace][$tag])) 2278 { 2279 return $image[0]['child'][$namespace][$tag]; 2280 } 2281 } 2282 } 2283 return null; 2284 } 2285 2286 function get_base($element = array()) 2287 { 2288 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base'])) 2289 { 2290 return $element['xml_base']; 2291 } 2292 elseif ($this->get_link() !== null) 2293 { 2294 return $this->get_link(); 2295 } 2296 else 2297 { 2298 return $this->subscribe_url(); 2299 } 2300 } 2301 2302 function sanitize($data, $type, $base = '') 2303 { 2304 return $this->sanitize->sanitize($data, $type, $base); 2305 } 2306 2307 function get_title() 2308 { 2309 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) 2310 { 2311 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); 2312 } 2313 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) 2314 { 2315 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); 2316 } 2317 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) 2318 { 2319 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); 2320 } 2321 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) 2322 { 2323 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); 2324 } 2325 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) 2326 { 2327 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); 2328 } 2329 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) 2330 { 2331 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2332 } 2333 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) 2334 { 2335 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2336 } 2337 else 2338 { 2339 return null; 2340 } 2341 } 2342 2343 function get_category($key = 0) 2344 { 2345 $categories = $this->get_categories(); 2346 if (isset($categories[$key])) 2347 { 2348 return $categories[$key]; 2349 } 2350 else 2351 { 2352 return null; 2353 } 2354 } 2355 2356 function get_categories() 2357 { 2358 $categories = array(); 2359 2360 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) 2361 { 2362 $term = null; 2363 $scheme = null; 2364 $label = null; 2365 if (isset($category['attribs']['']['term'])) 2366 { 2367 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); 2368 } 2369 if (isset($category['attribs']['']['scheme'])) 2370 { 2371 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); 2372 } 2373 if (isset($category['attribs']['']['label'])) 2374 { 2375 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); 2376 } 2377 $categories[] =& new $this->category_class($term, $scheme, $label); 2378 } 2379 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) 2380 { 2381 // This is really the label, but keep this as the term also for BC. 2382 // Label will also work on retrieving because that falls back to term. 2383 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2384 if (isset($category['attribs']['']['domain'])) 2385 { 2386 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); 2387 } 2388 else 2389 { 2390 $scheme = null; 2391 } 2392 $categories[] =& new $this->category_class($term, $scheme, null); 2393 } 2394 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) 2395 { 2396 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); 2397 } 2398 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) 2399 { 2400 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); 2401 } 2402 2403 if (!empty($categories)) 2404 { 2405 return SimplePie_Misc::array_unique($categories); 2406 } 2407 else 2408 { 2409 return null; 2410 } 2411 } 2412 2413 function get_author($key = 0) 2414 { 2415 $authors = $this->get_authors(); 2416 if (isset($authors[$key])) 2417 { 2418 return $authors[$key]; 2419 } 2420 else 2421 { 2422 return null; 2423 } 2424 } 2425 2426 function get_authors() 2427 { 2428 $authors = array(); 2429 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) 2430 { 2431 $name = null; 2432 $uri = null; 2433 $email = null; 2434 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) 2435 { 2436 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2437 } 2438 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) 2439 { 2440 $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])); 2441 } 2442 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) 2443 { 2444 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2445 } 2446 if ($name !== null || $email !== null || $uri !== null) 2447 { 2448 $authors[] =& new $this->author_class($name, $uri, $email); 2449 } 2450 } 2451 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) 2452 { 2453 $name = null; 2454 $url = null; 2455 $email = null; 2456 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) 2457 { 2458 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2459 } 2460 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) 2461 { 2462 $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])); 2463 } 2464 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) 2465 { 2466 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2467 } 2468 if ($name !== null || $email !== null || $url !== null) 2469 { 2470 $authors[] =& new $this->author_class($name, $url, $email); 2471 } 2472 } 2473 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) 2474 { 2475 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); 2476 } 2477 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) 2478 { 2479 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); 2480 } 2481 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) 2482 { 2483 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); 2484 } 2485 2486 if (!empty($authors)) 2487 { 2488 return SimplePie_Misc::array_unique($authors); 2489 } 2490 else 2491 { 2492 return null; 2493 } 2494 } 2495 2496 function get_contributor($key = 0) 2497 { 2498 $contributors = $this->get_contributors(); 2499 if (isset($contributors[$key])) 2500 { 2501 return $contributors[$key]; 2502 } 2503 else 2504 { 2505 return null; 2506 } 2507 } 2508 2509 function get_contributors() 2510 { 2511 $contributors = array(); 2512 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) 2513 { 2514 $name = null; 2515 $uri = null; 2516 $email = null; 2517 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) 2518 { 2519 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); 2520 } 2521 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) 2522 { 2523