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;
5520 $title = $title_parent;
5522 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5523 if (isset($link['attribs']['']['type']))
5525 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5527 if (isset($link['attribs']['']['length']))
5529 $length = ceil($link['attribs']['']['length']);
5531 if (isset($link['attribs']['']['title']))
5533 $title = $this->sanitize($link['attribs']['']['title'], SIMPLEPIE_CONSTRUCT_TEXT);
5536 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5537 $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, $width);
5541 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5543 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5556 $samplingrate = null;
5561 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5562 if (isset($link['attribs']['']['type']))
5564 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5566 if (isset($link['attribs']['']['length']))
5568 $length = ceil($link['attribs']['']['length']);
5571 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5572 $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);
5576 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5578 if (isset($enclosure[0]['attribs']['']['url']))
5591 $samplingrate = null;
5596 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5597 if (isset($enclosure[0]['attribs']['']['type']))
5599 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5601 if (isset($enclosure[0]['attribs']['']['length']))
5603 $length = ceil($enclosure[0]['attribs']['']['length']);
5606 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5607 $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);
5611 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))
5613 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5614 $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);
5617 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5619 if (!empty($this->data['enclosures']))
5621 return $this->data['enclosures'];
5629 function get_latitude()
5631 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5633 return (float) $return[0]['data'];
5635 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))
5637 return (float) $match[1];
5645 function get_longitude()
5647 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5649 return (float) $return[0]['data'];
5651 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5653 return (float) $return[0]['data'];
5655 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))
5657 return (float) $match[2];
5665 function get_source()
5667 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5669 return new $this->feed->source_class($this, $return[0]);
5678 * Creates the add_to_* methods' return data
5681 * @param string $item_url String to prefix to the item permalink
5682 * @param string $title_url String to prefix to the item title
5683 * (and suffix to the item permalink)
5684 * @return mixed URL if feed exists, false otherwise
5686 function add_to_service($item_url, $title_url = null, $summary_url = null)
5688 if ($this->get_permalink() !== null)
5690 $return = $item_url . rawurlencode($this->get_permalink());
5691 if ($title_url !== null && $this->get_title() !== null)
5693 $return .= $title_url . rawurlencode($this->get_title());
5695 if ($summary_url !== null && $this->get_description() !== null)
5697 $return .= $summary_url . rawurlencode($this->get_description());
5699 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5707 function add_to_blinklist()
5709 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5712 function add_to_blogmarks()
5714 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5717 function add_to_delicious()
5719 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5722 function add_to_digg()
5724 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5727 function add_to_furl()
5729 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5732 function add_to_magnolia()
5734 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5737 function add_to_myweb20()
5739 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5742 function add_to_newsvine()
5744 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5747 function add_to_reddit()
5749 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5752 function add_to_segnalo()
5754 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5757 function add_to_simpy()
5759 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5762 function add_to_spurl()
5764 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5767 function add_to_wists()
5769 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5772 function search_technorati()
5774 return $this->add_to_service('http://www.technorati.com/search/');
5778 class SimplePie_Source
5781 var $data = array();
5783 function SimplePie_Source($item, $data)
5785 $this->item = $item;
5786 $this->data = $data;
5789 function __toString()
5791 return md5(serialize($this->data));
5794 function get_source_tags($namespace, $tag)
5796 if (isset($this->data['child'][$namespace][$tag]))
5798 return $this->data['child'][$namespace][$tag];
5806 function get_base($element = array())
5808 return $this->item->get_base($element);
5811 function sanitize($data, $type, $base = '')
5813 return $this->item->sanitize($data, $type, $base);
5821 function get_title()
5823 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5825 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5827 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5829 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5831 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5833 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5835 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5837 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5839 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5841 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5843 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5845 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5847 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5849 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5857 function get_category($key = 0)
5859 $categories = $this->get_categories();
5860 if (isset($categories[$key]))
5862 return $categories[$key];
5870 function get_categories()
5872 $categories = array();
5874 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5879 if (isset($category['attribs']['']['term']))
5881 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5883 if (isset($category['attribs']['']['scheme']))
5885 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5887 if (isset($category['attribs']['']['label']))
5889 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5891 $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5893 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5895 // This is really the label, but keep this as the term also for BC.
5896 // Label will also work on retrieving because that falls back to term.
5897 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5898 if (isset($category['attribs']['']['domain']))
5900 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5906 $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5908 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5910 $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5912 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5914 $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5917 if (!empty($categories))
5919 return SimplePie_Misc::array_unique($categories);
5927 function get_author($key = 0)
5929 $authors = $this->get_authors();
5930 if (isset($authors[$key]))
5932 return $authors[$key];
5940 function get_authors()
5943 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5951 $avatar_date = null;
5953 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5955 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5957 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5959 $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]));
5961 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5963 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5965 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
5967 $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]));
5969 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
5971 $name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
5973 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
5975 $uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
5977 if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
5979 $avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
5982 if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
5984 $authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
5987 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5992 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5994 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5996 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5998 $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]));
6000 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6002 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6004 if ($name !== null || $email !== null || $url !== null)
6006 $authors[] = new $this->item->feed->author_class($name, $url, $email);
6009 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
6011 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6013 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
6015 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6017 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
6019 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
6022 if (!empty($authors))
6024 return SimplePie_Misc::array_unique($authors);
6032 function get_contributor($key = 0)
6034 $contributors = $this->get_contributors();
6035 if (isset($contributors[$key]))
6037 return $contributors[$key];
6045 function get_contributors()
6047 $contributors = array();
6048 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
6053 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
6055 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6057 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
6059 $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]));
6061 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6063 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6065 if ($name !== null || $email !== null || $uri !== null)
6067 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
6070 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6075 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6077 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6079 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6081 $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]));
6083 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6085 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6087 if ($name !== null || $email !== null || $url !== null)
6089 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
6093 if (!empty($contributors))
6095 return SimplePie_Misc::array_unique($contributors);
6103 function get_link($key = 0, $rel = 'alternate')
6105 $links = $this->get_links($rel);
6106 if (isset($links[$key]))
6108 return $links[$key];
6117 * Added for parity between the parent-level and the item/entry-level.
6119 function get_permalink()
6121 return $this->get_link(0);
6124 function get_links($rel = 'alternate')
6126 if (!isset($this->data['links']))
6128 $this->data['links'] = array();
6129 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6131 foreach ($links as $link)
6133 if (isset($link['attribs']['']['href']))
6135 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6136 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6140 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6142 foreach ($links as $link)
6144 if (isset($link['attribs']['']['href']))
6146 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6147 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6152 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6154 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6156 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6158 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6160 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6162 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6165 $keys = array_keys($this->data['links']);
6166 foreach ($keys as $key)
6168 if (SimplePie_Misc::is_isegment_nz_nc($key))
6170 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6172 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6173 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6177 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6180 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6182 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6184 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6188 if (isset($this->data['links'][$rel]))
6190 return $this->data['links'][$rel];
6198 function get_description()
6200 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6202 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6204 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6206 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6208 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6210 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6212 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6214 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6216 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6218 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6220 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6222 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6224 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6226 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6228 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6230 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6232 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6234 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6242 function get_copyright()
6244 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6246 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6248 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6250 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6252 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6254 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6256 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6258 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6260 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6262 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6270 function get_language()
6272 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6274 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6276 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6278 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6280 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6282 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6284 elseif (isset($this->data['xml_lang']))
6286 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6294 function get_latitude()
6296 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6298 return (float) $return[0]['data'];
6300 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))
6302 return (float) $match[1];
6310 function get_longitude()
6312 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6314 return (float) $return[0]['data'];
6316 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6318 return (float) $return[0]['data'];
6320 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))
6322 return (float) $match[2];
6330 function get_image_url()
6332 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6334 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6336 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6338 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6340 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6342 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6351 class SimplePie_Author
6361 // Constructor, used to input the data
6362 function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null, $name_date = null, $uri_date = null, $avatar_date = null)
6364 $this->name = $name;
6365 $this->link = $link;
6366 $this->email = $email;
6367 $this->avatar = $avatar;
6368 $this->name_date = $name_date;
6369 $this->uri_date = $uri_date;
6370 $this->avatar_date = $avatar_date;
6373 function __toString()
6375 // There is no $this->data here
6376 return md5(serialize($this));
6381 if ($this->name !== null)
6393 if ($this->link !== null)
6403 function get_email()
6405 if ($this->email !== null)
6407 return $this->email;
6415 function get_avatar()
6417 if ($this->avatar !== null)
6419 return $this->avatar;
6427 function get_name_date()
6429 if ($this->name_date !== null)
6431 return $this->name_date;
6438 function get_uri_date()
6440 if ($this->uri_date !== null)
6442 return $this->uri_date;
6449 function get_avatar_date()
6451 if ($this->avatar_date !== null)
6453 return $this->avatar_date;
6464 class SimplePie_Category
6470 // Constructor, used to input the data
6471 function SimplePie_Category($term = null, $scheme = null, $label = null)
6473 $this->term = $term;
6474 $this->scheme = $scheme;
6475 $this->label = $label;
6478 function __toString()
6480 // There is no $this->data here
6481 return md5(serialize($this));
6486 if ($this->term !== null)
6496 function get_scheme()
6498 if ($this->scheme !== null)
6500 return $this->scheme;
6508 function get_label()
6510 if ($this->label !== null)
6512 return $this->label;
6516 return $this->get_term();
6521 class SimplePie_Enclosure
6551 // Constructor, used to input the data
6552 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)
6554 $this->bitrate = $bitrate;
6555 $this->captions = $captions;
6556 $this->categories = $categories;
6557 $this->channels = $channels;
6558 $this->copyright = $copyright;
6559 $this->credits = $credits;
6560 $this->description = $description;
6561 $this->duration = $duration;
6562 $this->expression = $expression;
6563 $this->framerate = $framerate;
6564 $this->hashes = $hashes;
6565 $this->height = $height;
6566 $this->javascript = $javascript;
6567 $this->keywords = $keywords;
6568 $this->lang = $lang;
6569 $this->length = $length;
6570 $this->link = $link;
6571 $this->medium = $medium;
6572 $this->player = $player;
6573 $this->ratings = $ratings;
6574 $this->restrictions = $restrictions;
6575 $this->samplingrate = $samplingrate;
6576 $this->thumbnails = $thumbnails;
6577 $this->title = $title;
6578 $this->type = $type;
6579 $this->width = $width;
6580 if (class_exists('idna_convert'))
6582 $idn = new idna_convert;
6583 $parsed = SimplePie_Misc::parse_url($link);
6584 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6586 $this->handler = $this->get_handler(); // Needs to load last
6589 function __toString()
6591 // There is no $this->data here
6592 return md5(serialize($this));
6595 function get_bitrate()
6597 if ($this->bitrate !== null)
6599 return $this->bitrate;
6607 function get_caption($key = 0)
6609 $captions = $this->get_captions();
6610 if (isset($captions[$key]))
6612 return $captions[$key];
6620 function get_captions()
6622 if ($this->captions !== null)
6624 return $this->captions;
6632 function get_category($key = 0)
6634 $categories = $this->get_categories();
6635 if (isset($categories[$key]))
6637 return $categories[$key];
6645 function get_categories()
6647 if ($this->categories !== null)
6649 return $this->categories;
6657 function get_channels()
6659 if ($this->channels !== null)
6661 return $this->channels;
6669 function get_copyright()
6671 if ($this->copyright !== null)
6673 return $this->copyright;
6681 function get_credit($key = 0)
6683 $credits = $this->get_credits();
6684 if (isset($credits[$key]))
6686 return $credits[$key];
6694 function get_credits()
6696 if ($this->credits !== null)
6698 return $this->credits;
6706 function get_description()
6708 if ($this->description !== null)
6710 return $this->description;
6718 function get_duration($convert = false)
6720 if ($this->duration !== null)
6724 $time = SimplePie_Misc::time_hms($this->duration);
6729 return $this->duration;
6738 function get_expression()
6740 if ($this->expression !== null)
6742 return $this->expression;
6750 function get_extension()
6752 if ($this->link !== null)
6754 $url = SimplePie_Misc::parse_url($this->link);
6755 if ($url['path'] !== '')
6757 return pathinfo($url['path'], PATHINFO_EXTENSION);
6763 function get_framerate()
6765 if ($this->framerate !== null)
6767 return $this->framerate;
6775 function get_handler()
6777 return $this->get_real_type(true);
6780 function get_hash($key = 0)
6782 $hashes = $this->get_hashes();
6783 if (isset($hashes[$key]))
6785 return $hashes[$key];
6793 function get_hashes()
6795 if ($this->hashes !== null)
6797 return $this->hashes;
6805 function get_height()
6807 if ($this->height !== null)
6809 return $this->height;
6817 function get_language()
6819 if ($this->lang !== null)
6829 function get_keyword($key = 0)
6831 $keywords = $this->get_keywords();
6832 if (isset($keywords[$key]))
6834 return $keywords[$key];
6842 function get_keywords()
6844 if ($this->keywords !== null)
6846 return $this->keywords;
6854 function get_length()
6856 if ($this->length !== null)
6858 return $this->length;
6868 if ($this->link !== null)
6870 return urldecode($this->link);
6878 function get_medium()
6880 if ($this->medium !== null)
6882 return $this->medium;
6890 function get_player()
6892 if ($this->player !== null)
6894 return $this->player;
6902 function get_rating($key = 0)
6904 $ratings = $this->get_ratings();
6905 if (isset($ratings[$key]))
6907 return $ratings[$key];
6915 function get_ratings()
6917 if ($this->ratings !== null)
6919 return $this->ratings;
6927 function get_restriction($key = 0)
6929 $restrictions = $this->get_restrictions();
6930 if (isset($restrictions[$key]))
6932 return $restrictions[$key];
6940 function get_restrictions()
6942 if ($this->restrictions !== null)
6944 return $this->restrictions;
6952 function get_sampling_rate()
6954 if ($this->samplingrate !== null)
6956 return $this->samplingrate;
6966 $length = $this->get_length();
6967 if ($length !== null)
6969 return round($length/1048576, 2);
6977 function get_thumbnail($key = 0)
6979 $thumbnails = $this->get_thumbnails();
6980 if (isset($thumbnails[$key]))
6982 return $thumbnails[$key];
6990 function get_thumbnails()
6992 if ($this->thumbnails !== null)
6994 return $this->thumbnails;
7002 function get_title()
7004 if ($this->title !== null)
7006 return $this->title;
7016 if ($this->type !== null)
7026 function get_width()
7028 if ($this->width !== null)
7030 return $this->width;
7038 function native_embed($options='')
7040 return $this->embed($options, true);
7044 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
7046 function embed($options = '', $native = false)
7056 $bgcolor = '#ffffff';
7058 $widescreen = false;
7059 $handler = $this->get_handler();
7060 $type = $this->get_real_type();
7062 // Process options and reassign values as necessary
7063 if (is_array($options))
7069 $options = explode(',', $options);
7070 foreach($options as $option)
7072 $opt = explode(':', $option, 2);
7073 if (isset($opt[0], $opt[1]))
7075 $opt[0] = trim($opt[0]);
7076 $opt[1] = trim($opt[1]);
7092 $altclass = $opt[1];
7112 $mediaplayer = $opt[1];
7116 $widescreen = $opt[1];
7123 $mime = explode('/', $type, 2);
7126 // Process values for 'auto'
7127 if ($width === 'auto')
7129 if ($mime === 'video')
7131 if ($height === 'auto')
7135 elseif ($widescreen)
7137 $width = round((intval($height)/9)*16);
7141 $width = round((intval($height)/3)*4);
7150 if ($height === 'auto')
7152 if ($mime === 'audio')
7156 elseif ($mime === 'video')
7158 if ($width === 'auto')
7169 elseif ($widescreen)
7171 $height = round((intval($width)/16)*9);
7175 $height = round((intval($width)/4)*3);
7183 elseif ($mime === 'audio')
7188 // Set proper placeholder value
7189 if ($mime === 'audio')
7191 $placeholder = $audio;
7193 elseif ($mime === 'video')
7195 $placeholder = $video;
7200 // Make sure the JS library is included
7203 static $javascript_outputted = null;
7204 if (!$javascript_outputted && $this->javascript)
7206 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7207 $javascript_outputted = true;
7212 if ($handler === 'odeo')
7216 $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>';
7220 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7225 elseif ($handler === 'flash')
7229 $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>";
7233 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7237 // Flash Media Player file types.
7238 // Preferred handler for MP3 file types.
7239 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7244 $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>";
7248 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7252 // QuickTime 7 file types. Need to test with QuickTime 6.
7253 // Only handle MP3's if the Flash Media Player is not present.
7254 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7259 if ($placeholder !== '')
7261 $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>";
7265 $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>";
7270 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7275 elseif ($handler === 'wmedia')
7280 $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>";
7284 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7289 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7294 function get_real_type($find_handler = false)
7296 // If it's Odeo, let's get it out of the way.
7297 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7302 // Mime-types by handler.
7303 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7304 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7305 $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
7306 $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
7307 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7309 if ($this->get_type() !== null)
7311 $type = strtolower($this->type);
7318 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7319 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7321 switch (strtolower($this->get_extension()))
7326 $type = 'audio/acc';
7333 $type = 'audio/aiff';
7337 $type = 'audio/wav';
7344 $type = 'audio/midi';
7348 $type = 'audio/x-m4a';
7353 $type = 'audio/mp3';
7357 $type = 'audio/wav';
7361 $type = 'audio/x-ms-wax';
7365 $type = 'audio/x-ms-wma';
7371 $type = 'video/3gpp';
7376 $type = 'video/3gpp2';
7380 $type = 'video/x-ms-asf';
7384 $type = 'video/x-flv';
7398 $type = 'video/mpeg';
7402 $type = 'video/x-m4v';
7407 $type = 'video/quicktime';
7412 $type = 'video/mp4';
7416 $type = 'video/sd-video';
7420 $type = 'video/x-ms-wm';
7424 $type = 'video/x-ms-wmv';
7428 $type = 'video/x-ms-wvx';
7433 $type = 'application/futuresplash';
7437 $type = 'application/x-shockwave-flash';
7444 if (in_array($type, $types_flash))
7448 elseif (in_array($type, $types_fmedia))
7452 elseif (in_array($type, $types_quicktime))
7456 elseif (in_array($type, $types_wmedia))
7460 elseif (in_array($type, $types_mp3))
7476 class SimplePie_Caption
7484 // Constructor, used to input the data
7485 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7487 $this->type = $type;
7488 $this->lang = $lang;
7489 $this->startTime = $startTime;
7490 $this->endTime = $endTime;
7491 $this->text = $text;
7494 function __toString()
7496 // There is no $this->data here
7497 return md5(serialize($this));
7500 function get_endtime()
7502 if ($this->endTime !== null)
7504 return $this->endTime;
7512 function get_language()
7514 if ($this->lang !== null)
7524 function get_starttime()
7526 if ($this->startTime !== null)
7528 return $this->startTime;
7538 if ($this->text !== null)
7550 if ($this->type !== null)
7561 class SimplePie_Credit
7567 // Constructor, used to input the data
7568 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7570 $this->role = $role;
7571 $this->scheme = $scheme;
7572 $this->name = $name;
7575 function __toString()
7577 // There is no $this->data here
7578 return md5(serialize($this));
7583 if ($this->role !== null)
7593 function get_scheme()
7595 if ($this->scheme !== null)
7597 return $this->scheme;
7607 if ($this->name !== null)
7618 class SimplePie_Copyright
7623 // Constructor, used to input the data
7624 function SimplePie_Copyright($url = null, $label = null)
7627 $this->label = $label;
7630 function __toString()
7632 // There is no $this->data here
7633 return md5(serialize($this));
7638 if ($this->url !== null)
7648 function get_attribution()
7650 if ($this->label !== null)
7652 return $this->label;
7661 class SimplePie_Rating
7666 // Constructor, used to input the data
7667 function SimplePie_Rating($scheme = null, $value = null)
7669 $this->scheme = $scheme;
7670 $this->value = $value;
7673 function __toString()
7675 // There is no $this->data here
7676 return md5(serialize($this));
7679 function get_scheme()
7681 if ($this->scheme !== null)
7683 return $this->scheme;
7691 function get_value()
7693 if ($this->value !== null)
7695 return $this->value;
7704 class SimplePie_Restriction
7710 // Constructor, used to input the data
7711 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7713 $this->relationship = $relationship;
7714 $this->type = $type;
7715 $this->value = $value;
7718 function __toString()
7720 // There is no $this->data here
7721 return md5(serialize($this));
7724 function get_relationship()
7726 if ($this->relationship !== null)
7728 return $this->relationship;
7738 if ($this->type !== null)
7748 function get_value()
7750 if ($this->value !== null)
7752 return $this->value;
7762 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7764 class SimplePie_File
7768 var $success = true;
7769 var $headers = array();
7774 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7776 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7778 if (class_exists('idna_convert'))
7780 $idn = new idna_convert;
7781 $parsed = SimplePie_Misc::parse_url($url);
7782 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7785 $this->useragent = $useragent;
7786 if (preg_match('/^http(s)?:\/\//i', $url))
7788 if ($useragent === null)
7790 $useragent = ini_get('user_agent');
7791 $this->useragent = $useragent;
7793 if (!is_array($headers))
7797 if (!$force_fsockopen && function_exists('curl_exec'))
7799 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7801 $headers2 = array();
7802 foreach ($headers as $key => $value)
7804 $headers2[] = "$key: $value";
7806 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7808 curl_setopt($fp, CURLOPT_ENCODING, '');
7810 curl_setopt($fp, CURLOPT_URL, $url);
7811 curl_setopt($fp, CURLOPT_HEADER, 1);
7812 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7813 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7814 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7815 curl_setopt($fp, CURLOPT_REFERER, $url);
7816 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7817 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7818 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7820 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7821 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7824 $this->headers = curl_exec($fp);
7825 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7827 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7828 $this->headers = curl_exec($fp);
7830 if (curl_errno($fp))
7832 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7833 $this->success = false;
7837 $info = curl_getinfo($fp);
7839 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7840 $this->headers = array_pop($this->headers);
7841 $parser = new SimplePie_HTTP_Parser($this->headers);
7842 if ($parser->parse())
7844 $this->headers = $parser->headers;
7845 $this->body = $parser->body;
7846 $this->status_code = $parser->status_code;
7847 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)
7850 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7851 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7858 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7859 $url_parts = parse_url($url);
7860 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7862 $url_parts['host'] = "ssl://$url_parts[host]";
7863 $url_parts['port'] = 443;
7865 if (!isset($url_parts['port']))
7867 $url_parts['port'] = 80;
7869 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7872 $this->error = 'fsockopen error: ' . $errstr;
7873 $this->success = false;
7877 stream_set_timeout($fp, $timeout);
7878 if (isset($url_parts['path']))
7880 if (isset($url_parts['query']))
7882 $get = "$url_parts[path]?$url_parts[query]";
7886 $get = $url_parts['path'];
7893 $out = "GET $get HTTP/1.0\r\n";
7894 $out .= "Host: $url_parts[host]\r\n";
7895 $out .= "User-Agent: $useragent\r\n";
7896 if (extension_loaded('zlib'))
7898 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7901 if (isset($url_parts['user']) && isset($url_parts['pass']))
7903 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7905 foreach ($headers as $key => $value)
7907 $out .= "$key: $value\r\n";
7909 $out .= "Connection: Close\r\n\r\n";
7912 $info = stream_get_meta_data($fp);
7914 $this->headers = '';
7915 while (!$info['eof'] && !$info['timed_out'])
7917 $this->headers .= fread($fp, 1160);
7918 $info = stream_get_meta_data($fp);
7920 if (!$info['timed_out'])
7922 $parser = new SimplePie_HTTP_Parser($this->headers);
7923 if ($parser->parse())
7925 $this->headers = $parser->headers;
7926 $this->body = $parser->body;
7927 $this->status_code = $parser->status_code;
7928 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)
7931 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7932 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7934 if (isset($this->headers['content-encoding']))
7936 // Hey, we act dumb elsewhere, so let's do that here too
7937 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7941 $decoder = new SimplePie_gzdecode($this->body);
7942 if (!$decoder->parse())
7944 $this->error = 'Unable to decode HTTP "gzip" stream';
7945 $this->success = false;
7949 $this->body = $decoder->data;
7954 if (($body = gzuncompress($this->body)) === false)
7956 if (($body = gzinflate($this->body)) === false)
7958 $this->error = 'Unable to decode HTTP "deflate" stream';
7959 $this->success = false;
7962 $this->body = $body;
7966 $this->error = 'Unknown content coding';
7967 $this->success = false;
7974 $this->error = 'fsocket timed out';
7975 $this->success = false;
7983 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7984 if (!$this->body = file_get_contents($url))
7986 $this->error = 'file_get_contents could not read the file';
7987 $this->success = false;
7994 * HTTP Response Parser
7996 * @package SimplePie
7998 class SimplePie_HTTP_Parser
8006 var $http_version = 0.0;
8014 var $status_code = 0;
8025 * Key/value pairs of the headers
8030 var $headers = array();
8033 * Body of the response
8041 * Current state of the state machine
8046 var $state = 'http_version';
8057 * Input data length (to avoid calling strlen() everytime this is needed)
8062 var $data_length = 0;
8065 * Current position of the pointer
8073 * Name of the hedaer currently being parsed
8081 * Value of the hedaer currently being parsed
8089 * Create an instance of the class with the input data
8092 * @param string $data Input data
8094 function SimplePie_HTTP_Parser($data)
8096 $this->data = $data;
8097 $this->data_length = strlen($this->data);
8101 * Parse the input data
8104 * @return bool true on success, false on failure
8108 while ($this->state && $this->state !== 'emit' && $this->has_data())
8110 $state = $this->state;
8114 if ($this->state === 'emit' || $this->state === 'body')
8120 $this->http_version = '';
8121 $this->status_code = '';
8123 $this->headers = array();
8130 * Check whether there is data beyond the pointer
8133 * @return bool true if there is further data, false if not
8137 return (bool) ($this->position < $this->data_length);
8141 * See if the next character is LWS
8144 * @return bool true if the next character is LWS, false if not
8146 function is_linear_whitespace()
8148 return (bool) ($this->data[$this->position] === "\x09"
8149 || $this->data[$this->position] === "\x20"
8150 || ($this->data[$this->position] === "\x0A"
8151 && isset($this->data[$this->position + 1])
8152 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8156 * Parse the HTTP version
8160 function http_version()
8162 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8164 $len = strspn($this->data, '0123456789.', 5);
8165 $this->http_version = substr($this->data, 5, $len);
8166 $this->position += 5 + $len;
8167 if (substr_count($this->http_version, '.') <= 1)
8169 $this->http_version = (float) $this->http_version;
8170 $this->position += strspn($this->data, "\x09\x20", $this->position);
8171 $this->state = 'status';
8175 $this->state = false;
8180 $this->state = false;
8185 * Parse the status code
8191 if ($len = strspn($this->data, '0123456789', $this->position))
8193 $this->status_code = (int) substr($this->data, $this->position, $len);
8194 $this->position += $len;
8195 $this->state = 'reason';
8199 $this->state = false;
8204 * Parse the reason phrase
8210 $len = strcspn($this->data, "\x0A", $this->position);
8211 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8212 $this->position += $len + 1;
8213 $this->state = 'new_line';
8217 * Deal with a new line, shifting data around as needed
8223 $this->value = trim($this->value, "\x0D\x20");
8224 if ($this->name !== '' && $this->value !== '')
8226 $this->name = strtolower($this->name);
8227 if (isset($this->headers[$this->name]))
8229 $this->headers[$this->name] .= ', ' . $this->value;
8233 $this->headers[$this->name] = $this->value;
8238 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8240 $this->position += 2;
8241 $this->state = 'body';
8243 elseif ($this->data[$this->position] === "\x0A")
8246 $this->state = 'body';
8250 $this->state = 'name';
8255 * Parse a header name
8261 $len = strcspn($this->data, "\x0A:", $this->position);
8262 if (isset($this->data[$this->position + $len]))
8264 if ($this->data[$this->position + $len] === "\x0A")
8266 $this->position += $len;
8267 $this->state = 'new_line';
8271 $this->name = substr($this->data, $this->position, $len);
8272 $this->position += $len + 1;
8273 $this->state = 'value';
8278 $this->state = false;
8283 * Parse LWS, replacing consecutive LWS characters with a single space
8287 function linear_whitespace()
8291 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8293 $this->position += 2;
8295 elseif ($this->data[$this->position] === "\x0A")
8299 $this->position += strspn($this->data, "\x09\x20", $this->position);
8300 } while ($this->has_data() && $this->is_linear_whitespace());
8301 $this->value .= "\x20";
8305 * See what state to move to while within non-quoted header values
8311 if ($this->is_linear_whitespace())
8313 $this->linear_whitespace();
8317 switch ($this->data[$this->position])
8321 $this->state = 'quote';
8326 $this->state = 'new_line';
8330 $this->state = 'value_char';
8337 * Parse a header value while outside quotes
8341 function value_char()
8343 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8344 $this->value .= substr($this->data, $this->position, $len);
8345 $this->position += $len;
8346 $this->state = 'value';
8350 * See what state to move to while within quoted header values
8356 if ($this->is_linear_whitespace())
8358 $this->linear_whitespace();
8362 switch ($this->data[$this->position])
8366 $this->state = 'value';
8371 $this->state = 'new_line';
8376 $this->state = 'quote_escaped';
8380 $this->state = 'quote_char';
8387 * Parse a header value while within quotes
8391 function quote_char()
8393 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8394 $this->value .= substr($this->data, $this->position, $len);
8395 $this->position += $len;
8396 $this->state = 'value';
8400 * Parse an escaped character within quotes
8404 function quote_escaped()
8406 $this->value .= $this->data[$this->position];
8408 $this->state = 'quote';
8418 $this->body = substr($this->data, $this->position);
8419 $this->state = 'emit';
8426 * @package SimplePie
8428 class SimplePie_gzdecode
8434 * @see gzdecode::$data
8436 var $compressed_data;
8439 * Size of compressed data
8443 var $compressed_size;
8446 * Minimum size of a valid gzip string
8450 var $min_compressed_size = 18;
8453 * Current position of pointer
8470 * @see gzdecode::$compressed_data
8499 * @see gzdecode::$extra_field
8500 * @see gzdecode::$SI2
8508 * @see gzdecode::$extra_field
8509 * @see gzdecode::$SI1
8514 * Extra field content
8517 * @see gzdecode::$SI1
8518 * @see gzdecode::$SI2
8530 * Human readable comment
8537 * Don't allow anything to be set
8541 function __set($name, $value)
8543 trigger_error("Cannot write property $name", E_USER_ERROR);
8547 * Set the compressed string and related properties
8551 function SimplePie_gzdecode($data)
8553 $this->compressed_data = $data;
8554 $this->compressed_size = strlen($data);
8558 * Decode the GZIP stream
8564 if ($this->compressed_size >= $this->min_compressed_size)
8566 // Check ID1, ID2, and CM
8567 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8572 // Get the FLG (FLaGs)
8573 $this->flags = ord($this->compressed_data[3]);
8575 // FLG bits above (1 << 4) are reserved
8576 if ($this->flags > 0x1F)
8581 // Advance the pointer after the above
8582 $this->position += 4;
8585 $mtime = substr($this->compressed_data, $this->position, 4);
8586 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8587 if (current(unpack('S', "\x00\x01")) === 1)
8589 $mtime = strrev($mtime);
8591 $this->MTIME = current(unpack('l', $mtime));
8592 $this->position += 4;
8594 // Get the XFL (eXtra FLags)
8595 $this->XFL = ord($this->compressed_data[$this->position++]);
8597 // Get the OS (Operating System)
8598 $this->OS = ord($this->compressed_data[$this->position++]);
8601 if ($this->flags & 4)
8603 // Read subfield IDs
8604 $this->SI1 = $this->compressed_data[$this->position++];
8605 $this->SI2 = $this->compressed_data[$this->position++];
8607 // SI2 set to zero is reserved for future use
8608 if ($this->SI2 === "\x00")
8613 // Get the length of the extra field
8614 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8617 // Check the length of the string is still valid
8618 $this->min_compressed_size += $len + 4;
8619 if ($this->compressed_size >= $this->min_compressed_size)
8621 // Set the extra field to the given data
8622 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8623 $this->position += $len;
8632 if ($this->flags & 8)
8634 // Get the length of the filename
8635 $len = strcspn($this->compressed_data, "\x00", $this->position);
8637 // Check the length of the string is still valid
8638 $this->min_compressed_size += $len + 1;
8639 if ($this->compressed_size >= $this->min_compressed_size)
8641 // Set the original filename to the given string
8642 $this->filename = substr($this->compressed_data, $this->position, $len);
8643 $this->position += $len + 1;
8651 // Parse the FCOMMENT
8652 if ($this->flags & 16)
8654 // Get the length of the comment
8655 $len = strcspn($this->compressed_data, "\x00", $this->position);
8657 // Check the length of the string is still valid
8658 $this->min_compressed_size += $len + 1;
8659 if ($this->compressed_size >= $this->min_compressed_size)
8661 // Set the original comment to the given string
8662 $this->comment = substr($this->compressed_data, $this->position, $len);
8663 $this->position += $len + 1;
8672 if ($this->flags & 2)
8674 // Check the length of the string is still valid
8675 $this->min_compressed_size += $len + 2;
8676 if ($this->compressed_size >= $this->min_compressed_size)
8679 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8681 // Check the CRC matches
8682 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8684 $this->position += 2;
8697 // Decompress the actual data
8698 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8704 $this->position = $this->compressed_size - 8;
8707 // Check CRC of data
8708 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8709 $this->position += 4;
8710 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8715 // Check ISIZE of data
8716 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8717 $this->position += 4;
8718 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8723 // Wow, against all odds, we've actually got a valid gzip string
8733 class SimplePie_Cache
8736 * Don't call the constructor. Please.
8740 function SimplePie_Cache()
8742 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8746 * Create a new SimplePie_Cache object
8751 function create($location, $filename, $extension)
8753 $location_iri = new SimplePie_IRI($location);
8754 switch ($location_iri->get_scheme())
8757 if (extension_loaded('mysql'))
8759 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8764 return new SimplePie_Cache_File($location, $filename, $extension);
8769 class SimplePie_Cache_File
8776 function SimplePie_Cache_File($location, $filename, $extension)
8778 $this->location = $location;
8779 $this->filename = $filename;
8780 $this->extension = $extension;
8781 $this->name = "$this->location/$this->filename.$this->extension";
8784 function save($data)
8786 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8788 if (is_a($data, 'SimplePie'))
8790 $data = $data->data;
8793 $data = serialize($data);
8795 if (function_exists('file_put_contents'))
8797 return (bool) file_put_contents($this->name, $data);
8801 $fp = fopen($this->name, 'wb');
8815 if (file_exists($this->name) && is_readable($this->name))
8817 return unserialize(file_get_contents($this->name));
8824 if (file_exists($this->name))
8826 return filemtime($this->name);
8833 if (file_exists($this->name))
8835 return touch($this->name);
8842 if (file_exists($this->name))
8844 return unlink($this->name);
8850 class SimplePie_Cache_DB
8852 function prepare_simplepie_object_for_cache($data)
8854 $items = $data->get_items();
8855 $items_by_id = array();
8859 foreach ($items as $item)
8861 $items_by_id[$item->get_id()] = $item;
8864 if (count($items_by_id) !== count($items))
8866 $items_by_id = array();
8867 foreach ($items as $item)
8869 $items_by_id[$item->get_id(true)] = $item;
8873 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8875 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8877 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8879 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8881 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8883 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8885 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8887 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8894 if ($channel !== null)
8896 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8898 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8900 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8902 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8904 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8906 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8908 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8910 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8912 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8914 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8917 if (isset($data->data['items']))
8919 unset($data->data['items']);
8921 if (isset($data->data['ordered_items']))
8923 unset($data->data['ordered_items']);
8926 return array(serialize($data->data), $items_by_id);
8930 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8936 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8938 $host = $mysql_location->get_host();
8939 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8941 $server = ':' . substr($host, 5, -1);
8946 if ($mysql_location->get_port() !== null)
8948 $server .= ':' . $mysql_location->get_port();
8952 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8954 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8958 $username = $mysql_location->get_userinfo();
8962 if ($this->mysql = mysql_connect($server, $username, $password))
8964 $this->id = $name . $extension;
8965 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8966 if (!isset($this->options['prefix'][0]))
8968 $this->options['prefix'][0] = '';
8971 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8972 && mysql_query('SET NAMES utf8')
8973 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8976 while ($row = mysql_fetch_row($query))
8981 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8983 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)))'))
8985 $this->mysql = null;
8989 if (!in_array($this->options['prefix'][0] . 'items', $db))
8991 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)))'))
8993 $this->mysql = null;
8999 $this->mysql = null;
9004 function save($data)
9008 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
9010 if (is_a($data, 'SimplePie'))
9014 // This keyword needs to defy coding standards for PHP4 compatibility
9015 $data = clone($data);
9018 $prepared = $this->prepare_simplepie_object_for_cache($data);
9020 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9022 if (mysql_num_rows($query))
9024 $items = count($prepared[1]);
9027 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9031 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
9034 if (!mysql_query($sql, $this->mysql))
9039 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))
9044 $ids = array_keys($prepared[1]);
9047 foreach ($ids as $id)
9049 $database_ids[] = mysql_real_escape_string($id);
9052 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))
9054 $existing_ids = array();
9055 while ($row = mysql_fetch_row($query))
9057 $existing_ids[] = $row[0];
9060 $new_ids = array_diff($ids, $existing_ids);
9062 foreach ($new_ids as $new_id)
9064 if (!($date = $prepared[1][$new_id]->get_date('U')))
9069 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))
9083 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
9085 if (mysql_num_rows($query))
9087 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))
9092 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))
9103 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)))
9105 $data = unserialize($row[1]);
9107 if (isset($this->options['items'][0]))
9109 $items = (int) $this->options['items'][0];
9113 $items = (int) $row[0];
9118 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9120 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9122 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9124 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9126 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9128 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9130 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9132 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9141 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9144 $sql .= ' LIMIT ' . $items;
9147 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9149 while ($row = mysql_fetch_row($query))
9151 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9167 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)))
9179 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))
9191 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)))
9202 class SimplePie_Misc
9204 function time_hms($seconds)
9208 $hours = floor($seconds / 3600);
9209 $remainder = $seconds % 3600;
9212 $time .= $hours.':';
9215 $minutes = floor($remainder / 60);
9216 $seconds = $remainder % 60;
9217 if ($minutes < 10 && $hours > 0)
9219 $minutes = '0' . $minutes;
9223 $seconds = '0' . $seconds;
9226 $time .= $minutes.':';
9232 function absolutize_url($relative, $base)
9235 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9236 return $iri->get_iri();
9239 function remove_dot_segments($input)
9242 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9244 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9245 if (strpos($input, '../') === 0)
9247 $input = substr($input, 3);
9249 elseif (strpos($input, './') === 0)
9251 $input = substr($input, 2);
9253 // 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,
9254 elseif (strpos($input, '/./') === 0)
9256 $input = substr_replace($input, '/', 0, 3);
9258 elseif ($input === '/.')
9262 // 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,
9263 elseif (strpos($input, '/../') === 0)
9265 $input = substr_replace($input, '/', 0, 4);
9266 $output = substr_replace($output, '', strrpos($output, '/'));
9268 elseif ($input === '/..')
9271 $output = substr_replace($output, '', strrpos($output, '/'));
9273 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9274 elseif ($input === '.' || $input === '..')
9278 // 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
9279 elseif (($pos = strpos($input, '/', 1)) !== false)
9281 $output .= substr($input, 0, $pos);
9282 $input = substr_replace($input, '', 0, $pos);
9290 return $output . $input;
9293 function get_element($realname, $string)
9296 $name = preg_quote($realname, '/');
9297 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9299 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9301 $return[$i]['tag'] = $realname;
9302 $return[$i]['full'] = $matches[$i][0][0];
9303 $return[$i]['offset'] = $matches[$i][0][1];
9304 if (strlen($matches[$i][3][0]) <= 2)
9306 $return[$i]['self_closing'] = true;
9310 $return[$i]['self_closing'] = false;
9311 $return[$i]['content'] = $matches[$i][4][0];
9313 $return[$i]['attribs'] = array();
9314 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))
9316 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9318 if (count($attribs[$j]) === 2)
9320 $attribs[$j][2] = $attribs[$j][1];
9322 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9330 function element_implode($element)
9332 $full = "<$element[tag]";
9333 foreach ($element['attribs'] as $key => $value)
9335 $key = strtolower($key);
9336 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9338 if ($element['self_closing'])
9344 $full .= ">$element[content]</$element[tag]>";
9349 function error($message, $level, $file, $line)
9351 if ((ini_get('error_reporting') & $level) > 0)
9356 $note = 'PHP Error';
9358 case E_USER_WARNING:
9359 $note = 'PHP Warning';
9362 $note = 'PHP Notice';
9365 $note = 'Unknown Error';
9370 if (!function_exists('error_log'))
9375 $log_file = @ini_get('error_log');
9376 if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9383 @error_log("$note: $message in $file on line $line", 0);
9391 * If a file has been cached, retrieve and display it.
9393 * This is most useful for caching images (get_favicon(), etc.),
9394 * however it works for all cached files. This WILL NOT display ANY
9395 * file/image/page/whatever, but rather only display what has already
9396 * been cached by SimplePie.
9399 * @see SimplePie::get_favicon()
9400 * @param str $identifier_url URL that is used to identify the content.
9401 * This may or may not be the actual URL of the live content.
9402 * @param str $cache_location Location of SimplePie's cache. Defaults
9404 * @param str $cache_extension The file extension that the file was
9405 * cached with. Defaults to 'spc'.
9406 * @param str $cache_class Name of the cache-handling class being used
9407 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9408 * as-is unless you've overloaded the class.
9409 * @param str $cache_name_function Obsolete. Exists for backwards
9410 * compatibility reasons only.
9412 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9414 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9416 if ($file = $cache->load())
9418 if (isset($file['headers']['content-type']))
9420 header('Content-type:' . $file['headers']['content-type']);
9424 header('Content-type: application/octet-stream');
9426 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9431 die('Cached file for ' . $identifier_url . ' cannot be found.');
9434 function fix_protocol($url, $http = 1)
9436 $url = SimplePie_Misc::normalize_url($url);
9437 $parsed = SimplePie_Misc::parse_url($url);
9438 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9440 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9443 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9445 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9448 if ($http === 2 && $parsed['scheme'] !== '')
9452 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9454 return substr_replace($url, 'podcast', 0, 4);
9456 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9458 return substr_replace($url, 'itpc', 0, 4);
9466 function parse_url($url)
9468 $iri = new SimplePie_IRI($url);
9470 'scheme' => (string) $iri->get_scheme(),
9471 'authority' => (string) $iri->get_authority(),
9472 'path' => (string) $iri->get_path(),
9473 'query' => (string) $iri->get_query(),
9474 'fragment' => (string) $iri->get_fragment()
9478 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9480 $iri = new SimplePie_IRI('');
9481 $iri->set_scheme($scheme);
9482 $iri->set_authority($authority);
9483 $iri->set_path($path);
9484 $iri->set_query($query);
9485 $iri->set_fragment($fragment);
9486 return $iri->get_iri();
9489 function normalize_url($url)
9491 $iri = new SimplePie_IRI($url);
9492 return $iri->get_iri();
9495 function percent_encoding_normalization($match)
9497 $integer = hexdec($match[1]);
9498 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9500 return chr($integer);
9504 return strtoupper($match[0]);
9509 * Remove bad UTF-8 bytes
9511 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9512 * FAQ: Multilingual Forms (modified to include full ASCII range)
9514 * @author Geoffrey Sneddon
9515 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9516 * @param string $str String to remove bad UTF-8 bytes from
9517 * @return string UTF-8 string
9519 function utf8_bad_replace($str)
9521 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9525 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9529 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))
9531 return implode("\xEF\xBF\xBD", $matches[0]);
9533 elseif ($str !== '')
9535 return "\xEF\xBF\xBD";
9544 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9548 * @param string $string Windows-1252 encoded string
9549 * @return string UTF-8 encoded string
9551 function windows_1252_to_utf8($string)
9553 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");
9555 return strtr($string, $convert_table);
9558 function change_encoding($data, $input, $output)
9560 $input = SimplePie_Misc::encoding($input);
9561 $output = SimplePie_Misc::encoding($output);
9563 // We fail to fail on non US-ASCII bytes
9564 if ($input === 'US-ASCII')
9566 static $non_ascii_octects = '';
9567 if (!$non_ascii_octects)
9569 for ($i = 0x80; $i <= 0xFF; $i++)
9571 $non_ascii_octects .= chr($i);
9574 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9577 // This is first, as behaviour of this is completely predictable
9578 if ($input === 'Windows-1252' && $output === 'UTF-8')
9580 return SimplePie_Misc::windows_1252_to_utf8($data);
9582 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9583 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9587 // This is last, as behaviour of this varies with OS userland and PHP version
9588 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9592 // If we can't do anything, just fail
9599 function encoding($charset)
9601 // Normalization from UTS #22
9602 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9604 case 'adobestandardencoding':
9605 case 'csadobestandardencoding':
9606 return 'Adobe-Standard-Encoding';
9608 case 'adobesymbolencoding':
9610 return 'Adobe-Symbol-Encoding';
9614 return 'Amiga-1251';
9616 case 'ansix31101983':
9618 case 'csiso99naplps':
9621 return 'ANSI_X3.110-1983';
9625 case 'csiso89asmo449':
9636 return 'Big5-HKSCS';
9647 case 'csiso4unitedkingdom':
9655 case 'csiso47bsviewdata':
9657 return 'BS_viewdata';
9665 case 'csaz243419851':
9666 case 'csiso121canadian1':
9669 return 'CSA_Z243.4-1985-1';
9672 case 'csaz243419852':
9673 case 'csiso122canadian2':
9676 return 'CSA_Z243.4-1985-2';
9678 case 'csaz24341985gr':
9679 case 'csiso123csaz24341985gr':
9681 return 'CSA_Z243.4-1985-gr';
9683 case 'csiso139csn369103':
9686 return 'CSN_369103';
9693 case 'csiso21german':
9704 case 'csiso646danish':
9710 case 'csibmebcdicatde':
9712 return 'EBCDIC-AT-DE';
9714 case 'csebcdicatdea':
9716 return 'EBCDIC-AT-DE-A';
9718 case 'csebcdiccafr':
9720 return 'EBCDIC-CA-FR';
9722 case 'csebcdicdkno':
9724 return 'EBCDIC-DK-NO';
9726 case 'csebcdicdknoa':
9728 return 'EBCDIC-DK-NO-A';
9736 return 'EBCDIC-ES-A';
9740 return 'EBCDIC-ES-S';
9742 case 'csebcdicfise':
9744 return 'EBCDIC-FI-SE';
9746 case 'csebcdicfisea':
9748 return 'EBCDIC-FI-SE-A';
9770 case 'csiso111ecmacyrillic':
9771 case 'ecmacyrillic':
9774 return 'ECMA-cyrillic';
9776 case 'csiso17spanish':
9782 case 'csiso85spanish2':
9788 case 'cseucfixwidjapanese':
9789 case 'extendedunixcodefixedwidthforjapanese':
9790 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9792 case 'cseucpkdfmtjapanese':
9794 case 'extendedunixcodepackedformatforjapanese':
9795 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9803 case 'csiso58gb231280':
9813 case 'csiso57gb1988':
9817 return 'GB_1988-80';
9819 case 'csiso153gost1976874':
9823 return 'GOST_19768-74';
9826 case 'csiso150greekccitt':
9829 return 'greek-ccitt';
9831 case 'csiso88greek7':
9836 case 'csiso18greek7old':
9839 return 'greek7-old';
9843 return 'HP-DeskTop';
9855 return 'HP-Pi-font';
9864 return 'HZ-GB-2312';
9866 case 'csibmsymbols':
9868 return 'IBM-Symbols';
9877 case 'pcmultilingual850euro':
9882 case 'ebcdiclatin9euro':
9888 case 'ebcdicus37euro':
9894 case 'ebcdicde273euro':
9900 case 'ebcdicdk277euro':
9901 case 'ebcdicno277euro':
9907 case 'ebcdicfi278euro':
9908 case 'ebcdicse278euro':
9914 case 'ebcdicit280euro':
9920 case 'ebcdices284euro':
9926 case 'ebcdicgb285euro':
9932 case 'ebcdicfr297euro':
9938 case 'ebcdicinternational500euro':
9944 case 'ebcdicis871euro':
10019 case 'ebcdicjpkana':
10031 case 'ebcdiccpar1':
10049 case 'cspc8codepage437':
10061 case 'cspc775baltic':
10067 case 'cspc850multilingual':
10110 case 'cspc862latinhebrew':
10152 case 'ebcdiccproece':
10165 case 'ebcdiccyrillic':
10193 case 'ebcdiccpar2':
10205 case 'csiso143iecp271':
10208 return 'IEC_P27-1';
10210 case 'csiso49inis':
10215 case 'csiso50inis8':
10220 case 'csiso51iniscyrillic':
10221 case 'iniscyrillic':
10223 return 'INIS-cyrillic';
10225 case 'csinvariant':
10227 return 'INVARIANT';
10230 return 'ISO-2022-CN';
10232 case 'iso2022cnext':
10233 return 'ISO-2022-CN-EXT';
10235 case 'csiso2022jp':
10237 return 'ISO-2022-JP';
10239 case 'csiso2022jp2':
10241 return 'ISO-2022-JP-2';
10243 case 'csiso2022kr':
10245 return 'ISO-2022-KR';
10247 case 'cswindows30latin1':
10248 case 'iso88591windows30latin1':
10249 return 'ISO-8859-1-Windows-3.0-Latin-1';
10251 case 'cswindows31latin1':
10252 case 'iso88591windows31latin1':
10253 return 'ISO-8859-1-Windows-3.1-Latin-1';
10255 case 'csisolatin2':
10257 case 'iso885921987':
10261 return 'ISO-8859-2';
10263 case 'cswindows31latin2':
10264 case 'iso88592windowslatin2':
10265 return 'ISO-8859-2-Windows-Latin-2';
10267 case 'csisolatin3':
10269 case 'iso885931988':
10273 return 'ISO-8859-3';
10275 case 'csisolatin4':
10277 case 'iso885941988':
10281 return 'ISO-8859-4';
10283 case 'csisolatincyrillic':
10286 case 'iso885951988':
10288 return 'ISO-8859-5';
10292 case 'csisolatinarabic':
10295 case 'iso885961987':
10297 return 'ISO-8859-6';
10299 case 'csiso88596e':
10301 return 'ISO-8859-6-E';
10303 case 'csiso88596i':
10305 return 'ISO-8859-6-I';
10307 case 'csisolatingreek':
10313 case 'iso885971987':
10315 return 'ISO-8859-7';
10317 case 'csisolatinhebrew':
10320 case 'iso885981988':
10322 return 'ISO-8859-8';
10324 case 'csiso88598e':
10326 return 'ISO-8859-8-E';
10328 case 'csiso88598i':
10330 return 'ISO-8859-8-I';
10332 case 'cswindows31latin5':
10333 case 'iso88599windowslatin5':
10334 return 'ISO-8859-9-Windows-Latin-5';
10336 case 'csisolatin6':
10338 case 'iso8859101992':
10342 return 'ISO-8859-10';
10345 return 'ISO-8859-13';
10348 case 'iso8859141998':
10353 return 'ISO-8859-14';
10357 return 'ISO-8859-15';
10360 case 'iso8859162001':
10364 return 'ISO-8859-16';
10367 return 'ISO-10646-J-1';
10370 case 'iso10646ucs2':
10371 return 'ISO-10646-UCS-2';
10374 case 'iso10646ucs4':
10375 return 'ISO-10646-UCS-4';
10377 case 'csunicodeascii':
10378 case 'iso10646ucsbasic':
10379 return 'ISO-10646-UCS-Basic';
10381 case 'csunicodelatin1':
10383 case 'iso10646unicodelatin1':
10384 return 'ISO-10646-Unicode-Latin1';
10386 case 'csiso10646utf1':
10387 case 'iso10646utf1':
10388 return 'ISO-10646-UTF-1';
10390 case 'csiso115481':
10392 case 'isotr115481':
10393 return 'ISO-11548-1';
10397 return 'iso-ir-90';
10399 case 'csunicodeibm1261':
10400 case 'isounicodeibm1261':
10401 return 'ISO-Unicode-IBM-1261';
10403 case 'csunicodeibm1264':
10404 case 'isounicodeibm1264':
10405 return 'ISO-Unicode-IBM-1264';
10407 case 'csunicodeibm1265':
10408 case 'isounicodeibm1265':
10409 return 'ISO-Unicode-IBM-1265';
10411 case 'csunicodeibm1268':
10412 case 'isounicodeibm1268':
10413 return 'ISO-Unicode-IBM-1268';
10415 case 'csunicodeibm1276':
10416 case 'isounicodeibm1276':
10417 return 'ISO-Unicode-IBM-1276';
10419 case 'csiso646basic1983':
10420 case 'iso646basic1983':
10422 return 'ISO_646.basic:1983';
10424 case 'csiso2intlrefversion':
10426 case 'iso646irv1983':
10428 return 'ISO_646.irv:1983';
10432 case 'iso20331983':
10434 return 'ISO_2033-1983';
10436 case 'csiso5427cyrillic':
10441 case 'iso5427cyrillic1981':
10442 case 'iso54271981':
10444 return 'ISO_5427:1981';
10446 case 'csiso5428greek':
10447 case 'iso54281980':
10449 return 'ISO_5428:1980';
10451 case 'csiso6937add':
10454 return 'ISO_6937-2-25';
10456 case 'csisotextcomm':
10457 case 'iso69372add':
10459 return 'ISO_6937-2-add';
10461 case 'csiso8859supp':
10462 case 'iso8859supp':
10465 return 'ISO_8859-supp';
10467 case 'csiso10367box':
10468 case 'iso10367box':
10470 return 'ISO_10367-box';
10472 case 'csiso15italian':
10478 case 'csiso13jisc6220jp':
10480 case 'jisc62201969':
10481 case 'jisc62201969jp':
10484 return 'JIS_C6220-1969-jp';
10486 case 'csiso14jisc6220ro':
10489 case 'jisc62201969ro':
10491 return 'JIS_C6220-1969-ro';
10493 case 'csiso42jisc62261978':
10495 case 'jisc62261978':
10496 return 'JIS_C6226-1978';
10498 case 'csiso87jisx208':
10500 case 'jisc62261983':
10501 case 'jisx2081983':
10503 return 'JIS_C6226-1983';
10505 case 'csiso91jisc62291984a':
10507 case 'jisc62291984a':
10509 return 'JIS_C6229-1984-a';
10511 case 'csiso92jisc62991984b':
10512 case 'iso646jpocrb':
10514 case 'jisc62291984b':
10516 return 'JIS_C6229-1984-b';
10518 case 'csiso93jis62291984badd':
10520 case 'jisc62291984badd':
10522 return 'JIS_C6229-1984-b-add';
10524 case 'csiso94jis62291984hand':
10526 case 'jisc62291984hand':
10528 return 'JIS_C6229-1984-hand';
10530 case 'csiso95jis62291984handadd':
10532 case 'jisc62291984handadd':
10533 case 'jpocrhandadd':
10534 return 'JIS_C6229-1984-hand-add';
10536 case 'csiso96jisc62291984kana':
10538 case 'jisc62291984kana':
10539 return 'JIS_C6229-1984-kana';
10541 case 'csjisencoding':
10542 case 'jisencoding':
10543 return 'JIS_Encoding';
10545 case 'cshalfwidthkatakana':
10548 return 'JIS_X0201';
10550 case 'csiso159jisx2121990':
10552 case 'jisx2121990':
10554 return 'JIS_X0212-1990';
10556 case 'csiso141jusib1002':
10562 return 'JUS_I.B1.002';
10564 case 'csiso147macedonian':
10566 case 'jusib1003mac':
10568 return 'JUS_I.B1.003-mac';
10570 case 'csiso146serbian':
10572 case 'jusib1003serb':
10574 return 'JUS_I.B1.003-serb';
10576 case 'koi7switched':
10577 return 'KOI7-switched';
10594 case 'strk10482002':
10597 case 'csiso19latingreek':
10600 return 'latin-greek';
10602 case 'csiso27latingreek1':
10604 case 'latingreek1':
10605 return 'Latin-greek-1';
10607 case 'csiso158lap':
10611 return 'latin-lap';
10613 case 'csmacintosh':
10616 return 'macintosh';
10618 case 'csmicrosoftpublishing':
10619 case 'microsoftpublishing':
10620 return 'Microsoft-Publishing';
10630 case 'csiso86hungarian':
10635 return 'MSZ_7795.3';
10640 return 'NATS-DANO';
10642 case 'csnatsdanoadd':
10644 case 'natsdanoadd':
10645 return 'NATS-DANO-ADD';
10650 return 'NATS-SEFI';
10652 case 'csnatssefiadd':
10654 case 'natssefiadd':
10655 return 'NATS-SEFI-ADD';
10657 case 'csiso151cuba':
10662 return 'NC_NC00-10:81';
10664 case 'csiso69french':
10669 return 'NF_Z_62-010';
10671 case 'csiso25french':
10674 case 'nfz620101973':
10675 return 'NF_Z_62-010_(1973)';
10677 case 'csiso60danishnorwegian':
10678 case 'csiso60norwegian1':
10683 return 'NS_4551-1';
10685 case 'csiso61norwegian2':
10690 return 'NS_4551-2';
10692 case 'osdebcdicdf3irv':
10693 return 'OSD_EBCDIC_DF03_IRV';
10695 case 'osdebcdicdf41':
10696 return 'OSD_EBCDIC_DF04_1';
10698 case 'osdebcdicdf415':
10699 return 'OSD_EBCDIC_DF04_15';
10701 case 'cspc8danishnorwegian':
10702 case 'pc8danishnorwegian':
10703 return 'PC8-Danish-Norwegian';
10705 case 'cspc8turkish':
10707 return 'PC8-Turkish';
10709 case 'csiso16portuguese':
10715 case 'csiso84portuguese2':
10723 case 'cyrillicasian':
10731 case 'csiso10swedish':
10738 return 'SEN_850200_B';
10740 case 'csiso11swedishfornames':
10745 return 'SEN_850200_C';
10750 return 'Shift_JIS';
10752 case 'csiso102t617bit':
10755 return 'T.61-7bit';
10757 case 'csiso103t618bit':
10761 return 'T.61-8bit';
10763 case 'csiso128t101g2':
10772 case 'csunicode11':
10774 return 'UNICODE-1-1';
10776 case 'csunicode11utf7':
10777 case 'unicode11utf7':
10778 return 'UNICODE-1-1-UTF-7';
10780 case 'csunknown8bit':
10781 case 'unknown8bit':
10782 return 'UNKNOWN-8BIT';
10784 case 'ansix341968':
10785 case 'ansix341986':
10790 case 'iso646irv1991':
10825 case 'csventurainternational':
10826 case 'venturainternational':
10827 return 'Ventura-International';
10829 case 'csventuramath':
10830 case 'venturamath':
10831 return 'Ventura-Math';
10833 case 'csventuraus':
10835 return 'Ventura-US';
10837 case 'csiso70videotexsupp1':
10839 case 'videotexsuppl':
10840 return 'videotex-suppl';
10850 case 'cswindows31j':
10852 return 'Windows-31J';
10856 return 'windows-874';
10859 case 'csksc56011987':
10864 case 'ksc56011987':
10865 case 'ksc56011989':
10867 return 'windows-949';
10869 case 'windows1250':
10870 return 'windows-1250';
10872 case 'windows1251':
10873 return 'windows-1251';
10876 case 'csisolatin1':
10879 case 'iso885911987':
10883 case 'windows1252':
10884 return 'windows-1252';
10886 case 'windows1253':
10887 return 'windows-1253';
10889 case 'csisolatin5':
10891 case 'iso885991989':
10895 case 'windows1254':
10896 return 'windows-1254';
10898 case 'windows1255':
10899 return 'windows-1255';
10901 case 'windows1256':
10902 return 'windows-1256';
10904 case 'windows1257':
10905 return 'windows-1257';
10907 case 'windows1258':
10908 return 'windows-1258';
10915 function get_curl_version()
10917 if (is_array($curl = curl_version()))
10919 $curl = $curl['version'];
10921 elseif (substr($curl, 0, 5) === 'curl/')
10923 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10925 elseif (substr($curl, 0, 8) === 'libcurl/')
10927 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10936 function is_subclass_of($class1, $class2)
10938 if (func_num_args() !== 2)
10940 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10942 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10944 return is_subclass_of($class1, $class2);
10946 elseif (is_string($class1) && is_string($class2))
10948 if (class_exists($class1))
10950 if (class_exists($class2))
10952 $class2 = strtolower($class2);
10953 while ($class1 = strtolower(get_parent_class($class1)))
10955 if ($class1 === $class2)
10964 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10971 * Strip HTML comments
10974 * @param string $data Data to strip comments from
10975 * @return string Comment stripped string
10977 function strip_comments($data)
10980 while (($start = strpos($data, '<!--')) !== false)
10982 $output .= substr($data, 0, $start);
10983 if (($end = strpos($data, '-->', $start)) !== false)
10985 $data = substr_replace($data, '', 0, $end + 3);
10992 return $output . $data;
10995 function parse_date($dt)
10997 $parser = SimplePie_Parse_Date::get();
10998 return $parser->parse($dt);
11002 * Decode HTML entities
11006 * @param string $data Input data
11007 * @return string Output data
11009 function entities_decode($data)
11011 $decoder = new SimplePie_Decode_HTML_Entities($data);
11012 return $decoder->parse();
11016 * Remove RFC822 comments
11019 * @param string $data Data to strip comments from
11020 * @return string Comment stripped string
11022 function uncomment_rfc822($string)
11024 $string = (string) $string;
11026 $length = strlen($string);
11031 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
11033 $output .= substr($string, $position, $pos - $position);
11034 $position = $pos + 1;
11035 if ($string[$pos - 1] !== '\\')
11038 while ($depth && $position < $length)
11040 $position += strcspn($string, '()', $position);
11041 if ($string[$position - 1] === '\\')
11046 elseif (isset($string[$position]))
11048 switch ($string[$position])
11071 $output .= substr($string, $position);
11076 function parse_mime($mime)
11078 if (($pos = strpos($mime, ';')) === false)
11080 return trim($mime);
11084 return trim(substr($mime, 0, $pos));
11088 function htmlspecialchars_decode($string, $quote_style)
11090 if (function_exists('htmlspecialchars_decode'))
11092 return htmlspecialchars_decode($string, $quote_style);
11096 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
11100 function atom_03_construct_type($attribs)
11102 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
11104 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11108 $mode = SIMPLEPIE_CONSTRUCT_NONE;
11110 if (isset($attribs['']['type']))
11112 switch (strtolower(trim($attribs['']['type'])))
11116 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11120 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11123 case 'application/xhtml+xml':
11124 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11127 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11132 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11136 function atom_10_construct_type($attribs)
11138 if (isset($attribs['']['type']))
11140 switch (strtolower(trim($attribs['']['type'])))
11143 return SIMPLEPIE_CONSTRUCT_TEXT;
11146 return SIMPLEPIE_CONSTRUCT_HTML;
11149 return SIMPLEPIE_CONSTRUCT_XHTML;
11152 return SIMPLEPIE_CONSTRUCT_NONE;
11155 return SIMPLEPIE_CONSTRUCT_TEXT;
11158 function atom_10_content_construct_type($attribs)
11160 if (isset($attribs['']['type']))
11162 $type = strtolower(trim($attribs['']['type']));
11166 return SIMPLEPIE_CONSTRUCT_TEXT;
11169 return SIMPLEPIE_CONSTRUCT_HTML;
11172 return SIMPLEPIE_CONSTRUCT_XHTML;
11174 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11176 return SIMPLEPIE_CONSTRUCT_NONE;
11180 return SIMPLEPIE_CONSTRUCT_BASE64;
11185 return SIMPLEPIE_CONSTRUCT_TEXT;
11189 function is_isegment_nz_nc($string)
11191 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);
11194 function space_seperated_tokens($string)
11196 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11197 $string_length = strlen($string);
11199 $position = strspn($string, $space_characters);
11202 while ($position < $string_length)
11204 $len = strcspn($string, $space_characters, $position);
11205 $tokens[] = substr($string, $position, $len);
11207 $position += strspn($string, $space_characters, $position);
11213 function array_unique($array)
11215 if (version_compare(PHP_VERSION, '5.2', '>='))
11217 return array_unique($array);
11221 $array = (array) $array;
11222 $new_array = array();
11223 $new_array_strings = array();
11224 foreach ($array as $key => $value)
11226 if (is_object($value))
11228 if (method_exists($value, '__toString'))
11230 $cmp = $value->__toString();
11234 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11237 elseif (is_array($value))
11239 $cmp = (string) reset($value);
11243 $cmp = (string) $value;
11245 if (!in_array($cmp, $new_array_strings))
11247 $new_array[$key] = $value;
11248 $new_array_strings[] = $cmp;
11256 * Converts a unicode codepoint to a UTF-8 character
11260 * @param int $codepoint Unicode codepoint
11261 * @return string UTF-8 character
11263 function codepoint_to_utf8($codepoint)
11265 $codepoint = (int) $codepoint;
11266 if ($codepoint < 0)
11270 else if ($codepoint <= 0x7f)
11272 return chr($codepoint);
11274 else if ($codepoint <= 0x7ff)
11276 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11278 else if ($codepoint <= 0xffff)
11280 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11282 else if ($codepoint <= 0x10ffff)
11284 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11288 // U+FFFD REPLACEMENT CHARACTER
11289 return "\xEF\xBF\xBD";
11294 * Re-implementation of PHP 5's stripos()
11296 * Returns the numeric position of the first occurrence of needle in the
11301 * @param object $haystack
11302 * @param string $needle Note that the needle may be a string of one or more
11303 * characters. If needle is not a string, it is converted to an integer
11304 * and applied as the ordinal value of a character.
11305 * @param int $offset The optional offset parameter allows you to specify which
11306 * character in haystack to start searching. The position returned is still
11307 * relative to the beginning of haystack.
11308 * @return bool If needle is not found, stripos() will return boolean false.
11310 function stripos($haystack, $needle, $offset = 0)
11312 if (function_exists('stripos'))
11314 return stripos($haystack, $needle, $offset);
11318 if (is_string($needle))
11320 $needle = strtolower($needle);
11322 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11324 $needle = strtolower(chr($needle));
11328 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11332 return strpos(strtolower($haystack), $needle, $offset);
11337 * Similar to parse_str()
11339 * Returns an associative array of name/value pairs, where the value is an
11340 * array of values that have used the same name
11344 * @param string $str The input string.
11347 function parse_str($str)
11350 $str = explode('&', $str);
11352 foreach ($str as $section)
11354 if (strpos($section, '=') !== false)
11356 list($name, $value) = explode('=', $section, 2);
11357 $return[urldecode($name)][] = urldecode($value);
11361 $return[urldecode($section)][] = null;
11369 * Detect XML encoding, as per XML 1.0 Appendix F.1
11371 * @todo Add support for EBCDIC
11372 * @param string $data XML data
11373 * @return array Possible encodings
11375 function xml_encoding($data)
11377 // UTF-32 Big Endian BOM
11378 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11380 $encoding[] = 'UTF-32BE';
11382 // UTF-32 Little Endian BOM
11383 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11385 $encoding[] = 'UTF-32LE';
11387 // UTF-16 Big Endian BOM
11388 elseif (substr($data, 0, 2) === "\xFE\xFF")
11390 $encoding[] = 'UTF-16BE';
11392 // UTF-16 Little Endian BOM
11393 elseif (substr($data, 0, 2) === "\xFF\xFE")
11395 $encoding[] = 'UTF-16LE';
11398 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11400 $encoding[] = 'UTF-8';
11402 // UTF-32 Big Endian Without BOM
11403 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")
11405 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11407 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11408 if ($parser->parse())
11410 $encoding[] = $parser->encoding;
11413 $encoding[] = 'UTF-32BE';
11415 // UTF-32 Little Endian Without BOM
11416 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")
11418 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11420 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11421 if ($parser->parse())
11423 $encoding[] = $parser->encoding;
11426 $encoding[] = 'UTF-32LE';
11428 // UTF-16 Big Endian Without BOM
11429 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11431 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11433 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11434 if ($parser->parse())
11436 $encoding[] = $parser->encoding;
11439 $encoding[] = 'UTF-16BE';
11441 // UTF-16 Little Endian Without BOM
11442 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11444 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11446 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11447 if ($parser->parse())
11449 $encoding[] = $parser->encoding;
11452 $encoding[] = 'UTF-16LE';
11454 // US-ASCII (or superset)
11455 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11457 if ($pos = strpos($data, "\x3F\x3E"))
11459 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11460 if ($parser->parse())
11462 $encoding[] = $parser->encoding;
11465 $encoding[] = 'UTF-8';
11467 // Fallback to UTF-8
11470 $encoding[] = 'UTF-8';
11475 function output_javascript()
11477 if (function_exists('ob_gzhandler'))
11479 ob_start('ob_gzhandler');
11481 header('Content-type: text/javascript; charset: UTF-8');
11482 header('Cache-Control: must-revalidate');
11483 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11485 function embed_odeo(link) {
11486 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>');
11489 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11490 if (placeholder != '') {
11491 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>');
11494 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>');
11498 function embed_flash(bgcolor, width, height, link, loop, type) {
11499 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>');
11502 function embed_flv(width, height, link, placeholder, loop, player) {
11503 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>');
11506 function embed_wmedia(width, height, link) {
11507 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11514 * Decode HTML Entities
11516 * This implements HTML5 as of revision 967 (2007-06-28)
11518 * @package SimplePie
11520 class SimplePie_Decode_HTML_Entities
11523 * Data to be parsed
11531 * Currently consumed bytes
11536 var $consumed = '';
11539 * Position of the current byte being parsed
11547 * Create an instance of the class with the input data
11550 * @param string $data Input data
11552 function SimplePie_Decode_HTML_Entities($data)
11554 $this->data = $data;
11558 * Parse the input data
11561 * @return string Output data
11565 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11569 $this->consumed = '';
11571 return $this->data;
11575 * Consume the next byte
11578 * @return mixed The next byte, or false, if there is no more data
11582 if (isset($this->data[$this->position]))
11584 $this->consumed .= $this->data[$this->position];
11585 return $this->data[$this->position++];
11594 * Consume a range of characters
11597 * @param string $chars Characters to consume
11598 * @return mixed A series of characters that match the range, or false
11600 function consume_range($chars)
11602 if ($len = strspn($this->data, $chars, $this->position))
11604 $data = substr($this->data, $this->position, $len);
11605 $this->consumed .= $data;
11606 $this->position += $len;
11616 * Unconsume one byte
11620 function unconsume()
11622 $this->consumed = substr($this->consumed, 0, -1);
11633 switch ($this->consume())
11647 switch ($this->consume())
11651 $range = '0123456789ABCDEFabcdef';
11656 $range = '0123456789';
11658 $this->unconsume();
11662 if ($codepoint = $this->consume_range($range))
11664 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");
11668 $codepoint = hexdec($codepoint);
11672 $codepoint = intval($codepoint);
11675 if (isset($windows_1252_specials[$codepoint]))
11677 $replacement = $windows_1252_specials[$codepoint];
11681 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11684 if (!in_array($this->consume(), array(';', false), true))
11686 $this->unconsume();
11689 $consumed_length = strlen($this->consumed);
11690 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11691 $this->position += strlen($replacement) - $consumed_length;
11696 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");
11698 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11700 $consumed = substr($this->consumed, 1);
11701 if (isset($entities[$consumed]))
11703 $match = $consumed;
11707 if ($match !== null)
11709 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11710 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11718 * IRI parser/serialiser
11720 * @package SimplePie
11722 class SimplePie_IRI
11781 * Whether the object represents a valid IRI
11786 var $valid = array();
11789 * Return the entire IRI when you try and read the object as a string
11794 function __toString()
11796 return $this->get_iri();
11800 * Create a new IRI object, from a specified string
11803 * @param string $iri
11804 * @return SimplePie_IRI
11806 function SimplePie_IRI($iri)
11808 $iri = (string) $iri;
11811 $parsed = $this->parse_iri($iri);
11812 $this->set_scheme($parsed['scheme']);
11813 $this->set_authority($parsed['authority']);
11814 $this->set_path($parsed['path']);
11815 $this->set_query($parsed['query']);
11816 $this->set_fragment($parsed['fragment']);
11821 * Create a new IRI object by resolving a relative IRI
11825 * @param SimplePie_IRI $base Base IRI
11826 * @param string $relative Relative IRI
11827 * @return SimplePie_IRI
11829 function absolutize($base, $relative)
11831 $relative = (string) $relative;
11832 if ($relative !== '')
11834 $relative = new SimplePie_IRI($relative);
11835 if ($relative->get_scheme() !== null)
11837 $target = $relative;
11839 elseif ($base->get_iri() !== null)
11841 if ($relative->get_authority() !== null)
11843 $target = $relative;
11844 $target->set_scheme($base->get_scheme());
11848 $target = new SimplePie_IRI('');
11849 $target->set_scheme($base->get_scheme());
11850 $target->set_userinfo($base->get_userinfo());
11851 $target->set_host($base->get_host());
11852 $target->set_port($base->get_port());
11853 if ($relative->get_path() !== null)
11855 if (strpos($relative->get_path(), '/') === 0)
11857 $target->set_path($relative->get_path());
11859 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11861 $target->set_path('/' . $relative->get_path());
11863 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11865 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11869 $target->set_path($relative->get_path());
11871 $target->set_query($relative->get_query());
11875 $target->set_path($base->get_path());
11876 if ($relative->get_query() !== null)
11878 $target->set_query($relative->get_query());
11880 elseif ($base->get_query() !== null)
11882 $target->set_query($base->get_query());
11886 $target->set_fragment($relative->get_fragment());
11890 // No base URL, just return the relative URL
11891 $target = $relative;
11902 * Parse an IRI into scheme/authority/path/query/fragment segments
11905 * @param string $iri
11908 function parse_iri($iri)
11910 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11911 for ($i = count($match); $i <= 9; $i++)
11915 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11919 * Remove dot segments from a path
11922 * @param string $input
11925 function remove_dot_segments($input)
11928 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11930 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11931 if (strpos($input, '../') === 0)
11933 $input = substr($input, 3);
11935 elseif (strpos($input, './') === 0)
11937 $input = substr($input, 2);
11939 // 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,
11940 elseif (strpos($input, '/./') === 0)
11942 $input = substr_replace($input, '/', 0, 3);
11944 elseif ($input === '/.')
11948 // 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,
11949 elseif (strpos($input, '/../') === 0)
11951 $input = substr_replace($input, '/', 0, 4);
11952 $output = substr_replace($output, '', strrpos($output, '/'));
11954 elseif ($input === '/..')
11957 $output = substr_replace($output, '', strrpos($output, '/'));
11959 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11960 elseif ($input === '.' || $input === '..')
11964 // 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
11965 elseif (($pos = strpos($input, '/', 1)) !== false)
11967 $output .= substr($input, 0, $pos);
11968 $input = substr_replace($input, '', 0, $pos);
11976 return $output . $input;
11980 * Replace invalid character with percent encoding
11983 * @param string $string Input string
11984 * @param string $valid_chars Valid characters
11985 * @param int $case Normalise case
11988 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11991 if ($case & SIMPLEPIE_LOWERCASE)
11993 $string = strtolower($string);
11995 elseif ($case & SIMPLEPIE_UPPERCASE)
11997 $string = strtoupper($string);
12000 // Store position and string length (to avoid constantly recalculating this)
12002 $strlen = strlen($string);
12004 // Loop as long as we have invalid characters, advancing the position to the next invalid character
12005 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
12007 // If we have a % character
12008 if ($string[$position] === '%')
12010 // If we have a pct-encoded section
12011 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
12013 // Get the the represented character
12014 $chr = chr(hexdec(substr($string, $position + 1, 2)));
12016 // If the character is valid, replace the pct-encoded with the actual character while normalising case
12017 if (strpos($valid_chars, $chr) !== false)
12019 if ($case & SIMPLEPIE_LOWERCASE)
12021 $chr = strtolower($chr);
12023 elseif ($case & SIMPLEPIE_UPPERCASE)
12025 $chr = strtoupper($chr);
12027 $string = substr_replace($string, $chr, $position, 3);
12032 // Otherwise just normalise the pct-encoded to uppercase
12035 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
12039 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
12042 $string = substr_replace($string, '%25', $position, 1);
12047 // If we have an invalid character, change into its pct-encoded form
12050 $replacement = sprintf("%%%02X", ord($string[$position]));
12051 $string = str_replace($string[$position], $replacement, $string);
12052 $strlen = strlen($string);
12059 * Check if the object represents a valid IRI
12064 function is_valid()
12066 return array_sum($this->valid) === count($this->valid);
12070 * Set the scheme. Returns true on success, false on failure (if there are
12071 * any invalid characters).
12074 * @param string $scheme
12077 function set_scheme($scheme)
12079 if ($scheme === null || $scheme === '')
12081 $this->scheme = null;
12085 $len = strlen($scheme);
12089 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12091 $this->scheme = null;
12092 $this->valid[__FUNCTION__] = false;
12097 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12099 $this->scheme = null;
12100 $this->valid[__FUNCTION__] = false;
12104 $this->scheme = strtolower($scheme);
12106 $this->valid[__FUNCTION__] = true;
12111 * Set the authority. Returns true on success, false on failure (if there are
12112 * any invalid characters).
12115 * @param string $authority
12118 function set_authority($authority)
12120 if (($userinfo_end = strrpos($authority, '@')) !== false)
12122 $userinfo = substr($authority, 0, $userinfo_end);
12123 $authority = substr($authority, $userinfo_end + 1);
12130 if (($port_start = strpos($authority, ':')) !== false)
12132 $port = substr($authority, $port_start + 1);
12133 $authority = substr($authority, 0, $port_start);
12140 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12144 * Set the userinfo.
12147 * @param string $userinfo
12150 function set_userinfo($userinfo)
12152 if ($userinfo === null || $userinfo === '')
12154 $this->userinfo = null;
12158 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12160 $this->valid[__FUNCTION__] = true;
12165 * Set the host. Returns true on success, false on failure (if there are
12166 * any invalid characters).
12169 * @param string $host
12172 function set_host($host)
12174 if ($host === null || $host === '')
12176 $this->host = null;
12177 $this->valid[__FUNCTION__] = true;
12180 elseif ($host[0] === '[' && substr($host, -1) === ']')
12182 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12184 $this->host = $host;
12185 $this->valid[__FUNCTION__] = true;
12190 $this->host = null;
12191 $this->valid[__FUNCTION__] = false;
12197 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12198 $this->valid[__FUNCTION__] = true;
12204 * Set the port. Returns true on success, false on failure (if there are
12205 * any invalid characters).
12208 * @param string $port
12211 function set_port($port)
12213 if ($port === null || $port === '')
12215 $this->port = null;
12216 $this->valid[__FUNCTION__] = true;
12219 elseif (strspn($port, '0123456789') === strlen($port))
12221 $this->port = (int) $port;
12222 $this->valid[__FUNCTION__] = true;
12227 $this->port = null;
12228 $this->valid[__FUNCTION__] = false;
12237 * @param string $path
12240 function set_path($path)
12242 if ($path === null || $path === '')
12244 $this->path = null;
12245 $this->valid[__FUNCTION__] = true;
12248 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12250 $this->path = null;
12251 $this->valid[__FUNCTION__] = false;
12256 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12257 if ($this->scheme !== null)
12259 $this->path = $this->remove_dot_segments($this->path);
12261 $this->valid[__FUNCTION__] = true;
12270 * @param string $query
12273 function set_query($query)
12275 if ($query === null || $query === '')
12277 $this->query = null;
12281 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
12283 $this->valid[__FUNCTION__] = true;
12288 * Set the fragment.
12291 * @param string $fragment
12294 function set_fragment($fragment)
12296 if ($fragment === null || $fragment === '')
12298 $this->fragment = null;
12302 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12304 $this->valid[__FUNCTION__] = true;
12309 * Get the complete IRI
12317 if ($this->scheme !== null)
12319 $iri .= $this->scheme . ':';
12321 if (($authority = $this->get_authority()) !== null)
12323 $iri .= '//' . $authority;
12325 if ($this->path !== null)
12327 $iri .= $this->path;
12329 if ($this->query !== null)
12331 $iri .= '?' . $this->query;
12333 if ($this->fragment !== null)
12335 $iri .= '#' . $this->fragment;
12354 function get_scheme()
12356 return $this->scheme;
12360 * Get the complete authority
12365 function get_authority()
12368 if ($this->userinfo !== null)
12370 $authority .= $this->userinfo . '@';
12372 if ($this->host !== null)
12374 $authority .= $this->host;
12376 if ($this->port !== null)
12378 $authority .= ':' . $this->port;
12381 if ($authority !== '')
12392 * Get the user information
12397 function get_userinfo()
12399 return $this->userinfo;
12408 function get_host()
12410 return $this->host;
12419 function get_port()
12421 return $this->port;
12430 function get_path()
12432 return $this->path;
12441 function get_query()
12443 return $this->query;
12452 function get_fragment()
12454 return $this->fragment;
12459 * Class to validate and to work with IPv6 addresses.
12461 * @package SimplePie
12462 * @copyright 2003-2005 The PHP Group
12463 * @license http://www.opensource.org/licenses/bsd-license.php
12464 * @link http://pear.php.net/package/Net_IPv6
12465 * @author Alexander Merz <alexander.merz@web.de>
12466 * @author elfrink at introweb dot nl
12467 * @author Josh Peck <jmp at joshpeck dot org>
12468 * @author Geoffrey Sneddon <geoffers@gmail.com>
12470 class SimplePie_Net_IPv6
12473 * Removes a possible existing netmask specification of an IP address.
12475 * @param string $ip the (compressed) IP as Hex representation
12476 * @return string the IP the without netmask
12481 function removeNetmaskSpec($ip)
12483 if (strpos($ip, '/') !== false)
12485 list($addr, $nm) = explode('/', $ip);
12495 * Uncompresses an IPv6 address
12497 * RFC 2373 allows you to compress zeros in an address to '::'. This
12498 * function expects an valid IPv6 address and expands the '::' to
12499 * the required zeros.
12501 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12502 * ::1 -> 0:0:0:0:0:0:0:1
12506 * @param string $ip a valid IPv6-address (hex format)
12507 * @return string the uncompressed IPv6-address (hex format)
12509 function Uncompress($ip)
12511 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12514 if (strpos($ip, '::') !== false)
12516 list($ip1, $ip2) = explode('::', $ip);
12524 if (($pos = substr_count($ip1, ':')) > 0)
12540 if (($pos = substr_count($ip2, ':')) > 0)
12549 if (strstr($ip2, '.'))
12554 if ($c1 === -1 && $c2 === -1)
12556 $uip = '0:0:0:0:0:0:0:0';
12559 else if ($c1 === -1)
12561 $fill = str_repeat('0:', 7 - $c2);
12562 $uip = str_replace('::', $fill, $uip);
12565 else if ($c2 === -1)
12567 $fill = str_repeat(':0', 7 - $c1);
12568 $uip = str_replace('::', $fill, $uip);
12573 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12574 $uip = str_replace('::', $fill, $uip);
12575 $uip = str_replace('::', ':', $uip);
12582 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12584 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12585 * an IPv4 compatible address
12587 * Example: 0:0:0:0:0:0:13.1.68.3
12588 * 0:0:0:0:0:FFFF:129.144.52.38
12592 * @param string $ip a valid IPv6-address (hex format)
12593 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12595 function SplitV64($ip)
12597 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12598 if (strstr($ip, '.'))
12600 $pos = strrpos($ip, ':');
12602 $ipPart = explode('_', $ip);
12607 return array($ip, '');
12612 * Checks an IPv6 address
12614 * Checks if the given IP is IPv6-compatible
12618 * @param string $ip a valid IPv6-address
12619 * @return bool true if $ip is an IPv6 address
12621 function checkIPv6($ip)
12623 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12625 if (!empty($ipPart[0]))
12627 $ipv6 = explode(':', $ipPart[0]);
12628 for ($i = 0; $i < count($ipv6); $i++)
12630 $dec = hexdec($ipv6[$i]);
12631 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12632 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12641 elseif ($count === 6 && !empty($ipPart[1]))
12643 $ipv4 = explode('.', $ipPart[1]);
12645 foreach ($ipv4 as $ipv4_part)
12647 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12673 * @package SimplePie
12675 class SimplePie_Parse_Date
12680 * @access protected
12686 * List of days, calendar day name => ordinal day number in the week
12688 * @access protected
12751 'keskiviikko' => 3,
12775 * List of months, calendar month name => calendar month number
12777 * @access protected
12780 var $month = array(
12791 // No long form of May
12920 * List of timezones, abbreviation => offset from UTC
12922 * @access protected
12925 var $timezone = array(
13128 * Cached PCRE for SimplePie_Parse_Date::$day
13130 * @access protected
13136 * Cached PCRE for SimplePie_Parse_Date::$month
13138 * @access protected
13144 * Array of user-added callback methods
13149 var $built_in = array();
13152 * Array of user-added callback methods
13157 var $user = array();
13160 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13161 * self::month_pcre, and self::built_in
13165 function SimplePie_Parse_Date()
13167 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13168 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13171 if (!isset($cache[get_class($this)]))
13173 $all_methods = get_class_methods($this);
13175 foreach ($all_methods as $method)
13177 if (strtolower(substr($method, 0, 5)) === 'date_')
13179 $cache[get_class($this)][] = $method;
13184 foreach ($cache[get_class($this)] as $method)
13186 $this->built_in[] = $method;
13200 $object = new SimplePie_Parse_Date;
13210 * @param string $date Date to parse
13211 * @return int Timestamp corresponding to date string, or false on failure
13213 function parse($date)
13215 foreach ($this->user as $method)
13217 if (($returned = call_user_func($method, $date)) !== false)
13223 foreach ($this->built_in as $method)
13225 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13235 * Add a callback method to parse a date
13239 * @param callback $callback
13241 function add_callback($callback)
13243 if (is_callable($callback))
13245 $this->user[] = $callback;
13249 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13254 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13255 * well as allowing any of upper or lower case "T", horizontal tabs, or
13256 * spaces to be used as the time seperator (including more than one))
13258 * @access protected
13259 * @return int Timestamp
13261 function date_w3cdtf($date)
13266 $year = '([0-9]{4})';
13267 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13268 $decimal = '([0-9]*)';
13269 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13270 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13272 if (preg_match($pcre, $date, $match))
13275 Capturing subpatterns:
13282 7: Decimal fraction of a second
13286 11: Timezone minutes
13289 // Fill in empty matches
13290 for ($i = count($match); $i <= 3; $i++)
13295 for ($i = count($match); $i <= 7; $i++)
13300 // Numeric timezone
13301 if (isset($match[9]) && $match[9] !== '')
13303 $timezone = $match[10] * 3600;
13304 $timezone += $match[11] * 60;
13305 if ($match[9] === '-')
13307 $timezone = 0 - $timezone;
13315 // Convert the number of seconds to an integer, taking decimals into account
13316 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13318 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13327 * Remove RFC822 comments
13329 * @access protected
13330 * @param string $data Data to strip comments from
13331 * @return string Comment stripped string
13333 function remove_rfc2822_comments($string)
13335 $string = (string) $string;
13337 $length = strlen($string);
13342 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13344 $output .= substr($string, $position, $pos - $position);
13345 $position = $pos + 1;
13346 if ($string[$pos - 1] !== '\\')
13349 while ($depth && $position < $length)
13351 $position += strcspn($string, '()', $position);
13352 if ($string[$position - 1] === '\\')
13357 elseif (isset($string[$position]))
13359 switch ($string[$position])
13382 $output .= substr($string, $position);
13388 * Parse RFC2822's date format
13390 * @access protected
13391 * @return int Timestamp
13393 function date_rfc2822($date)
13398 $wsp = '[\x09\x20]';
13399 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13400 $optional_fws = $fws . '?';
13401 $day_name = $this->day_pcre;
13402 $month = $this->month_pcre;
13403 $day = '([0-9]{1,2})';
13404 $hour = $minute = $second = '([0-9]{2})';
13405 $year = '([0-9]{2,4})';
13406 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13407 $character_zone = '([A-Z]{1,5})';
13408 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13409 $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';
13411 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13414 Capturing subpatterns:
13424 10: Timezone minutes
13425 11: Alphabetic timezone
13428 // Find the month number
13429 $month = $this->month[strtolower($match[3])];
13431 // Numeric timezone
13432 if ($match[8] !== '')
13434 $timezone = $match[9] * 3600;
13435 $timezone += $match[10] * 60;
13436 if ($match[8] === '-')
13438 $timezone = 0 - $timezone;
13441 // Character timezone
13442 elseif (isset($this->timezone[strtoupper($match[11])]))
13444 $timezone = $this->timezone[strtoupper($match[11])];
13446 // Assume everything else to be -0000
13452 // Deal with 2/3 digit years
13453 if ($match[4] < 50)
13457 elseif ($match[4] < 1000)
13462 // Second is optional, if it is empty set it to zero
13463 if ($match[7] !== '')
13465 $second = $match[7];
13472 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13481 * Parse RFC850's date format
13483 * @access protected
13484 * @return int Timestamp
13486 function date_rfc850($date)
13491 $space = '[\x09\x20]+';
13492 $day_name = $this->day_pcre;
13493 $month = $this->month_pcre;
13494 $day = '([0-9]{1,2})';
13495 $year = $hour = $minute = $second = '([0-9]{2})';
13496 $zone = '([A-Z]{1,5})';
13497 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13499 if (preg_match($pcre, $date, $match))
13502 Capturing subpatterns:
13514 $month = $this->month[strtolower($match[3])];
13516 // Character timezone
13517 if (isset($this->timezone[strtoupper($match[8])]))
13519 $timezone = $this->timezone[strtoupper($match[8])];
13521 // Assume everything else to be -0000
13527 // Deal with 2 digit year
13528 if ($match[4] < 50)
13537 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13546 * Parse C99's asctime()'s date format
13548 * @access protected
13549 * @return int Timestamp
13551 function date_asctime($date)
13556 $space = '[\x09\x20]+';
13557 $wday_name = $this->day_pcre;
13558 $mon_name = $this->month_pcre;
13559 $day = '([0-9]{1,2})';
13560 $hour = $sec = $min = '([0-9]{2})';
13561 $year = '([0-9]{4})';
13562 $terminator = '\x0A?\x00?';
13563 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13565 if (preg_match($pcre, $date, $match))
13568 Capturing subpatterns:
13578 $month = $this->month[strtolower($match[2])];
13579 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13588 * Parse dates using strtotime()
13590 * @access protected
13591 * @return int Timestamp
13593 function date_strtotime($date)
13595 $strtotime = strtotime($date);
13596 if ($strtotime === -1 || $strtotime === false)
13608 * Content-type sniffing
13610 * @package SimplePie
13612 class SimplePie_Content_Type_Sniffer
13617 * @var SimplePie_File
13623 * Create an instance of the class with the input file
13626 * @param SimplePie_Content_Type_Sniffer $file Input file
13628 function SimplePie_Content_Type_Sniffer($file)
13630 $this->file = $file;
13634 * Get the Content-Type of the specified file
13637 * @return string Actual Content-Type
13639 function get_type()
13641 if (isset($this->file->headers['content-type']))
13643 if (!isset($this->file->headers['content-encoding'])
13644 && ($this->file->headers['content-type'] === 'text/plain'
13645 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13646 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13648 return $this->text_or_binary();
13651 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13653 $official = substr($this->file->headers['content-type'], 0, $pos);
13657 $official = $this->file->headers['content-type'];
13659 $official = strtolower($official);
13661 if ($official === 'unknown/unknown'
13662 || $official === 'application/unknown')
13664 return $this->unknown();
13666 elseif (substr($official, -4) === '+xml'
13667 || $official === 'text/xml'
13668 || $official === 'application/xml')
13672 elseif (substr($official, 0, 6) === 'image/')
13674 if ($return = $this->image())
13683 elseif ($official === 'text/html')
13685 return $this->feed_or_html();
13694 return $this->unknown();
13699 * Sniff text or binary
13702 * @return string Actual Content-Type
13704 function text_or_binary()
13706 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13707 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13708 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13709 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13711 return 'text/plain';
13713 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13715 return 'application/octect-stream';
13719 return 'text/plain';
13727 * @return string Actual Content-Type
13731 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13732 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13733 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13734 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13736 return 'text/html';
13738 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13740 return 'application/pdf';
13742 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13744 return 'application/postscript';
13746 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13747 || substr($this->file->body, 0, 6) === 'GIF89a')
13749 return 'image/gif';
13751 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13753 return 'image/png';
13755 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13757 return 'image/jpeg';
13759 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13761 return 'image/bmp';
13765 return $this->text_or_binary();
13773 * @return string Actual Content-Type
13777 if (substr($this->file->body, 0, 6) === 'GIF87a'
13778 || substr($this->file->body, 0, 6) === 'GIF89a')
13780 return 'image/gif';
13782 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13784 return 'image/png';
13786 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13788 return 'image/jpeg';
13790 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13792 return 'image/bmp';
13804 * @return string Actual Content-Type
13806 function feed_or_html()
13808 $len = strlen($this->file->body);
13809 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13811 while ($pos < $len)
13813 switch ($this->file->body[$pos])
13819 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13827 return 'text/html';
13830 if (substr($this->file->body, $pos, 3) === '!--')
13833 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13839 return 'text/html';
13842 elseif (substr($this->file->body, $pos, 1) === '!')
13844 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13850 return 'text/html';
13853 elseif (substr($this->file->body, $pos, 1) === '?')
13855 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13861 return 'text/html';
13864 elseif (substr($this->file->body, $pos, 3) === 'rss'
13865 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13867 return 'application/rss+xml';
13869 elseif (substr($this->file->body, $pos, 4) === 'feed')
13871 return 'application/atom+xml';
13875 return 'text/html';
13879 return 'text/html';
13884 * Parses the XML Declaration
13886 * @package SimplePie
13888 class SimplePie_XML_Declaration_Parser
13896 var $version = '1.0';
13904 var $encoding = 'UTF-8';
13912 var $standalone = false;
13915 * Current state of the state machine
13920 var $state = 'before_version_name';
13931 * Input data length (to avoid calling strlen() everytime this is needed)
13936 var $data_length = 0;
13939 * Current position of the pointer
13947 * Create an instance of the class with the input data
13950 * @param string $data Input data
13952 function SimplePie_XML_Declaration_Parser($data)
13954 $this->data = $data;
13955 $this->data_length = strlen($this->data);
13959 * Parse the input data
13962 * @return bool true on success, false on failure
13966 while ($this->state && $this->state !== 'emit' && $this->has_data())
13968 $state = $this->state;
13972 if ($this->state === 'emit')
13978 $this->version = '';
13979 $this->encoding = '';
13980 $this->standalone = '';
13986 * Check whether there is data beyond the pointer
13989 * @return bool true if there is further data, false if not
13991 function has_data()
13993 return (bool) ($this->position < $this->data_length);
13997 * Advance past any whitespace
13999 * @return int Number of whitespace characters passed
14001 function skip_whitespace()
14003 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14004 $this->position += $whitespace;
14005 return $whitespace;
14011 function get_value()
14013 $quote = substr($this->data, $this->position, 1);
14014 if ($quote === '"' || $quote === "'")
14017 $len = strcspn($this->data, $quote, $this->position);
14018 if ($this->has_data())
14020 $value = substr($this->data, $this->position, $len);
14021 $this->position += $len + 1;
14028 function before_version_name()
14030 if ($this->skip_whitespace())
14032 $this->state = 'version_name';
14036 $this->state = false;
14040 function version_name()
14042 if (substr($this->data, $this->position, 7) === 'version')
14044 $this->position += 7;
14045 $this->skip_whitespace();
14046 $this->state = 'version_equals';
14050 $this->state = false;
14054 function version_equals()
14056 if (substr($this->data, $this->position, 1) === '=')
14059 $this->skip_whitespace();
14060 $this->state = 'version_value';
14064 $this->state = false;
14068 function version_value()
14070 if ($this->version = $this->get_value())
14072 $this->skip_whitespace();
14073 if ($this->has_data())
14075 $this->state = 'encoding_name';
14079 $this->state = 'emit';
14084 $this->state = false;
14088 function encoding_name()
14090 if (substr($this->data, $this->position, 8) === 'encoding')
14092 $this->position += 8;
14093 $this->skip_whitespace();
14094 $this->state = 'encoding_equals';
14098 $this->state = 'standalone_name';
14102 function encoding_equals()
14104 if (substr($this->data, $this->position, 1) === '=')
14107 $this->skip_whitespace();
14108 $this->state = 'encoding_value';
14112 $this->state = false;
14116 function encoding_value()
14118 if ($this->encoding = $this->get_value())
14120 $this->skip_whitespace();
14121 if ($this->has_data())
14123 $this->state = 'standalone_name';
14127 $this->state = 'emit';
14132 $this->state = false;
14136 function standalone_name()
14138 if (substr($this->data, $this->position, 10) === 'standalone')
14140 $this->position += 10;
14141 $this->skip_whitespace();
14142 $this->state = 'standalone_equals';
14146 $this->state = false;
14150 function standalone_equals()
14152 if (substr($this->data, $this->position, 1) === '=')
14155 $this->skip_whitespace();
14156 $this->state = 'standalone_value';
14160 $this->state = false;
14164 function standalone_value()
14166 if ($standalone = $this->get_value())
14168 switch ($standalone)
14171 $this->standalone = true;
14175 $this->standalone = false;
14179 $this->state = false;
14183 $this->skip_whitespace();
14184 if ($this->has_data())
14186 $this->state = false;
14190 $this->state = 'emit';
14195 $this->state = false;
14200 class SimplePie_Locator
14205 var $local = array();
14206 var $elsewhere = array();
14207 var $file_class = 'SimplePie_File';
14208 var $cached_entities = array();
14211 var $base_location = 0;
14212 var $checked_feeds = 0;
14213 var $max_checked_feeds = 10;
14214 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14216 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14218 $this->file =& $file;
14219 $this->file_class = $file_class;
14220 $this->useragent = $useragent;
14221 $this->timeout = $timeout;
14222 $this->max_checked_feeds = $max_checked_feeds;
14223 $this->content_type_sniffer_class = $content_type_sniffer_class;
14226 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14228 if ($this->is_feed($this->file))
14230 return $this->file;
14233 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14235 $sniffer = new $this->content_type_sniffer_class($this->file);
14236 if ($sniffer->get_type() !== 'text/html')
14242 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14247 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14249 return $working[0];
14252 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14254 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14259 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14264 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14269 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14277 function is_feed(&$file)
14279 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14281 $sniffer = new $this->content_type_sniffer_class($file);
14282 $sniffed = $sniffer->get_type();
14283 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14292 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14302 function get_base()
14304 $this->http_base = $this->file->url;
14305 $this->base = $this->http_base;
14306 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14307 foreach ($elements as $element)
14309 if ($element['attribs']['href']['data'] !== '')
14311 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14312 $this->base_location = $element['offset'];
14318 function autodiscovery()
14320 $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));
14323 foreach ($links as $link)
14325 if ($this->checked_feeds === $this->max_checked_feeds)
14329 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14331 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14333 if ($this->base_location < $link['offset'])
14335 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14339 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14342 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]))
14344 $this->checked_feeds++;
14345 $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14346 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))
14348 $feeds[$href] = $feed;
14355 if (!empty($feeds))
14357 return array_values($feeds);
14364 function get_links()
14366 $links = SimplePie_Misc::get_element('a', $this->file->body);
14367 foreach ($links as $link)
14369 if (isset($link['attribs']['href']['data']))
14371 $href = trim($link['attribs']['href']['data']);
14372 $parsed = SimplePie_Misc::parse_url($href);
14373 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14375 if ($this->base_location < $link['offset'])
14377 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14381 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14384 $current = SimplePie_Misc::parse_url($this->file->url);
14386 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14388 $this->local[] = $href;
14392 $this->elsewhere[] = $href;
14397 $this->local = array_unique($this->local);
14398 $this->elsewhere = array_unique($this->elsewhere);
14399 if (!empty($this->local) || !empty($this->elsewhere))
14406 function extension(&$array)
14408 foreach ($array as $key => $value)
14410 if ($this->checked_feeds === $this->max_checked_feeds)
14414 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14416 $this->checked_feeds++;
14417 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14418 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))
14424 unset($array[$key]);
14431 function body(&$array)
14433 foreach ($array as $key => $value)
14435 if ($this->checked_feeds === $this->max_checked_feeds)
14439 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14441 $this->checked_feeds++;
14442 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14443 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))
14449 unset($array[$key]);
14457 class SimplePie_Parser
14462 var $current_column;
14464 var $separator = ' ';
14465 var $namespace = array('');
14466 var $element = array('');
14467 var $xml_base = array('');
14468 var $xml_base_explicit = array(false);
14469 var $xml_lang = array('');
14470 var $data = array();
14471 var $datas = array(array());
14472 var $current_xhtml_construct = -1;
14475 function parse(&$data, $encoding)
14477 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14478 if (strtoupper($encoding) === 'US-ASCII')
14480 $this->encoding = 'UTF-8';
14484 $this->encoding = $encoding;
14488 // UTF-32 Big Endian BOM
14489 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14491 $data = substr($data, 4);
14493 // UTF-32 Little Endian BOM
14494 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14496 $data = substr($data, 4);
14498 // UTF-16 Big Endian BOM
14499 elseif (substr($data, 0, 2) === "\xFE\xFF")
14501 $data = substr($data, 2);
14503 // UTF-16 Little Endian BOM
14504 elseif (substr($data, 0, 2) === "\xFF\xFE")
14506 $data = substr($data, 2);
14509 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14511 $data = substr($data, 3);
14514 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14516 $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14517 if ($declaration->parse())
14519 $data = substr($data, $pos + 2);
14520 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14524 $this->error_string = 'SimplePie bug! Please report this!';
14531 static $xml_is_sane = null;
14532 if ($xml_is_sane === null)
14534 $parser_check = xml_parser_create();
14535 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
14536 xml_parser_free($parser_check);
14537 $xml_is_sane = isset($values[0]['value']);
14540 // Create the parser
14543 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14544 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14545 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14546 xml_set_object($xml, $this);
14547 xml_set_character_data_handler($xml, 'cdata');
14548 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14551 if (!xml_parse($xml, $data, true))
14553 $this->error_code = xml_get_error_code($xml);
14554 $this->error_string = xml_error_string($this->error_code);
14557 $this->current_line = xml_get_current_line_number($xml);
14558 $this->current_column = xml_get_current_column_number($xml);
14559 $this->current_byte = xml_get_current_byte_index($xml);
14560 xml_parser_free($xml);
14565 libxml_clear_errors();
14566 $xml = new XMLReader();
14568 while (@$xml->read())
14570 switch ($xml->nodeType)
14573 case constant('XMLReader::END_ELEMENT'):
14574 if ($xml->namespaceURI !== '')
14576 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14580 $tagName = $xml->localName;
14582 $this->tag_close(null, $tagName);
14584 case constant('XMLReader::ELEMENT'):
14585 $empty = $xml->isEmptyElement;
14586 if ($xml->namespaceURI !== '')
14588 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14592 $tagName = $xml->localName;
14594 $attributes = array();
14595 while ($xml->moveToNextAttribute())
14597 if ($xml->namespaceURI !== '')
14599 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14603 $attrName = $xml->localName;
14605 $attributes[$attrName] = $xml->value;
14607 $this->tag_open(null, $tagName, $attributes);
14610 $this->tag_close(null, $tagName);
14613 case constant('XMLReader::TEXT'):
14615 case constant('XMLReader::CDATA'):
14616 $this->cdata(null, $xml->value);
14620 if ($error = libxml_get_last_error())
14622 $this->error_code = $error->code;
14623 $this->error_string = $error->message;
14624 $this->current_line = $error->line;
14625 $this->current_column = $error->column;
14635 function get_error_code()
14637 return $this->error_code;
14640 function get_error_string()
14642 return $this->error_string;
14645 function get_current_line()
14647 return $this->current_line;
14650 function get_current_column()
14652 return $this->current_column;
14655 function get_current_byte()
14657 return $this->current_byte;
14660 function get_data()
14662 return $this->data;
14665 function tag_open($parser, $tag, $attributes)
14667 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14669 $attribs = array();
14670 foreach ($attributes as $name => $value)
14672 list($attrib_namespace, $attribute) = $this->split_ns($name);
14673 $attribs[$attrib_namespace][$attribute] = $value;
14676 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14678 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14679 $this->xml_base_explicit[] = true;
14683 $this->xml_base[] = end($this->xml_base);
14684 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14687 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14689 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14693 $this->xml_lang[] = end($this->xml_lang);
14696 if ($this->current_xhtml_construct >= 0)
14698 $this->current_xhtml_construct++;
14699 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14701 $this->data['data'] .= '<' . end($this->element);
14702 if (isset($attribs['']))
14704 foreach ($attribs[''] as $name => $value)
14706 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14709 $this->data['data'] .= '>';
14714 $this->datas[] =& $this->data;
14715 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14716 $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));
14717 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')
14718 || (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'))
14720 $this->current_xhtml_construct = 0;
14725 function cdata($parser, $cdata)
14727 if ($this->current_xhtml_construct >= 0)
14729 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14733 $this->data['data'] .= $cdata;
14737 function tag_close($parser, $tag)
14739 if ($this->current_xhtml_construct >= 0)
14741 $this->current_xhtml_construct--;
14742 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')))
14744 $this->data['data'] .= '</' . end($this->element) . '>';
14747 if ($this->current_xhtml_construct === -1)
14749 $this->data =& $this->datas[count($this->datas) - 1];
14750 array_pop($this->datas);
14753 array_pop($this->element);
14754 array_pop($this->namespace);
14755 array_pop($this->xml_base);
14756 array_pop($this->xml_base_explicit);
14757 array_pop($this->xml_lang);
14760 function split_ns($string)
14762 static $cache = array();
14763 if (!isset($cache[$string]))
14765 if ($pos = strpos($string, $this->separator))
14767 static $separator_length;
14768 if (!$separator_length)
14770 $separator_length = strlen($this->separator);
14772 $namespace = substr($string, 0, $pos);
14773 $local_name = substr($string, $pos + $separator_length);
14774 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14776 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14779 // Normalize the Media RSS namespaces
14780 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14782 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14784 $cache[$string] = array($namespace, $local_name);
14788 $cache[$string] = array('', $string);
14791 return $cache[$string];
14796 * @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
14798 class SimplePie_Sanitize
14804 var $remove_div = true;
14805 var $image_handler = '';
14806 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14807 var $encode_instead_of_strip = false;
14808 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14809 var $strip_comments = false;
14810 var $output_encoding = 'UTF-8';
14811 var $enable_cache = true;
14812 var $cache_location = './cache';
14813 var $cache_name_function = 'md5';
14814 var $cache_class = 'SimplePie_Cache';
14815 var $file_class = 'SimplePie_File';
14817 var $useragent = '';
14818 var $force_fsockopen = false;
14820 var $replace_url_attributes = array(
14823 'blockquote' => 'cite',
14825 'form' => 'action',
14826 'img' => array('longdesc', 'src'),
14832 function remove_div($enable = true)
14834 $this->remove_div = (bool) $enable;
14837 function set_image_handler($page = false)
14841 $this->image_handler = (string) $page;
14845 $this->image_handler = false;
14849 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14851 if (isset($enable_cache))
14853 $this->enable_cache = (bool) $enable_cache;
14856 if ($cache_location)
14858 $this->cache_location = (string) $cache_location;
14861 if ($cache_name_function)
14863 $this->cache_name_function = (string) $cache_name_function;
14868 $this->cache_class = (string) $cache_class;
14872 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14876 $this->file_class = (string) $file_class;
14881 $this->timeout = (string) $timeout;
14886 $this->useragent = (string) $useragent;
14889 if ($force_fsockopen)
14891 $this->force_fsockopen = (string) $force_fsockopen;
14895 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14899 if (is_array($tags))
14901 $this->strip_htmltags = $tags;
14905 $this->strip_htmltags = explode(',', $tags);
14910 $this->strip_htmltags = false;
14914 function encode_instead_of_strip($encode = false)
14916 $this->encode_instead_of_strip = (bool) $encode;
14919 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14923 if (is_array($attribs))
14925 $this->strip_attributes = $attribs;
14929 $this->strip_attributes = explode(',', $attribs);
14934 $this->strip_attributes = false;
14938 function strip_comments($strip = false)
14940 $this->strip_comments = (bool) $strip;
14943 function set_output_encoding($encoding = 'UTF-8')
14945 $this->output_encoding = (string) $encoding;
14949 * Set element/attribute key/value pairs of HTML attributes
14950 * containing URLs that need to be resolved relative to the feed
14954 * @param array $element_attribute Element/attribute key/value pairs
14956 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'))
14958 $this->replace_url_attributes = (array) $element_attribute;
14961 function sanitize($data, $type, $base = '')
14963 $data = trim($data);
14964 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14966 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14968 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))
14970 $type |= SIMPLEPIE_CONSTRUCT_HTML;
14974 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14978 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14980 $data = base64_decode($data);
14983 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14985 if ($this->remove_div)
14987 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14988 $data = preg_replace('/<\/div>$/', '', $data);
14992 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14996 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14999 if ($this->strip_comments)
15001 $data = SimplePie_Misc::strip_comments($data);
15004 // Strip out HTML tags and attributes that might cause various security problems.
15005 // Based on recommendations by Mark Pilgrim at:
15006 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15007 if ($this->strip_htmltags)
15009 foreach ($this->strip_htmltags as $tag)
15011 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15012 while (preg_match($pcre, $data))
15014 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15019 if ($this->strip_attributes)
15021 foreach ($this->strip_attributes as $attrib)
15023 $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);
15027 // Replace relative URLs
15028 $this->base = $base;
15029 foreach ($this->replace_url_attributes as $element => $attributes)
15031 $data = $this->replace_urls($data, $element, $attributes);
15034 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15035 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15037 $images = SimplePie_Misc::get_element('img', $data);
15038 foreach ($images as $img)
15040 if (isset($img['attribs']['src']['data']))
15042 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15043 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15045 if ($cache->load())
15047 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15048 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15052 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15053 $headers = $file->headers;
15055 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15057 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15059 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15060 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15064 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);
15072 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15073 $data = trim($data);
15076 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15078 $data = SimplePie_Misc::absolutize_url($data, $base);
15081 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15083 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15086 if ($this->output_encoding !== 'UTF-8')
15088 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15094 function replace_urls($data, $tag, $attributes)
15096 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15098 $elements = SimplePie_Misc::get_element($tag, $data);
15099 foreach ($elements as $element)
15101 if (is_array($attributes))
15103 foreach ($attributes as $attribute)
15105 if (isset($element['attribs'][$attribute]['data']))
15107 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15108 $new_element = SimplePie_Misc::element_implode($element);
15109 $data = str_replace($element['full'], $new_element, $data);
15110 $element['full'] = $new_element;
15114 elseif (isset($element['attribs'][$attributes]['data']))
15116 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15117 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15124 function do_strip_htmltags($match)
15126 if ($this->encode_instead_of_strip)
15128 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15130 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15131 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15132 return "<$match[1]$match[2]>$match[3]</$match[1]>";
15136 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15139 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))