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-2009, 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-2009 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.2.1-dev');
58 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
60 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
63 * SimplePie Website URL
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
69 * @see SimplePie::set_useragent()
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
80 * @see SimplePie::set_autodiscovery_level()
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
85 * Feed Link Element Autodiscovery
86 * @see SimplePie::set_autodiscovery_level()
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
91 * Local Feed Extension Autodiscovery
92 * @see SimplePie::set_autodiscovery_level()
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
97 * Local Feed Body Autodiscovery
98 * @see SimplePie::set_autodiscovery_level()
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
103 * Remote Feed Extension Autodiscovery
104 * @see SimplePie::set_autodiscovery_level()
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
109 * Remote Feed Body Autodiscovery
110 * @see SimplePie::set_autodiscovery_level()
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
115 * All Feed Autodiscovery
116 * @see SimplePie::set_autodiscovery_level()
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
123 define('SIMPLEPIE_TYPE_NONE', 0);
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
131 * RSS 0.91 (Netscape)
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
136 * RSS 0.91 (Userland)
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
141 * RSS 0.91 (both Netscape and Userland)
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
176 * Non-RDF-based RSS (truly intended as syndication format)
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
203 define('SIMPLEPIE_TYPE_ALL', 1023);
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
226 * base64-encoded construct
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
236 * A construct that might be HTML
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
248 define('SIMPLEPIE_SAME_CASE', 1);
251 * Change to lowercase
253 define('SIMPLEPIE_LOWERCASE', 2);
256 * Change to uppercase
258 define('SIMPLEPIE_UPPERCASE', 4);
261 * PCRE for HTML attributes
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]*');
266 * PCRE for XML attributes
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
301 * RSS 1.0 Content Module Namespace
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
307 * (Stupid, I know, but I'm certain it will confuse people less with support.)
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
322 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
332 * Media RSS Namespace
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
337 * Wrong Media RSS Namespace
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
342 * iTunes RSS Namespace
344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
352 * IANA Link Relations Registry
354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
357 * Whether we're running on PHP5
359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
377 * fsockopen() file source
379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
387 * file_get_contents() file source
389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
399 * @var array Raw data
405 * @var mixed Error string
411 * @var object Instance of SimplePie_Sanitize (or other class)
412 * @see SimplePie::set_sanitize_class()
418 * @var string SimplePie Useragent
419 * @see SimplePie::set_useragent()
422 var $useragent = SIMPLEPIE_USERAGENT;
425 * @var string Feed URL
426 * @see SimplePie::set_feed_url()
432 * @var object Instance of SimplePie_File to use as a feed
433 * @see SimplePie::set_file()
439 * @var string Raw feed data
440 * @see SimplePie::set_raw_data()
446 * @var int Timeout for fetching remote files
447 * @see SimplePie::set_timeout()
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()
458 var $force_fsockopen = false;
461 * @var bool Force the given data/URL to be treated as a feed no matter what
463 * @see SimplePie::force_feed()
466 var $force_feed = false;
469 * @var bool Enable/Disable XML dump
470 * @see SimplePie::enable_xml_dump()
473 var $xml_dump = false;
476 * @var bool Enable/Disable Caching
477 * @see SimplePie::enable_cache()
483 * @var int Cache duration (in seconds)
484 * @see SimplePie::set_cache_duration()
487 var $cache_duration = 3600;
490 * @var int Auto-discovery cache duration (in seconds)
491 * @see SimplePie::set_autodiscovery_cache_duration()
494 var $autodiscovery_cache_duration = 604800; // 7 Days.
497 * @var string Cache location (relative to executing script)
498 * @see SimplePie::set_cache_location()
501 var $cache_location = './cache';
504 * @var string Function that creates the cache filename
505 * @see SimplePie::set_cache_name_function()
508 var $cache_name_function = 'md5';
511 * @var bool Reorder feed by date descending
512 * @see SimplePie::enable_order_by_date()
515 var $order_by_date = true;
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()
523 var $input_encoding = false;
526 * @var int Feed Autodiscovery Level
527 * @see SimplePie::set_autodiscovery_level()
530 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
533 * @var string Class used for caching feeds
534 * @see SimplePie::set_cache_class()
537 var $cache_class = 'SimplePie_Cache';
540 * @var string Class used for locating feeds
541 * @see SimplePie::set_locator_class()
544 var $locator_class = 'SimplePie_Locator';
547 * @var string Class used for parsing feeds
548 * @see SimplePie::set_parser_class()
551 var $parser_class = 'SimplePie_Parser';
554 * @var string Class used for fetching feeds
555 * @see SimplePie::set_file_class()
558 var $file_class = 'SimplePie_File';
561 * @var string Class used for items
562 * @see SimplePie::set_item_class()
565 var $item_class = 'SimplePie_Item';
568 * @var string Class used for authors
569 * @see SimplePie::set_author_class()
572 var $author_class = 'SimplePie_Author';
575 * @var string Class used for categories
576 * @see SimplePie::set_category_class()
579 var $category_class = 'SimplePie_Category';
582 * @var string Class used for enclosures
583 * @see SimplePie::set_enclosures_class()
586 var $enclosure_class = 'SimplePie_Enclosure';
589 * @var string Class used for Media RSS <media:text> captions
590 * @see SimplePie::set_caption_class()
593 var $caption_class = 'SimplePie_Caption';
596 * @var string Class used for Media RSS <media:copyright>
597 * @see SimplePie::set_copyright_class()
600 var $copyright_class = 'SimplePie_Copyright';
603 * @var string Class used for Media RSS <media:credit>
604 * @see SimplePie::set_credit_class()
607 var $credit_class = 'SimplePie_Credit';
610 * @var string Class used for Media RSS <media:rating>
611 * @see SimplePie::set_rating_class()
614 var $rating_class = 'SimplePie_Rating';
617 * @var string Class used for Media RSS <media:restriction>
618 * @see SimplePie::set_restriction_class()
621 var $restriction_class = 'SimplePie_Restriction';
624 * @var string Class used for content-type sniffing
625 * @see SimplePie::set_content_type_sniffer_class()
628 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
631 * @var string Class used for item sources.
632 * @see SimplePie::set_source_class()
635 var $source_class = 'SimplePie_Source';
638 * @var mixed Set javascript query string parameter (false, or
639 * anything type-cast to false, disables this feature)
640 * @see SimplePie::set_javascript()
643 var $javascript = 'js';
646 * @var int Maximum number of feeds to check with autodiscovery
647 * @see SimplePie::set_max_checked_feeds()
650 var $max_checked_feeds = 10;
653 * @var array All the feeds found during the autodiscovery process
654 * @see SimplePie::get_all_discovered_feeds()
657 var $all_discovered_feeds = array();
660 * @var string Web-accessible path to the handler_favicon.php file.
661 * @see SimplePie::set_favicon_handler()
664 var $favicon_handler = '';
667 * @var string Web-accessible path to the handler_image.php file.
668 * @see SimplePie::set_image_handler()
671 var $image_handler = '';
674 * @var array Stores the URLs when multiple feeds are being initialized.
675 * @see SimplePie::set_feed_url()
678 var $multifeed_url = array();
681 * @var array Stores SimplePie objects when multiple feeds initialized.
684 var $multifeed_objects = array();
687 * @var array Stores the get_object_vars() array for use with multifeeds.
688 * @see SimplePie::set_feed_url()
691 var $config_settings = null;
694 * @var integer Stores the number of items to return per-feed with multifeeds.
695 * @see SimplePie::set_item_limit()
701 * @var array Stores the default attributes to be stripped by strip_attributes().
702 * @see SimplePie::strip_attributes()
705 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
708 * @var array Stores the default tags to be stripped by strip_htmltags().
709 * @see SimplePie::strip_htmltags()
712 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
715 * The SimplePie class contains feed level data and options
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.
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.
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.
735 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
737 // Other objects, instances created here so we can set options on them
738 $this->sanitize = new SimplePie_Sanitize;
740 // Set options if they're passed to the constructor
741 if ($cache_location !== null)
743 $this->set_cache_location($cache_location);
746 if ($cache_duration !== null)
748 $this->set_cache_duration($cache_duration);
751 // Only init the script if we're passed a feed URL
752 if ($feed_url !== null)
754 $this->set_feed_url($feed_url);
760 * Used for converting object to a string
762 function __toString()
764 return md5(serialize($this->data));
768 * Remove items that link back to this before destroying this object
770 function __destruct()
772 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
774 if (!empty($this->data['items']))
776 foreach ($this->data['items'] as $item)
780 unset($item, $this->data['items']);
782 if (!empty($this->data['ordered_items']))
784 foreach ($this->data['ordered_items'] as $item)
788 unset($item, $this->data['ordered_items']);
794 * Force the given data/URL to be treated as a feed no matter what it
799 * @param bool $enable Force the given data/URL to be treated as a feed
801 function force_feed($enable = false)
803 $this->force_feed = (bool) $enable;
807 * This is the URL of the feed you want to parse.
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.
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.
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()
822 function set_feed_url($url)
826 $this->multifeed_url = array();
827 foreach ($url as $value)
829 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
834 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
839 * Provides an instance of SimplePie_File to use as a feed
842 * @param object &$file Instance of SimplePie_File (or subclass)
843 * @return bool True on success, false on failure
845 function set_file(&$file)
847 if (is_a($file, 'SimplePie_File'))
849 $this->feed_url = $file->url;
850 $this->file =& $file;
857 * Allows you to use a string of RSS/Atom data instead of a remote feed.
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
865 * @param string $data RSS or Atom data as a string.
866 * @see SimplePie::set_feed_url()
868 function set_raw_data($data)
870 $this->raw_data = $data;
874 * Allows you to override the default timeout for fetching remote feeds.
876 * This allows you to change the maximum time the feed's server to respond
877 * and send the feed back.
881 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
883 function set_timeout($timeout = 10)
885 $this->timeout = (int) $timeout;
889 * Forces SimplePie to use fsockopen() instead of the preferred cURL
894 * @param bool $enable Force fsockopen() to be used
896 function force_fsockopen($enable = false)
898 $this->force_fsockopen = (bool) $enable;
902 * Outputs the raw XML content of the feed, after it has gone through
903 * SimplePie's filters.
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.
913 * @since 1.0 Preview Release
914 * @param bool $enable Enable XML dump
916 function enable_xml_dump($enable = false)
918 $this->xml_dump = (bool) $enable;
922 * Enables/disables caching in SimplePie.
924 * This option allows you to disable caching all-together in SimplePie.
925 * However, disabling the cache can lead to longer load times.
928 * @since 1.0 Preview Release
929 * @param bool $enable Enable caching
931 function enable_cache($enable = true)
933 $this->cache = (bool) $enable;
937 * Set the length of time (in seconds) that the contents of a feed
941 * @param int $seconds The feed content cache duration.
943 function set_cache_duration($seconds = 3600)
945 $this->cache_duration = (int) $seconds;
949 * Set the length of time (in seconds) that the autodiscovered feed
950 * URL will be cached.
953 * @param int $seconds The autodiscovered feed URL cache duration.
955 function set_autodiscovery_cache_duration($seconds = 604800)
957 $this->autodiscovery_cache_duration = (int) $seconds;
961 * Set the file system location where the cached files should be stored.
964 * @param string $location The file system location.
966 function set_cache_location($location = './cache')
968 $this->cache_location = (string) $location;
972 * Determines whether feed items should be sorted into reverse chronological order.
975 * @param bool $enable Sort as reverse chronological order.
977 function enable_order_by_date($enable = true)
979 $this->order_by_date = (bool) $enable;
983 * Allows you to override the character encoding reported by the feed.
986 * @param string $encoding Character encoding.
988 function set_input_encoding($encoding = false)
992 $this->input_encoding = (string) $encoding;
996 $this->input_encoding = false;
1001 * Set how much feed autodiscovery to do
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)
1014 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1016 $this->autodiscovery = (int) $level;
1020 * Allows you to change which class SimplePie uses for caching.
1021 * Useful when you are overloading or extending SimplePie's default classes.
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
1028 function set_cache_class($class = 'SimplePie_Cache')
1030 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1032 $this->cache_class = $class;
1039 * Allows you to change which class SimplePie uses for auto-discovery.
1040 * Useful when you are overloading or extending SimplePie's default classes.
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
1047 function set_locator_class($class = 'SimplePie_Locator')
1049 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1051 $this->locator_class = $class;
1058 * Allows you to change which class SimplePie uses for XML parsing.
1059 * Useful when you are overloading or extending SimplePie's default classes.
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
1066 function set_parser_class($class = 'SimplePie_Parser')
1068 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1070 $this->parser_class = $class;
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.
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
1085 function set_file_class($class = 'SimplePie_File')
1087 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1089 $this->file_class = $class;
1096 * Allows you to change which class SimplePie uses for data sanitization.
1097 * Useful when you are overloading or extending SimplePie's default classes.
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
1104 function set_sanitize_class($class = 'SimplePie_Sanitize')
1106 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1108 $this->sanitize = new $class;
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.
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
1123 function set_item_class($class = 'SimplePie_Item')
1125 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1127 $this->item_class = $class;
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.
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
1142 function set_author_class($class = 'SimplePie_Author')
1144 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1146 $this->author_class = $class;
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.
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
1161 function set_category_class($class = 'SimplePie_Category')
1163 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1165 $this->category_class = $class;
1172 * Allows you to change which class SimplePie uses for feed enclosures.
1173 * Useful when you are overloading or extending SimplePie's default classes.
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
1180 function set_enclosure_class($class = 'SimplePie_Enclosure')
1182 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1184 $this->enclosure_class = $class;
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.
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
1199 function set_caption_class($class = 'SimplePie_Caption')
1201 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1203 $this->caption_class = $class;
1210 * Allows you to change which class SimplePie uses for <media:copyright>
1211 * Useful when you are overloading or extending SimplePie's default classes.
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
1218 function set_copyright_class($class = 'SimplePie_Copyright')
1220 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1222 $this->copyright_class = $class;
1229 * Allows you to change which class SimplePie uses for <media:credit>
1230 * Useful when you are overloading or extending SimplePie's default classes.
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
1237 function set_credit_class($class = 'SimplePie_Credit')
1239 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1241 $this->credit_class = $class;
1248 * Allows you to change which class SimplePie uses for <media:rating>
1249 * Useful when you are overloading or extending SimplePie's default classes.
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
1256 function set_rating_class($class = 'SimplePie_Rating')
1258 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1260 $this->rating_class = $class;
1267 * Allows you to change which class SimplePie uses for <media:restriction>
1268 * Useful when you are overloading or extending SimplePie's default classes.
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
1275 function set_restriction_class($class = 'SimplePie_Restriction')
1277 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1279 $this->restriction_class = $class;
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.
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
1294 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1296 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1298 $this->content_type_sniffer_class = $class;
1305 * Allows you to change which class SimplePie uses item sources.
1306 * Useful when you are overloading or extending SimplePie's default classes.
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
1313 function set_source_class($class = 'SimplePie_Source')
1315 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1317 $this->source_class = $class;
1324 * Allows you to override the default user agent string.
1327 * @param string $ua New user agent string.
1329 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1331 $this->useragent = (string) $ua;
1335 * Set callback function to create cache filename with
1338 * @param mixed $function Callback function
1340 function set_cache_name_function($function = 'md5')
1342 if (is_callable($function))
1344 $this->cache_name_function = $function;
1349 * Set javascript query string parameter
1352 * @param mixed $get Javascript query string parameter
1354 function set_javascript($get = 'js')
1358 $this->javascript = (string) $get;
1362 $this->javascript = false;
1367 * Set options to make SP as fast as possible. Forgoes a
1368 * substantial amount of data sanitization in favor of speed.
1371 * @param bool $set Whether to set them or not
1373 function set_stupidly_fast($set = false)
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);
1387 * Set maximum number of feeds to check with autodiscovery
1390 * @param int $max Maximum number of feeds to check
1392 function set_max_checked_feeds($max = 10)
1394 $this->max_checked_feeds = (int) $max;
1397 function remove_div($enable = true)
1399 $this->sanitize->remove_div($enable);
1402 function strip_htmltags($tags = '', $encode = null)
1406 $tags = $this->strip_htmltags;
1408 $this->sanitize->strip_htmltags($tags);
1409 if ($encode !== null)
1411 $this->sanitize->encode_instead_of_strip($tags);
1415 function encode_instead_of_strip($enable = true)
1417 $this->sanitize->encode_instead_of_strip($enable);
1420 function strip_attributes($attribs = '')
1422 if ($attribs === '')
1424 $attribs = $this->strip_attributes;
1426 $this->sanitize->strip_attributes($attribs);
1429 function set_output_encoding($encoding = 'UTF-8')
1431 $this->sanitize->set_output_encoding($encoding);
1434 function strip_comments($strip = false)
1436 $this->sanitize->strip_comments($strip);
1440 * Set element/attribute key/value pairs of HTML attributes
1441 * containing URLs that need to be resolved relative to the feed
1445 * @param array $element_attribute Element/attribute key/value pairs
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'))
1449 $this->sanitize->set_url_replacements($element_attribute);
1453 * Set the handler to enable the display of cached favicons.
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.
1459 function set_favicon_handler($page = false, $qs = 'i')
1461 if ($page !== false)
1463 $this->favicon_handler = $page . '?' . $qs . '=';
1467 $this->favicon_handler = '';
1472 * Set the handler to enable the display of cached images.
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.
1478 function set_image_handler($page = false, $qs = 'i')
1480 if ($page !== false)
1482 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1486 $this->image_handler = '';
1491 * Set the limit for items returned per-feed with multifeeds.
1494 * @param integer $limit The maximum number of items to return.
1496 function set_item_limit($limit = 0)
1498 $this->item_limit = (int) $limit;
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'))
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'))
1511 static $xml_is_sane = null;
1512 if ($xml_is_sane === null)
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']);
1525 if (isset($_GET[$this->javascript]))
1527 SimplePie_Misc::output_javascript();
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);
1535 if ($this->feed_url !== null || $this->raw_data !== null)
1537 $this->data = array();
1538 $this->multifeed_objects = array();
1541 if ($this->feed_url !== null)
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'] !== '')
1547 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1549 // If it's enabled and we don't want an XML dump, use the cache
1550 if ($cache && !$this->xml_dump)
1553 $this->data = $cache->load();
1554 if (!empty($this->data))
1556 // If the cache is for an outdated build of SimplePie
1557 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1560 $this->data = array();
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)
1566 $this->data = array();
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']))
1571 // If the autodiscovery cache is still valid use it.
1572 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1574 // Do not need to do feed autodiscovery yet.
1575 if ($this->data['feed_url'] === $this->data['url'])
1578 $this->data = array();
1582 $this->set_feed_url($this->data['feed_url']);
1583 return $this->init();
1587 // Check if the cache has been updated
1588 elseif ($cache->mtime() + $this->cache_duration < time())
1590 // If we have last-modified and/or etag set
1591 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1594 if (isset($this->data['headers']['last-modified']))
1596 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1598 if (isset($this->data['headers']['etag']))
1600 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1602 $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1605 if ($file->status_code === 304)
1612 $headers = $file->headers;
1621 // If the cache is still valid, just return true
1627 // If the cache is empty, delete it
1631 $this->data = array();
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.
1637 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1639 $file =& $this->file;
1643 $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
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)))
1649 $this->error = $file->error;
1650 if (!empty($this->data))
1660 if (!$this->force_feed)
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))
1666 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1668 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1672 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673 if (!$cache->save($this))
1675 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1677 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1679 $this->feed_url = $file->url;
1683 $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1684 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1691 $headers = $file->headers;
1692 $data = $file->body;
1693 $sniffer = new $this->content_type_sniffer_class($file);
1694 $sniffed = $sniffer->get_type();
1698 $data = $this->raw_data;
1701 // Set up array of possible encodings
1702 $encodings = array();
1704 // First check to see if input has been overridden.
1705 if ($this->input_encoding !== false)
1707 $encodings[] = $this->input_encoding;
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');
1713 // RFC 3023 (only applies to sniffed content)
1714 if (isset($sniffed))
1716 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1718 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1720 $encodings[] = strtoupper($charset[1]);
1722 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723 $encodings[] = 'UTF-8';
1725 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1727 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1729 $encodings[] = $charset[1];
1731 $encodings[] = 'US-ASCII';
1733 // Text MIME-type default
1734 elseif (substr($sniffed, 0, 5) === 'text/')
1736 $encodings[] = 'US-ASCII';
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';
1745 // There's no point in trying an encoding twice
1746 $encodings = array_unique($encodings);
1748 // If we want the XML, just output that with the most likely encoding and quit
1749 if ($this->xml_dump)
1751 header('Content-type: text/xml; charset=' . $encodings[0]);
1756 // Loop through each possible encoding, till we return something, or run out of possibilities
1757 foreach ($encodings as $encoding)
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'))
1762 // Create new parser
1763 $parser = new $this->parser_class();
1765 // If it's parsed fine
1766 if ($parser->parse($utf8_data, 'UTF-8'))
1768 $this->data = $parser->get_data();
1769 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1771 if (isset($headers))
1773 $this->data['headers'] = $headers;
1775 $this->data['build'] = SIMPLEPIE_BUILD;
1777 // Cache the file if caching is enabled
1778 if ($cache && !$cache->save($this))
1780 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1786 $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1787 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1795 // We have an error, just set SimplePie_Misc::error to it and quit
1796 $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1800 $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1802 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1805 elseif (!empty($this->multifeed_url))
1809 $this->multifeed_objects = array();
1810 foreach ($this->multifeed_url as $url)
1814 // This keyword needs to defy coding standards for PHP4 compatibility
1815 $this->multifeed_objects[$i] = clone($this);
1819 $this->multifeed_objects[$i] = $this;
1821 $this->multifeed_objects[$i]->set_feed_url($url);
1822 $success |= $this->multifeed_objects[$i]->init();
1825 return (bool) $success;
1834 * Return the error message for the occured error
1837 * @return string Error message
1841 return $this->error;
1844 function get_encoding()
1846 return $this->sanitize->output_encoding;
1849 function handle_content_type($mime = 'text/html')
1851 if (!headers_sent())
1853 $header = "Content-type: $mime;";
1854 if ($this->get_encoding())
1856 $header .= ' charset=' . $this->get_encoding();
1860 $header .= ' charset=UTF-8';
1868 if (!isset($this->data['type']))
1870 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1873 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1875 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1877 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1879 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
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']))
1886 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
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']))
1893 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1896 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1898 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1901 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
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']))
1907 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1910 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1914 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1921 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1925 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1929 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1933 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1940 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1943 return $this->data['type'];
1947 * Returns the URL for the favicon of the feed's website.
1949 * @todo Cache atom:icon
1953 function get_favicon()
1955 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1957 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1959 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1961 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1963 if ($this->cache && $this->favicon_handler)
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');
1970 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1974 $file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
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)
1978 $sniffer = new $this->content_type_sniffer_class($file);
1979 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1981 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1983 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1987 trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1988 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2001 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
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
2012 function subscribe_url()
2014 if ($this->feed_url !== null)
2016 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2024 function subscribe_feed()
2026 if ($this->feed_url !== null)
2028 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2036 function subscribe_outlook()
2038 if ($this->feed_url !== null)
2040 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2048 function subscribe_podcast()
2050 if ($this->feed_url !== null)
2052 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2060 function subscribe_itunes()
2062 if ($this->feed_url !== null)
2064 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2073 * Creates the subscribe_* methods' return data
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
2081 function subscribe_service($feed_url, $site_url = null)
2083 if ($this->subscribe_url())
2085 $return = $feed_url . rawurlencode($this->feed_url);
2086 if ($site_url !== null && $this->get_link() !== null)
2088 $return .= $site_url . rawurlencode($this->get_link());
2090 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2098 function subscribe_aol()
2100 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2103 function subscribe_bloglines()
2105 return $this->subscribe_service('http://www.bloglines.com/sub/');
2108 function subscribe_eskobo()
2110 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2113 function subscribe_feedfeeds()
2115 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2118 function subscribe_feedster()
2120 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2123 function subscribe_google()
2125 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2128 function subscribe_gritwire()
2130 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2133 function subscribe_msn()
2135 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2138 function subscribe_netvibes()
2140 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2143 function subscribe_newsburst()
2145 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2148 function subscribe_newsgator()
2150 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2153 function subscribe_odeo()
2155 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2158 function subscribe_podnova()
2160 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2163 function subscribe_rojo()
2165 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2168 function subscribe_yahoo()
2170 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2173 function get_feed_tags($namespace, $tag)
2175 $type = $this->get_type();
2176 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2178 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2180 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2183 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2185 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2187 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2190 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2192 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2194 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2197 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2199 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2201 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2207 function get_channel_tags($namespace, $tag)
2209 $type = $this->get_type();
2210 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2212 if ($return = $this->get_feed_tags($namespace, $tag))
2217 if ($type & SIMPLEPIE_TYPE_RSS_10)
2219 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2221 if (isset($channel[0]['child'][$namespace][$tag]))
2223 return $channel[0]['child'][$namespace][$tag];
2227 if ($type & SIMPLEPIE_TYPE_RSS_090)
2229 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2231 if (isset($channel[0]['child'][$namespace][$tag]))
2233 return $channel[0]['child'][$namespace][$tag];
2237 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2239 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2241 if (isset($channel[0]['child'][$namespace][$tag]))
2243 return $channel[0]['child'][$namespace][$tag];
2250 function get_image_tags($namespace, $tag)
2252 $type = $this->get_type();
2253 if ($type & SIMPLEPIE_TYPE_RSS_10)
2255 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2257 if (isset($image[0]['child'][$namespace][$tag]))
2259 return $image[0]['child'][$namespace][$tag];
2263 if ($type & SIMPLEPIE_TYPE_RSS_090)
2265 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2267 if (isset($image[0]['child'][$namespace][$tag]))
2269 return $image[0]['child'][$namespace][$tag];
2273 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2275 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2277 if (isset($image[0]['child'][$namespace][$tag]))
2279 return $image[0]['child'][$namespace][$tag];
2286 function get_base($element = array())
2288 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2290 return $element['xml_base'];
2292 elseif ($this->get_link() !== null)
2294 return $this->get_link();
2298 return $this->subscribe_url();
2302 function sanitize($data, $type, $base = '')
2304 return $this->sanitize->sanitize($data, $type, $base);
2307 function get_title()
2309 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2311 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2313 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2315 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2317 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2319 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2321 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2323 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2325 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2327 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2329 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2331 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2333 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2335 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2343 function get_category($key = 0)
2345 $categories = $this->get_categories();
2346 if (isset($categories[$key]))
2348 return $categories[$key];
2356 function get_categories()
2358 $categories = array();
2360 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2365 if (isset($category['attribs']['']['term']))
2367 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2369 if (isset($category['attribs']['']['scheme']))
2371 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2373 if (isset($category['attribs']['']['label']))
2375 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2377 $categories[] = new $this->category_class($term, $scheme, $label);
2379 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
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']))
2386 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2392 $categories[] = new $this->category_class($term, $scheme, null);
2394 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2396 $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2398 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2400 $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2403 if (!empty($categories))
2405 return SimplePie_Misc::array_unique($categories);
2413 function get_author($key = 0)
2415 $authors = $this->get_authors();
2416 if (isset($authors[$key]))
2418 return $authors[$key];
2426 function get_authors()
2429 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2437 $avatar_date = null;
2439 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2441 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2443 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2445 $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]));
2447 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2449 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2451 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
2453 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
2455 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
2457 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
2459 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
2461 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
2463 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
2465 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
2468 if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
2470 $authors[] = new $this->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
2473 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2478 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2480 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2482 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2484 $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]));
2486 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2488 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2490 if ($name !== null || $email !== null || $url !== null)
2492 $authors[] = new $this->author_class($name, $url, $email);
2495 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2497 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2499 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2501 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2503 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2505 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2508 if (!empty($authors))
2510 return SimplePie_Misc::array_unique($authors);
2518 function get_contributor($key = 0)
2520 $contributors = $this->get_contributors();
2521 if (isset($contributors[$key]))
2523 return $contributors[$key];
2531 function get_contributors()
2533 $contributors = array();
2534 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2539 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2541 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2543 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2545 $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]));
2547 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2549 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2551 if ($name !== null || $email !== null || $uri !== null)
2553 $contributors[] = new $this->author_class($name, $uri, $email);
2556 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2561 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2563 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2565 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2567 $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]));
2569 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2571 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2573 if ($name !== null || $email !== null || $url !== null)
2575 $contributors[] = new $this->author_class($name, $url, $email);
2579 if (!empty($contributors))
2581 return SimplePie_Misc::array_unique($contributors);
2589 function get_link($key = 0, $rel = 'alternate')
2591 $links = $this->get_links($rel);
2592 if (isset($links[$key]))
2594 return $links[$key];
2603 * Added for parity between the parent-level and the item/entry-level.
2605 function get_permalink()
2607 return $this->get_link(0);
2610 function get_links($rel = 'alternate')
2612 if (!isset($this->data['links']))
2614 $this->data['links'] = array();
2615 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2617 foreach ($links as $link)
2619 if (isset($link['attribs']['']['href']))
2621 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2622 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2626 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2628 foreach ($links as $link)
2630 if (isset($link['attribs']['']['href']))
2632 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2633 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2638 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2640 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2642 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2644 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2646 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2648 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2651 $keys = array_keys($this->data['links']);
2652 foreach ($keys as $key)
2654 if (SimplePie_Misc::is_isegment_nz_nc($key))
2656 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2658 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2659 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2663 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2666 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2668 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2670 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2674 if (isset($this->data['links'][$rel]))
2676 return $this->data['links'][$rel];
2684 function get_all_discovered_feeds()
2686 return $this->all_discovered_feeds;
2689 function get_description()
2691 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2693 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2695 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2697 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2699 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2701 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2703 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2705 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2707 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2709 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2711 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2713 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2715 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2717 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2719 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2721 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2723 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2725 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2733 function get_copyright()
2735 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2737 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2739 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2741 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2743 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2745 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2747 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2749 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2751 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2753 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2761 function get_language()
2763 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2765 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2767 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2769 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2771 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2773 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2775 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2777 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2779 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2781 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2783 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2785 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2787 elseif (isset($this->data['headers']['content-language']))
2789 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2797 function get_latitude()
2800 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2802 return (float) $return[0]['data'];
2804 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2806 return (float) $match[1];
2814 function get_longitude()
2816 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2818 return (float) $return[0]['data'];
2820 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2822 return (float) $return[0]['data'];
2824 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2826 return (float) $match[2];
2834 function get_image_title()
2836 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2838 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2840 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2842 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2844 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2846 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2848 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2850 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2852 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2854 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2862 function get_image_url()
2864 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2866 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2868 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2870 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2872 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2874 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2876 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2878 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2880 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2882 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2884 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2886 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2894 function get_image_link()
2896 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2898 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2900 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2902 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2904 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2906 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2914 function get_image_width()
2916 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2918 return round($return[0]['data']);
2920 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2930 function get_image_height()
2932 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2934 return round($return[0]['data']);
2936 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2946 function get_item_quantity($max = 0)
2949 $qty = count($this->get_items());
2956 return ($qty > $max) ? $max : $qty;
2960 function get_item($key = 0)
2962 $items = $this->get_items();
2963 if (isset($items[$key]))
2965 return $items[$key];
2973 function get_items($start = 0, $end = 0)
2975 if (!isset($this->data['items']))
2977 if (!empty($this->multifeed_objects))
2979 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2983 $this->data['items'] = array();
2984 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2986 $keys = array_keys($items);
2987 foreach ($keys as $key)
2989 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2992 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2994 $keys = array_keys($items);
2995 foreach ($keys as $key)
2997 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3000 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
3002 $keys = array_keys($items);
3003 foreach ($keys as $key)
3005 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3008 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
3010 $keys = array_keys($items);
3011 foreach ($keys as $key)
3013 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3016 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
3018 $keys = array_keys($items);
3019 foreach ($keys as $key)
3021 $this->data['items'][] = new $this->item_class($this, $items[$key]);
3027 if (!empty($this->data['items']))
3029 // If we want to order it by date, check if all items have a date, and then sort it
3030 if ($this->order_by_date && empty($this->multifeed_objects))
3032 if (!isset($this->data['ordered_items']))
3035 foreach ($this->data['items'] as $item)
3037 if (!$item->get_date('U'))
3044 $this->data['ordered_items'] = $this->data['items'];
3047 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3050 $items = $this->data['ordered_items'];
3054 $items = $this->data['items'];
3057 // Slice the data as desired
3060 return array_slice($items, $start);
3064 return array_slice($items, $start, $end);
3076 function sort_items($a, $b)
3078 return $a->get_date('U') <= $b->get_date('U');
3084 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3086 if (is_array($urls) && sizeof($urls) > 0)
3089 foreach ($urls as $arg)
3091 if (is_a($arg, 'SimplePie'))
3093 $items = array_merge($items, $arg->get_items(0, $limit));
3097 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3102 foreach ($items as $item)
3104 if (!$item->get_date('U'))
3113 usort($items, array('SimplePie', 'sort_items'));
3118 return array_slice($items, $start);
3122 return array_slice($items, $start, $end);
3127 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3133 class SimplePie_Item
3136 var $data = array();
3138 function SimplePie_Item($feed, $data)
3140 $this->feed = $feed;
3141 $this->data = $data;
3144 function __toString()
3146 return md5(serialize($this->data));
3150 * Remove items that link back to this before destroying this object
3152 function __destruct()
3154 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3160 function get_item_tags($namespace, $tag)
3162 if (isset($this->data['child'][$namespace][$tag]))
3164 return $this->data['child'][$namespace][$tag];
3172 function get_base($element = array())
3174 return $this->feed->get_base($element);
3177 function sanitize($data, $type, $base = '')
3179 return $this->feed->sanitize($data, $type, $base);
3187 function get_id($hash = false)
3191 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3193 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3195 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3197 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3199 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3201 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3203 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3205 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3207 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3209 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3211 elseif (($return = $this->get_permalink()) !== null)
3215 elseif (($return = $this->get_title()) !== null)
3220 if ($this->get_permalink() !== null || $this->get_title() !== null)
3222 return md5($this->get_permalink() . $this->get_title());
3226 return md5(serialize($this->data));
3230 function get_title()
3232 if (!isset($this->data['title']))
3234 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3236 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3238 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3240 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3242 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3244 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3246 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3248 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3250 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3252 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3254 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3256 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3258 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3260 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3264 $this->data['title'] = null;
3267 return $this->data['title'];
3270 function get_description($description_only = false)
3272 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3274 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3276 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3278 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3280 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3282 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3284 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3286 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3288 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3290 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3292 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3294 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3296 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3298 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3300 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3302 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3304 elseif (!$description_only)
3306 return $this->get_content(true);
3314 function get_content($content_only = false)
3316 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3318 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3320 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3322 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3324 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3326 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3328 elseif (!$content_only)
3330 return $this->get_description(true);
3338 function get_category($key = 0)
3340 $categories = $this->get_categories();
3341 if (isset($categories[$key]))
3343 return $categories[$key];
3351 function get_categories()
3353 $categories = array();
3355 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3360 if (isset($category['attribs']['']['term']))
3362 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3364 if (isset($category['attribs']['']['scheme']))
3366 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3368 if (isset($category['attribs']['']['label']))
3370 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3372 $categories[] = new $this->feed->category_class($term, $scheme, $label);
3374 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3376 // This is really the label, but keep this as the term also for BC.
3377 // Label will also work on retrieving because that falls back to term.
3378 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3379 if (isset($category['attribs']['']['domain']))
3381 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3387 $categories[] = new $this->feed->category_class($term, $scheme, null);
3389 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3391 $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3393 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3395 $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3398 if (!empty($categories))
3400 return SimplePie_Misc::array_unique($categories);
3408 function get_author($key = 0)
3410 $authors = $this->get_authors();
3411 if (isset($authors[$key]))
3413 return $authors[$key];
3421 function get_contributor($key = 0)
3423 $contributors = $this->get_contributors();
3424 if (isset($contributors[$key]))
3426 return $contributors[$key];
3434 function get_contributors()
3436 $contributors = array();
3437 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3442 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3444 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3446 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3448 $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]));
3450 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3452 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3454 if ($name !== null || $email !== null || $uri !== null)
3456 $contributors[] = new $this->feed->author_class($name, $uri, $email);
3459 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3464 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3466 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3468 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3470 $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]));
3472 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3474 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3476 if ($name !== null || $email !== null || $url !== null)
3478 $contributors[] = new $this->feed->author_class($name, $url, $email);
3482 if (!empty($contributors))
3484 return SimplePie_Misc::array_unique($contributors);
3492 function get_authors()
3495 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3503 $avatar_date = null;
3504 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3506 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3508 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3510 $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]));
3512 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3514 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3516 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
3518 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
3520 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
3522 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
3524 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
3526 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
3528 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
3530 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
3533 if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
3535 $authors[] = new $this->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
3538 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3543 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3545 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3547 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3549 $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]));
3551 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3553 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3555 if ($name !== null || $email !== null || $url !== null)
3557 $authors[] = new $this->feed->author_class($name, $url, $email);
3560 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3562 $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3564 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3566 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3568 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3570 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3572 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3574 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3577 if (!empty($authors))
3579 return SimplePie_Misc::array_unique($authors);
3581 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3585 elseif ($authors = $this->feed->get_authors())
3595 function get_copyright()
3597 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3599 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3601 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3603 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3605 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3607 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3615 function get_date($date_format = 'j F Y, g:i a')
3617 if (!isset($this->data['date']))
3619 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3621 $this->data['date']['raw'] = $return[0]['data'];
3623 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3625 $this->data['date']['raw'] = $return[0]['data'];
3627 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3629 $this->data['date']['raw'] = $return[0]['data'];
3631 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3633 $this->data['date']['raw'] = $return[0]['data'];
3635 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3637 $this->data['date']['raw'] = $return[0]['data'];
3639 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3641 $this->data['date']['raw'] = $return[0]['data'];
3643 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3645 $this->data['date']['raw'] = $return[0]['data'];
3647 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3649 $this->data['date']['raw'] = $return[0]['data'];
3652 if (!empty($this->data['date']['raw']))
3654 $parser = SimplePie_Parse_Date::get();
3655 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3659 $this->data['date'] = null;
3662 if ($this->data['date'])
3664 $date_format = (string) $date_format;
3665 switch ($date_format)
3668 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3671 return $this->data['date']['parsed'];
3674 return date($date_format, $this->data['date']['parsed']);
3683 function get_local_date($date_format = '%c')
3687 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3689 elseif (($date = $this->get_date('U')) !== null)
3691 return strftime($date_format, $date);
3699 function get_permalink()
3701 $link = $this->get_link();
3702 $enclosure = $this->get_enclosure(0);
3707 elseif ($enclosure !== null)
3709 return $enclosure->get_link();
3717 function get_link($key = 0, $rel = 'alternate')
3719 $links = $this->get_links($rel);
3720 if ($links[$key] !== null)
3722 return $links[$key];
3730 function get_links($rel = 'alternate')
3732 if (!isset($this->data['links']))
3734 $this->data['links'] = array();
3735 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3737 if (isset($link['attribs']['']['href']))
3739 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3740 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3744 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3746 if (isset($link['attribs']['']['href']))
3748 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3749 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3752 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3754 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3756 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3758 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3760 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3762 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3764 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3766 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3768 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3772 $keys = array_keys($this->data['links']);
3773 foreach ($keys as $key)
3775 if (SimplePie_Misc::is_isegment_nz_nc($key))
3777 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3779 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3780 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3784 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3787 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3789 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3791 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3794 if (isset($this->data['links'][$rel]))
3796 return $this->data['links'][$rel];
3805 * @todo Add ability to prefer one type of content over another (in a media group).
3807 function get_enclosure($key = 0, $prefer = null)
3809 $enclosures = $this->get_enclosures();
3810 if (isset($enclosures[$key]))
3812 return $enclosures[$key];
3821 * Grabs all available enclosures (podcasts, etc.)
3823 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3825 * At this point, we're pretty much assuming that all enclosures for an item are the same content. Anything else is too complicated to properly support.
3827 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3828 * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
3830 function get_enclosures()
3832 if (!isset($this->data['enclosures']))
3834 $this->data['enclosures'] = array();
3837 $captions_parent = null;
3838 $categories_parent = null;
3839 $copyrights_parent = null;
3840 $credits_parent = null;
3841 $description_parent = null;
3842 $duration_parent = null;
3843 $hashes_parent = null;
3844 $keywords_parent = null;
3845 $player_parent = null;
3846 $ratings_parent = null;
3847 $restrictions_parent = null;
3848 $thumbnails_parent = null;
3849 $title_parent = null;
3851 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3852 $parent = $this->get_feed();
3855 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3857 foreach ($captions as $caption)
3859 $caption_type = null;
3860 $caption_lang = null;
3861 $caption_startTime = null;
3862 $caption_endTime = null;
3863 $caption_text = null;
3864 if (isset($caption['attribs']['']['type']))
3866 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3868 if (isset($caption['attribs']['']['lang']))
3870 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3872 if (isset($caption['attribs']['']['start']))
3874 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3876 if (isset($caption['attribs']['']['end']))
3878 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3880 if (isset($caption['data']))
3882 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3884 $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3887 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3889 foreach ($captions as $caption)
3891 $caption_type = null;
3892 $caption_lang = null;
3893 $caption_startTime = null;
3894 $caption_endTime = null;
3895 $caption_text = null;
3896 if (isset($caption['attribs']['']['type']))
3898 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3900 if (isset($caption['attribs']['']['lang']))
3902 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3904 if (isset($caption['attribs']['']['start']))
3906 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3908 if (isset($caption['attribs']['']['end']))
3910 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3912 if (isset($caption['data']))
3914 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3916 $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3919 if (is_array($captions_parent))
3921 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3925 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3930 if (isset($category['data']))
3932 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3934 if (isset($category['attribs']['']['scheme']))
3936 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3940 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3942 if (isset($category['attribs']['']['label']))
3944 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3946 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3948 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3953 if (isset($category['data']))
3955 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3957 if (isset($category['attribs']['']['scheme']))
3959 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3963 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3965 if (isset($category['attribs']['']['label']))
3967 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3969 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3971 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3974 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3976 if (isset($category['attribs']['']['text']))
3978 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3980 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3982 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3984 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3986 if (isset($subcategory['attribs']['']['text']))
3988 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3990 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3994 if (is_array($categories_parent))
3996 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
4000 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4002 $copyright_url = null;
4003 $copyright_label = null;
4004 if (isset($copyright[0]['attribs']['']['url']))
4006 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4008 if (isset($copyright[0]['data']))
4010 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4012 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
4014 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
4016 $copyright_url = null;
4017 $copyright_label = null;
4018 if (isset($copyright[0]['attribs']['']['url']))
4020 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4022 if (isset($copyright[0]['data']))
4024 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4026 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
4030 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4032 foreach ($credits as $credit)
4034 $credit_role = null;
4035 $credit_scheme = null;
4036 $credit_name = null;
4037 if (isset($credit['attribs']['']['role']))
4039 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4041 if (isset($credit['attribs']['']['scheme']))
4043 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4047 $credit_scheme = 'urn:ebu';
4049 if (isset($credit['data']))
4051 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4053 $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4056 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4058 foreach ($credits as $credit)
4060 $credit_role = null;
4061 $credit_scheme = null;
4062 $credit_name = null;
4063 if (isset($credit['attribs']['']['role']))
4065 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4067 if (isset($credit['attribs']['']['scheme']))
4069 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4073 $credit_scheme = 'urn:ebu';
4075 if (isset($credit['data']))
4077 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4079 $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4082 if (is_array($credits_parent))
4084 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4088 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4090 if (isset($description_parent[0]['data']))
4092 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4095 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4097 if (isset($description_parent[0]['data']))
4099 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4104 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4109 if (isset($duration_parent[0]['data']))
4111 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4112 if (sizeof($temp) > 0)
4114 (int) $seconds = array_pop($temp);
4116 if (sizeof($temp) > 0)
4118 (int) $minutes = array_pop($temp);
4119 $seconds += $minutes * 60;
4121 if (sizeof($temp) > 0)
4123 (int) $hours = array_pop($temp);
4124 $seconds += $hours * 3600;
4127 $duration_parent = $seconds;
4132 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4134 foreach ($hashes_iterator as $hash)
4138 if (isset($hash['data']))
4140 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4142 if (isset($hash['attribs']['']['algo']))
4144 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4150 $hashes_parent[] = $algo.':'.$value;
4153 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4155 foreach ($hashes_iterator as $hash)
4159 if (isset($hash['data']))
4161 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4163 if (isset($hash['attribs']['']['algo']))
4165 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4171 $hashes_parent[] = $algo.':'.$value;
4174 if (is_array($hashes_parent))
4176 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4180 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4182 if (isset($keywords[0]['data']))
4184 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4185 foreach ($temp as $word)
4187 $keywords_parent[] = trim($word);
4192 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4194 if (isset($keywords[0]['data']))
4196 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4197 foreach ($temp as $word)
4199 $keywords_parent[] = trim($word);
4204 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4206 if (isset($keywords[0]['data']))
4208 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4209 foreach ($temp as $word)
4211 $keywords_parent[] = trim($word);
4216 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4218 if (isset($keywords[0]['data']))
4220 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4221 foreach ($temp as $word)
4223 $keywords_parent[] = trim($word);
4228 if (is_array($keywords_parent))
4230 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4234 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4236 if (isset($player_parent[0]['attribs']['']['url']))
4238 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4241 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4243 if (isset($player_parent[0]['attribs']['']['url']))
4245 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4250 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4252 foreach ($ratings as $rating)
4254 $rating_scheme = null;
4255 $rating_value = null;
4256 if (isset($rating['attribs']['']['scheme']))
4258 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4262 $rating_scheme = 'urn:simple';
4264 if (isset($rating['data']))
4266 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4268 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4271 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4273 foreach ($ratings as $rating)
4275 $rating_scheme = 'urn:itunes';
4276 $rating_value = null;
4277 if (isset($rating['data']))
4279 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4281 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4284 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4286 foreach ($ratings as $rating)
4288 $rating_scheme = null;
4289 $rating_value = null;
4290 if (isset($rating['attribs']['']['scheme']))
4292 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4296 $rating_scheme = 'urn:simple';
4298 if (isset($rating['data']))
4300 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4302 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4305 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4307 foreach ($ratings as $rating)
4309 $rating_scheme = 'urn:itunes';
4310 $rating_value = null;
4311 if (isset($rating['data']))
4313 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4315 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4318 if (is_array($ratings_parent))
4320 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4324 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4326 foreach ($restrictions as $restriction)
4328 $restriction_relationship = null;
4329 $restriction_type = null;
4330 $restriction_value = null;
4331 if (isset($restriction['attribs']['']['relationship']))
4333 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4335 if (isset($restriction['attribs']['']['type']))
4337 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4339 if (isset($restriction['data']))
4341 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4343 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4346 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4348 foreach ($restrictions as $restriction)
4350 $restriction_relationship = 'allow';
4351 $restriction_type = null;
4352 $restriction_value = 'itunes';
4353 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4355 $restriction_relationship = 'deny';
4357 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4360 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4362 foreach ($restrictions as $restriction)
4364 $restriction_relationship = null;
4365 $restriction_type = null;
4366 $restriction_value = null;
4367 if (isset($restriction['attribs']['']['relationship']))
4369 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4371 if (isset($restriction['attribs']['']['type']))
4373 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4375 if (isset($restriction['data']))
4377 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4379 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4382 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4384 foreach ($restrictions as $restriction)
4386 $restriction_relationship = 'allow';
4387 $restriction_type = null;
4388 $restriction_value = 'itunes';
4389 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4391 $restriction_relationship = 'deny';
4393 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4396 if (is_array($restrictions_parent))
4398 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4402 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4404 foreach ($thumbnails as $thumbnail)
4406 if (isset($thumbnail['attribs']['']['url']))
4408 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4412 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4414 foreach ($thumbnails as $thumbnail)
4416 if (isset($thumbnail['attribs']['']['url']))
4418 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4424 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4426 if (isset($title_parent[0]['data']))
4428 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4431 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4433 if (isset($title_parent[0]['data']))
4435 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4453 $samplingrate = null;
4463 $description = null;
4468 $restrictions = null;
4472 // If we have media:group tags, loop through them.
4473 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4475 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4477 // If we have media:content tags, loop through them.
4478 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4480 if (isset($content['attribs']['']['url']))
4493 $samplingrate = null;
4503 $description = null;
4508 $restrictions = null;
4512 // Start checking the attributes of media:content
4513 if (isset($content['attribs']['']['bitrate']))
4515 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4517 if (isset($content['attribs']['']['channels']))
4519 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4521 if (isset($content['attribs']['']['duration']))
4523 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4527 $duration = $duration_parent;
4529 if (isset($content['attribs']['']['expression']))
4531 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4533 if (isset($content['attribs']['']['framerate']))
4535 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4537 if (isset($content['attribs']['']['height']))
4539 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4541 if (isset($content['attribs']['']['lang']))
4543 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4545 if (isset($content['attribs']['']['fileSize']))
4547 $length = ceil($content['attribs']['']['fileSize']);
4549 if (isset($content['attribs']['']['medium']))
4551 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4553 if (isset($content['attribs']['']['samplingrate']))
4555 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4557 if (isset($content['attribs']['']['type']))
4559 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4561 if (isset($content['attribs']['']['width']))
4563 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4565 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4567 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4570 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4572 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4574 $caption_type = null;
4575 $caption_lang = null;
4576 $caption_startTime = null;
4577 $caption_endTime = null;
4578 $caption_text = null;
4579 if (isset($caption['attribs']['']['type']))
4581 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4583 if (isset($caption['attribs']['']['lang']))
4585 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4587 if (isset($caption['attribs']['']['start']))
4589 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4591 if (isset($caption['attribs']['']['end']))
4593 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4595 if (isset($caption['data']))
4597 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4599 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4601 if (is_array($captions))
4603 $captions = array_values(SimplePie_Misc::array_unique($captions));
4606 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4608 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4610 $caption_type = null;
4611 $caption_lang = null;
4612 $caption_startTime = null;
4613 $caption_endTime = null;
4614 $caption_text = null;
4615 if (isset($caption['attribs']['']['type']))
4617 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4619 if (isset($caption['attribs']['']['lang']))
4621 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4623 if (isset($caption['attribs']['']['start']))
4625 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4627 if (isset($caption['attribs']['']['end']))
4629 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4631 if (isset($caption['data']))
4633 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4635 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4637 if (is_array($captions))
4639 $captions = array_values(SimplePie_Misc::array_unique($captions));
4644 $captions = $captions_parent;
4648 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4650 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4655 if (isset($category['data']))
4657 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4659 if (isset($category['attribs']['']['scheme']))
4661 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4665 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4667 if (isset($category['attribs']['']['label']))
4669 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4671 $categories[] = new $this->feed->category_class($term, $scheme, $label);
4674 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4676 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4681 if (isset($category['data']))
4683 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4685 if (isset($category['attribs']['']['scheme']))
4687 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4691 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4693 if (isset($category['attribs']['']['label']))
4695 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4697 $categories[] = new $this->feed->category_class($term, $scheme, $label);
4700 if (is_array($categories) && is_array($categories_parent))
4702 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4704 elseif (is_array($categories))
4706 $categories = array_values(SimplePie_Misc::array_unique($categories));
4708 elseif (is_array($categories_parent))
4710 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4714 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4716 $copyright_url = null;
4717 $copyright_label = null;
4718 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4720 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4722 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4724 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4726 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4728 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4730 $copyright_url = null;
4731 $copyright_label = null;
4732 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4734 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4736 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4738 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4740 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4744 $copyrights = $copyrights_parent;
4748 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4750 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4752 $credit_role = null;
4753 $credit_scheme = null;
4754 $credit_name = null;
4755 if (isset($credit['attribs']['']['role']))
4757 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4759 if (isset($credit['attribs']['']['scheme']))
4761 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4765 $credit_scheme = 'urn:ebu';
4767 if (isset($credit['data']))
4769 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4771 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4773 if (is_array($credits))
4775 $credits = array_values(SimplePie_Misc::array_unique($credits));
4778 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4780 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4782 $credit_role = null;
4783 $credit_scheme = null;
4784 $credit_name = null;
4785 if (isset($credit['attribs']['']['role']))
4787 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4789 if (isset($credit['attribs']['']['scheme']))
4791 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4795 $credit_scheme = 'urn:ebu';
4797 if (isset($credit['data']))
4799 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4801 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4803 if (is_array($credits))
4805 $credits = array_values(SimplePie_Misc::array_unique($credits));
4810 $credits = $credits_parent;
4814 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4816 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4818 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4820 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4824 $description = $description_parent;
4828 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4830 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4834 if (isset($hash['data']))
4836 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4838 if (isset($hash['attribs']['']['algo']))
4840 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4846 $hashes[] = $algo.':'.$value;
4848 if (is_array($hashes))
4850 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4853 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4855 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4859 if (isset($hash['data']))
4861 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4863 if (isset($hash['attribs']['']['algo']))
4865 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4871 $hashes[] = $algo.':'.$value;
4873 if (is_array($hashes))
4875 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4880 $hashes = $hashes_parent;
4884 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4886 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4888 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4889 foreach ($temp as $word)
4891 $keywords[] = trim($word);
4895 if (is_array($keywords))
4897 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4900 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4902 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4904 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4905 foreach ($temp as $word)
4907 $keywords[] = trim($word);
4911 if (is_array($keywords))
4913 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4918 $keywords = $keywords_parent;
4922 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4924 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4926 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4928 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4932 $player = $player_parent;
4936 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4938 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4940 $rating_scheme = null;
4941 $rating_value = null;
4942 if (isset($rating['attribs']['']['scheme']))
4944 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4948 $rating_scheme = 'urn:simple';
4950 if (isset($rating['data']))
4952 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4954 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4956 if (is_array($ratings))
4958 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4961 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4963 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4965 $rating_scheme = null;
4966 $rating_value = null;
4967 if (isset($rating['attribs']['']['scheme']))
4969 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4973 $rating_scheme = 'urn:simple';
4975 if (isset($rating['data']))
4977 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4979 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4981 if (is_array($ratings))
4983 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4988 $ratings = $ratings_parent;
4992 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4994 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4996 $restriction_relationship = null;
4997 $restriction_type = null;
4998 $restriction_value = null;
4999 if (isset($restriction['attribs']['']['relationship']))
5001 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5003 if (isset($restriction['attribs']['']['type']))
5005 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5007 if (isset($restriction['data']))
5009 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5011 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5013 if (is_array($restrictions))
5015 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5018 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5020 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5022 $restriction_relationship = null;
5023 $restriction_type = null;
5024 $restriction_value = null;
5025 if (isset($restriction['attribs']['']['relationship']))
5027 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5029 if (isset($restriction['attribs']['']['type']))
5031 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5033 if (isset($restriction['data']))
5035 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5037 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5039 if (is_array($restrictions))
5041 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5046 $restrictions = $restrictions_parent;
5050 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5052 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5054 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5056 if (is_array($thumbnails))
5058 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5061 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5063 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5065 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5067 if (is_array($thumbnails))
5069 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5074 $thumbnails = $thumbnails_parent;
5078 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5080 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5082 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5084 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5088 $title = $title_parent;
5091 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5097 // If we have standalone media:content tags, loop through them.
5098 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5100 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5102 if (isset($content['attribs']['']['url']))
5115 $samplingrate = null;
5125 $description = null;
5130 $restrictions = null;
5134 // Start checking the attributes of media:content
5135 if (isset($content['attribs']['']['bitrate']))
5137 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5139 if (isset($content['attribs']['']['channels']))
5141 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5143 if (isset($content['attribs']['']['duration']))
5145 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5149 $duration = $duration_parent;
5151 if (isset($content['attribs']['']['expression']))
5153 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5155 if (isset($content['attribs']['']['framerate']))
5157 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5159 if (isset($content['attribs']['']['height']))
5161 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5163 if (isset($content['attribs']['']['lang']))
5165 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5167 if (isset($content['attribs']['']['fileSize']))
5169 $length = ceil($content['attribs']['']['fileSize']);
5171 if (isset($content['attribs']['']['medium']))
5173 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5175 if (isset($content['attribs']['']['samplingrate']))
5177 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5179 if (isset($content['attribs']['']['type']))
5181 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5183 if (isset($content['attribs']['']['width']))
5185 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5187 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5189 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5192 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5194 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5196 $caption_type = null;
5197 $caption_lang = null;
5198 $caption_startTime = null;
5199 $caption_endTime = null;
5200 $caption_text = null;
5201 if (isset($caption['attribs']['']['type']))
5203 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5205 if (isset($caption['attribs']['']['lang']))
5207 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5209 if (isset($caption['attribs']['']['start']))
5211 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5213 if (isset($caption['attribs']['']['end']))
5215 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5217 if (isset($caption['data']))
5219 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5221 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5223 if (is_array($captions))
5225 $captions = array_values(SimplePie_Misc::array_unique($captions));
5230 $captions = $captions_parent;
5234 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5236 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5241 if (isset($category['data']))
5243 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5245 if (isset($category['attribs']['']['scheme']))
5247 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5251 $scheme = 'http://search.yahoo.com/mrss/category_schema';
5253 if (isset($category['attribs']['']['label']))
5255 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5257 $categories[] = new $this->feed->category_class($term, $scheme, $label);
5260 if (is_array($categories) && is_array($categories_parent))
5262 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5264 elseif (is_array($categories))
5266 $categories = array_values(SimplePie_Misc::array_unique($categories));
5268 elseif (is_array($categories_parent))
5270 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5278 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5280 $copyright_url = null;
5281 $copyright_label = null;
5282 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5284 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5286 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5288 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5290 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
5294 $copyrights = $copyrights_parent;
5298 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5300 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5302 $credit_role = null;
5303 $credit_scheme = null;
5304 $credit_name = null;
5305 if (isset($credit['attribs']['']['role']))
5307 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5309 if (isset($credit['attribs']['']['scheme']))
5311 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5315 $credit_scheme = 'urn:ebu';
5317 if (isset($credit['data']))
5319 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5321 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5323 if (is_array($credits))
5325 $credits = array_values(SimplePie_Misc::array_unique($credits));
5330 $credits = $credits_parent;
5334 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5336 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5340 $description = $description_parent;
5344 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5346 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5350 if (isset($hash['data']))
5352 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5354 if (isset($hash['attribs']['']['algo']))
5356 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5362 $hashes[] = $algo.':'.$value;
5364 if (is_array($hashes))
5366 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5371 $hashes = $hashes_parent;
5375 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5377 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5379 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5380 foreach ($temp as $word)
5382 $keywords[] = trim($word);
5386 if (is_array($keywords))
5388 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5393 $keywords = $keywords_parent;
5397 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5399 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5403 $player = $player_parent;
5407 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5409 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5411 $rating_scheme = null;
5412 $rating_value = null;
5413 if (isset($rating['attribs']['']['scheme']))
5415 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5419 $rating_scheme = 'urn:simple';
5421 if (isset($rating['data']))
5423 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5425 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
5427 if (is_array($ratings))
5429 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5434 $ratings = $ratings_parent;
5438 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5440 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5442 $restriction_relationship = null;
5443 $restriction_type = null;
5444 $restriction_value = null;
5445 if (isset($restriction['attribs']['']['relationship']))
5447 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5449 if (isset($restriction['attribs']['']['type']))
5451 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5453 if (isset($restriction['data']))
5455 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5457 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5459 if (is_array($restrictions))
5461 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5466 $restrictions = $restrictions_parent;
5470 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5472 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5474 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5476 if (is_array($thumbnails))
5478 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5483 $thumbnails = $thumbnails_parent;
5487 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5489 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5493 $title = $title_parent;
5496 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5501 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5503 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5516 $samplingrate = null;
5521 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5522 if (isset($link['attribs']['']['type']))
5524 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5526 if (isset($link['attribs']['']['length']))
5528 $length = ceil($link['attribs']['']['length']);
5531 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5532 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5536 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5538 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5551 $samplingrate = null;
5556 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5557 if (isset($link['attribs']['']['type']))
5559 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5561 if (isset($link['attribs']['']['length']))
5563 $length = ceil($link['attribs']['']['length']);
5566 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5567 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5571 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5573 if (isset($enclosure[0]['attribs']['']['url']))
5586 $samplingrate = null;
5591 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5592 if (isset($enclosure[0]['attribs']['']['type']))
5594 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5596 if (isset($enclosure[0]['attribs']['']['length']))
5598 $length = ceil($enclosure[0]['attribs']['']['length']);
5601 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5602 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5606 if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
5608 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5609 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5612 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5614 if (!empty($this->data['enclosures']))
5616 return $this->data['enclosures'];
5624 function get_latitude()
5626 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5628 return (float) $return[0]['data'];
5630 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5632 return (float) $match[1];
5640 function get_longitude()
5642 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5644 return (float) $return[0]['data'];
5646 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5648 return (float) $return[0]['data'];
5650 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5652 return (float) $match[2];
5660 function get_source()
5662 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5664 return new $this->feed->source_class($this, $return[0]);
5673 * Creates the add_to_* methods' return data
5676 * @param string $item_url String to prefix to the item permalink
5677 * @param string $title_url String to prefix to the item title
5678 * (and suffix to the item permalink)
5679 * @return mixed URL if feed exists, false otherwise
5681 function add_to_service($item_url, $title_url = null, $summary_url = null)
5683 if ($this->get_permalink() !== null)
5685 $return = $item_url . rawurlencode($this->get_permalink());
5686 if ($title_url !== null && $this->get_title() !== null)
5688 $return .= $title_url . rawurlencode($this->get_title());
5690 if ($summary_url !== null && $this->get_description() !== null)
5692 $return .= $summary_url . rawurlencode($this->get_description());
5694 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5702 function add_to_blinklist()
5704 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5707 function add_to_blogmarks()
5709 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5712 function add_to_delicious()
5714 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5717 function add_to_digg()
5719 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5722 function add_to_furl()
5724 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5727 function add_to_magnolia()
5729 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5732 function add_to_myweb20()
5734 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5737 function add_to_newsvine()
5739 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5742 function add_to_reddit()
5744 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5747 function add_to_segnalo()
5749 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5752 function add_to_simpy()
5754 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5757 function add_to_spurl()
5759 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5762 function add_to_wists()
5764 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5767 function search_technorati()
5769 return $this->add_to_service('http://www.technorati.com/search/');
5773 class SimplePie_Source
5776 var $data = array();
5778 function SimplePie_Source($item, $data)
5780 $this->item = $item;
5781 $this->data = $data;
5784 function __toString()
5786 return md5(serialize($this->data));
5789 function get_source_tags($namespace, $tag)
5791 if (isset($this->data['child'][$namespace][$tag]))
5793 return $this->data['child'][$namespace][$tag];
5801 function get_base($element = array())
5803 return $this->item->get_base($element);
5806 function sanitize($data, $type, $base = '')
5808 return $this->item->sanitize($data, $type, $base);
5816 function get_title()
5818 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5820 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5822 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5824 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5826 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5828 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5830 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5832 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5834 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5836 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5838 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5840 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5842 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5844 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5852 function get_category($key = 0)
5854 $categories = $this->get_categories();
5855 if (isset($categories[$key]))
5857 return $categories[$key];
5865 function get_categories()
5867 $categories = array();
5869 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5874 if (isset($category['attribs']['']['term']))
5876 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5878 if (isset($category['attribs']['']['scheme']))
5880 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5882 if (isset($category['attribs']['']['label']))
5884 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5886 $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5888 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5890 // This is really the label, but keep this as the term also for BC.
5891 // Label will also work on retrieving because that falls back to term.
5892 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5893 if (isset($category['attribs']['']['domain']))
5895 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5901 $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5903 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5905 $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5907 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5909 $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5912 if (!empty($categories))
5914 return SimplePie_Misc::array_unique($categories);
5922 function get_author($key = 0)
5924 $authors = $this->get_authors();
5925 if (isset($authors[$key]))
5927 return $authors[$key];
5935 function get_authors()
5938 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5946 $avatar_date = null;
5948 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5950 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5952 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5954 $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]));
5956 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5958 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5960 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
5962 $avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
5964 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
5966 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
5968 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
5970 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
5972 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
5974 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
5977 if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
5979 $authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
5982 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5987 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5989 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5991 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5993 $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]));
5995 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5997 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5999 if ($name !== null || $email !== null || $url !== null)
6001 $authors[] = new $this->item->feed->author_class($name, $url, $email);
6004 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
6006 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6008 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
6010 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6012 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
6014 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6017 if (!empty($authors))
6019 return SimplePie_Misc::array_unique($authors);
6027 function get_contributor($key = 0)
6029 $contributors = $this->get_contributors();
6030 if (isset($contributors[$key]))
6032 return $contributors[$key];
6040 function get_contributors()
6042 $contributors = array();
6043 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
6048 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6050 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6052 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6054 $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]));
6056 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6058 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6060 if ($name !== null || $email !== null || $uri !== null)
6062 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
6065 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6070 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6072 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6074 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6076 $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]));
6078 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6080 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6082 if ($name !== null || $email !== null || $url !== null)
6084 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
6088 if (!empty($contributors))
6090 return SimplePie_Misc::array_unique($contributors);
6098 function get_link($key = 0, $rel = 'alternate')
6100 $links = $this->get_links($rel);
6101 if (isset($links[$key]))
6103 return $links[$key];
6112 * Added for parity between the parent-level and the item/entry-level.
6114 function get_permalink()
6116 return $this->get_link(0);
6119 function get_links($rel = 'alternate')
6121 if (!isset($this->data['links']))
6123 $this->data['links'] = array();
6124 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6126 foreach ($links as $link)
6128 if (isset($link['attribs']['']['href']))
6130 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6131 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6135 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6137 foreach ($links as $link)
6139 if (isset($link['attribs']['']['href']))
6141 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6142 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6147 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6149 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6151 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6153 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6155 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6157 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6160 $keys = array_keys($this->data['links']);
6161 foreach ($keys as $key)
6163 if (SimplePie_Misc::is_isegment_nz_nc($key))
6165 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6167 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6168 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6172 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6175 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6177 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6179 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6183 if (isset($this->data['links'][$rel]))
6185 return $this->data['links'][$rel];
6193 function get_description()
6195 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6197 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6199 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6201 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6203 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6205 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6207 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6209 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6211 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6213 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6215 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6217 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6219 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6221 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6223 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6225 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6227 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6229 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6237 function get_copyright()
6239 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6241 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6243 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6245 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6247 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6249 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6251 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6253 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6255 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6257 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6265 function get_language()
6267 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6269 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6271 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6273 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6275 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6277 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6279 elseif (isset($this->data['xml_lang']))
6281 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6289 function get_latitude()
6291 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6293 return (float) $return[0]['data'];
6295 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6297 return (float) $match[1];
6305 function get_longitude()
6307 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6309 return (float) $return[0]['data'];
6311 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6313 return (float) $return[0]['data'];
6315 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6317 return (float) $match[2];
6325 function get_image_url()
6327 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6329 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6331 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6333 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6335 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6337 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6346 class SimplePie_Author
6356 // Constructor, used to input the data
6357 function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null, $name_date = null, $uri_date = null, $avatar_date = null)
6359 $this->name = $name;
6360 $this->link = $link;
6361 $this->email = $email;
6362 $this->avatar = $avatar;
6363 $this->name_date = $name_date;
6364 $this->uri_date = $uri_date;
6365 $this->avatar_date = $avatar_date;
6368 function __toString()
6370 // There is no $this->data here
6371 return md5(serialize($this));
6376 if ($this->name !== null)
6388 if ($this->link !== null)
6398 function get_email()
6400 if ($this->email !== null)
6402 return $this->email;
6410 function get_avatar()
6412 if ($this->avatar !== null)
6414 return $this->avatar;
6422 function get_name_date()
6424 if ($this->name_date !== null)
6426 return $this->name_date;
6433 function get_uri_date()
6435 if ($this->uri_date !== null)
6437 return $this->uri_date;
6444 function get_avatar_date()
6446 if ($this->avatar_date !== null)
6448 return $this->avatar_date;
6459 class SimplePie_Category
6465 // Constructor, used to input the data
6466 function SimplePie_Category($term = null, $scheme = null, $label = null)
6468 $this->term = $term;
6469 $this->scheme = $scheme;
6470 $this->label = $label;
6473 function __toString()
6475 // There is no $this->data here
6476 return md5(serialize($this));
6481 if ($this->term !== null)
6491 function get_scheme()
6493 if ($this->scheme !== null)
6495 return $this->scheme;
6503 function get_label()
6505 if ($this->label !== null)
6507 return $this->label;
6511 return $this->get_term();
6516 class SimplePie_Enclosure
6546 // Constructor, used to input the data
6547 function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
6549 $this->bitrate = $bitrate;
6550 $this->captions = $captions;
6551 $this->categories = $categories;
6552 $this->channels = $channels;
6553 $this->copyright = $copyright;
6554 $this->credits = $credits;
6555 $this->description = $description;
6556 $this->duration = $duration;
6557 $this->expression = $expression;
6558 $this->framerate = $framerate;
6559 $this->hashes = $hashes;
6560 $this->height = $height;
6561 $this->javascript = $javascript;
6562 $this->keywords = $keywords;
6563 $this->lang = $lang;
6564 $this->length = $length;
6565 $this->link = $link;
6566 $this->medium = $medium;
6567 $this->player = $player;
6568 $this->ratings = $ratings;
6569 $this->restrictions = $restrictions;
6570 $this->samplingrate = $samplingrate;
6571 $this->thumbnails = $thumbnails;
6572 $this->title = $title;
6573 $this->type = $type;
6574 $this->width = $width;
6575 if (class_exists('idna_convert'))
6577 $idn = new idna_convert;
6578 $parsed = SimplePie_Misc::parse_url($link);
6579 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6581 $this->handler = $this->get_handler(); // Needs to load last
6584 function __toString()
6586 // There is no $this->data here
6587 return md5(serialize($this));
6590 function get_bitrate()
6592 if ($this->bitrate !== null)
6594 return $this->bitrate;
6602 function get_caption($key = 0)
6604 $captions = $this->get_captions();
6605 if (isset($captions[$key]))
6607 return $captions[$key];
6615 function get_captions()
6617 if ($this->captions !== null)
6619 return $this->captions;
6627 function get_category($key = 0)
6629 $categories = $this->get_categories();
6630 if (isset($categories[$key]))
6632 return $categories[$key];
6640 function get_categories()
6642 if ($this->categories !== null)
6644 return $this->categories;
6652 function get_channels()
6654 if ($this->channels !== null)
6656 return $this->channels;
6664 function get_copyright()
6666 if ($this->copyright !== null)
6668 return $this->copyright;
6676 function get_credit($key = 0)
6678 $credits = $this->get_credits();
6679 if (isset($credits[$key]))
6681 return $credits[$key];
6689 function get_credits()
6691 if ($this->credits !== null)
6693 return $this->credits;
6701 function get_description()
6703 if ($this->description !== null)
6705 return $this->description;
6713 function get_duration($convert = false)
6715 if ($this->duration !== null)
6719 $time = SimplePie_Misc::time_hms($this->duration);
6724 return $this->duration;
6733 function get_expression()
6735 if ($this->expression !== null)
6737 return $this->expression;
6745 function get_extension()
6747 if ($this->link !== null)
6749 $url = SimplePie_Misc::parse_url($this->link);
6750 if ($url['path'] !== '')
6752 return pathinfo($url['path'], PATHINFO_EXTENSION);
6758 function get_framerate()
6760 if ($this->framerate !== null)
6762 return $this->framerate;
6770 function get_handler()
6772 return $this->get_real_type(true);
6775 function get_hash($key = 0)
6777 $hashes = $this->get_hashes();
6778 if (isset($hashes[$key]))
6780 return $hashes[$key];
6788 function get_hashes()
6790 if ($this->hashes !== null)
6792 return $this->hashes;
6800 function get_height()
6802 if ($this->height !== null)
6804 return $this->height;
6812 function get_language()
6814 if ($this->lang !== null)
6824 function get_keyword($key = 0)
6826 $keywords = $this->get_keywords();
6827 if (isset($keywords[$key]))
6829 return $keywords[$key];
6837 function get_keywords()
6839 if ($this->keywords !== null)
6841 return $this->keywords;
6849 function get_length()
6851 if ($this->length !== null)
6853 return $this->length;
6863 if ($this->link !== null)
6865 return urldecode($this->link);
6873 function get_medium()
6875 if ($this->medium !== null)
6877 return $this->medium;
6885 function get_player()
6887 if ($this->player !== null)
6889 return $this->player;
6897 function get_rating($key = 0)
6899 $ratings = $this->get_ratings();
6900 if (isset($ratings[$key]))
6902 return $ratings[$key];
6910 function get_ratings()
6912 if ($this->ratings !== null)
6914 return $this->ratings;
6922 function get_restriction($key = 0)
6924 $restrictions = $this->get_restrictions();
6925 if (isset($restrictions[$key]))
6927 return $restrictions[$key];
6935 function get_restrictions()
6937 if ($this->restrictions !== null)
6939 return $this->restrictions;
6947 function get_sampling_rate()
6949 if ($this->samplingrate !== null)
6951 return $this->samplingrate;
6961 $length = $this->get_length();
6962 if ($length !== null)
6964 return round($length/1048576, 2);
6972 function get_thumbnail($key = 0)
6974 $thumbnails = $this->get_thumbnails();
6975 if (isset($thumbnails[$key]))
6977 return $thumbnails[$key];
6985 function get_thumbnails()
6987 if ($this->thumbnails !== null)
6989 return $this->thumbnails;
6997 function get_title()
6999 if ($this->title !== null)
7001 return $this->title;
7011 if ($this->type !== null)
7021 function get_width()
7023 if ($this->width !== null)
7025 return $this->width;
7033 function native_embed($options='')
7035 return $this->embed($options, true);
7039 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
7041 function embed($options = '', $native = false)
7051 $bgcolor = '#ffffff';
7053 $widescreen = false;
7054 $handler = $this->get_handler();
7055 $type = $this->get_real_type();
7057 // Process options and reassign values as necessary
7058 if (is_array($options))
7064 $options = explode(',', $options);
7065 foreach($options as $option)
7067 $opt = explode(':', $option, 2);
7068 if (isset($opt[0], $opt[1]))
7070 $opt[0] = trim($opt[0]);
7071 $opt[1] = trim($opt[1]);
7087 $altclass = $opt[1];
7107 $mediaplayer = $opt[1];
7111 $widescreen = $opt[1];
7118 $mime = explode('/', $type, 2);
7121 // Process values for 'auto'
7122 if ($width === 'auto')
7124 if ($mime === 'video')
7126 if ($height === 'auto')
7130 elseif ($widescreen)
7132 $width = round((intval($height)/9)*16);
7136 $width = round((intval($height)/3)*4);
7145 if ($height === 'auto')
7147 if ($mime === 'audio')
7151 elseif ($mime === 'video')
7153 if ($width === 'auto')
7164 elseif ($widescreen)
7166 $height = round((intval($width)/16)*9);
7170 $height = round((intval($width)/4)*3);
7178 elseif ($mime === 'audio')
7183 // Set proper placeholder value
7184 if ($mime === 'audio')
7186 $placeholder = $audio;
7188 elseif ($mime === 'video')
7190 $placeholder = $video;
7195 // Make sure the JS library is included
7198 static $javascript_outputted = null;
7199 if (!$javascript_outputted && $this->javascript)
7201 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7202 $javascript_outputted = true;
7207 if ($handler === 'odeo')
7211 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.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=' . $this->get_link() . '"></embed>';
7215 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7220 elseif ($handler === 'flash')
7224 $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
7228 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7232 // Flash Media Player file types.
7233 // Preferred handler for MP3 file types.
7234 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7239 $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
7243 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7247 // QuickTime 7 file types. Need to test with QuickTime 6.
7248 // Only handle MP3's if the Flash Media Player is not present.
7249 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7254 if ($placeholder !== '')
7256 $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7260 $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
7265 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7270 elseif ($handler === 'wmedia')
7275 $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
7279 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7284 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7289 function get_real_type($find_handler = false)
7291 // If it's Odeo, let's get it out of the way.
7292 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7297 // Mime-types by handler.
7298 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7299 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7300 $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
7301 $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
7302 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7304 if ($this->get_type() !== null)
7306 $type = strtolower($this->type);
7313 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7314 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7316 switch (strtolower($this->get_extension()))
7321 $type = 'audio/acc';
7328 $type = 'audio/aiff';
7332 $type = 'audio/wav';
7339 $type = 'audio/midi';
7343 $type = 'audio/x-m4a';
7348 $type = 'audio/mp3';
7352 $type = 'audio/wav';
7356 $type = 'audio/x-ms-wax';
7360 $type = 'audio/x-ms-wma';
7366 $type = 'video/3gpp';
7371 $type = 'video/3gpp2';
7375 $type = 'video/x-ms-asf';
7379 $type = 'video/x-flv';
7393 $type = 'video/mpeg';
7397 $type = 'video/x-m4v';
7402 $type = 'video/quicktime';
7407 $type = 'video/mp4';
7411 $type = 'video/sd-video';
7415 $type = 'video/x-ms-wm';
7419 $type = 'video/x-ms-wmv';
7423 $type = 'video/x-ms-wvx';
7428 $type = 'application/futuresplash';
7432 $type = 'application/x-shockwave-flash';
7439 if (in_array($type, $types_flash))
7443 elseif (in_array($type, $types_fmedia))
7447 elseif (in_array($type, $types_quicktime))
7451 elseif (in_array($type, $types_wmedia))
7455 elseif (in_array($type, $types_mp3))
7471 class SimplePie_Caption
7479 // Constructor, used to input the data
7480 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7482 $this->type = $type;
7483 $this->lang = $lang;
7484 $this->startTime = $startTime;
7485 $this->endTime = $endTime;
7486 $this->text = $text;
7489 function __toString()
7491 // There is no $this->data here
7492 return md5(serialize($this));
7495 function get_endtime()
7497 if ($this->endTime !== null)
7499 return $this->endTime;
7507 function get_language()
7509 if ($this->lang !== null)
7519 function get_starttime()
7521 if ($this->startTime !== null)
7523 return $this->startTime;
7533 if ($this->text !== null)
7545 if ($this->type !== null)
7556 class SimplePie_Credit
7562 // Constructor, used to input the data
7563 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7565 $this->role = $role;
7566 $this->scheme = $scheme;
7567 $this->name = $name;
7570 function __toString()
7572 // There is no $this->data here
7573 return md5(serialize($this));
7578 if ($this->role !== null)
7588 function get_scheme()
7590 if ($this->scheme !== null)
7592 return $this->scheme;
7602 if ($this->name !== null)
7613 class SimplePie_Copyright
7618 // Constructor, used to input the data
7619 function SimplePie_Copyright($url = null, $label = null)
7622 $this->label = $label;
7625 function __toString()
7627 // There is no $this->data here
7628 return md5(serialize($this));
7633 if ($this->url !== null)
7643 function get_attribution()
7645 if ($this->label !== null)
7647 return $this->label;
7656 class SimplePie_Rating
7661 // Constructor, used to input the data
7662 function SimplePie_Rating($scheme = null, $value = null)
7664 $this->scheme = $scheme;
7665 $this->value = $value;
7668 function __toString()
7670 // There is no $this->data here
7671 return md5(serialize($this));
7674 function get_scheme()
7676 if ($this->scheme !== null)
7678 return $this->scheme;
7686 function get_value()
7688 if ($this->value !== null)
7690 return $this->value;
7699 class SimplePie_Restriction
7705 // Constructor, used to input the data
7706 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7708 $this->relationship = $relationship;
7709 $this->type = $type;
7710 $this->value = $value;
7713 function __toString()
7715 // There is no $this->data here
7716 return md5(serialize($this));
7719 function get_relationship()
7721 if ($this->relationship !== null)
7723 return $this->relationship;
7733 if ($this->type !== null)
7743 function get_value()
7745 if ($this->value !== null)
7747 return $this->value;
7757 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7759 class SimplePie_File
7763 var $success = true;
7764 var $headers = array();
7769 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7771 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7773 if (class_exists('idna_convert'))
7775 $idn = new idna_convert;
7776 $parsed = SimplePie_Misc::parse_url($url);
7777 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7780 $this->useragent = $useragent;
7781 if (preg_match('/^http(s)?:\/\//i', $url))
7783 if ($useragent === null)
7785 $useragent = ini_get('user_agent');
7786 $this->useragent = $useragent;
7788 if (!is_array($headers))
7792 if (!$force_fsockopen && function_exists('curl_exec'))
7794 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7796 $headers2 = array();
7797 foreach ($headers as $key => $value)
7799 $headers2[] = "$key: $value";
7801 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7803 curl_setopt($fp, CURLOPT_ENCODING, '');
7805 curl_setopt($fp, CURLOPT_URL, $url);
7806 curl_setopt($fp, CURLOPT_HEADER, 1);
7807 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7808 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7809 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7810 curl_setopt($fp, CURLOPT_REFERER, $url);
7811 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7812 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7813 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7815 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7816 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7819 $this->headers = curl_exec($fp);
7820 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7822 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7823 $this->headers = curl_exec($fp);
7825 if (curl_errno($fp))
7827 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7828 $this->success = false;
7832 $info = curl_getinfo($fp);
7834 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7835 $this->headers = array_pop($this->headers);
7836 $parser = new SimplePie_HTTP_Parser($this->headers);
7837 if ($parser->parse())
7839 $this->headers = $parser->headers;
7840 $this->body = $parser->body;
7841 $this->status_code = $parser->status_code;
7842 if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7845 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7846 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7853 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7854 $url_parts = parse_url($url);
7855 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7857 $url_parts['host'] = "ssl://$url_parts[host]";
7858 $url_parts['port'] = 443;
7860 if (!isset($url_parts['port']))
7862 $url_parts['port'] = 80;
7864 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7867 $this->error = 'fsockopen error: ' . $errstr;
7868 $this->success = false;
7872 stream_set_timeout($fp, $timeout);
7873 if (isset($url_parts['path']))
7875 if (isset($url_parts['query']))
7877 $get = "$url_parts[path]?$url_parts[query]";
7881 $get = $url_parts['path'];
7888 $out = "GET $get HTTP/1.0\r\n";
7889 $out .= "Host: $url_parts[host]\r\n";
7890 $out .= "User-Agent: $useragent\r\n";
7891 if (extension_loaded('zlib'))
7893 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7896 if (isset($url_parts['user']) && isset($url_parts['pass']))
7898 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7900 foreach ($headers as $key => $value)
7902 $out .= "$key: $value\r\n";
7904 $out .= "Connection: Close\r\n\r\n";
7907 $info = stream_get_meta_data($fp);
7909 $this->headers = '';
7910 while (!$info['eof'] && !$info['timed_out'])
7912 $this->headers .= fread($fp, 1160);
7913 $info = stream_get_meta_data($fp);
7915 if (!$info['timed_out'])
7917 $parser = new SimplePie_HTTP_Parser($this->headers);
7918 if ($parser->parse())
7920 $this->headers = $parser->headers;
7921 $this->body = $parser->body;
7922 $this->status_code = $parser->status_code;
7923 if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
7926 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7927 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7929 if (isset($this->headers['content-encoding']))
7931 // Hey, we act dumb elsewhere, so let's do that here too
7932 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7936 $decoder = new SimplePie_gzdecode($this->body);
7937 if (!$decoder->parse())
7939 $this->error = 'Unable to decode HTTP "gzip" stream';
7940 $this->success = false;
7944 $this->body = $decoder->data;
7949 if (($body = gzuncompress($this->body)) === false)
7951 if (($body = gzinflate($this->body)) === false)
7953 $this->error = 'Unable to decode HTTP "deflate" stream';
7954 $this->success = false;
7957 $this->body = $body;
7961 $this->error = 'Unknown content coding';
7962 $this->success = false;
7969 $this->error = 'fsocket timed out';
7970 $this->success = false;
7978 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7979 if (!$this->body = file_get_contents($url))
7981 $this->error = 'file_get_contents could not read the file';
7982 $this->success = false;
7989 * HTTP Response Parser
7991 * @package SimplePie
7993 class SimplePie_HTTP_Parser
8001 var $http_version = 0.0;
8009 var $status_code = 0;
8020 * Key/value pairs of the headers
8025 var $headers = array();
8028 * Body of the response
8036 * Current state of the state machine
8041 var $state = 'http_version';
8052 * Input data length (to avoid calling strlen() everytime this is needed)
8057 var $data_length = 0;
8060 * Current position of the pointer
8068 * Name of the hedaer currently being parsed
8076 * Value of the hedaer currently being parsed
8084 * Create an instance of the class with the input data
8087 * @param string $data Input data
8089 function SimplePie_HTTP_Parser($data)
8091 $this->data = $data;
8092 $this->data_length = strlen($this->data);
8096 * Parse the input data
8099 * @return bool true on success, false on failure
8103 while ($this->state && $this->state !== 'emit' && $this->has_data())
8105 $state = $this->state;
8109 if ($this->state === 'emit' || $this->state === 'body')
8115 $this->http_version = '';
8116 $this->status_code = '';
8118 $this->headers = array();
8125 * Check whether there is data beyond the pointer
8128 * @return bool true if there is further data, false if not
8132 return (bool) ($this->position < $this->data_length);
8136 * See if the next character is LWS
8139 * @return bool true if the next character is LWS, false if not
8141 function is_linear_whitespace()
8143 return (bool) ($this->data[$this->position] === "\x09"
8144 || $this->data[$this->position] === "\x20"
8145 || ($this->data[$this->position] === "\x0A"
8146 && isset($this->data[$this->position + 1])
8147 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8151 * Parse the HTTP version
8155 function http_version()
8157 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8159 $len = strspn($this->data, '0123456789.', 5);
8160 $this->http_version = substr($this->data, 5, $len);
8161 $this->position += 5 + $len;
8162 if (substr_count($this->http_version, '.') <= 1)
8164 $this->http_version = (float) $this->http_version;
8165 $this->position += strspn($this->data, "\x09\x20", $this->position);
8166 $this->state = 'status';
8170 $this->state = false;
8175 $this->state = false;
8180 * Parse the status code
8186 if ($len = strspn($this->data, '0123456789', $this->position))
8188 $this->status_code = (int) substr($this->data, $this->position, $len);
8189 $this->position += $len;
8190 $this->state = 'reason';
8194 $this->state = false;
8199 * Parse the reason phrase
8205 $len = strcspn($this->data, "\x0A", $this->position);
8206 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8207 $this->position += $len + 1;
8208 $this->state = 'new_line';
8212 * Deal with a new line, shifting data around as needed
8218 $this->value = trim($this->value, "\x0D\x20");
8219 if ($this->name !== '' && $this->value !== '')
8221 $this->name = strtolower($this->name);
8222 if (isset($this->headers[$this->name]))
8224 $this->headers[$this->name] .= ', ' . $this->value;
8228 $this->headers[$this->name] = $this->value;
8233 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8235 $this->position += 2;
8236 $this->state = 'body';
8238 elseif ($this->data[$this->position] === "\x0A")
8241 $this->state = 'body';
8245 $this->state = 'name';
8250 * Parse a header name
8256 $len = strcspn($this->data, "\x0A:", $this->position);
8257 if (isset($this->data[$this->position + $len]))
8259 if ($this->data[$this->position + $len] === "\x0A")
8261 $this->position += $len;
8262 $this->state = 'new_line';
8266 $this->name = substr($this->data, $this->position, $len);
8267 $this->position += $len + 1;
8268 $this->state = 'value';
8273 $this->state = false;
8278 * Parse LWS, replacing consecutive LWS characters with a single space
8282 function linear_whitespace()
8286 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8288 $this->position += 2;
8290 elseif ($this->data[$this->position] === "\x0A")
8294 $this->position += strspn($this->data, "\x09\x20", $this->position);
8295 } while ($this->has_data() && $this->is_linear_whitespace());
8296 $this->value .= "\x20";
8300 * See what state to move to while within non-quoted header values
8306 if ($this->is_linear_whitespace())
8308 $this->linear_whitespace();
8312 switch ($this->data[$this->position])
8316 $this->state = 'quote';
8321 $this->state = 'new_line';
8325 $this->state = 'value_char';
8332 * Parse a header value while outside quotes
8336 function value_char()
8338 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8339 $this->value .= substr($this->data, $this->position, $len);
8340 $this->position += $len;
8341 $this->state = 'value';
8345 * See what state to move to while within quoted header values
8351 if ($this->is_linear_whitespace())
8353 $this->linear_whitespace();
8357 switch ($this->data[$this->position])
8361 $this->state = 'value';
8366 $this->state = 'new_line';
8371 $this->state = 'quote_escaped';
8375 $this->state = 'quote_char';
8382 * Parse a header value while within quotes
8386 function quote_char()
8388 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8389 $this->value .= substr($this->data, $this->position, $len);
8390 $this->position += $len;
8391 $this->state = 'value';
8395 * Parse an escaped character within quotes
8399 function quote_escaped()
8401 $this->value .= $this->data[$this->position];
8403 $this->state = 'quote';
8413 $this->body = substr($this->data, $this->position);
8414 $this->state = 'emit';
8421 * @package SimplePie
8423 class SimplePie_gzdecode
8429 * @see gzdecode::$data
8431 var $compressed_data;
8434 * Size of compressed data
8438 var $compressed_size;
8441 * Minimum size of a valid gzip string
8445 var $min_compressed_size = 18;
8448 * Current position of pointer
8465 * @see gzdecode::$compressed_data
8494 * @see gzdecode::$extra_field
8495 * @see gzdecode::$SI2
8503 * @see gzdecode::$extra_field
8504 * @see gzdecode::$SI1
8509 * Extra field content
8512 * @see gzdecode::$SI1
8513 * @see gzdecode::$SI2
8525 * Human readable comment
8532 * Don't allow anything to be set
8536 function __set($name, $value)
8538 trigger_error("Cannot write property $name", E_USER_ERROR);
8542 * Set the compressed string and related properties
8546 function SimplePie_gzdecode($data)
8548 $this->compressed_data = $data;
8549 $this->compressed_size = strlen($data);
8553 * Decode the GZIP stream
8559 if ($this->compressed_size >= $this->min_compressed_size)
8561 // Check ID1, ID2, and CM
8562 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8567 // Get the FLG (FLaGs)
8568 $this->flags = ord($this->compressed_data[3]);
8570 // FLG bits above (1 << 4) are reserved
8571 if ($this->flags > 0x1F)
8576 // Advance the pointer after the above
8577 $this->position += 4;
8580 $mtime = substr($this->compressed_data, $this->position, 4);
8581 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8582 if (current(unpack('S', "\x00\x01")) === 1)
8584 $mtime = strrev($mtime);
8586 $this->MTIME = current(unpack('l', $mtime));
8587 $this->position += 4;
8589 // Get the XFL (eXtra FLags)
8590 $this->XFL = ord($this->compressed_data[$this->position++]);
8592 // Get the OS (Operating System)
8593 $this->OS = ord($this->compressed_data[$this->position++]);
8596 if ($this->flags & 4)
8598 // Read subfield IDs
8599 $this->SI1 = $this->compressed_data[$this->position++];
8600 $this->SI2 = $this->compressed_data[$this->position++];
8602 // SI2 set to zero is reserved for future use
8603 if ($this->SI2 === "\x00")
8608 // Get the length of the extra field
8609 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8612 // Check the length of the string is still valid
8613 $this->min_compressed_size += $len + 4;
8614 if ($this->compressed_size >= $this->min_compressed_size)
8616 // Set the extra field to the given data
8617 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8618 $this->position += $len;
8627 if ($this->flags & 8)
8629 // Get the length of the filename
8630 $len = strcspn($this->compressed_data, "\x00", $this->position);
8632 // Check the length of the string is still valid
8633 $this->min_compressed_size += $len + 1;
8634 if ($this->compressed_size >= $this->min_compressed_size)
8636 // Set the original filename to the given string
8637 $this->filename = substr($this->compressed_data, $this->position, $len);
8638 $this->position += $len + 1;
8646 // Parse the FCOMMENT
8647 if ($this->flags & 16)
8649 // Get the length of the comment
8650 $len = strcspn($this->compressed_data, "\x00", $this->position);
8652 // Check the length of the string is still valid
8653 $this->min_compressed_size += $len + 1;
8654 if ($this->compressed_size >= $this->min_compressed_size)
8656 // Set the original comment to the given string
8657 $this->comment = substr($this->compressed_data, $this->position, $len);
8658 $this->position += $len + 1;
8667 if ($this->flags & 2)
8669 // Check the length of the string is still valid
8670 $this->min_compressed_size += $len + 2;
8671 if ($this->compressed_size >= $this->min_compressed_size)
8674 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8676 // Check the CRC matches
8677 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8679 $this->position += 2;
8692 // Decompress the actual data
8693 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8699 $this->position = $this->compressed_size - 8;
8702 // Check CRC of data
8703 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8704 $this->position += 4;
8705 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8710 // Check ISIZE of data
8711 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8712 $this->position += 4;
8713 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8718 // Wow, against all odds, we've actually got a valid gzip string
8728 class SimplePie_Cache
8731 * Don't call the constructor. Please.
8735 function SimplePie_Cache()
8737 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8741 * Create a new SimplePie_Cache object
8746 function create($location, $filename, $extension)
8748 $location_iri = new SimplePie_IRI($location);
8749 switch ($location_iri->get_scheme())
8752 if (extension_loaded('mysql'))
8754 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8759 return new SimplePie_Cache_File($location, $filename, $extension);
8764 class SimplePie_Cache_File
8771 function SimplePie_Cache_File($location, $filename, $extension)
8773 $this->location = $location;
8774 $this->filename = $filename;
8775 $this->extension = $extension;
8776 $this->name = "$this->location/$this->filename.$this->extension";
8779 function save($data)
8781 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8783 if (is_a($data, 'SimplePie'))
8785 $data = $data->data;
8788 $data = serialize($data);
8790 if (function_exists('file_put_contents'))
8792 return (bool) file_put_contents($this->name, $data);
8796 $fp = fopen($this->name, 'wb');
8810 if (file_exists($this->name) && is_readable($this->name))
8812 return unserialize(file_get_contents($this->name));
8819 if (file_exists($this->name))
8821 return filemtime($this->name);
8828 if (file_exists($this->name))
8830 return touch($this->name);
8837 if (file_exists($this->name))
8839 return unlink($this->name);
8845 class SimplePie_Cache_DB
8847 function prepare_simplepie_object_for_cache($data)
8849 $items = $data->get_items();
8850 $items_by_id = array();
8854 foreach ($items as $item)
8856 $items_by_id[$item->get_id()] = $item;
8859 if (count($items_by_id) !== count($items))
8861 $items_by_id = array();
8862 foreach ($items as $item)
8864 $items_by_id[$item->get_id(true)] = $item;
8868 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8870 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8872 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8874 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8876 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8878 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8880 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8882 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8889 if ($channel !== null)
8891 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8893 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8895 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8897 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8899 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8901 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8903 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8905 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8907 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8909 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8912 if (isset($data->data['items']))
8914 unset($data->data['items']);
8916 if (isset($data->data['ordered_items']))
8918 unset($data->data['ordered_items']);
8921 return array(serialize($data->data), $items_by_id);
8925 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8931 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8933 $host = $mysql_location->get_host();
8934 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8936 $server = ':' . substr($host, 5, -1);
8941 if ($mysql_location->get_port() !== null)
8943 $server .= ':' . $mysql_location->get_port();
8947 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8949 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8953 $username = $mysql_location->get_userinfo();
8957 if ($this->mysql = mysql_connect($server, $username, $password))
8959 $this->id = $name . $extension;
8960 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8961 if (!isset($this->options['prefix'][0]))
8963 $this->options['prefix'][0] = '';
8966 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8967 && mysql_query('SET NAMES utf8')
8968 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8971 while ($row = mysql_fetch_row($query))
8976 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8978 if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
8980 $this->mysql = null;
8984 if (!in_array($this->options['prefix'][0] . 'items', $db))
8986 if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
8988 $this->mysql = null;
8994 $this->mysql = null;
8999 function save($data)
9003 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
9005 if (is_a($data, 'SimplePie'))
9009 // This keyword needs to defy coding standards for PHP4 compatibility
9010 $data = clone($data);
9013 $prepared = $this->prepare_simplepie_object_for_cache($data);
9015 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9017 if (mysql_num_rows($query))
9019 $items = count($prepared[1]);
9022 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9026 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9029 if (!mysql_query($sql, $this->mysql))
9034 elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
9039 $ids = array_keys($prepared[1]);
9042 foreach ($ids as $id)
9044 $database_ids[] = mysql_real_escape_string($id);
9047 if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
9049 $existing_ids = array();
9050 while ($row = mysql_fetch_row($query))
9052 $existing_ids[] = $row[0];
9055 $new_ids = array_diff($ids, $existing_ids);
9057 foreach ($new_ids as $new_id)
9059 if (!($date = $prepared[1][$new_id]->get_date('U')))
9064 if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
9078 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9080 if (mysql_num_rows($query))
9082 if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
9087 elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
9098 if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9100 $data = unserialize($row[1]);
9102 if (isset($this->options['items'][0]))
9104 $items = (int) $this->options['items'][0];
9108 $items = (int) $row[0];
9113 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9115 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9117 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9119 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9121 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9123 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9125 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9127 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9136 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9139 $sql .= ' LIMIT ' . $items;
9142 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9144 while ($row = mysql_fetch_row($query))
9146 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9162 if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
9174 if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
9186 if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
9197 class SimplePie_Misc
9199 function time_hms($seconds)
9203 $hours = floor($seconds / 3600);
9204 $remainder = $seconds % 3600;
9207 $time .= $hours.':';
9210 $minutes = floor($remainder / 60);
9211 $seconds = $remainder % 60;
9212 if ($minutes < 10 && $hours > 0)
9214 $minutes = '0' . $minutes;
9218 $seconds = '0' . $seconds;
9221 $time .= $minutes.':';
9227 function absolutize_url($relative, $base)
9230 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9231 return $iri->get_iri();
9234 function remove_dot_segments($input)
9237 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9239 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9240 if (strpos($input, '../') === 0)
9242 $input = substr($input, 3);
9244 elseif (strpos($input, './') === 0)
9246 $input = substr($input, 2);
9248 // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
9249 elseif (strpos($input, '/./') === 0)
9251 $input = substr_replace($input, '/', 0, 3);
9253 elseif ($input === '/.')
9257 // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
9258 elseif (strpos($input, '/../') === 0)
9260 $input = substr_replace($input, '/', 0, 4);
9261 $output = substr_replace($output, '', strrpos($output, '/'));
9263 elseif ($input === '/..')
9266 $output = substr_replace($output, '', strrpos($output, '/'));
9268 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9269 elseif ($input === '.' || $input === '..')
9273 // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
9274 elseif (($pos = strpos($input, '/', 1)) !== false)
9276 $output .= substr($input, 0, $pos);
9277 $input = substr_replace($input, '', 0, $pos);
9285 return $output . $input;
9288 function get_element($realname, $string)
9291 $name = preg_quote($realname, '/');
9292 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9294 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9296 $return[$i]['tag'] = $realname;
9297 $return[$i]['full'] = $matches[$i][0][0];
9298 $return[$i]['offset'] = $matches[$i][0][1];
9299 if (strlen($matches[$i][3][0]) <= 2)
9301 $return[$i]['self_closing'] = true;
9305 $return[$i]['self_closing'] = false;
9306 $return[$i]['content'] = $matches[$i][4][0];
9308 $return[$i]['attribs'] = array();
9309 if (isset($matches[$i][2][0]) && preg_match_all('/[\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]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
9311 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9313 if (count($attribs[$j]) === 2)
9315 $attribs[$j][2] = $attribs[$j][1];
9317 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9325 function element_implode($element)
9327 $full = "<$element[tag]";
9328 foreach ($element['attribs'] as $key => $value)
9330 $key = strtolower($key);
9331 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9333 if ($element['self_closing'])
9339 $full .= ">$element[content]</$element[tag]>";
9344 function error($message, $level, $file, $line)
9346 if ((ini_get('error_reporting') & $level) > 0)
9351 $note = 'PHP Error';
9353 case E_USER_WARNING:
9354 $note = 'PHP Warning';
9357 $note = 'PHP Notice';
9360 $note = 'Unknown Error';
9365 if (!function_exists('error_log'))
9370 $log_file = @ini_get('error_log');
9371 if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9378 @error_log("$note: $message in $file on line $line", 0);
9386 * If a file has been cached, retrieve and display it.
9388 * This is most useful for caching images (get_favicon(), etc.),
9389 * however it works for all cached files. This WILL NOT display ANY
9390 * file/image/page/whatever, but rather only display what has already
9391 * been cached by SimplePie.
9394 * @see SimplePie::get_favicon()
9395 * @param str $identifier_url URL that is used to identify the content.
9396 * This may or may not be the actual URL of the live content.
9397 * @param str $cache_location Location of SimplePie's cache. Defaults
9399 * @param str $cache_extension The file extension that the file was
9400 * cached with. Defaults to 'spc'.
9401 * @param str $cache_class Name of the cache-handling class being used
9402 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9403 * as-is unless you've overloaded the class.
9404 * @param str $cache_name_function Obsolete. Exists for backwards
9405 * compatibility reasons only.
9407 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9409 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9411 if ($file = $cache->load())
9413 if (isset($file['headers']['content-type']))
9415 header('Content-type:' . $file['headers']['content-type']);
9419 header('Content-type: application/octet-stream');
9421 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9426 die('Cached file for ' . $identifier_url . ' cannot be found.');
9429 function fix_protocol($url, $http = 1)
9431 $url = SimplePie_Misc::normalize_url($url);
9432 $parsed = SimplePie_Misc::parse_url($url);
9433 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9435 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9438 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9440 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9443 if ($http === 2 && $parsed['scheme'] !== '')
9447 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9449 return substr_replace($url, 'podcast', 0, 4);
9451 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9453 return substr_replace($url, 'itpc', 0, 4);
9461 function parse_url($url)
9463 $iri = new SimplePie_IRI($url);
9465 'scheme' => (string) $iri->get_scheme(),
9466 'authority' => (string) $iri->get_authority(),
9467 'path' => (string) $iri->get_path(),
9468 'query' => (string) $iri->get_query(),
9469 'fragment' => (string) $iri->get_fragment()
9473 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9475 $iri = new SimplePie_IRI('');
9476 $iri->set_scheme($scheme);
9477 $iri->set_authority($authority);
9478 $iri->set_path($path);
9479 $iri->set_query($query);
9480 $iri->set_fragment($fragment);
9481 return $iri->get_iri();
9484 function normalize_url($url)
9486 $iri = new SimplePie_IRI($url);
9487 return $iri->get_iri();
9490 function percent_encoding_normalization($match)
9492 $integer = hexdec($match[1]);
9493 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9495 return chr($integer);
9499 return strtoupper($match[0]);
9504 * Remove bad UTF-8 bytes
9506 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9507 * FAQ: Multilingual Forms (modified to include full ASCII range)
9509 * @author Geoffrey Sneddon
9510 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9511 * @param string $str String to remove bad UTF-8 bytes from
9512 * @return string UTF-8 string
9514 function utf8_bad_replace($str)
9516 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9520 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9524 elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
9526 return implode("\xEF\xBF\xBD", $matches[0]);
9528 elseif ($str !== '')
9530 return "\xEF\xBF\xBD";
9539 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9543 * @param string $string Windows-1252 encoded string
9544 * @return string UTF-8 encoded string
9546 function windows_1252_to_utf8($string)
9548 static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
9550 return strtr($string, $convert_table);
9553 function change_encoding($data, $input, $output)
9555 $input = SimplePie_Misc::encoding($input);
9556 $output = SimplePie_Misc::encoding($output);
9558 // We fail to fail on non US-ASCII bytes
9559 if ($input === 'US-ASCII')
9561 static $non_ascii_octects = '';
9562 if (!$non_ascii_octects)
9564 for ($i = 0x80; $i <= 0xFF; $i++)
9566 $non_ascii_octects .= chr($i);
9569 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9572 // This is first, as behaviour of this is completely predictable
9573 if ($input === 'Windows-1252' && $output === 'UTF-8')
9575 return SimplePie_Misc::windows_1252_to_utf8($data);
9577 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9578 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9582 // This is last, as behaviour of this varies with OS userland and PHP version
9583 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9587 // If we can't do anything, just fail
9594 function encoding($charset)
9596 // Normalization from UTS #22
9597 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9599 case 'adobestandardencoding':
9600 case 'csadobestandardencoding':
9601 return 'Adobe-Standard-Encoding';
9603 case 'adobesymbolencoding':
9605 return 'Adobe-Symbol-Encoding';
9609 return 'Amiga-1251';
9611 case 'ansix31101983':
9613 case 'csiso99naplps':
9616 return 'ANSI_X3.110-1983';
9620 case 'csiso89asmo449':
9631 return 'Big5-HKSCS';
9642 case 'csiso4unitedkingdom':
9650 case 'csiso47bsviewdata':
9652 return 'BS_viewdata';
9660 case 'csaz243419851':
9661 case 'csiso121canadian1':
9664 return 'CSA_Z243.4-1985-1';
9667 case 'csaz243419852':
9668 case 'csiso122canadian2':
9671 return 'CSA_Z243.4-1985-2';
9673 case 'csaz24341985gr':
9674 case 'csiso123csaz24341985gr':
9676 return 'CSA_Z243.4-1985-gr';
9678 case 'csiso139csn369103':
9681 return 'CSN_369103';
9688 case 'csiso21german':
9699 case 'csiso646danish':
9705 case 'csibmebcdicatde':
9707 return 'EBCDIC-AT-DE';
9709 case 'csebcdicatdea':
9711 return 'EBCDIC-AT-DE-A';
9713 case 'csebcdiccafr':
9715 return 'EBCDIC-CA-FR';
9717 case 'csebcdicdkno':
9719 return 'EBCDIC-DK-NO';
9721 case 'csebcdicdknoa':
9723 return 'EBCDIC-DK-NO-A';
9731 return 'EBCDIC-ES-A';
9735 return 'EBCDIC-ES-S';
9737 case 'csebcdicfise':
9739 return 'EBCDIC-FI-SE';
9741 case 'csebcdicfisea':
9743 return 'EBCDIC-FI-SE-A';
9765 case 'csiso111ecmacyrillic':
9766 case 'ecmacyrillic':
9769 return 'ECMA-cyrillic';
9771 case 'csiso17spanish':
9777 case 'csiso85spanish2':
9783 case 'cseucfixwidjapanese':
9784 case 'extendedunixcodefixedwidthforjapanese':
9785 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9787 case 'cseucpkdfmtjapanese':
9789 case 'extendedunixcodepackedformatforjapanese':
9790 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9798 case 'csiso58gb231280':
9808 case 'csiso57gb1988':
9812 return 'GB_1988-80';
9814 case 'csiso153gost1976874':
9818 return 'GOST_19768-74';
9821 case 'csiso150greekccitt':
9824 return 'greek-ccitt';
9826 case 'csiso88greek7':
9831 case 'csiso18greek7old':
9834 return 'greek7-old';
9838 return 'HP-DeskTop';
9850 return 'HP-Pi-font';
9859 return 'HZ-GB-2312';
9861 case 'csibmsymbols':
9863 return 'IBM-Symbols';
9872 case 'pcmultilingual850euro':
9877 case 'ebcdiclatin9euro':
9883 case 'ebcdicus37euro':
9889 case 'ebcdicde273euro':
9895 case 'ebcdicdk277euro':
9896 case 'ebcdicno277euro':
9902 case 'ebcdicfi278euro':
9903 case 'ebcdicse278euro':
9909 case 'ebcdicit280euro':
9915 case 'ebcdices284euro':
9921 case 'ebcdicgb285euro':
9927 case 'ebcdicfr297euro':
9933 case 'ebcdicinternational500euro':
9939 case 'ebcdicis871euro':
10014 case 'ebcdicjpkana':
10026 case 'ebcdiccpar1':
10044 case 'cspc8codepage437':
10056 case 'cspc775baltic':
10062 case 'cspc850multilingual':
10105 case 'cspc862latinhebrew':
10147 case 'ebcdiccproece':
10160 case 'ebcdiccyrillic':
10188 case 'ebcdiccpar2':
10200 case 'csiso143iecp271':
10203 return 'IEC_P27-1';
10205 case 'csiso49inis':
10210 case 'csiso50inis8':
10215 case 'csiso51iniscyrillic':
10216 case 'iniscyrillic':
10218 return 'INIS-cyrillic';
10220 case 'csinvariant':
10222 return 'INVARIANT';
10225 return 'ISO-2022-CN';
10227 case 'iso2022cnext':
10228 return 'ISO-2022-CN-EXT';
10230 case 'csiso2022jp':
10232 return 'ISO-2022-JP';
10234 case 'csiso2022jp2':
10236 return 'ISO-2022-JP-2';
10238 case 'csiso2022kr':
10240 return 'ISO-2022-KR';
10242 case 'cswindows30latin1':
10243 case 'iso88591windows30latin1':
10244 return 'ISO-8859-1-Windows-3.0-Latin-1';
10246 case 'cswindows31latin1':
10247 case 'iso88591windows31latin1':
10248 return 'ISO-8859-1-Windows-3.1-Latin-1';
10250 case 'csisolatin2':
10252 case 'iso885921987':
10256 return 'ISO-8859-2';
10258 case 'cswindows31latin2':
10259 case 'iso88592windowslatin2':
10260 return 'ISO-8859-2-Windows-Latin-2';
10262 case 'csisolatin3':
10264 case 'iso885931988':
10268 return 'ISO-8859-3';
10270 case 'csisolatin4':
10272 case 'iso885941988':
10276 return 'ISO-8859-4';
10278 case 'csisolatincyrillic':
10281 case 'iso885951988':
10283 return 'ISO-8859-5';
10287 case 'csisolatinarabic':
10290 case 'iso885961987':
10292 return 'ISO-8859-6';
10294 case 'csiso88596e':
10296 return 'ISO-8859-6-E';
10298 case 'csiso88596i':
10300 return 'ISO-8859-6-I';
10302 case 'csisolatingreek':
10308 case 'iso885971987':
10310 return 'ISO-8859-7';
10312 case 'csisolatinhebrew':
10315 case 'iso885981988':
10317 return 'ISO-8859-8';
10319 case 'csiso88598e':
10321 return 'ISO-8859-8-E';
10323 case 'csiso88598i':
10325 return 'ISO-8859-8-I';
10327 case 'cswindows31latin5':
10328 case 'iso88599windowslatin5':
10329 return 'ISO-8859-9-Windows-Latin-5';
10331 case 'csisolatin6':
10333 case 'iso8859101992':
10337 return 'ISO-8859-10';
10340 return 'ISO-8859-13';
10343 case 'iso8859141998':
10348 return 'ISO-8859-14';
10352 return 'ISO-8859-15';
10355 case 'iso8859162001':
10359 return 'ISO-8859-16';
10362 return 'ISO-10646-J-1';
10365 case 'iso10646ucs2':
10366 return 'ISO-10646-UCS-2';
10369 case 'iso10646ucs4':
10370 return 'ISO-10646-UCS-4';
10372 case 'csunicodeascii':
10373 case 'iso10646ucsbasic':
10374 return 'ISO-10646-UCS-Basic';
10376 case 'csunicodelatin1':
10378 case 'iso10646unicodelatin1':
10379 return 'ISO-10646-Unicode-Latin1';
10381 case 'csiso10646utf1':
10382 case 'iso10646utf1':
10383 return 'ISO-10646-UTF-1';
10385 case 'csiso115481':
10387 case 'isotr115481':
10388 return 'ISO-11548-1';
10392 return 'iso-ir-90';
10394 case 'csunicodeibm1261':
10395 case 'isounicodeibm1261':
10396 return 'ISO-Unicode-IBM-1261';
10398 case 'csunicodeibm1264':
10399 case 'isounicodeibm1264':
10400 return 'ISO-Unicode-IBM-1264';
10402 case 'csunicodeibm1265':
10403 case 'isounicodeibm1265':
10404 return 'ISO-Unicode-IBM-1265';
10406 case 'csunicodeibm1268':
10407 case 'isounicodeibm1268':
10408 return 'ISO-Unicode-IBM-1268';
10410 case 'csunicodeibm1276':
10411 case 'isounicodeibm1276':
10412 return 'ISO-Unicode-IBM-1276';
10414 case 'csiso646basic1983':
10415 case 'iso646basic1983':
10417 return 'ISO_646.basic:1983';
10419 case 'csiso2intlrefversion':
10421 case 'iso646irv1983':
10423 return 'ISO_646.irv:1983';
10427 case 'iso20331983':
10429 return 'ISO_2033-1983';
10431 case 'csiso5427cyrillic':
10436 case 'iso5427cyrillic1981':
10437 case 'iso54271981':
10439 return 'ISO_5427:1981';
10441 case 'csiso5428greek':
10442 case 'iso54281980':
10444 return 'ISO_5428:1980';
10446 case 'csiso6937add':
10449 return 'ISO_6937-2-25';
10451 case 'csisotextcomm':
10452 case 'iso69372add':
10454 return 'ISO_6937-2-add';
10456 case 'csiso8859supp':
10457 case 'iso8859supp':
10460 return 'ISO_8859-supp';
10462 case 'csiso10367box':
10463 case 'iso10367box':
10465 return 'ISO_10367-box';
10467 case 'csiso15italian':
10473 case 'csiso13jisc6220jp':
10475 case 'jisc62201969':
10476 case 'jisc62201969jp':
10479 return 'JIS_C6220-1969-jp';
10481 case 'csiso14jisc6220ro':
10484 case 'jisc62201969ro':
10486 return 'JIS_C6220-1969-ro';
10488 case 'csiso42jisc62261978':
10490 case 'jisc62261978':
10491 return 'JIS_C6226-1978';
10493 case 'csiso87jisx208':
10495 case 'jisc62261983':
10496 case 'jisx2081983':
10498 return 'JIS_C6226-1983';
10500 case 'csiso91jisc62291984a':
10502 case 'jisc62291984a':
10504 return 'JIS_C6229-1984-a';
10506 case 'csiso92jisc62991984b':
10507 case 'iso646jpocrb':
10509 case 'jisc62291984b':
10511 return 'JIS_C6229-1984-b';
10513 case 'csiso93jis62291984badd':
10515 case 'jisc62291984badd':
10517 return 'JIS_C6229-1984-b-add';
10519 case 'csiso94jis62291984hand':
10521 case 'jisc62291984hand':
10523 return 'JIS_C6229-1984-hand';
10525 case 'csiso95jis62291984handadd':
10527 case 'jisc62291984handadd':
10528 case 'jpocrhandadd':
10529 return 'JIS_C6229-1984-hand-add';
10531 case 'csiso96jisc62291984kana':
10533 case 'jisc62291984kana':
10534 return 'JIS_C6229-1984-kana';
10536 case 'csjisencoding':
10537 case 'jisencoding':
10538 return 'JIS_Encoding';
10540 case 'cshalfwidthkatakana':
10543 return 'JIS_X0201';
10545 case 'csiso159jisx2121990':
10547 case 'jisx2121990':
10549 return 'JIS_X0212-1990';
10551 case 'csiso141jusib1002':
10557 return 'JUS_I.B1.002';
10559 case 'csiso147macedonian':
10561 case 'jusib1003mac':
10563 return 'JUS_I.B1.003-mac';
10565 case 'csiso146serbian':
10567 case 'jusib1003serb':
10569 return 'JUS_I.B1.003-serb';
10571 case 'koi7switched':
10572 return 'KOI7-switched';
10589 case 'strk10482002':
10592 case 'csiso19latingreek':
10595 return 'latin-greek';
10597 case 'csiso27latingreek1':
10599 case 'latingreek1':
10600 return 'Latin-greek-1';
10602 case 'csiso158lap':
10606 return 'latin-lap';
10608 case 'csmacintosh':
10611 return 'macintosh';
10613 case 'csmicrosoftpublishing':
10614 case 'microsoftpublishing':
10615 return 'Microsoft-Publishing';
10625 case 'csiso86hungarian':
10630 return 'MSZ_7795.3';
10635 return 'NATS-DANO';
10637 case 'csnatsdanoadd':
10639 case 'natsdanoadd':
10640 return 'NATS-DANO-ADD';
10645 return 'NATS-SEFI';
10647 case 'csnatssefiadd':
10649 case 'natssefiadd':
10650 return 'NATS-SEFI-ADD';
10652 case 'csiso151cuba':
10657 return 'NC_NC00-10:81';
10659 case 'csiso69french':
10664 return 'NF_Z_62-010';
10666 case 'csiso25french':
10669 case 'nfz620101973':
10670 return 'NF_Z_62-010_(1973)';
10672 case 'csiso60danishnorwegian':
10673 case 'csiso60norwegian1':
10678 return 'NS_4551-1';
10680 case 'csiso61norwegian2':
10685 return 'NS_4551-2';
10687 case 'osdebcdicdf3irv':
10688 return 'OSD_EBCDIC_DF03_IRV';
10690 case 'osdebcdicdf41':
10691 return 'OSD_EBCDIC_DF04_1';
10693 case 'osdebcdicdf415':
10694 return 'OSD_EBCDIC_DF04_15';
10696 case 'cspc8danishnorwegian':
10697 case 'pc8danishnorwegian':
10698 return 'PC8-Danish-Norwegian';
10700 case 'cspc8turkish':
10702 return 'PC8-Turkish';
10704 case 'csiso16portuguese':
10710 case 'csiso84portuguese2':
10718 case 'cyrillicasian':
10726 case 'csiso10swedish':
10733 return 'SEN_850200_B';
10735 case 'csiso11swedishfornames':
10740 return 'SEN_850200_C';
10745 return 'Shift_JIS';
10747 case 'csiso102t617bit':
10750 return 'T.61-7bit';
10752 case 'csiso103t618bit':
10756 return 'T.61-8bit';
10758 case 'csiso128t101g2':
10767 case 'csunicode11':
10769 return 'UNICODE-1-1';
10771 case 'csunicode11utf7':
10772 case 'unicode11utf7':
10773 return 'UNICODE-1-1-UTF-7';
10775 case 'csunknown8bit':
10776 case 'unknown8bit':
10777 return 'UNKNOWN-8BIT';
10779 case 'ansix341968':
10780 case 'ansix341986':
10785 case 'iso646irv1991':
10820 case 'csventurainternational':
10821 case 'venturainternational':
10822 return 'Ventura-International';
10824 case 'csventuramath':
10825 case 'venturamath':
10826 return 'Ventura-Math';
10828 case 'csventuraus':
10830 return 'Ventura-US';
10832 case 'csiso70videotexsupp1':
10834 case 'videotexsuppl':
10835 return 'videotex-suppl';
10845 case 'cswindows31j':
10847 return 'Windows-31J';
10851 return 'windows-874';
10854 case 'csksc56011987':
10859 case 'ksc56011987':
10860 case 'ksc56011989':
10862 return 'windows-949';
10864 case 'windows1250':
10865 return 'windows-1250';
10867 case 'windows1251':
10868 return 'windows-1251';
10871 case 'csisolatin1':
10874 case 'iso885911987':
10878 case 'windows1252':
10879 return 'windows-1252';
10881 case 'windows1253':
10882 return 'windows-1253';
10884 case 'csisolatin5':
10886 case 'iso885991989':
10890 case 'windows1254':
10891 return 'windows-1254';
10893 case 'windows1255':
10894 return 'windows-1255';
10896 case 'windows1256':
10897 return 'windows-1256';
10899 case 'windows1257':
10900 return 'windows-1257';
10902 case 'windows1258':
10903 return 'windows-1258';
10910 function get_curl_version()
10912 if (is_array($curl = curl_version()))
10914 $curl = $curl['version'];
10916 elseif (substr($curl, 0, 5) === 'curl/')
10918 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10920 elseif (substr($curl, 0, 8) === 'libcurl/')
10922 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10931 function is_subclass_of($class1, $class2)
10933 if (func_num_args() !== 2)
10935 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10937 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10939 return is_subclass_of($class1, $class2);
10941 elseif (is_string($class1) && is_string($class2))
10943 if (class_exists($class1))
10945 if (class_exists($class2))
10947 $class2 = strtolower($class2);
10948 while ($class1 = strtolower(get_parent_class($class1)))
10950 if ($class1 === $class2)
10959 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10966 * Strip HTML comments
10969 * @param string $data Data to strip comments from
10970 * @return string Comment stripped string
10972 function strip_comments($data)
10975 while (($start = strpos($data, '<!--')) !== false)
10977 $output .= substr($data, 0, $start);
10978 if (($end = strpos($data, '-->', $start)) !== false)
10980 $data = substr_replace($data, '', 0, $end + 3);
10987 return $output . $data;
10990 function parse_date($dt)
10992 $parser = SimplePie_Parse_Date::get();
10993 return $parser->parse($dt);
10997 * Decode HTML entities
11001 * @param string $data Input data
11002 * @return string Output data
11004 function entities_decode($data)
11006 $decoder = new SimplePie_Decode_HTML_Entities($data);
11007 return $decoder->parse();
11011 * Remove RFC822 comments
11014 * @param string $data Data to strip comments from
11015 * @return string Comment stripped string
11017 function uncomment_rfc822($string)
11019 $string = (string) $string;
11021 $length = strlen($string);
11026 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11028 $output .= substr($string, $position, $pos - $position);
11029 $position = $pos + 1;
11030 if ($string[$pos - 1] !== '\\')
11033 while ($depth && $position < $length)
11035 $position += strcspn($string, '()', $position);
11036 if ($string[$position - 1] === '\\')
11041 elseif (isset($string[$position]))
11043 switch ($string[$position])
11066 $output .= substr($string, $position);
11071 function parse_mime($mime)
11073 if (($pos = strpos($mime, ';')) === false)
11075 return trim($mime);
11079 return trim(substr($mime, 0, $pos));
11083 function htmlspecialchars_decode($string, $quote_style)
11085 if (function_exists('htmlspecialchars_decode'))
11087 return htmlspecialchars_decode($string, $quote_style);
11091 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11095 function atom_03_construct_type($attribs)
11097 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11099 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11103 $mode = SIMPLEPIE_CONSTRUCT_NONE;
11105 if (isset($attribs['']['type']))
11107 switch (strtolower(trim($attribs['']['type'])))
11111 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11115 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11118 case 'application/xhtml+xml':
11119 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11122 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11127 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11131 function atom_10_construct_type($attribs)
11133 if (isset($attribs['']['type']))
11135 switch (strtolower(trim($attribs['']['type'])))
11138 return SIMPLEPIE_CONSTRUCT_TEXT;
11141 return SIMPLEPIE_CONSTRUCT_HTML;
11144 return SIMPLEPIE_CONSTRUCT_XHTML;
11147 return SIMPLEPIE_CONSTRUCT_NONE;
11150 return SIMPLEPIE_CONSTRUCT_TEXT;
11153 function atom_10_content_construct_type($attribs)
11155 if (isset($attribs['']['type']))
11157 $type = strtolower(trim($attribs['']['type']));
11161 return SIMPLEPIE_CONSTRUCT_TEXT;
11164 return SIMPLEPIE_CONSTRUCT_HTML;
11167 return SIMPLEPIE_CONSTRUCT_XHTML;
11169 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11171 return SIMPLEPIE_CONSTRUCT_NONE;
11175 return SIMPLEPIE_CONSTRUCT_BASE64;
11180 return SIMPLEPIE_CONSTRUCT_TEXT;
11184 function is_isegment_nz_nc($string)
11186 return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
11189 function space_seperated_tokens($string)
11191 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11192 $string_length = strlen($string);
11194 $position = strspn($string, $space_characters);
11197 while ($position < $string_length)
11199 $len = strcspn($string, $space_characters, $position);
11200 $tokens[] = substr($string, $position, $len);
11202 $position += strspn($string, $space_characters, $position);
11208 function array_unique($array)
11210 if (version_compare(PHP_VERSION, '5.2', '>='))
11212 return array_unique($array);
11216 $array = (array) $array;
11217 $new_array = array();
11218 $new_array_strings = array();
11219 foreach ($array as $key => $value)
11221 if (is_object($value))
11223 if (method_exists($value, '__toString'))
11225 $cmp = $value->__toString();
11229 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11232 elseif (is_array($value))
11234 $cmp = (string) reset($value);
11238 $cmp = (string) $value;
11240 if (!in_array($cmp, $new_array_strings))
11242 $new_array[$key] = $value;
11243 $new_array_strings[] = $cmp;
11251 * Converts a unicode codepoint to a UTF-8 character
11255 * @param int $codepoint Unicode codepoint
11256 * @return string UTF-8 character
11258 function codepoint_to_utf8($codepoint)
11260 $codepoint = (int) $codepoint;
11261 if ($codepoint < 0)
11265 else if ($codepoint <= 0x7f)
11267 return chr($codepoint);
11269 else if ($codepoint <= 0x7ff)
11271 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11273 else if ($codepoint <= 0xffff)
11275 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11277 else if ($codepoint <= 0x10ffff)
11279 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11283 // U+FFFD REPLACEMENT CHARACTER
11284 return "\xEF\xBF\xBD";
11289 * Re-implementation of PHP 5's stripos()
11291 * Returns the numeric position of the first occurrence of needle in the
11296 * @param object $haystack
11297 * @param string $needle Note that the needle may be a string of one or more
11298 * characters. If needle is not a string, it is converted to an integer
11299 * and applied as the ordinal value of a character.
11300 * @param int $offset The optional offset parameter allows you to specify which
11301 * character in haystack to start searching. The position returned is still
11302 * relative to the beginning of haystack.
11303 * @return bool If needle is not found, stripos() will return boolean false.
11305 function stripos($haystack, $needle, $offset = 0)
11307 if (function_exists('stripos'))
11309 return stripos($haystack, $needle, $offset);
11313 if (is_string($needle))
11315 $needle = strtolower($needle);
11317 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11319 $needle = strtolower(chr($needle));
11323 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11327 return strpos(strtolower($haystack), $needle, $offset);
11332 * Similar to parse_str()
11334 * Returns an associative array of name/value pairs, where the value is an
11335 * array of values that have used the same name
11339 * @param string $str The input string.
11342 function parse_str($str)
11345 $str = explode('&', $str);
11347 foreach ($str as $section)
11349 if (strpos($section, '=') !== false)
11351 list($name, $value) = explode('=', $section, 2);
11352 $return[urldecode($name)][] = urldecode($value);
11356 $return[urldecode($section)][] = null;
11364 * Detect XML encoding, as per XML 1.0 Appendix F.1
11366 * @todo Add support for EBCDIC
11367 * @param string $data XML data
11368 * @return array Possible encodings
11370 function xml_encoding($data)
11372 // UTF-32 Big Endian BOM
11373 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11375 $encoding[] = 'UTF-32BE';
11377 // UTF-32 Little Endian BOM
11378 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11380 $encoding[] = 'UTF-32LE';
11382 // UTF-16 Big Endian BOM
11383 elseif (substr($data, 0, 2) === "\xFE\xFF")
11385 $encoding[] = 'UTF-16BE';
11387 // UTF-16 Little Endian BOM
11388 elseif (substr($data, 0, 2) === "\xFF\xFE")
11390 $encoding[] = 'UTF-16LE';
11393 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11395 $encoding[] = 'UTF-8';
11397 // UTF-32 Big Endian Without BOM
11398 elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
11400 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11402 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11403 if ($parser->parse())
11405 $encoding[] = $parser->encoding;
11408 $encoding[] = 'UTF-32BE';
11410 // UTF-32 Little Endian Without BOM
11411 elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
11413 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11415 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11416 if ($parser->parse())
11418 $encoding[] = $parser->encoding;
11421 $encoding[] = 'UTF-32LE';
11423 // UTF-16 Big Endian Without BOM
11424 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11426 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11428 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11429 if ($parser->parse())
11431 $encoding[] = $parser->encoding;
11434 $encoding[] = 'UTF-16BE';
11436 // UTF-16 Little Endian Without BOM
11437 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11439 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11441 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11442 if ($parser->parse())
11444 $encoding[] = $parser->encoding;
11447 $encoding[] = 'UTF-16LE';
11449 // US-ASCII (or superset)
11450 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11452 if ($pos = strpos($data, "\x3F\x3E"))
11454 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11455 if ($parser->parse())
11457 $encoding[] = $parser->encoding;
11460 $encoding[] = 'UTF-8';
11462 // Fallback to UTF-8
11465 $encoding[] = 'UTF-8';
11470 function output_javascript()
11472 if (function_exists('ob_gzhandler'))
11474 ob_start('ob_gzhandler');
11476 header('Content-type: text/javascript; charset: UTF-8');
11477 header('Cache-Control: must-revalidate');
11478 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11480 function embed_odeo(link) {
11481 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>');
11484 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11485 if (placeholder != '') {
11486 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>');
11489 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>');
11493 function embed_flash(bgcolor, width, height, link, loop, type) {
11494 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>');
11497 function embed_flv(width, height, link, placeholder, loop, player) {
11498 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>');
11501 function embed_wmedia(width, height, link) {
11502 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11509 * Decode HTML Entities
11511 * This implements HTML5 as of revision 967 (2007-06-28)
11513 * @package SimplePie
11515 class SimplePie_Decode_HTML_Entities
11518 * Data to be parsed
11526 * Currently consumed bytes
11531 var $consumed = '';
11534 * Position of the current byte being parsed
11542 * Create an instance of the class with the input data
11545 * @param string $data Input data
11547 function SimplePie_Decode_HTML_Entities($data)
11549 $this->data = $data;
11553 * Parse the input data
11556 * @return string Output data
11560 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11564 $this->consumed = '';
11566 return $this->data;
11570 * Consume the next byte
11573 * @return mixed The next byte, or false, if there is no more data
11577 if (isset($this->data[$this->position]))
11579 $this->consumed .= $this->data[$this->position];
11580 return $this->data[$this->position++];
11589 * Consume a range of characters
11592 * @param string $chars Characters to consume
11593 * @return mixed A series of characters that match the range, or false
11595 function consume_range($chars)
11597 if ($len = strspn($this->data, $chars, $this->position))
11599 $data = substr($this->data, $this->position, $len);
11600 $this->consumed .= $data;
11601 $this->position += $len;
11611 * Unconsume one byte
11615 function unconsume()
11617 $this->consumed = substr($this->consumed, 0, -1);
11628 switch ($this->consume())
11642 switch ($this->consume())
11646 $range = '0123456789ABCDEFabcdef';
11651 $range = '0123456789';
11653 $this->unconsume();
11657 if ($codepoint = $this->consume_range($range))
11659 static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
11663 $codepoint = hexdec($codepoint);
11667 $codepoint = intval($codepoint);
11670 if (isset($windows_1252_specials[$codepoint]))
11672 $replacement = $windows_1252_specials[$codepoint];
11676 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11679 if (!in_array($this->consume(), array(';', false), true))
11681 $this->unconsume();
11684 $consumed_length = strlen($this->consumed);
11685 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11686 $this->position += strlen($replacement) - $consumed_length;
11691 static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
11693 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11695 $consumed = substr($this->consumed, 1);
11696 if (isset($entities[$consumed]))
11698 $match = $consumed;
11702 if ($match !== null)
11704 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11705 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11713 * IRI parser/serialiser
11715 * @package SimplePie
11717 class SimplePie_IRI
11776 * Whether the object represents a valid IRI
11781 var $valid = array();
11784 * Return the entire IRI when you try and read the object as a string
11789 function __toString()
11791 return $this->get_iri();
11795 * Create a new IRI object, from a specified string
11798 * @param string $iri
11799 * @return SimplePie_IRI
11801 function SimplePie_IRI($iri)
11803 $iri = (string) $iri;
11806 $parsed = $this->parse_iri($iri);
11807 $this->set_scheme($parsed['scheme']);
11808 $this->set_authority($parsed['authority']);
11809 $this->set_path($parsed['path']);
11810 $this->set_query($parsed['query']);
11811 $this->set_fragment($parsed['fragment']);
11816 * Create a new IRI object by resolving a relative IRI
11820 * @param SimplePie_IRI $base Base IRI
11821 * @param string $relative Relative IRI
11822 * @return SimplePie_IRI
11824 function absolutize($base, $relative)
11826 $relative = (string) $relative;
11827 if ($relative !== '')
11829 $relative = new SimplePie_IRI($relative);
11830 if ($relative->get_scheme() !== null)
11832 $target = $relative;
11834 elseif ($base->get_iri() !== null)
11836 if ($relative->get_authority() !== null)
11838 $target = $relative;
11839 $target->set_scheme($base->get_scheme());
11843 $target = new SimplePie_IRI('');
11844 $target->set_scheme($base->get_scheme());
11845 $target->set_userinfo($base->get_userinfo());
11846 $target->set_host($base->get_host());
11847 $target->set_port($base->get_port());
11848 if ($relative->get_path() !== null)
11850 if (strpos($relative->get_path(), '/') === 0)
11852 $target->set_path($relative->get_path());
11854 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11856 $target->set_path('/' . $relative->get_path());
11858 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11860 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11864 $target->set_path($relative->get_path());
11866 $target->set_query($relative->get_query());
11870 $target->set_path($base->get_path());
11871 if ($relative->get_query() !== null)
11873 $target->set_query($relative->get_query());
11875 elseif ($base->get_query() !== null)
11877 $target->set_query($base->get_query());
11881 $target->set_fragment($relative->get_fragment());
11885 // No base URL, just return the relative URL
11886 $target = $relative;
11897 * Parse an IRI into scheme/authority/path/query/fragment segments
11900 * @param string $iri
11903 function parse_iri($iri)
11905 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11906 for ($i = count($match); $i <= 9; $i++)
11910 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11914 * Remove dot segments from a path
11917 * @param string $input
11920 function remove_dot_segments($input)
11923 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11925 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11926 if (strpos($input, '../') === 0)
11928 $input = substr($input, 3);
11930 elseif (strpos($input, './') === 0)
11932 $input = substr($input, 2);
11934 // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
11935 elseif (strpos($input, '/./') === 0)
11937 $input = substr_replace($input, '/', 0, 3);
11939 elseif ($input === '/.')
11943 // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
11944 elseif (strpos($input, '/../') === 0)
11946 $input = substr_replace($input, '/', 0, 4);
11947 $output = substr_replace($output, '', strrpos($output, '/'));
11949 elseif ($input === '/..')
11952 $output = substr_replace($output, '', strrpos($output, '/'));
11954 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11955 elseif ($input === '.' || $input === '..')
11959 // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
11960 elseif (($pos = strpos($input, '/', 1)) !== false)
11962 $output .= substr($input, 0, $pos);
11963 $input = substr_replace($input, '', 0, $pos);
11971 return $output . $input;
11975 * Replace invalid character with percent encoding
11978 * @param string $string Input string
11979 * @param string $valid_chars Valid characters
11980 * @param int $case Normalise case
11983 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11986 if ($case & SIMPLEPIE_LOWERCASE)
11988 $string = strtolower($string);
11990 elseif ($case & SIMPLEPIE_UPPERCASE)
11992 $string = strtoupper($string);
11995 // Store position and string length (to avoid constantly recalculating this)
11997 $strlen = strlen($string);
11999 // Loop as long as we have invalid characters, advancing the position to the next invalid character
12000 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
12002 // If we have a % character
12003 if ($string[$position] === '%')
12005 // If we have a pct-encoded section
12006 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
12008 // Get the the represented character
12009 $chr = chr(hexdec(substr($string, $position + 1, 2)));
12011 // If the character is valid, replace the pct-encoded with the actual character while normalising case
12012 if (strpos($valid_chars, $chr) !== false)
12014 if ($case & SIMPLEPIE_LOWERCASE)
12016 $chr = strtolower($chr);
12018 elseif ($case & SIMPLEPIE_UPPERCASE)
12020 $chr = strtoupper($chr);
12022 $string = substr_replace($string, $chr, $position, 3);
12027 // Otherwise just normalise the pct-encoded to uppercase
12030 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
12034 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
12037 $string = substr_replace($string, '%25', $position, 1);
12042 // If we have an invalid character, change into its pct-encoded form
12045 $replacement = sprintf("%%%02X", ord($string[$position]));
12046 $string = str_replace($string[$position], $replacement, $string);
12047 $strlen = strlen($string);
12054 * Check if the object represents a valid IRI
12059 function is_valid()
12061 return array_sum($this->valid) === count($this->valid);
12065 * Set the scheme. Returns true on success, false on failure (if there are
12066 * any invalid characters).
12069 * @param string $scheme
12072 function set_scheme($scheme)
12074 if ($scheme === null || $scheme === '')
12076 $this->scheme = null;
12080 $len = strlen($scheme);
12084 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12086 $this->scheme = null;
12087 $this->valid[__FUNCTION__] = false;
12092 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12094 $this->scheme = null;
12095 $this->valid[__FUNCTION__] = false;
12099 $this->scheme = strtolower($scheme);
12101 $this->valid[__FUNCTION__] = true;
12106 * Set the authority. Returns true on success, false on failure (if there are
12107 * any invalid characters).
12110 * @param string $authority
12113 function set_authority($authority)
12115 if (($userinfo_end = strrpos($authority, '@')) !== false)
12117 $userinfo = substr($authority, 0, $userinfo_end);
12118 $authority = substr($authority, $userinfo_end + 1);
12125 if (($port_start = strpos($authority, ':')) !== false)
12127 $port = substr($authority, $port_start + 1);
12128 $authority = substr($authority, 0, $port_start);
12135 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12139 * Set the userinfo.
12142 * @param string $userinfo
12145 function set_userinfo($userinfo)
12147 if ($userinfo === null || $userinfo === '')
12149 $this->userinfo = null;
12153 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12155 $this->valid[__FUNCTION__] = true;
12160 * Set the host. Returns true on success, false on failure (if there are
12161 * any invalid characters).
12164 * @param string $host
12167 function set_host($host)
12169 if ($host === null || $host === '')
12171 $this->host = null;
12172 $this->valid[__FUNCTION__] = true;
12175 elseif ($host[0] === '[' && substr($host, -1) === ']')
12177 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12179 $this->host = $host;
12180 $this->valid[__FUNCTION__] = true;
12185 $this->host = null;
12186 $this->valid[__FUNCTION__] = false;
12192 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12193 $this->valid[__FUNCTION__] = true;
12199 * Set the port. Returns true on success, false on failure (if there are
12200 * any invalid characters).
12203 * @param string $port
12206 function set_port($port)
12208 if ($port === null || $port === '')
12210 $this->port = null;
12211 $this->valid[__FUNCTION__] = true;
12214 elseif (strspn($port, '0123456789') === strlen($port))
12216 $this->port = (int) $port;
12217 $this->valid[__FUNCTION__] = true;
12222 $this->port = null;
12223 $this->valid[__FUNCTION__] = false;
12232 * @param string $path
12235 function set_path($path)
12237 if ($path === null || $path === '')
12239 $this->path = null;
12240 $this->valid[__FUNCTION__] = true;
12243 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12245 $this->path = null;
12246 $this->valid[__FUNCTION__] = false;
12251 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12252 if ($this->scheme !== null)
12254 $this->path = $this->remove_dot_segments($this->path);
12256 $this->valid[__FUNCTION__] = true;
12265 * @param string $query
12268 function set_query($query)
12270 if ($query === null || $query === '')
12272 $this->query = null;
12276 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
12278 $this->valid[__FUNCTION__] = true;
12283 * Set the fragment.
12286 * @param string $fragment
12289 function set_fragment($fragment)
12291 if ($fragment === null || $fragment === '')
12293 $this->fragment = null;
12297 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12299 $this->valid[__FUNCTION__] = true;
12304 * Get the complete IRI
12312 if ($this->scheme !== null)
12314 $iri .= $this->scheme . ':';
12316 if (($authority = $this->get_authority()) !== null)
12318 $iri .= '//' . $authority;
12320 if ($this->path !== null)
12322 $iri .= $this->path;
12324 if ($this->query !== null)
12326 $iri .= '?' . $this->query;
12328 if ($this->fragment !== null)
12330 $iri .= '#' . $this->fragment;
12349 function get_scheme()
12351 return $this->scheme;
12355 * Get the complete authority
12360 function get_authority()
12363 if ($this->userinfo !== null)
12365 $authority .= $this->userinfo . '@';
12367 if ($this->host !== null)
12369 $authority .= $this->host;
12371 if ($this->port !== null)
12373 $authority .= ':' . $this->port;
12376 if ($authority !== '')
12387 * Get the user information
12392 function get_userinfo()
12394 return $this->userinfo;
12403 function get_host()
12405 return $this->host;
12414 function get_port()
12416 return $this->port;
12425 function get_path()
12427 return $this->path;
12436 function get_query()
12438 return $this->query;
12447 function get_fragment()
12449 return $this->fragment;
12454 * Class to validate and to work with IPv6 addresses.
12456 * @package SimplePie
12457 * @copyright 2003-2005 The PHP Group
12458 * @license http://www.opensource.org/licenses/bsd-license.php
12459 * @link http://pear.php.net/package/Net_IPv6
12460 * @author Alexander Merz <alexander.merz@web.de>
12461 * @author elfrink at introweb dot nl
12462 * @author Josh Peck <jmp at joshpeck dot org>
12463 * @author Geoffrey Sneddon <geoffers@gmail.com>
12465 class SimplePie_Net_IPv6
12468 * Removes a possible existing netmask specification of an IP address.
12470 * @param string $ip the (compressed) IP as Hex representation
12471 * @return string the IP the without netmask
12476 function removeNetmaskSpec($ip)
12478 if (strpos($ip, '/') !== false)
12480 list($addr, $nm) = explode('/', $ip);
12490 * Uncompresses an IPv6 address
12492 * RFC 2373 allows you to compress zeros in an address to '::'. This
12493 * function expects an valid IPv6 address and expands the '::' to
12494 * the required zeros.
12496 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12497 * ::1 -> 0:0:0:0:0:0:0:1
12501 * @param string $ip a valid IPv6-address (hex format)
12502 * @return string the uncompressed IPv6-address (hex format)
12504 function Uncompress($ip)
12506 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12509 if (strpos($ip, '::') !== false)
12511 list($ip1, $ip2) = explode('::', $ip);
12519 if (($pos = substr_count($ip1, ':')) > 0)
12535 if (($pos = substr_count($ip2, ':')) > 0)
12544 if (strstr($ip2, '.'))
12549 if ($c1 === -1 && $c2 === -1)
12551 $uip = '0:0:0:0:0:0:0:0';
12554 else if ($c1 === -1)
12556 $fill = str_repeat('0:', 7 - $c2);
12557 $uip = str_replace('::', $fill, $uip);
12560 else if ($c2 === -1)
12562 $fill = str_repeat(':0', 7 - $c1);
12563 $uip = str_replace('::', $fill, $uip);
12568 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12569 $uip = str_replace('::', $fill, $uip);
12570 $uip = str_replace('::', ':', $uip);
12577 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12579 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12580 * an IPv4 compatible address
12582 * Example: 0:0:0:0:0:0:13.1.68.3
12583 * 0:0:0:0:0:FFFF:129.144.52.38
12587 * @param string $ip a valid IPv6-address (hex format)
12588 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12590 function SplitV64($ip)
12592 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12593 if (strstr($ip, '.'))
12595 $pos = strrpos($ip, ':');
12597 $ipPart = explode('_', $ip);
12602 return array($ip, '');
12607 * Checks an IPv6 address
12609 * Checks if the given IP is IPv6-compatible
12613 * @param string $ip a valid IPv6-address
12614 * @return bool true if $ip is an IPv6 address
12616 function checkIPv6($ip)
12618 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12620 if (!empty($ipPart[0]))
12622 $ipv6 = explode(':', $ipPart[0]);
12623 for ($i = 0; $i < count($ipv6); $i++)
12625 $dec = hexdec($ipv6[$i]);
12626 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12627 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12636 elseif ($count === 6 && !empty($ipPart[1]))
12638 $ipv4 = explode('.', $ipPart[1]);
12640 foreach ($ipv4 as $ipv4_part)
12642 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12668 * @package SimplePie
12670 class SimplePie_Parse_Date
12675 * @access protected
12681 * List of days, calendar day name => ordinal day number in the week
12683 * @access protected
12746 'keskiviikko' => 3,
12770 * List of months, calendar month name => calendar month number
12772 * @access protected
12775 var $month = array(
12786 // No long form of May
12915 * List of timezones, abbreviation => offset from UTC
12917 * @access protected
12920 var $timezone = array(
13123 * Cached PCRE for SimplePie_Parse_Date::$day
13125 * @access protected
13131 * Cached PCRE for SimplePie_Parse_Date::$month
13133 * @access protected
13139 * Array of user-added callback methods
13144 var $built_in = array();
13147 * Array of user-added callback methods
13152 var $user = array();
13155 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13156 * self::month_pcre, and self::built_in
13160 function SimplePie_Parse_Date()
13162 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13163 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13166 if (!isset($cache[get_class($this)]))
13168 $all_methods = get_class_methods($this);
13170 foreach ($all_methods as $method)
13172 if (strtolower(substr($method, 0, 5)) === 'date_')
13174 $cache[get_class($this)][] = $method;
13179 foreach ($cache[get_class($this)] as $method)
13181 $this->built_in[] = $method;
13195 $object = new SimplePie_Parse_Date;
13205 * @param string $date Date to parse
13206 * @return int Timestamp corresponding to date string, or false on failure
13208 function parse($date)
13210 foreach ($this->user as $method)
13212 if (($returned = call_user_func($method, $date)) !== false)
13218 foreach ($this->built_in as $method)
13220 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13230 * Add a callback method to parse a date
13234 * @param callback $callback
13236 function add_callback($callback)
13238 if (is_callable($callback))
13240 $this->user[] = $callback;
13244 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13249 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13250 * well as allowing any of upper or lower case "T", horizontal tabs, or
13251 * spaces to be used as the time seperator (including more than one))
13253 * @access protected
13254 * @return int Timestamp
13256 function date_w3cdtf($date)
13261 $year = '([0-9]{4})';
13262 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13263 $decimal = '([0-9]*)';
13264 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13265 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13267 if (preg_match($pcre, $date, $match))
13270 Capturing subpatterns:
13277 7: Decimal fraction of a second
13281 11: Timezone minutes
13284 // Fill in empty matches
13285 for ($i = count($match); $i <= 3; $i++)
13290 for ($i = count($match); $i <= 7; $i++)
13295 // Numeric timezone
13296 if (isset($match[9]) && $match[9] !== '')
13298 $timezone = $match[10] * 3600;
13299 $timezone += $match[11] * 60;
13300 if ($match[9] === '-')
13302 $timezone = 0 - $timezone;
13310 // Convert the number of seconds to an integer, taking decimals into account
13311 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13313 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13322 * Remove RFC822 comments
13324 * @access protected
13325 * @param string $data Data to strip comments from
13326 * @return string Comment stripped string
13328 function remove_rfc2822_comments($string)
13330 $string = (string) $string;
13332 $length = strlen($string);
13337 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13339 $output .= substr($string, $position, $pos - $position);
13340 $position = $pos + 1;
13341 if ($string[$pos - 1] !== '\\')
13344 while ($depth && $position < $length)
13346 $position += strcspn($string, '()', $position);
13347 if ($string[$position - 1] === '\\')
13352 elseif (isset($string[$position]))
13354 switch ($string[$position])
13377 $output .= substr($string, $position);
13383 * Parse RFC2822's date format
13385 * @access protected
13386 * @return int Timestamp
13388 function date_rfc2822($date)
13393 $wsp = '[\x09\x20]';
13394 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13395 $optional_fws = $fws . '?';
13396 $day_name = $this->day_pcre;
13397 $month = $this->month_pcre;
13398 $day = '([0-9]{1,2})';
13399 $hour = $minute = $second = '([0-9]{2})';
13400 $year = '([0-9]{2,4})';
13401 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13402 $character_zone = '([A-Z]{1,5})';
13403 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13404 $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
13406 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13409 Capturing subpatterns:
13419 10: Timezone minutes
13420 11: Alphabetic timezone
13423 // Find the month number
13424 $month = $this->month[strtolower($match[3])];
13426 // Numeric timezone
13427 if ($match[8] !== '')
13429 $timezone = $match[9] * 3600;
13430 $timezone += $match[10] * 60;
13431 if ($match[8] === '-')
13433 $timezone = 0 - $timezone;
13436 // Character timezone
13437 elseif (isset($this->timezone[strtoupper($match[11])]))
13439 $timezone = $this->timezone[strtoupper($match[11])];
13441 // Assume everything else to be -0000
13447 // Deal with 2/3 digit years
13448 if ($match[4] < 50)
13452 elseif ($match[4] < 1000)
13457 // Second is optional, if it is empty set it to zero
13458 if ($match[7] !== '')
13460 $second = $match[7];
13467 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13476 * Parse RFC850's date format
13478 * @access protected
13479 * @return int Timestamp
13481 function date_rfc850($date)
13486 $space = '[\x09\x20]+';
13487 $day_name = $this->day_pcre;
13488 $month = $this->month_pcre;
13489 $day = '([0-9]{1,2})';
13490 $year = $hour = $minute = $second = '([0-9]{2})';
13491 $zone = '([A-Z]{1,5})';
13492 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13494 if (preg_match($pcre, $date, $match))
13497 Capturing subpatterns:
13509 $month = $this->month[strtolower($match[3])];
13511 // Character timezone
13512 if (isset($this->timezone[strtoupper($match[8])]))
13514 $timezone = $this->timezone[strtoupper($match[8])];
13516 // Assume everything else to be -0000
13522 // Deal with 2 digit year
13523 if ($match[4] < 50)
13532 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13541 * Parse C99's asctime()'s date format
13543 * @access protected
13544 * @return int Timestamp
13546 function date_asctime($date)
13551 $space = '[\x09\x20]+';
13552 $wday_name = $this->day_pcre;
13553 $mon_name = $this->month_pcre;
13554 $day = '([0-9]{1,2})';
13555 $hour = $sec = $min = '([0-9]{2})';
13556 $year = '([0-9]{4})';
13557 $terminator = '\x0A?\x00?';
13558 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13560 if (preg_match($pcre, $date, $match))
13563 Capturing subpatterns:
13573 $month = $this->month[strtolower($match[2])];
13574 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13583 * Parse dates using strtotime()
13585 * @access protected
13586 * @return int Timestamp
13588 function date_strtotime($date)
13590 $strtotime = strtotime($date);
13591 if ($strtotime === -1 || $strtotime === false)
13603 * Content-type sniffing
13605 * @package SimplePie
13607 class SimplePie_Content_Type_Sniffer
13612 * @var SimplePie_File
13618 * Create an instance of the class with the input file
13621 * @param SimplePie_Content_Type_Sniffer $file Input file
13623 function SimplePie_Content_Type_Sniffer($file)
13625 $this->file = $file;
13629 * Get the Content-Type of the specified file
13632 * @return string Actual Content-Type
13634 function get_type()
13636 if (isset($this->file->headers['content-type']))
13638 if (!isset($this->file->headers['content-encoding'])
13639 && ($this->file->headers['content-type'] === 'text/plain'
13640 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13641 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13643 return $this->text_or_binary();
13646 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13648 $official = substr($this->file->headers['content-type'], 0, $pos);
13652 $official = $this->file->headers['content-type'];
13654 $official = strtolower($official);
13656 if ($official === 'unknown/unknown'
13657 || $official === 'application/unknown')
13659 return $this->unknown();
13661 elseif (substr($official, -4) === '+xml'
13662 || $official === 'text/xml'
13663 || $official === 'application/xml')
13667 elseif (substr($official, 0, 6) === 'image/')
13669 if ($return = $this->image())
13678 elseif ($official === 'text/html')
13680 return $this->feed_or_html();
13689 return $this->unknown();
13694 * Sniff text or binary
13697 * @return string Actual Content-Type
13699 function text_or_binary()
13701 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13702 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13703 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13704 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13706 return 'text/plain';
13708 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13710 return 'application/octect-stream';
13714 return 'text/plain';
13722 * @return string Actual Content-Type
13726 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13727 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13728 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13729 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13731 return 'text/html';
13733 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13735 return 'application/pdf';
13737 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13739 return 'application/postscript';
13741 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13742 || substr($this->file->body, 0, 6) === 'GIF89a')
13744 return 'image/gif';
13746 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13748 return 'image/png';
13750 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13752 return 'image/jpeg';
13754 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13756 return 'image/bmp';
13760 return $this->text_or_binary();
13768 * @return string Actual Content-Type
13772 if (substr($this->file->body, 0, 6) === 'GIF87a'
13773 || substr($this->file->body, 0, 6) === 'GIF89a')
13775 return 'image/gif';
13777 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13779 return 'image/png';
13781 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13783 return 'image/jpeg';
13785 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13787 return 'image/bmp';
13799 * @return string Actual Content-Type
13801 function feed_or_html()
13803 $len = strlen($this->file->body);
13804 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13806 while ($pos < $len)
13808 switch ($this->file->body[$pos])
13814 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13822 return 'text/html';
13825 if (substr($this->file->body, $pos, 3) === '!--')
13828 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13834 return 'text/html';
13837 elseif (substr($this->file->body, $pos, 1) === '!')
13839 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13845 return 'text/html';
13848 elseif (substr($this->file->body, $pos, 1) === '?')
13850 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13856 return 'text/html';
13859 elseif (substr($this->file->body, $pos, 3) === 'rss'
13860 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13862 return 'application/rss+xml';
13864 elseif (substr($this->file->body, $pos, 4) === 'feed')
13866 return 'application/atom+xml';
13870 return 'text/html';
13874 return 'text/html';
13879 * Parses the XML Declaration
13881 * @package SimplePie
13883 class SimplePie_XML_Declaration_Parser
13891 var $version = '1.0';
13899 var $encoding = 'UTF-8';
13907 var $standalone = false;
13910 * Current state of the state machine
13915 var $state = 'before_version_name';
13926 * Input data length (to avoid calling strlen() everytime this is needed)
13931 var $data_length = 0;
13934 * Current position of the pointer
13942 * Create an instance of the class with the input data
13945 * @param string $data Input data
13947 function SimplePie_XML_Declaration_Parser($data)
13949 $this->data = $data;
13950 $this->data_length = strlen($this->data);
13954 * Parse the input data
13957 * @return bool true on success, false on failure
13961 while ($this->state && $this->state !== 'emit' && $this->has_data())
13963 $state = $this->state;
13967 if ($this->state === 'emit')
13973 $this->version = '';
13974 $this->encoding = '';
13975 $this->standalone = '';
13981 * Check whether there is data beyond the pointer
13984 * @return bool true if there is further data, false if not
13986 function has_data()
13988 return (bool) ($this->position < $this->data_length);
13992 * Advance past any whitespace
13994 * @return int Number of whitespace characters passed
13996 function skip_whitespace()
13998 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13999 $this->position += $whitespace;
14000 return $whitespace;
14006 function get_value()
14008 $quote = substr($this->data, $this->position, 1);
14009 if ($quote === '"' || $quote === "'")
14012 $len = strcspn($this->data, $quote, $this->position);
14013 if ($this->has_data())
14015 $value = substr($this->data, $this->position, $len);
14016 $this->position += $len + 1;
14023 function before_version_name()
14025 if ($this->skip_whitespace())
14027 $this->state = 'version_name';
14031 $this->state = false;
14035 function version_name()
14037 if (substr($this->data, $this->position, 7) === 'version')
14039 $this->position += 7;
14040 $this->skip_whitespace();
14041 $this->state = 'version_equals';
14045 $this->state = false;
14049 function version_equals()
14051 if (substr($this->data, $this->position, 1) === '=')
14054 $this->skip_whitespace();
14055 $this->state = 'version_value';
14059 $this->state = false;
14063 function version_value()
14065 if ($this->version = $this->get_value())
14067 $this->skip_whitespace();
14068 if ($this->has_data())
14070 $this->state = 'encoding_name';
14074 $this->state = 'emit';
14079 $this->state = false;
14083 function encoding_name()
14085 if (substr($this->data, $this->position, 8) === 'encoding')
14087 $this->position += 8;
14088 $this->skip_whitespace();
14089 $this->state = 'encoding_equals';
14093 $this->state = 'standalone_name';
14097 function encoding_equals()
14099 if (substr($this->data, $this->position, 1) === '=')
14102 $this->skip_whitespace();
14103 $this->state = 'encoding_value';
14107 $this->state = false;
14111 function encoding_value()
14113 if ($this->encoding = $this->get_value())
14115 $this->skip_whitespace();
14116 if ($this->has_data())
14118 $this->state = 'standalone_name';
14122 $this->state = 'emit';
14127 $this->state = false;
14131 function standalone_name()
14133 if (substr($this->data, $this->position, 10) === 'standalone')
14135 $this->position += 10;
14136 $this->skip_whitespace();
14137 $this->state = 'standalone_equals';
14141 $this->state = false;
14145 function standalone_equals()
14147 if (substr($this->data, $this->position, 1) === '=')
14150 $this->skip_whitespace();
14151 $this->state = 'standalone_value';
14155 $this->state = false;
14159 function standalone_value()
14161 if ($standalone = $this->get_value())
14163 switch ($standalone)
14166 $this->standalone = true;
14170 $this->standalone = false;
14174 $this->state = false;
14178 $this->skip_whitespace();
14179 if ($this->has_data())
14181 $this->state = false;
14185 $this->state = 'emit';
14190 $this->state = false;
14195 class SimplePie_Locator
14200 var $local = array();
14201 var $elsewhere = array();
14202 var $file_class = 'SimplePie_File';
14203 var $cached_entities = array();
14206 var $base_location = 0;
14207 var $checked_feeds = 0;
14208 var $max_checked_feeds = 10;
14209 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14211 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14213 $this->file =& $file;
14214 $this->file_class = $file_class;
14215 $this->useragent = $useragent;
14216 $this->timeout = $timeout;
14217 $this->max_checked_feeds = $max_checked_feeds;
14218 $this->content_type_sniffer_class = $content_type_sniffer_class;
14221 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14223 if ($this->is_feed($this->file))
14225 return $this->file;
14228 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14230 $sniffer = new $this->content_type_sniffer_class($this->file);
14231 if ($sniffer->get_type() !== 'text/html')
14237 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14242 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14244 return $working[0];
14247 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14249 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14254 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14259 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14264 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14272 function is_feed(&$file)
14274 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14276 $sniffer = new $this->content_type_sniffer_class($file);
14277 $sniffed = $sniffer->get_type();
14278 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14287 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14297 function get_base()
14299 $this->http_base = $this->file->url;
14300 $this->base = $this->http_base;
14301 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14302 foreach ($elements as $element)
14304 if ($element['attribs']['href']['data'] !== '')
14306 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14307 $this->base_location = $element['offset'];
14313 function autodiscovery()
14315 $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
14318 foreach ($links as $link)
14320 if ($this->checked_feeds === $this->max_checked_feeds)
14324 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14326 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14328 if ($this->base_location < $link['offset'])
14330 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14334 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14337 if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
14339 $this->checked_feeds++;
14340 $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14341 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14343 $feeds[$href] = $feed;
14350 if (!empty($feeds))
14352 return array_values($feeds);
14359 function get_links()
14361 $links = SimplePie_Misc::get_element('a', $this->file->body);
14362 foreach ($links as $link)
14364 if (isset($link['attribs']['href']['data']))
14366 $href = trim($link['attribs']['href']['data']);
14367 $parsed = SimplePie_Misc::parse_url($href);
14368 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14370 if ($this->base_location < $link['offset'])
14372 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14376 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14379 $current = SimplePie_Misc::parse_url($this->file->url);
14381 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14383 $this->local[] = $href;
14387 $this->elsewhere[] = $href;
14392 $this->local = array_unique($this->local);
14393 $this->elsewhere = array_unique($this->elsewhere);
14394 if (!empty($this->local) || !empty($this->elsewhere))
14401 function extension(&$array)
14403 foreach ($array as $key => $value)
14405 if ($this->checked_feeds === $this->max_checked_feeds)
14409 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14411 $this->checked_feeds++;
14412 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14413 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14419 unset($array[$key]);
14426 function body(&$array)
14428 foreach ($array as $key => $value)
14430 if ($this->checked_feeds === $this->max_checked_feeds)
14434 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14436 $this->checked_feeds++;
14437 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14438 if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
14444 unset($array[$key]);
14452 class SimplePie_Parser
14457 var $current_column;
14459 var $separator = ' ';
14460 var $namespace = array('');
14461 var $element = array('');
14462 var $xml_base = array('');
14463 var $xml_base_explicit = array(false);
14464 var $xml_lang = array('');
14465 var $data = array();
14466 var $datas = array(array());
14467 var $current_xhtml_construct = -1;
14470 function parse(&$data, $encoding)
14472 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14473 if (strtoupper($encoding) === 'US-ASCII')
14475 $this->encoding = 'UTF-8';
14479 $this->encoding = $encoding;
14483 // UTF-32 Big Endian BOM
14484 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14486 $data = substr($data, 4);
14488 // UTF-32 Little Endian BOM
14489 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14491 $data = substr($data, 4);
14493 // UTF-16 Big Endian BOM
14494 elseif (substr($data, 0, 2) === "\xFE\xFF")
14496 $data = substr($data, 2);
14498 // UTF-16 Little Endian BOM
14499 elseif (substr($data, 0, 2) === "\xFF\xFE")
14501 $data = substr($data, 2);
14504 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14506 $data = substr($data, 3);
14509 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14511 $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14512 if ($declaration->parse())
14514 $data = substr($data, $pos + 2);
14515 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14519 $this->error_string = 'SimplePie bug! Please report this!';
14526 static $xml_is_sane = null;
14527 if ($xml_is_sane === null)
14529 $parser_check = xml_parser_create();
14530 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
14531 xml_parser_free($parser_check);
14532 $xml_is_sane = isset($values[0]['value']);
14535 // Create the parser
14538 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14539 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14540 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14541 xml_set_object($xml, $this);
14542 xml_set_character_data_handler($xml, 'cdata');
14543 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14546 if (!xml_parse($xml, $data, true))
14548 $this->error_code = xml_get_error_code($xml);
14549 $this->error_string = xml_error_string($this->error_code);
14552 $this->current_line = xml_get_current_line_number($xml);
14553 $this->current_column = xml_get_current_column_number($xml);
14554 $this->current_byte = xml_get_current_byte_index($xml);
14555 xml_parser_free($xml);
14560 libxml_clear_errors();
14561 $xml = new XMLReader();
14563 while (@$xml->read())
14565 switch ($xml->nodeType)
14568 case constant('XMLReader::END_ELEMENT'):
14569 if ($xml->namespaceURI !== '')
14571 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14575 $tagName = $xml->localName;
14577 $this->tag_close(null, $tagName);
14579 case constant('XMLReader::ELEMENT'):
14580 $empty = $xml->isEmptyElement;
14581 if ($xml->namespaceURI !== '')
14583 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14587 $tagName = $xml->localName;
14589 $attributes = array();
14590 while ($xml->moveToNextAttribute())
14592 if ($xml->namespaceURI !== '')
14594 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14598 $attrName = $xml->localName;
14600 $attributes[$attrName] = $xml->value;
14602 $this->tag_open(null, $tagName, $attributes);
14605 $this->tag_close(null, $tagName);
14608 case constant('XMLReader::TEXT'):
14610 case constant('XMLReader::CDATA'):
14611 $this->cdata(null, $xml->value);
14615 if ($error = libxml_get_last_error())
14617 $this->error_code = $error->code;
14618 $this->error_string = $error->message;
14619 $this->current_line = $error->line;
14620 $this->current_column = $error->column;
14630 function get_error_code()
14632 return $this->error_code;
14635 function get_error_string()
14637 return $this->error_string;
14640 function get_current_line()
14642 return $this->current_line;
14645 function get_current_column()
14647 return $this->current_column;
14650 function get_current_byte()
14652 return $this->current_byte;
14655 function get_data()
14657 return $this->data;
14660 function tag_open($parser, $tag, $attributes)
14662 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14664 $attribs = array();
14665 foreach ($attributes as $name => $value)
14667 list($attrib_namespace, $attribute) = $this->split_ns($name);
14668 $attribs[$attrib_namespace][$attribute] = $value;
14671 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14673 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14674 $this->xml_base_explicit[] = true;
14678 $this->xml_base[] = end($this->xml_base);
14679 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14682 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14684 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14688 $this->xml_lang[] = end($this->xml_lang);
14691 if ($this->current_xhtml_construct >= 0)
14693 $this->current_xhtml_construct++;
14694 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14696 $this->data['data'] .= '<' . end($this->element);
14697 if (isset($attribs['']))
14699 foreach ($attribs[''] as $name => $value)
14701 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14704 $this->data['data'] .= '>';
14709 $this->datas[] =& $this->data;
14710 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14711 $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
14712 if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
14713 || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml'))
14715 $this->current_xhtml_construct = 0;
14720 function cdata($parser, $cdata)
14722 if ($this->current_xhtml_construct >= 0)
14724 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14728 $this->data['data'] .= $cdata;
14732 function tag_close($parser, $tag)
14734 if ($this->current_xhtml_construct >= 0)
14736 $this->current_xhtml_construct--;
14737 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
14739 $this->data['data'] .= '</' . end($this->element) . '>';
14742 if ($this->current_xhtml_construct === -1)
14744 $this->data =& $this->datas[count($this->datas) - 1];
14745 array_pop($this->datas);
14748 array_pop($this->element);
14749 array_pop($this->namespace);
14750 array_pop($this->xml_base);
14751 array_pop($this->xml_base_explicit);
14752 array_pop($this->xml_lang);
14755 function split_ns($string)
14757 static $cache = array();
14758 if (!isset($cache[$string]))
14760 if ($pos = strpos($string, $this->separator))
14762 static $separator_length;
14763 if (!$separator_length)
14765 $separator_length = strlen($this->separator);
14767 $namespace = substr($string, 0, $pos);
14768 $local_name = substr($string, $pos + $separator_length);
14769 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14771 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14774 // Normalize the Media RSS namespaces
14775 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14777 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14779 $cache[$string] = array($namespace, $local_name);
14783 $cache[$string] = array('', $string);
14786 return $cache[$string];
14791 * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
14793 class SimplePie_Sanitize
14799 var $remove_div = true;
14800 var $image_handler = '';
14801 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14802 var $encode_instead_of_strip = false;
14803 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14804 var $strip_comments = false;
14805 var $output_encoding = 'UTF-8';
14806 var $enable_cache = true;
14807 var $cache_location = './cache';
14808 var $cache_name_function = 'md5';
14809 var $cache_class = 'SimplePie_Cache';
14810 var $file_class = 'SimplePie_File';
14812 var $useragent = '';
14813 var $force_fsockopen = false;
14815 var $replace_url_attributes = array(
14818 'blockquote' => 'cite',
14820 'form' => 'action',
14821 'img' => array('longdesc', 'src'),
14827 function remove_div($enable = true)
14829 $this->remove_div = (bool) $enable;
14832 function set_image_handler($page = false)
14836 $this->image_handler = (string) $page;
14840 $this->image_handler = false;
14844 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14846 if (isset($enable_cache))
14848 $this->enable_cache = (bool) $enable_cache;
14851 if ($cache_location)
14853 $this->cache_location = (string) $cache_location;
14856 if ($cache_name_function)
14858 $this->cache_name_function = (string) $cache_name_function;
14863 $this->cache_class = (string) $cache_class;
14867 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14871 $this->file_class = (string) $file_class;
14876 $this->timeout = (string) $timeout;
14881 $this->useragent = (string) $useragent;
14884 if ($force_fsockopen)
14886 $this->force_fsockopen = (string) $force_fsockopen;
14890 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14894 if (is_array($tags))
14896 $this->strip_htmltags = $tags;
14900 $this->strip_htmltags = explode(',', $tags);
14905 $this->strip_htmltags = false;
14909 function encode_instead_of_strip($encode = false)
14911 $this->encode_instead_of_strip = (bool) $encode;
14914 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14918 if (is_array($attribs))
14920 $this->strip_attributes = $attribs;
14924 $this->strip_attributes = explode(',', $attribs);
14929 $this->strip_attributes = false;
14933 function strip_comments($strip = false)
14935 $this->strip_comments = (bool) $strip;
14938 function set_output_encoding($encoding = 'UTF-8')
14940 $this->output_encoding = (string) $encoding;
14944 * Set element/attribute key/value pairs of HTML attributes
14945 * containing URLs that need to be resolved relative to the feed
14949 * @param array $element_attribute Element/attribute key/value pairs
14951 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'))
14953 $this->replace_url_attributes = (array) $element_attribute;
14956 function sanitize($data, $type, $base = '')
14958 $data = trim($data);
14959 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14961 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14963 if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
14965 $type |= SIMPLEPIE_CONSTRUCT_HTML;
14969 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14973 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14975 $data = base64_decode($data);
14978 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14980 if ($this->remove_div)
14982 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14983 $data = preg_replace('/<\/div>$/', '', $data);
14987 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14991 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14994 if ($this->strip_comments)
14996 $data = SimplePie_Misc::strip_comments($data);
14999 // Strip out HTML tags and attributes that might cause various security problems.
15000 // Based on recommendations by Mark Pilgrim at:
15001 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15002 if ($this->strip_htmltags)
15004 foreach ($this->strip_htmltags as $tag)
15006 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15007 while (preg_match($pcre, $data))
15009 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15014 if ($this->strip_attributes)
15016 foreach ($this->strip_attributes as $attrib)
15018 $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
15022 // Replace relative URLs
15023 $this->base = $base;
15024 foreach ($this->replace_url_attributes as $element => $attributes)
15026 $data = $this->replace_urls($data, $element, $attributes);
15029 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15030 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15032 $images = SimplePie_Misc::get_element('img', $data);
15033 foreach ($images as $img)
15035 if (isset($img['attribs']['src']['data']))
15037 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15038 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15040 if ($cache->load())
15042 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15043 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15047 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15048 $headers = $file->headers;
15050 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15052 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15054 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15055 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15059 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
15067 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15068 $data = trim($data);
15071 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15073 $data = SimplePie_Misc::absolutize_url($data, $base);
15076 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15078 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15081 if ($this->output_encoding !== 'UTF-8')
15083 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15089 function replace_urls($data, $tag, $attributes)
15091 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15093 $elements = SimplePie_Misc::get_element($tag, $data);
15094 foreach ($elements as $element)
15096 if (is_array($attributes))
15098 foreach ($attributes as $attribute)
15100 if (isset($element['attribs'][$attribute]['data']))
15102 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15103 $new_element = SimplePie_Misc::element_implode($element);
15104 $data = str_replace($element['full'], $new_element, $data);
15105 $element['full'] = $new_element;
15109 elseif (isset($element['attribs'][$attributes]['data']))
15111 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15112 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15119 function do_strip_htmltags($match)
15121 if ($this->encode_instead_of_strip)
15123 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15125 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15126 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15127 return "<$match[1]$match[2]>$match[3]</$match[1]>";
15131 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15134 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))