5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
8 * Copyright (c) 2004-2008, Ryan Parman and Geoffrey Sneddon
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
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.
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
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.
37 * @copyright 2004-2008 Ryan Parman, Geoffrey Sneddon
39 * @author Geoffrey Sneddon
40 * @link http://simplepie.org/ SimplePie
41 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @todo phpDoc comments
49 define('SIMPLEPIE_NAME', 'SimplePie');
54 define('SIMPLEPIE_VERSION', '1.1.3');
59 define('SIMPLEPIE_BUILD', 20081219);
62 * SimplePie Website URL
64 define('SIMPLEPIE_URL', 'http://simplepie.org');
68 * @see SimplePie::set_useragent()
70 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
75 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
79 * @see SimplePie::set_autodiscovery_level()
81 define('SIMPLEPIE_LOCATOR_NONE', 0);
84 * Feed Link Element Autodiscovery
85 * @see SimplePie::set_autodiscovery_level()
87 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
90 * Local Feed Extension Autodiscovery
91 * @see SimplePie::set_autodiscovery_level()
93 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
96 * Local Feed Body Autodiscovery
97 * @see SimplePie::set_autodiscovery_level()
99 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
102 * Remote Feed Extension Autodiscovery
103 * @see SimplePie::set_autodiscovery_level()
105 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
108 * Remote Feed Body Autodiscovery
109 * @see SimplePie::set_autodiscovery_level()
111 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
114 * All Feed Autodiscovery
115 * @see SimplePie::set_autodiscovery_level()
117 define('SIMPLEPIE_LOCATOR_ALL', 31);
122 define('SIMPLEPIE_TYPE_NONE', 0);
127 define('SIMPLEPIE_TYPE_RSS_090', 1);
130 * RSS 0.91 (Netscape)
132 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
135 * RSS 0.91 (Userland)
137 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
140 * RSS 0.91 (both Netscape and Userland)
142 define('SIMPLEPIE_TYPE_RSS_091', 6);
147 define('SIMPLEPIE_TYPE_RSS_092', 8);
152 define('SIMPLEPIE_TYPE_RSS_093', 16);
157 define('SIMPLEPIE_TYPE_RSS_094', 32);
162 define('SIMPLEPIE_TYPE_RSS_10', 64);
167 define('SIMPLEPIE_TYPE_RSS_20', 128);
172 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
175 * Non-RDF-based RSS (truly intended as syndication format)
177 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
182 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
187 define('SIMPLEPIE_TYPE_ATOM_03', 256);
192 define('SIMPLEPIE_TYPE_ATOM_10', 512);
197 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
202 define('SIMPLEPIE_TYPE_ALL', 1023);
207 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
212 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
217 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
222 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
225 * base64-encoded construct
227 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
232 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
235 * A construct that might be HTML
237 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
242 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
245 * PCRE for HTML attributes
247 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]*');
250 * PCRE for XML attributes
252 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
257 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
262 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
267 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
272 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
277 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
282 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
285 * RSS 1.0 Content Module Namespace
287 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
291 * (Stupid, I know, but I'm certain it will confuse people less with support.)
293 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
298 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
303 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
306 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
308 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
313 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
316 * Media RSS Namespace
318 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
321 * Wrong Media RSS Namespace
323 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
326 * iTunes RSS Namespace
328 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
333 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
336 * IANA Link Relations Registry
338 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
341 * Whether we're running on PHP5
343 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
348 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
353 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
358 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
361 * fsockopen() file source
363 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
368 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
371 * file_get_contents() file source
373 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
379 * @version "Razzleberry"
380 * @copyright 2004-2007 Ryan Parman, Geoffrey Sneddon
381 * @author Ryan Parman
382 * @author Geoffrey Sneddon
383 * @todo Option for type of fetching (cache, not modified header, fetch, etc.)
388 * @var array Raw data
394 * @var mixed Error string
400 * @var object Instance of SimplePie_Sanitize (or other class)
401 * @see SimplePie::set_sanitize_class()
407 * @var string SimplePie Useragent
408 * @see SimplePie::set_useragent()
411 var $useragent = SIMPLEPIE_USERAGENT;
414 * @var string Feed URL
415 * @see SimplePie::set_feed_url()
421 * @var object Instance of SimplePie_File to use as a feed
422 * @see SimplePie::set_file()
428 * @var string Raw feed data
429 * @see SimplePie::set_raw_data()
435 * @var int Timeout for fetching remote files
436 * @see SimplePie::set_timeout()
442 * @var bool Forces fsockopen() to be used for remote files instead
443 * of cURL, even if a new enough version is installed
444 * @see SimplePie::force_fsockopen()
447 var $force_fsockopen = false;
450 * @var bool Force the given data/URL to be treated as a feed no matter what
452 * @see SimplePie::force_feed()
455 var $force_feed = false;
458 * @var bool Enable/Disable XML dump
459 * @see SimplePie::enable_xml_dump()
462 var $xml_dump = false;
465 * @var bool Enable/Disable Caching
466 * @see SimplePie::enable_cache()
472 * @var int Cache duration (in seconds)
473 * @see SimplePie::set_cache_duration()
476 var $cache_duration = 3600;
479 * @var int Auto-discovery cache duration (in seconds)
480 * @see SimplePie::set_autodiscovery_cache_duration()
483 var $autodiscovery_cache_duration = 604800; // 7 Days.
486 * @var string Cache location (relative to executing script)
487 * @see SimplePie::set_cache_location()
490 var $cache_location = './cache';
493 * @var string Function that creates the cache filename
494 * @see SimplePie::set_cache_name_function()
497 var $cache_name_function = 'md5';
500 * @var bool Reorder feed by date descending
501 * @see SimplePie::enable_order_by_date()
504 var $order_by_date = true;
507 * @var mixed Force input encoding to be set to the follow value
508 * (false, or anything type-cast to false, disables this feature)
509 * @see SimplePie::set_input_encoding()
512 var $input_encoding = false;
515 * @var int Feed Autodiscovery Level
516 * @see SimplePie::set_autodiscovery_level()
519 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
522 * @var string Class used for caching feeds
523 * @see SimplePie::set_cache_class()
526 var $cache_class = 'SimplePie_Cache';
529 * @var string Class used for locating feeds
530 * @see SimplePie::set_locator_class()
533 var $locator_class = 'SimplePie_Locator';
536 * @var string Class used for parsing feeds
537 * @see SimplePie::set_parser_class()
540 var $parser_class = 'SimplePie_Parser';
543 * @var string Class used for fetching feeds
544 * @see SimplePie::set_file_class()
547 var $file_class = 'SimplePie_File';
550 * @var string Class used for items
551 * @see SimplePie::set_item_class()
554 var $item_class = 'SimplePie_Item';
557 * @var string Class used for authors
558 * @see SimplePie::set_author_class()
561 var $author_class = 'SimplePie_Author';
564 * @var string Class used for categories
565 * @see SimplePie::set_category_class()
568 var $category_class = 'SimplePie_Category';
571 * @var string Class used for enclosures
572 * @see SimplePie::set_enclosures_class()
575 var $enclosure_class = 'SimplePie_Enclosure';
578 * @var string Class used for Media RSS <media:text> captions
579 * @see SimplePie::set_caption_class()
582 var $caption_class = 'SimplePie_Caption';
585 * @var string Class used for Media RSS <media:copyright>
586 * @see SimplePie::set_copyright_class()
589 var $copyright_class = 'SimplePie_Copyright';
592 * @var string Class used for Media RSS <media:credit>
593 * @see SimplePie::set_credit_class()
596 var $credit_class = 'SimplePie_Credit';
599 * @var string Class used for Media RSS <media:rating>
600 * @see SimplePie::set_rating_class()
603 var $rating_class = 'SimplePie_Rating';
606 * @var string Class used for Media RSS <media:restriction>
607 * @see SimplePie::set_restriction_class()
610 var $restriction_class = 'SimplePie_Restriction';
613 * @var string Class used for content-type sniffing
614 * @see SimplePie::set_content_type_sniffer_class()
617 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
620 * @var string Class used for item sources.
621 * @see SimplePie::set_source_class()
624 var $source_class = 'SimplePie_Source';
627 * @var mixed Set javascript query string parameter (false, or
628 * anything type-cast to false, disables this feature)
629 * @see SimplePie::set_javascript()
632 var $javascript = 'js';
635 * @var int Maximum number of feeds to check with autodiscovery
636 * @see SimplePie::set_max_checked_feeds()
639 var $max_checked_feeds = 10;
642 * @var string Web-accessible path to the handler_favicon.php file.
643 * @see SimplePie::set_favicon_handler()
646 var $favicon_handler = '';
649 * @var string Web-accessible path to the handler_image.php file.
650 * @see SimplePie::set_image_handler()
653 var $image_handler = '';
656 * @var array Stores the URLs when multiple feeds are being initialized.
657 * @see SimplePie::set_feed_url()
660 var $multifeed_url = array();
663 * @var array Stores SimplePie objects when multiple feeds initialized.
666 var $multifeed_objects = array();
669 * @var array Stores the get_object_vars() array for use with multifeeds.
670 * @see SimplePie::set_feed_url()
673 var $config_settings = null;
676 * @var integer Stores the number of items to return per-feed with multifeeds.
677 * @see SimplePie::set_item_limit()
683 * @var array Stores the default attributes to be stripped by strip_attributes().
684 * @see SimplePie::strip_attributes()
687 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
690 * @var array Stores the default tags to be stripped by strip_htmltags().
691 * @see SimplePie::strip_htmltags()
694 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
697 * The SimplePie class contains feed level data and options
699 * There are two ways that you can create a new SimplePie object. The first
700 * is by passing a feed URL as a parameter to the SimplePie constructor
701 * (as well as optionally setting the cache location and cache expiry). This
702 * will initialise the whole feed with all of the default settings, and you
703 * can begin accessing methods and properties immediately.
705 * The second way is to create the SimplePie object with no parameters
706 * at all. This will enable you to set configuration options. After setting
707 * them, you must initialise the feed using $feed->init(). At that point the
708 * object's methods and properties will be available to you. This format is
709 * what is used throughout this documentation.
712 * @since 1.0 Preview Release
713 * @param string $feed_url This is the URL you want to parse.
714 * @param string $cache_location This is where you want the cache to be stored.
715 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
717 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
719 // Other objects, instances created here so we can set options on them
720 $this->sanitize =& new SimplePie_Sanitize;
722 // Set options if they're passed to the constructor
723 if ($cache_location !== null)
725 $this->set_cache_location($cache_location);
728 if ($cache_duration !== null)
730 $this->set_cache_duration($cache_duration);
733 // Only init the script if we're passed a feed URL
734 if ($feed_url !== null)
736 $this->set_feed_url($feed_url);
742 * Used for converting object to a string
744 function __toString()
746 return md5(serialize($this->data));
750 * Remove items that link back to this before destroying this object
752 function __destruct()
754 if (!empty($this->data['items']))
756 foreach ($this->data['items'] as $item)
760 unset($this->data['items']);
762 if (!empty($this->data['ordered_items']))
764 foreach ($this->data['ordered_items'] as $item)
768 unset($this->data['ordered_items']);
773 * Force the given data/URL to be treated as a feed no matter what it
778 * @param bool $enable Force the given data/URL to be treated as a feed
780 function force_feed($enable = false)
782 $this->force_feed = (bool) $enable;
786 * This is the URL of the feed you want to parse.
788 * This allows you to enter the URL of the feed you want to parse, or the
789 * website you want to try to use auto-discovery on. This takes priority
790 * over any set raw data.
792 * You can set multiple feeds to mash together by passing an array instead
793 * of a string for the $url. Remember that with each additional feed comes
794 * additional processing and resources.
797 * @since 1.0 Preview Release
798 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
799 * @see SimplePie::set_raw_data()
801 function set_feed_url($url)
805 $this->multifeed_url = array();
806 foreach ($url as $value)
808 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
813 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
818 * Provides an instance of SimplePie_File to use as a feed
821 * @param object &$file Instance of SimplePie_File (or subclass)
822 * @return bool True on success, false on failure
824 function set_file(&$file)
826 if (is_a($file, 'SimplePie_File'))
828 $this->feed_url = $file->url;
829 $this->file =& $file;
836 * Allows you to use a string of RSS/Atom data instead of a remote feed.
838 * If you have a feed available as a string in PHP, you can tell SimplePie
839 * to parse that data string instead of a remote feed. Any set feed URL
844 * @param string $data RSS or Atom data as a string.
845 * @see SimplePie::set_feed_url()
847 function set_raw_data($data)
849 $this->raw_data = $data;
853 * Allows you to override the default timeout for fetching remote feeds.
855 * This allows you to change the maximum time the feed's server to respond
856 * and send the feed back.
860 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
862 function set_timeout($timeout = 10)
864 $this->timeout = (int) $timeout;
868 * Forces SimplePie to use fsockopen() instead of the preferred cURL
873 * @param bool $enable Force fsockopen() to be used
875 function force_fsockopen($enable = false)
877 $this->force_fsockopen = (bool) $enable;
881 * Outputs the raw XML content of the feed, after it has gone through
882 * SimplePie's filters.
884 * Used only for debugging, this function will output the XML content as
885 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
886 * before trying to parse it. Many parts of the feed are re-written in
887 * memory, and in the end, you have a parsable feed. XML dump shows you the
888 * actual XML that SimplePie tries to parse, which may or may not be very
889 * different from the original feed.
892 * @since 1.0 Preview Release
893 * @param bool $enable Enable XML dump
895 function enable_xml_dump($enable = false)
897 $this->xml_dump = (bool) $enable;
901 * Enables/disables caching in SimplePie.
903 * This option allows you to disable caching all-together in SimplePie.
904 * However, disabling the cache can lead to longer load times.
907 * @since 1.0 Preview Release
908 * @param bool $enable Enable caching
910 function enable_cache($enable = true)
912 $this->cache = (bool) $enable;
916 * Set the length of time (in seconds) that the contents of a feed
920 * @param int $seconds The feed content cache duration.
922 function set_cache_duration($seconds = 3600)
924 $this->cache_duration = (int) $seconds;
928 * Set the length of time (in seconds) that the autodiscovered feed
929 * URL will be cached.
932 * @param int $seconds The autodiscovered feed URL cache duration.
934 function set_autodiscovery_cache_duration($seconds = 604800)
936 $this->autodiscovery_cache_duration = (int) $seconds;
940 * Set the file system location where the cached files should be stored.
943 * @param string $location The file system location.
945 function set_cache_location($location = './cache')
947 $this->cache_location = (string) $location;
951 * Determines whether feed items should be sorted into reverse chronological order.
954 * @param bool $enable Sort as reverse chronological order.
956 function enable_order_by_date($enable = true)
958 $this->order_by_date = (bool) $enable;
962 * Allows you to override the character encoding reported by the feed.
965 * @param string $encoding Character encoding.
967 function set_input_encoding($encoding = false)
971 $this->input_encoding = (string) $encoding;
975 $this->input_encoding = false;
980 * Set how much feed autodiscovery to do
983 * @see SIMPLEPIE_LOCATOR_NONE
984 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
985 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
986 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
987 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
988 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
989 * @see SIMPLEPIE_LOCATOR_ALL
990 * @param int $level Feed Autodiscovery Level (level can be a
991 * combination of the above constants, see bitwise OR operator)
993 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
995 $this->autodiscovery = (int) $level;
999 * Allows you to change which class SimplePie uses for caching.
1000 * Useful when you are overloading or extending SimplePie's default classes.
1003 * @param string $class Name of custom class.
1004 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1005 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1007 function set_cache_class($class = 'SimplePie_Cache')
1009 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1011 $this->cache_class = $class;
1018 * Allows you to change which class SimplePie uses for auto-discovery.
1019 * Useful when you are overloading or extending SimplePie's default classes.
1022 * @param string $class Name of custom class.
1023 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1024 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1026 function set_locator_class($class = 'SimplePie_Locator')
1028 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1030 $this->locator_class = $class;
1037 * Allows you to change which class SimplePie uses for XML parsing.
1038 * Useful when you are overloading or extending SimplePie's default classes.
1041 * @param string $class Name of custom class.
1042 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1043 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1045 function set_parser_class($class = 'SimplePie_Parser')
1047 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1049 $this->parser_class = $class;
1056 * Allows you to change which class SimplePie uses for remote file fetching.
1057 * Useful when you are overloading or extending SimplePie's default classes.
1060 * @param string $class Name of custom class.
1061 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1062 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1064 function set_file_class($class = 'SimplePie_File')
1066 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1068 $this->file_class = $class;
1075 * Allows you to change which class SimplePie uses for data sanitization.
1076 * Useful when you are overloading or extending SimplePie's default classes.
1079 * @param string $class Name of custom class.
1080 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1081 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1083 function set_sanitize_class($class = 'SimplePie_Sanitize')
1085 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1087 $this->sanitize =& new $class;
1094 * Allows you to change which class SimplePie uses for handling feed items.
1095 * Useful when you are overloading or extending SimplePie's default classes.
1098 * @param string $class Name of custom class.
1099 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1100 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1102 function set_item_class($class = 'SimplePie_Item')
1104 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1106 $this->item_class = $class;
1113 * Allows you to change which class SimplePie uses for handling author data.
1114 * Useful when you are overloading or extending SimplePie's default classes.
1117 * @param string $class Name of custom class.
1118 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1119 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1121 function set_author_class($class = 'SimplePie_Author')
1123 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1125 $this->author_class = $class;
1132 * Allows you to change which class SimplePie uses for handling category data.
1133 * Useful when you are overloading or extending SimplePie's default classes.
1136 * @param string $class Name of custom class.
1137 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1138 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1140 function set_category_class($class = 'SimplePie_Category')
1142 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1144 $this->category_class = $class;
1151 * Allows you to change which class SimplePie uses for feed enclosures.
1152 * Useful when you are overloading or extending SimplePie's default classes.
1155 * @param string $class Name of custom class.
1156 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1157 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1159 function set_enclosure_class($class = 'SimplePie_Enclosure')
1161 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1163 $this->enclosure_class = $class;
1170 * Allows you to change which class SimplePie uses for <media:text> captions
1171 * Useful when you are overloading or extending SimplePie's default classes.
1174 * @param string $class Name of custom class.
1175 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1176 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1178 function set_caption_class($class = 'SimplePie_Caption')
1180 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1182 $this->caption_class = $class;
1189 * Allows you to change which class SimplePie uses for <media:copyright>
1190 * Useful when you are overloading or extending SimplePie's default classes.
1193 * @param string $class Name of custom class.
1194 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1195 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1197 function set_copyright_class($class = 'SimplePie_Copyright')
1199 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1201 $this->copyright_class = $class;
1208 * Allows you to change which class SimplePie uses for <media:credit>
1209 * Useful when you are overloading or extending SimplePie's default classes.
1212 * @param string $class Name of custom class.
1213 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1214 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1216 function set_credit_class($class = 'SimplePie_Credit')
1218 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1220 $this->credit_class = $class;
1227 * Allows you to change which class SimplePie uses for <media:rating>
1228 * Useful when you are overloading or extending SimplePie's default classes.
1231 * @param string $class Name of custom class.
1232 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1233 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1235 function set_rating_class($class = 'SimplePie_Rating')
1237 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1239 $this->rating_class = $class;
1246 * Allows you to change which class SimplePie uses for <media:restriction>
1247 * Useful when you are overloading or extending SimplePie's default classes.
1250 * @param string $class Name of custom class.
1251 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1252 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1254 function set_restriction_class($class = 'SimplePie_Restriction')
1256 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1258 $this->restriction_class = $class;
1265 * Allows you to change which class SimplePie uses for content-type sniffing.
1266 * Useful when you are overloading or extending SimplePie's default classes.
1269 * @param string $class Name of custom class.
1270 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1271 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1273 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1275 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1277 $this->content_type_sniffer_class = $class;
1284 * Allows you to change which class SimplePie uses item sources.
1285 * Useful when you are overloading or extending SimplePie's default classes.
1288 * @param string $class Name of custom class.
1289 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1290 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1292 function set_source_class($class = 'SimplePie_Source')
1294 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1296 $this->source_class = $class;
1303 * Allows you to override the default user agent string.
1306 * @param string $ua New user agent string.
1308 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1310 $this->useragent = (string) $ua;
1314 * Set callback function to create cache filename with
1317 * @param mixed $function Callback function
1319 function set_cache_name_function($function = 'md5')
1321 if (is_callable($function))
1323 $this->cache_name_function = $function;
1328 * Set javascript query string parameter
1331 * @param mixed $get Javascript query string parameter
1333 function set_javascript($get = 'js')
1337 $this->javascript = (string) $get;
1341 $this->javascript = false;
1346 * Set options to make SP as fast as possible. Forgoes a
1347 * substantial amount of data sanitization in favor of speed.
1350 * @param bool $set Whether to set them or not
1352 function set_stupidly_fast($set = false)
1356 $this->enable_order_by_date(false);
1357 $this->remove_div(false);
1358 $this->strip_comments(false);
1359 $this->strip_htmltags(false);
1360 $this->strip_attributes(false);
1361 $this->set_image_handler(false);
1366 * Set maximum number of feeds to check with autodiscovery
1369 * @param int $max Maximum number of feeds to check
1371 function set_max_checked_feeds($max = 10)
1373 $this->max_checked_feeds = (int) $max;
1376 function remove_div($enable = true)
1378 $this->sanitize->remove_div($enable);
1381 function strip_htmltags($tags = '', $encode = null)
1385 $tags = $this->strip_htmltags;
1387 $this->sanitize->strip_htmltags($tags);
1388 if ($encode !== null)
1390 $this->sanitize->encode_instead_of_strip($tags);
1394 function encode_instead_of_strip($enable = true)
1396 $this->sanitize->encode_instead_of_strip($enable);
1399 function strip_attributes($attribs = '')
1401 if ($attribs === '')
1403 $attribs = $this->strip_attributes;
1405 $this->sanitize->strip_attributes($attribs);
1408 function set_output_encoding($encoding = 'UTF-8')
1410 $this->sanitize->set_output_encoding($encoding);
1413 function strip_comments($strip = false)
1415 $this->sanitize->strip_comments($strip);
1419 * Set element/attribute key/value pairs of HTML attributes
1420 * containing URLs that need to be resolved relative to the feed
1424 * @param array $element_attribute Element/attribute key/value pairs
1426 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'))
1428 $this->sanitize->set_url_replacements($element_attribute);
1432 * Set the handler to enable the display of cached favicons.
1435 * @param str $page Web-accessible path to the handler_favicon.php file.
1436 * @param str $qs The query string that the value should be passed to.
1438 function set_favicon_handler($page = false, $qs = 'i')
1442 $this->favicon_handler = $page . '?' . $qs . '=';
1446 $this->favicon_handler = '';
1451 * Set the handler to enable the display of cached images.
1454 * @param str $page Web-accessible path to the handler_image.php file.
1455 * @param str $qs The query string that the value should be passed to.
1457 function set_image_handler($page = false, $qs = 'i')
1461 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1465 $this->image_handler = '';
1470 * Set the limit for items returned per-feed with multifeeds.
1473 * @param integer $limit The maximum number of items to return.
1475 function set_item_limit($limit = 0)
1477 $this->item_limit = (int) $limit;
1482 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1486 if (isset($_GET[$this->javascript]))
1488 if (function_exists('ob_gzhandler'))
1490 ob_start('ob_gzhandler');
1492 header('Content-type: text/javascript; charset: UTF-8');
1493 header('Cache-Control: must-revalidate');
1494 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
1496 function embed_odeo(link) {
1497 document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
1500 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
1501 if (placeholder != '') {
1502 document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
1505 document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
1509 function embed_flash(bgcolor, width, height, link, loop, type) {
1510 document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
1513 function embed_flv(width, height, link, placeholder, loop, player) {
1514 document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
1517 function embed_wmedia(width, height, link) {
1518 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
1524 // Pass whatever was set with config options over to the sanitizer.
1525 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1526 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1528 if ($this->feed_url !== null || $this->raw_data !== null)
1530 $this->data = array();
1531 $this->multifeed_objects = array();
1534 if ($this->feed_url !== null)
1536 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1537 // Decide whether to enable caching
1538 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1540 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1542 // If it's enabled and we don't want an XML dump, use the cache
1543 if ($cache && !$this->xml_dump)
1546 $this->data = $cache->load();
1547 if (!empty($this->data))
1549 // If the cache is for an outdated build of SimplePie
1550 if (!isset($this->data['build']) || $this->data['build'] != SIMPLEPIE_BUILD)
1553 $this->data = array();
1555 // If we've hit a collision just rerun it with caching disabled
1556 elseif (isset($this->data['url']) && $this->data['url'] != $this->feed_url)
1559 $this->data = array();
1561 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1562 elseif (isset($this->data['feed_url']))
1564 // If the autodiscovery cache is still valid use it.
1565 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1567 // Do not need to do feed autodiscovery yet.
1568 if ($this->data['feed_url'] == $this->data['url'])
1571 $this->data = array();
1575 $this->set_feed_url($this->data['feed_url']);
1576 return $this->init();
1580 // Check if the cache has been updated
1581 elseif ($cache->mtime() + $this->cache_duration < time())
1583 // If we have last-modified and/or etag set
1584 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1587 if (isset($this->data['headers']['last-modified']))
1589 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1591 if (isset($this->data['headers']['etag']))
1593 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1595 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1598 if ($file->status_code == 304)
1605 $headers = $file->headers;
1614 // If the cache is still valid, just return true
1620 // If the cache is empty, delete it
1624 $this->data = array();
1627 // 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.
1630 if (is_a($this->file, 'SimplePie_File') && $this->file->url == $this->feed_url)
1632 $file =& $this->file;
1636 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1639 // If the file connection has an error, set SimplePie::error to that and quit
1640 if (!$file->success)
1642 $this->error = $file->error;
1643 if (!empty($this->data))
1653 if (!$this->force_feed)
1655 // Check if the supplied URL is a feed, if it isn't, look for it.
1656 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1657 if (!$locate->is_feed($file))
1659 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1661 if ($file = $locate->find($this->autodiscovery))
1665 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1666 if (!$cache->save($this))
1668 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1670 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1672 $this->feed_url = $file->url;
1676 $this->error = "A feed could not be found at $this->feed_url";
1677 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1684 $headers = $file->headers;
1685 $data = $file->body;
1686 $sniffer = new $this->content_type_sniffer_class($file);
1687 $sniffed = $sniffer->get_type();
1691 $data = $this->raw_data;
1694 // Set up array of possible encodings
1695 $encodings = array();
1697 // First check to see if input has been overridden.
1698 if ($this->input_encoding !== false)
1700 $encodings[] = $this->input_encoding;
1703 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1704 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1706 // RFC 3023 (only applies to sniffed content)
1707 if (isset($sniffed))
1709 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1711 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1713 $encodings[] = strtoupper($charset[1]);
1715 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1716 $encodings[] = 'UTF-8';
1718 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1720 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1722 $encodings[] = $charset[1];
1724 $encodings[] = 'US-ASCII';
1726 // Text MIME-type default
1727 elseif (substr($sniffed, 0, 5) === 'text/')
1729 $encodings[] = 'US-ASCII';
1733 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1734 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1735 $encodings[] = 'UTF-8';
1736 $encodings[] = 'ISO-8859-1';
1738 // There's no point in trying an encoding twice
1739 $encodings = array_unique($encodings);
1741 // If we want the XML, just output that with the most likely encoding and quit
1742 if ($this->xml_dump)
1744 header('Content-type: text/xml; charset=' . $encodings[0]);
1749 // Loop through each possible encoding, till we return something, or run out of possibilities
1750 foreach ($encodings as $encoding)
1752 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1753 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1755 // Create new parser
1756 $parser =& new $this->parser_class();
1758 // If it's parsed fine
1759 if ($parser->parse($utf8_data, 'UTF-8'))
1761 $this->data = $parser->get_data();
1762 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1764 if (isset($headers))
1766 $this->data['headers'] = $headers;
1768 $this->data['build'] = SIMPLEPIE_BUILD;
1770 // Cache the file if caching is enabled
1771 if ($cache && !$cache->save($this))
1773 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1779 $this->error = "A feed could not be found at $this->feed_url";
1780 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1786 // We have an error, just set SimplePie::error to it and quit
1787 $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1788 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1791 elseif (!empty($this->multifeed_url))
1795 $this->multifeed_objects = array();
1796 foreach ($this->multifeed_url as $url)
1800 // This keyword needs to defy coding standards for PHP4 compatibility
1801 $this->multifeed_objects[$i] = clone($this);
1805 $this->multifeed_objects[$i] = $this;
1807 $this->multifeed_objects[$i]->set_feed_url($url);
1808 $success |= $this->multifeed_objects[$i]->init();
1811 return (bool) $success;
1820 * Return the error message for the occured error
1823 * @return string Error message
1827 return $this->error;
1830 function get_encoding()
1832 return $this->sanitize->output_encoding;
1835 function handle_content_type($mime = 'text/html')
1837 if (!headers_sent())
1839 $header = "Content-type: $mime;";
1840 if ($this->get_encoding())
1842 $header .= ' charset=' . $this->get_encoding();
1846 $header .= ' charset=UTF-8';
1854 if (!isset($this->data['type']))
1856 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1857 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1859 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1861 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1863 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1865 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1867 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1868 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1869 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1870 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1872 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1874 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1875 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1876 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1877 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1879 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1882 elseif (isset($this->data['child']['']['rss']))
1884 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1885 if (isset($this->data['child']['']['rss'][0]['attribs']['']['version']))
1887 switch (trim($this->data['child']['']['rss'][0]['attribs']['']['version']))
1890 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1891 if (isset($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
1893 switch (trim($this->data['child']['']['rss'][0]['child']['']['skiphours']['hour'][0]['data']))
1896 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1900 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1907 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1911 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1915 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1919 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1926 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1929 return $this->data['type'];
1933 * Returns the URL for the favicon of the feed's website.
1935 * @todo Cache atom:icon
1939 function get_favicon()
1941 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1943 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1945 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1947 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1949 if ($this->cache && $this->favicon_handler)
1951 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1952 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1956 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1960 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1962 if ($file->success && ($file->status_code == 200 || ($file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1964 $sniffer = new $this->content_type_sniffer_class($file);
1965 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1967 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1969 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1973 trigger_error("$cache->name is not writeable", E_USER_WARNING);
1974 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1982 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
1989 * @todo If we have a perm redirect we should return the new URL
1990 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1991 * @todo Also, |atom:link|@rel=self
1993 function subscribe_url()
1995 if ($this->feed_url !== null)
1997 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2005 function subscribe_feed()
2007 if ($this->feed_url !== null)
2009 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2017 function subscribe_outlook()
2019 if ($this->feed_url !== null)
2021 return 'outlook' . $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2029 function subscribe_podcast()
2031 if ($this->feed_url !== null)
2033 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2041 function subscribe_itunes()
2043 if ($this->feed_url !== null)
2045 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2054 * Creates the subscribe_* methods' return data
2057 * @param string $feed_url String to prefix to the feed URL
2058 * @param string $site_url String to prefix to the site URL (and
2059 * suffix to the feed URL)
2060 * @return mixed URL if feed exists, false otherwise
2062 function subscribe_service($feed_url, $site_url = null)
2064 if ($this->subscribe_url())
2066 $return = $this->sanitize($feed_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->feed_url);
2067 if ($site_url !== null && $this->get_link() !== null)
2069 $return .= $this->sanitize($site_url, SIMPLEPIE_CONSTRUCT_IRI) . rawurlencode($this->get_link());
2079 function subscribe_aol()
2081 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2084 function subscribe_bloglines()
2086 return urldecode($this->subscribe_service('http://www.bloglines.com/sub/'));
2089 function subscribe_eskobo()
2091 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2094 function subscribe_feedfeeds()
2096 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2099 function subscribe_feedster()
2101 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2104 function subscribe_google()
2106 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2109 function subscribe_gritwire()
2111 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2114 function subscribe_msn()
2116 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2119 function subscribe_netvibes()
2121 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2124 function subscribe_newsburst()
2126 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2129 function subscribe_newsgator()
2131 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2134 function subscribe_odeo()
2136 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2139 function subscribe_podnova()
2141 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2144 function subscribe_rojo()
2146 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2149 function subscribe_yahoo()
2151 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2154 function get_feed_tags($namespace, $tag)
2156 $type = $this->get_type();
2157 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2159 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2161 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2164 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2166 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2168 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2171 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2173 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2175 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2178 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2180 if (isset($this->data['child']['']['rss'][0]['child'][$namespace][$tag]))
2182 return $this->data['child']['']['rss'][0]['child'][$namespace][$tag];
2188 function get_channel_tags($namespace, $tag)
2190 $type = $this->get_type();
2191 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2193 if ($return = $this->get_feed_tags($namespace, $tag))
2198 if ($type & SIMPLEPIE_TYPE_RSS_10)
2200 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2202 if (isset($channel[0]['child'][$namespace][$tag]))
2204 return $channel[0]['child'][$namespace][$tag];
2208 if ($type & SIMPLEPIE_TYPE_RSS_090)
2210 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2212 if (isset($channel[0]['child'][$namespace][$tag]))
2214 return $channel[0]['child'][$namespace][$tag];
2218 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2220 if ($channel = $this->get_feed_tags('', 'channel'))
2222 if (isset($channel[0]['child'][$namespace][$tag]))
2224 return $channel[0]['child'][$namespace][$tag];
2231 function get_image_tags($namespace, $tag)
2233 $type = $this->get_type();
2234 if ($type & SIMPLEPIE_TYPE_RSS_10)
2236 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2238 if (isset($image[0]['child'][$namespace][$tag]))
2240 return $image[0]['child'][$namespace][$tag];
2244 if ($type & SIMPLEPIE_TYPE_RSS_090)
2246 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2248 if (isset($image[0]['child'][$namespace][$tag]))
2250 return $image[0]['child'][$namespace][$tag];
2254 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2256 if ($image = $this->get_channel_tags('', 'image'))
2258 if (isset($image[0]['child'][$namespace][$tag]))
2260 return $image[0]['child'][$namespace][$tag];
2267 function get_base($element = array())
2269 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2271 return $element['xml_base'];
2273 elseif ($this->get_link() !== null)
2275 return $this->get_link();
2279 return $this->subscribe_url();
2283 function sanitize($data, $type, $base = '')
2285 return $this->sanitize->sanitize($data, $type, $base);
2288 function get_title()
2290 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2292 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2294 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2296 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2298 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2300 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2302 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2304 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2306 elseif ($return = $this->get_channel_tags('', 'title'))
2308 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2310 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2312 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2314 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2316 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2324 function get_category($key = 0)
2326 $categories = $this->get_categories();
2327 if (isset($categories[$key]))
2329 return $categories[$key];
2337 function get_categories()
2339 $categories = array();
2341 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2346 if (isset($category['attribs']['']['term']))
2348 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2350 if (isset($category['attribs']['']['scheme']))
2352 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2354 if (isset($category['attribs']['']['label']))
2356 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2358 $categories[] =& new $this->category_class($term, $scheme, $label);
2360 foreach ((array) $this->get_channel_tags('', 'category') as $category)
2362 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2364 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2366 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2368 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2370 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2373 if (!empty($categories))
2375 return SimplePie_Misc::array_unique($categories);
2383 function get_author($key = 0)
2385 $authors = $this->get_authors();
2386 if (isset($authors[$key]))
2388 return $authors[$key];
2396 function get_authors()
2399 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2404 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2406 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2408 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2410 $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]));
2412 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2414 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2416 if ($name !== null || $email !== null || $uri !== null)
2418 $authors[] =& new $this->author_class($name, $uri, $email);
2421 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2426 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2428 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2430 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2432 $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]));
2434 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2436 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2438 if ($name !== null || $email !== null || $url !== null)
2440 $authors[] =& new $this->author_class($name, $url, $email);
2443 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2445 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2447 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2449 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2451 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2453 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2456 if (!empty($authors))
2458 return SimplePie_Misc::array_unique($authors);
2466 function get_contributor($key = 0)
2468 $contributors = $this->get_contributors();
2469 if (isset($contributors[$key]))
2471 return $contributors[$key];
2479 function get_contributors()
2481 $contributors = array();
2482 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2487 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2489 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2491 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2493 $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]));
2495 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2497 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2499 if ($name !== null || $email !== null || $uri !== null)
2501 $contributors[] =& new $this->author_class($name, $uri, $email);
2504 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2509 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2511 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2513 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2515 $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]));
2517 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2519 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2521 if ($name !== null || $email !== null || $url !== null)
2523 $contributors[] =& new $this->author_class($name, $url, $email);
2527 if (!empty($contributors))
2529 return SimplePie_Misc::array_unique($contributors);
2537 function get_link($key = 0, $rel = 'alternate')
2539 $links = $this->get_links($rel);
2540 if (isset($links[$key]))
2542 return $links[$key];
2551 * Added for parity between the parent-level and the item/entry-level.
2553 function get_permalink()
2555 return $this->get_link(0);
2558 function get_links($rel = 'alternate')
2560 if (!isset($this->data['links']))
2562 $this->data['links'] = array();
2563 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2565 foreach ($links as $link)
2567 if (isset($link['attribs']['']['href']))
2569 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2570 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2574 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2576 foreach ($links as $link)
2578 if (isset($link['attribs']['']['href']))
2580 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2581 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2586 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2588 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2590 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2592 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2594 if ($links = $this->get_channel_tags('', 'link'))
2596 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2599 $keys = array_keys($this->data['links']);
2600 foreach ($keys as $key)
2602 if (SimplePie_Misc::is_isegment_nz_nc($key))
2604 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2606 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2607 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2611 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2614 elseif (substr($key, 0, 41) == SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2616 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2618 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2622 if (isset($this->data['links'][$rel]))
2624 return $this->data['links'][$rel];
2632 function get_description()
2634 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2636 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2638 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2640 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2642 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2644 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2646 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2648 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2650 elseif ($return = $this->get_channel_tags('', 'description'))
2652 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2654 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2656 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2658 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2660 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2662 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2664 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2666 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2668 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2676 function get_copyright()
2678 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2680 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2682 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2684 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2686 elseif ($return = $this->get_channel_tags('', 'copyright'))
2688 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2690 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2692 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2694 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2696 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2704 function get_language()
2706 if ($return = $this->get_channel_tags('', 'language'))
2708 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2710 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2712 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2714 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2716 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2718 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2720 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2722 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2724 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2726 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2728 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2730 elseif (isset($this->data['headers']['content-language']))
2732 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2740 function get_latitude()
2742 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2744 return (float) $return[0]['data'];
2746 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2748 return (float) $match[1];
2756 function get_longitude()
2758 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2760 return (float) $return[0]['data'];
2762 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2764 return (float) $return[0]['data'];
2766 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2768 return (float) $match[2];
2776 function get_image_title()
2778 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2780 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2782 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2784 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2786 elseif ($return = $this->get_image_tags('', 'title'))
2788 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2790 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2792 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2794 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2796 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2804 function get_image_url()
2806 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2808 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2810 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2812 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2814 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2816 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2818 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2820 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2822 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2824 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2826 elseif ($return = $this->get_image_tags('', 'url'))
2828 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2836 function get_image_link()
2838 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2840 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2842 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2844 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2846 elseif ($return = $this->get_image_tags('', 'link'))
2848 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2856 function get_image_width()
2858 if ($return = $this->get_image_tags('', 'width'))
2860 return round($return[0]['data']);
2862 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
2872 function get_image_height()
2874 if ($return = $this->get_image_tags('', 'height'))
2876 return round($return[0]['data']);
2878 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags('', 'url'))
2888 function get_item_quantity($max = 0)
2890 $qty = count($this->get_items());
2897 return ($qty > $max) ? $max : $qty;
2901 function get_item($key = 0)
2903 $items = $this->get_items();
2904 if (isset($items[$key]))
2906 return $items[$key];
2914 function get_items($start = 0, $end = 0)
2916 if (!empty($this->multifeed_objects))
2918 return SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2920 elseif (!isset($this->data['items']))
2922 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2924 $keys = array_keys($items);
2925 foreach ($keys as $key)
2927 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2930 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2932 $keys = array_keys($items);
2933 foreach ($keys as $key)
2935 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2938 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2940 $keys = array_keys($items);
2941 foreach ($keys as $key)
2943 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2946 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2948 $keys = array_keys($items);
2949 foreach ($keys as $key)
2951 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2954 if ($items = $this->get_channel_tags('', 'item'))
2956 $keys = array_keys($items);
2957 foreach ($keys as $key)
2959 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2964 if (!empty($this->data['items']))
2966 // If we want to order it by date, check if all items have a date, and then sort it
2967 if ($this->order_by_date)
2969 if (!isset($this->data['ordered_items']))
2972 foreach ($this->data['items'] as $item)
2974 if (!$item->get_date('U'))
2981 $this->data['ordered_items'] = $this->data['items'];
2984 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
2987 $items = $this->data['ordered_items'];
2991 $items = $this->data['items'];
2994 // Slice the data as desired
2997 return array_slice($items, $start);
3001 return array_slice($items, $start, $end);
3010 function sort_items($a, $b)
3012 return $a->get_date('U') <= $b->get_date('U');
3015 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3017 if (is_array($urls) && sizeof($urls) > 0)
3020 foreach ($urls as $arg)
3022 if (is_a($arg, 'SimplePie'))
3024 $items = array_merge($items, $arg->get_items(0, $limit));
3028 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3033 foreach ($items as $item)
3035 if (!$item->get_date('U'))
3044 usort($items, array('SimplePie', 'sort_items'));
3049 return array_slice($items, $start);
3053 return array_slice($items, $start, $end);
3058 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3064 class SimplePie_Item
3067 var $data = array();
3069 function SimplePie_Item($feed, $data)
3071 $this->feed = $feed;
3072 $this->data = $data;
3075 function __toString()
3077 return md5(serialize($this->data));
3081 * Remove items that link back to this before destroying this object
3083 function __destruct()
3088 function get_item_tags($namespace, $tag)
3090 if (isset($this->data['child'][$namespace][$tag]))
3092 return $this->data['child'][$namespace][$tag];
3100 function get_base($element = array())
3102 return $this->feed->get_base($element);
3105 function sanitize($data, $type, $base = '')
3107 return $this->feed->sanitize($data, $type, $base);
3115 function get_id($hash = false)
3119 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3121 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3123 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3125 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3127 elseif ($return = $this->get_item_tags('', 'guid'))
3129 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3131 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3133 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3135 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3137 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3139 elseif (($return = $this->get_permalink()) !== null)
3143 elseif (($return = $this->get_title()) !== null)
3148 if ($this->get_permalink() !== null || $this->get_title() !== null)
3150 return md5($this->get_permalink() . $this->get_title());
3154 return md5(serialize($this->data));
3158 function get_title()
3160 if (!isset($this->data['title']))
3162 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3164 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3166 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3168 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3170 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3172 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3174 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3176 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3178 elseif ($return = $this->get_item_tags('', 'title'))
3180 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3182 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3184 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3186 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3188 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3192 $this->data['title'] = null;
3195 return $this->data['title'];
3198 function get_description($description_only = false)
3200 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3202 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3204 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3206 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3208 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3210 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3212 elseif ($return = $this->get_item_tags('', 'description'))
3214 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3216 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3218 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3220 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3222 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3224 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3226 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3228 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3230 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3232 elseif (!$description_only)
3234 return $this->get_content(true);
3242 function get_content($content_only = false)
3244 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3246 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3248 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3250 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3252 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3254 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3256 elseif (!$content_only)
3258 return $this->get_description(true);
3266 function get_category($key = 0)
3268 $categories = $this->get_categories();
3269 if (isset($categories[$key]))
3271 return $categories[$key];