2 if ( !class_exists( 'SimplePie' ) ) :
6 * A PHP-Based RSS and Atom Feed Framework.
7 * Takes the hard work out of managing a complete RSS/Atom solution.
9 * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without modification, are
13 * permitted provided that the following conditions are met:
15 * * Redistributions of source code must retain the above copyright notice, this list of
16 * conditions and the following disclaimer.
18 * * Redistributions in binary form must reproduce the above copyright notice, this list
19 * of conditions and the following disclaimer in the documentation and/or other materials
20 * provided with the distribution.
22 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
23 * to endorse or promote products derived from this software without specific prior
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
29 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
38 * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
40 * @author Geoffrey Sneddon
41 * @link http://simplepie.org/ SimplePie
42 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
43 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
44 * @todo phpDoc comments
50 define('SIMPLEPIE_NAME', 'SimplePie');
55 define('SIMPLEPIE_VERSION', '1.2');
60 define('SIMPLEPIE_BUILD', '20090627192103');
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", 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";
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("$cache->name is not writeable", E_USER_WARNING);
1786 $this->error = "A feed could not be found at $this->feed_url";
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('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';
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", 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)
2434 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2436 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2438 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2440 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2442 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2444 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2446 if ($name !== null || $email !== null || $uri !== null)
2448 $authors[] =& new $this->author_class($name, $uri, $email);
2451 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2456 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2458 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2460 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2462 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2464 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2466 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2468 if ($name !== null || $email !== null || $url !== null)
2470 $authors[] =& new $this->author_class($name, $url, $email);
2473 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2475 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2477 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2479 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2481 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2483 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2486 if (!empty($authors))
2488 return SimplePie_Misc::array_unique($authors);
2496 function get_contributor($key = 0)
2498 $contributors = $this->get_contributors();
2499 if (isset($contributors[$key]))
2501 return $contributors[$key];
2509 function get_contributors()
2511 $contributors = array();
2512 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2517 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2519 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2521 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2523 $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]));
2525 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2527 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2529 if ($name !== null || $email !== null || $uri !== null)
2531 $contributors[] =& new $this->author_class($name, $uri, $email);
2534 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2539 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2541 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2543 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2545 $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]));
2547 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2549 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2551 if ($name !== null || $email !== null || $url !== null)
2553 $contributors[] =& new $this->author_class($name, $url, $email);
2557 if (!empty($contributors))
2559 return SimplePie_Misc::array_unique($contributors);
2567 function get_link($key = 0, $rel = 'alternate')
2569 $links = $this->get_links($rel);
2570 if (isset($links[$key]))
2572 return $links[$key];
2581 * Added for parity between the parent-level and the item/entry-level.
2583 function get_permalink()
2585 return $this->get_link(0);
2588 function get_links($rel = 'alternate')
2590 if (!isset($this->data['links']))
2592 $this->data['links'] = array();
2593 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2595 foreach ($links as $link)
2597 if (isset($link['attribs']['']['href']))
2599 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2600 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2604 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2606 foreach ($links as $link)
2608 if (isset($link['attribs']['']['href']))
2610 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2611 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2616 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2618 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2620 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2622 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2624 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2626 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2629 $keys = array_keys($this->data['links']);
2630 foreach ($keys as $key)
2632 if (SimplePie_Misc::is_isegment_nz_nc($key))
2634 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2636 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2637 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2641 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2644 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2646 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2648 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2652 if (isset($this->data['links'][$rel]))
2654 return $this->data['links'][$rel];
2662 function get_all_discovered_feeds()
2664 return $this->all_discovered_feeds;
2667 function get_description()
2669 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2671 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2673 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2675 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2677 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2679 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2681 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2683 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2685 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2687 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2689 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2691 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2693 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2695 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2697 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2699 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2701 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2703 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2711 function get_copyright()
2713 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2715 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2717 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2719 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2721 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2723 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2725 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2727 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2729 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2731 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2739 function get_language()
2741 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2743 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2745 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2747 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2749 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2751 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2753 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2755 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2757 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2759 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2761 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2763 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2765 elseif (isset($this->data['headers']['content-language']))
2767 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2775 function get_latitude()
2777 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2779 return (float) $return[0]['data'];
2781 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2783 return (float) $match[1];
2791 function get_longitude()
2793 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2795 return (float) $return[0]['data'];
2797 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2799 return (float) $return[0]['data'];
2801 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
2803 return (float) $match[2];
2811 function get_image_title()
2813 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2815 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2817 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2819 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2821 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2823 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2825 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2827 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2829 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2831 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2839 function get_image_url()
2841 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2843 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2845 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2847 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2849 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2851 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2853 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2855 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2857 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2859 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2861 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2863 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2871 function get_image_link()
2873 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2875 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2877 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2879 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2881 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2883 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2891 function get_image_width()
2893 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2895 return round($return[0]['data']);
2897 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2907 function get_image_height()
2909 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2911 return round($return[0]['data']);
2913 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2923 function get_item_quantity($max = 0)
2926 $qty = count($this->get_items());
2933 return ($qty > $max) ? $max : $qty;
2937 function get_item($key = 0)
2939 $items = $this->get_items();
2940 if (isset($items[$key]))
2942 return $items[$key];
2950 function get_items($start = 0, $end = 0)
2952 if (!isset($this->data['items']))
2954 if (!empty($this->multifeed_objects))
2956 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2960 $this->data['items'] = array();
2961 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2963 $keys = array_keys($items);
2964 foreach ($keys as $key)
2966 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2969 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2971 $keys = array_keys($items);
2972 foreach ($keys as $key)
2974 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2977 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2979 $keys = array_keys($items);
2980 foreach ($keys as $key)
2982 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2985 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2987 $keys = array_keys($items);
2988 foreach ($keys as $key)
2990 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2993 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2995 $keys = array_keys($items);
2996 foreach ($keys as $key)
2998 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
3004 if (!empty($this->data['items']))
3006 // If we want to order it by date, check if all items have a date, and then sort it
3007 if ($this->order_by_date && empty($this->multifeed_objects))
3009 if (!isset($this->data['ordered_items']))
3012 foreach ($this->data['items'] as $item)
3014 if (!$item->get_date('U'))
3021 $this->data['ordered_items'] = $this->data['items'];
3024 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3027 $items = $this->data['ordered_items'];
3031 $items = $this->data['items'];
3034 // Slice the data as desired
3037 return array_slice($items, $start);
3041 return array_slice($items, $start, $end);
3053 function sort_items($a, $b)
3055 return $a->get_date('U') <= $b->get_date('U');
3061 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3063 if (is_array($urls) && sizeof($urls) > 0)
3066 foreach ($urls as $arg)
3068 if (is_a($arg, 'SimplePie'))
3070 $items = array_merge($items, $arg->get_items(0, $limit));
3074 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3079 foreach ($items as $item)
3081 if (!$item->get_date('U'))
3090 usort($items, array('SimplePie', 'sort_items'));
3095 return array_slice($items, $start);
3099 return array_slice($items, $start, $end);
3104 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3110 class SimplePie_Item
3113 var $data = array();
3115 function SimplePie_Item($feed, $data)
3117 $this->feed = $feed;
3118 $this->data = $data;
3121 function __toString()
3123 return md5(serialize($this->data));
3127 * Remove items that link back to this before destroying this object
3129 function __destruct()
3131 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3137 function get_item_tags($namespace, $tag)
3139 if (isset($this->data['child'][$namespace][$tag]))
3141 return $this->data['child'][$namespace][$tag];
3149 function get_base($element = array())
3151 return $this->feed->get_base($element);
3154 function sanitize($data, $type, $base = '')
3156 return $this->feed->sanitize($data, $type, $base);
3164 function get_id($hash = false)
3168 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3170 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3172 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3174 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3176 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3178 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3180 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3182 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3184 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3186 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3188 elseif (($return = $this->get_permalink()) !== null)
3192 elseif (($return = $this->get_title()) !== null)
3197 if ($this->get_permalink() !== null || $this->get_title() !== null)
3199 return md5($this->get_permalink() . $this->get_title());
3203 return md5(serialize($this->data));
3207 function get_title()
3209 if (!isset($this->data['title']))
3211 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3213 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3215 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3217 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3219 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3221 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3223 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3225 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3227 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3229 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3231 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3233 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3235 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3237 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3241 $this->data['title'] = null;
3244 return $this->data['title'];
3247 function get_description($description_only = false)
3249 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3251 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3253 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3255 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3257 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3259 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3261 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3263 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3265 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3267 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3269 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3271 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3273 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3275 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3277 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3279 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3281 elseif (!$description_only)
3283 return $this->get_content(true);
3291 function get_content($content_only = false)
3293 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3295 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3297 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3299 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3301 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3303 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3305 elseif (!$content_only)
3307 return $this->get_description(true);
3315 function get_category($key = 0)
3317 $categories = $this->get_categories();
3318 if (isset($categories[$key]))
3320 return $categories[$key];
3328 function get_categories()
3330 $categories = array();
3332 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3337 if (isset($category['attribs']['']['term']))
3339 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3341 if (isset($category['attribs']['']['scheme']))
3343 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3345 if (isset($category['attribs']['']['label']))
3347 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3349 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3351 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3353 // This is really the label, but keep this as the term also for BC.
3354 // Label will also work on retrieving because that falls back to term.
3355 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3356 if (isset($category['attribs']['']['domain']))
3358 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3364 $categories[] =& new $this->feed->category_class($term, $scheme, null);
3366 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3368 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3370 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3372 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3375 if (!empty($categories))
3377 return SimplePie_Misc::array_unique($categories);
3385 function get_author($key = 0)
3387 $authors = $this->get_authors();
3388 if (isset($authors[$key]))
3390 return $authors[$key];
3398 function get_contributor($key = 0)
3400 $contributors = $this->get_contributors();
3401 if (isset($contributors[$key]))
3403 return $contributors[$key];
3411 function get_contributors()
3413 $contributors = array();
3414 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3419 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3421 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3423 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3425 $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]));
3427 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3429 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3431 if ($name !== null || $email !== null || $uri !== null)
3433 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3436 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3441 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3443 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3445 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3447 $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]));
3449 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3451 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3453 if ($name !== null || $email !== null || $url !== null)
3455 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3459 if (!empty($contributors))
3461 return SimplePie_Misc::array_unique($contributors);
3469 function get_authors()
3472 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3477 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3479 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3481 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3483 $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]));
3485 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3487 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3489 if ($name !== null || $email !== null || $uri !== null)
3491 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3494 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3499 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3501 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3503 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3505 $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]));
3507 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3509 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3511 if ($name !== null || $email !== null || $url !== null)
3513 $authors[] =& new $this->feed->author_class($name, $url, $email);
3516 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3518 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3520 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3522 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3524 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3526 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3528 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3530 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3533 if (!empty($authors))
3535 return SimplePie_Misc::array_unique($authors);
3537 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3541 elseif ($authors = $this->feed->get_authors())
3551 function get_copyright()
3553 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3555 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3557 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3559 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3561 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3563 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3571 function get_date($date_format = 'j F Y, g:i a')
3573 if (!isset($this->data['date']))
3575 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3577 $this->data['date']['raw'] = $return[0]['data'];
3579 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3581 $this->data['date']['raw'] = $return[0]['data'];
3583 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3585 $this->data['date']['raw'] = $return[0]['data'];
3587 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3589 $this->data['date']['raw'] = $return[0]['data'];
3591 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3593 $this->data['date']['raw'] = $return[0]['data'];
3595 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3597 $this->data['date']['raw'] = $return[0]['data'];
3599 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3601 $this->data['date']['raw'] = $return[0]['data'];
3603 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3605 $this->data['date']['raw'] = $return[0]['data'];
3608 if (!empty($this->data['date']['raw']))
3610 $parser = SimplePie_Parse_Date::get();
3611 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3615 $this->data['date'] = null;
3618 if ($this->data['date'])
3620 $date_format = (string) $date_format;
3621 switch ($date_format)
3624 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3627 return $this->data['date']['parsed'];
3630 return date($date_format, $this->data['date']['parsed']);
3639 function get_local_date($date_format = '%c')
3643 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3645 elseif (($date = $this->get_date('U')) !== null)
3647 return strftime($date_format, $date);
3655 function get_permalink()
3657 $link = $this->get_link();
3658 $enclosure = $this->get_enclosure(0);
3663 elseif ($enclosure !== null)
3665 return $enclosure->get_link();
3673 function get_link($key = 0, $rel = 'alternate')
3675 $links = $this->get_links($rel);
3676 if ($links[$key] !== null)
3678 return $links[$key];
3686 function get_links($rel = 'alternate')
3688 if (!isset($this->data['links']))
3690 $this->data['links'] = array();
3691 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3693 if (isset($link['attribs']['']['href']))
3695 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3696 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3700 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3702 if (isset($link['attribs']['']['href']))
3704 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3705 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3708 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3710 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3712 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3714 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3716 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3718 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3720 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3722 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3724 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3728 $keys = array_keys($this->data['links']);
3729 foreach ($keys as $key)
3731 if (SimplePie_Misc::is_isegment_nz_nc($key))
3733 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3735 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3736 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3740 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3743 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3745 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3747 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3750 if (isset($this->data['links'][$rel]))
3752 return $this->data['links'][$rel];
3761 * @todo Add ability to prefer one type of content over another (in a media group).
3763 function get_enclosure($key = 0, $prefer = null)
3765 $enclosures = $this->get_enclosures();
3766 if (isset($enclosures[$key]))
3768 return $enclosures[$key];
3777 * Grabs all available enclosures (podcasts, etc.)
3779 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3781 * 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.
3783 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3784 * @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).
3786 function get_enclosures()
3788 if (!isset($this->data['enclosures']))
3790 $this->data['enclosures'] = array();
3793 $captions_parent = null;
3794 $categories_parent = null;
3795 $copyrights_parent = null;
3796 $credits_parent = null;
3797 $description_parent = null;
3798 $duration_parent = null;
3799 $hashes_parent = null;
3800 $keywords_parent = null;
3801 $player_parent = null;
3802 $ratings_parent = null;
3803 $restrictions_parent = null;
3804 $thumbnails_parent = null;
3805 $title_parent = null;
3807 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3808 $parent = $this->get_feed();
3811 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3813 foreach ($captions as $caption)
3815 $caption_type = null;
3816 $caption_lang = null;
3817 $caption_startTime = null;
3818 $caption_endTime = null;
3819 $caption_text = null;
3820 if (isset($caption['attribs']['']['type']))
3822 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3824 if (isset($caption['attribs']['']['lang']))
3826 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3828 if (isset($caption['attribs']['']['start']))
3830 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3832 if (isset($caption['attribs']['']['end']))
3834 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3836 if (isset($caption['data']))
3838 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3840 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3843 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3845 foreach ($captions as $caption)
3847 $caption_type = null;
3848 $caption_lang = null;
3849 $caption_startTime = null;
3850 $caption_endTime = null;
3851 $caption_text = null;
3852 if (isset($caption['attribs']['']['type']))
3854 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3856 if (isset($caption['attribs']['']['lang']))
3858 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3860 if (isset($caption['attribs']['']['start']))
3862 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3864 if (isset($caption['attribs']['']['end']))
3866 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3868 if (isset($caption['data']))
3870 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3872 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3875 if (is_array($captions_parent))
3877 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3881 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3886 if (isset($category['data']))
3888 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3890 if (isset($category['attribs']['']['scheme']))
3892 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3896 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3898 if (isset($category['attribs']['']['label']))
3900 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3902 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3904 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3909 if (isset($category['data']))
3911 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3913 if (isset($category['attribs']['']['scheme']))
3915 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3919 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3921 if (isset($category['attribs']['']['label']))
3923 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3925 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3927 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3930 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3932 if (isset($category['attribs']['']['text']))
3934 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3936 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3938 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3940 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3942 if (isset($subcategory['attribs']['']['text']))
3944 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3946 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3950 if (is_array($categories_parent))
3952 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3956 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3958 $copyright_url = null;
3959 $copyright_label = null;
3960 if (isset($copyright[0]['attribs']['']['url']))
3962 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3964 if (isset($copyright[0]['data']))
3966 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3968 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3970 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3972 $copyright_url = null;
3973 $copyright_label = null;
3974 if (isset($copyright[0]['attribs']['']['url']))
3976 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3978 if (isset($copyright[0]['data']))
3980 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3982 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3986 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3988 foreach ($credits as $credit)
3990 $credit_role = null;
3991 $credit_scheme = null;
3992 $credit_name = null;
3993 if (isset($credit['attribs']['']['role']))
3995 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3997 if (isset($credit['attribs']['']['scheme']))
3999 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4003 $credit_scheme = 'urn:ebu';
4005 if (isset($credit['data']))
4007 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4009 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4012 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4014 foreach ($credits as $credit)
4016 $credit_role = null;
4017 $credit_scheme = null;
4018 $credit_name = null;
4019 if (isset($credit['attribs']['']['role']))
4021 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4023 if (isset($credit['attribs']['']['scheme']))
4025 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4029 $credit_scheme = 'urn:ebu';
4031 if (isset($credit['data']))
4033 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4035 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4038 if (is_array($credits_parent))
4040 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4044 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4046 if (isset($description_parent[0]['data']))
4048 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4051 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4053 if (isset($description_parent[0]['data']))
4055 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4060 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4065 if (isset($duration_parent[0]['data']))
4067 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4068 if (sizeof($temp) > 0)
4070 $seconds = (int) array_pop($temp);
4072 if (sizeof($temp) > 0)
4074 $minutes = (int) array_pop($temp);
4075 $seconds += $minutes * 60;
4077 if (sizeof($temp) > 0)
4079 $hours = (int) array_pop($temp);
4080 $seconds += $hours * 3600;
4083 $duration_parent = $seconds;
4088 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4090 foreach ($hashes_iterator as $hash)
4094 if (isset($hash['data']))
4096 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4098 if (isset($hash['attribs']['']['algo']))
4100 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4106 $hashes_parent[] = $algo.':'.$value;
4109 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4111 foreach ($hashes_iterator as $hash)
4115 if (isset($hash['data']))
4117 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4119 if (isset($hash['attribs']['']['algo']))
4121 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4127 $hashes_parent[] = $algo.':'.$value;
4130 if (is_array($hashes_parent))
4132 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4136 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4138 if (isset($keywords[0]['data']))
4140 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4141 foreach ($temp as $word)
4143 $keywords_parent[] = trim($word);
4148 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4150 if (isset($keywords[0]['data']))
4152 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4153 foreach ($temp as $word)
4155 $keywords_parent[] = trim($word);
4160 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4162 if (isset($keywords[0]['data']))
4164 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4165 foreach ($temp as $word)
4167 $keywords_parent[] = trim($word);
4172 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4174 if (isset($keywords[0]['data']))
4176 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4177 foreach ($temp as $word)
4179 $keywords_parent[] = trim($word);
4184 if (is_array($keywords_parent))
4186 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4190 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4192 if (isset($player_parent[0]['attribs']['']['url']))
4194 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4197 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4199 if (isset($player_parent[0]['attribs']['']['url']))
4201 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4206 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4208 foreach ($ratings as $rating)
4210 $rating_scheme = null;
4211 $rating_value = null;
4212 if (isset($rating['attribs']['']['scheme']))
4214 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4218 $rating_scheme = 'urn:simple';
4220 if (isset($rating['data']))
4222 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4224 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4227 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4229 foreach ($ratings as $rating)
4231 $rating_scheme = 'urn:itunes';
4232 $rating_value = null;
4233 if (isset($rating['data']))
4235 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4237 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4240 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4242 foreach ($ratings as $rating)
4244 $rating_scheme = null;
4245 $rating_value = null;
4246 if (isset($rating['attribs']['']['scheme']))
4248 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4252 $rating_scheme = 'urn:simple';
4254 if (isset($rating['data']))
4256 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4258 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4261 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4263 foreach ($ratings as $rating)
4265 $rating_scheme = 'urn:itunes';
4266 $rating_value = null;
4267 if (isset($rating['data']))
4269 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4271 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4274 if (is_array($ratings_parent))
4276 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4280 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4282 foreach ($restrictions as $restriction)
4284 $restriction_relationship = null;
4285 $restriction_type = null;
4286 $restriction_value = null;
4287 if (isset($restriction['attribs']['']['relationship']))
4289 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4291 if (isset($restriction['attribs']['']['type']))
4293 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4295 if (isset($restriction['data']))
4297 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4299 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4302 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4304 foreach ($restrictions as $restriction)
4306 $restriction_relationship = 'allow';
4307 $restriction_type = null;
4308 $restriction_value = 'itunes';
4309 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4311 $restriction_relationship = 'deny';
4313 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4316 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4318 foreach ($restrictions as $restriction)
4320 $restriction_relationship = null;
4321 $restriction_type = null;
4322 $restriction_value = null;
4323 if (isset($restriction['attribs']['']['relationship']))
4325 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4327 if (isset($restriction['attribs']['']['type']))
4329 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4331 if (isset($restriction['data']))
4333 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4335 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4338 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4340 foreach ($restrictions as $restriction)
4342 $restriction_relationship = 'allow';
4343 $restriction_type = null;
4344 $restriction_value = 'itunes';
4345 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4347 $restriction_relationship = 'deny';
4349 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4352 if (is_array($restrictions_parent))
4354 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4358 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4360 foreach ($thumbnails as $thumbnail)
4362 if (isset($thumbnail['attribs']['']['url']))
4364 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4368 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4370 foreach ($thumbnails as $thumbnail)
4372 if (isset($thumbnail['attribs']['']['url']))
4374 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4380 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4382 if (isset($title_parent[0]['data']))
4384 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4387 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4389 if (isset($title_parent[0]['data']))
4391 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4409 $samplingrate = null;
4419 $description = null;
4424 $restrictions = null;
4428 // If we have media:group tags, loop through them.
4429 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4431 // If we have media:content tags, loop through them.
4432 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4434 if (isset($content['attribs']['']['url']))
4447 $samplingrate = null;
4457 $description = null;
4462 $restrictions = null;
4466 // Start checking the attributes of media:content
4467 if (isset($content['attribs']['']['bitrate']))
4469 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4471 if (isset($content['attribs']['']['channels']))
4473 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4475 if (isset($content['attribs']['']['duration']))
4477 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4481 $duration = $duration_parent;
4483 if (isset($content['attribs']['']['expression']))
4485 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4487 if (isset($content['attribs']['']['framerate']))
4489 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4491 if (isset($content['attribs']['']['height']))
4493 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4495 if (isset($content['attribs']['']['lang']))
4497 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4499 if (isset($content['attribs']['']['fileSize']))
4501 $length = ceil($content['attribs']['']['fileSize']);
4503 if (isset($content['attribs']['']['medium']))
4505 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4507 if (isset($content['attribs']['']['samplingrate']))
4509 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4511 if (isset($content['attribs']['']['type']))
4513 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4515 if (isset($content['attribs']['']['width']))
4517 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4519 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4521 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4524 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4526 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4528 $caption_type = null;
4529 $caption_lang = null;
4530 $caption_startTime = null;
4531 $caption_endTime = null;
4532 $caption_text = null;
4533 if (isset($caption['attribs']['']['type']))
4535 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4537 if (isset($caption['attribs']['']['lang']))
4539 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4541 if (isset($caption['attribs']['']['start']))
4543 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4545 if (isset($caption['attribs']['']['end']))
4547 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4549 if (isset($caption['data']))
4551 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4553 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4555 if (is_array($captions))
4557 $captions = array_values(SimplePie_Misc::array_unique($captions));
4560 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4562 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4564 $caption_type = null;
4565 $caption_lang = null;
4566 $caption_startTime = null;
4567 $caption_endTime = null;
4568 $caption_text = null;
4569 if (isset($caption['attribs']['']['type']))
4571 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4573 if (isset($caption['attribs']['']['lang']))
4575 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4577 if (isset($caption['attribs']['']['start']))
4579 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4581 if (isset($caption['attribs']['']['end']))
4583 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4585 if (isset($caption['data']))
4587 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4589 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4591 if (is_array($captions))
4593 $captions = array_values(SimplePie_Misc::array_unique($captions));
4598 $captions = $captions_parent;
4602 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4604 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4609 if (isset($category['data']))
4611 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4613 if (isset($category['attribs']['']['scheme']))
4615 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4619 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4621 if (isset($category['attribs']['']['label']))
4623 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4625 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4628 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4630 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4635 if (isset($category['data']))
4637 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4639 if (isset($category['attribs']['']['scheme']))
4641 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4645 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4647 if (isset($category['attribs']['']['label']))
4649 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4651 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4654 if (is_array($categories) && is_array($categories_parent))
4656 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4658 elseif (is_array($categories))
4660 $categories = array_values(SimplePie_Misc::array_unique($categories));
4662 elseif (is_array($categories_parent))
4664 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4668 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4670 $copyright_url = null;
4671 $copyright_label = null;
4672 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4674 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4676 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4678 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4680 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4682 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4684 $copyright_url = null;
4685 $copyright_label = null;
4686 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4688 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4690 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4692 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4694 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4698 $copyrights = $copyrights_parent;
4702 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4704 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4706 $credit_role = null;
4707 $credit_scheme = null;
4708 $credit_name = null;
4709 if (isset($credit['attribs']['']['role']))
4711 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4713 if (isset($credit['attribs']['']['scheme']))
4715 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4719 $credit_scheme = 'urn:ebu';
4721 if (isset($credit['data']))
4723 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4725 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4727 if (is_array($credits))
4729 $credits = array_values(SimplePie_Misc::array_unique($credits));
4732 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4734 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4736 $credit_role = null;
4737 $credit_scheme = null;
4738 $credit_name = null;
4739 if (isset($credit['attribs']['']['role']))
4741 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4743 if (isset($credit['attribs']['']['scheme']))
4745 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4749 $credit_scheme = 'urn:ebu';
4751 if (isset($credit['data']))
4753 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4755 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4757 if (is_array($credits))
4759 $credits = array_values(SimplePie_Misc::array_unique($credits));
4764 $credits = $credits_parent;
4768 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4770 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4772 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4774 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4778 $description = $description_parent;
4782 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4784 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4788 if (isset($hash['data']))
4790 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4792 if (isset($hash['attribs']['']['algo']))
4794 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4800 $hashes[] = $algo.':'.$value;
4802 if (is_array($hashes))
4804 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4807 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4809 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4813 if (isset($hash['data']))
4815 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4817 if (isset($hash['attribs']['']['algo']))
4819 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4825 $hashes[] = $algo.':'.$value;
4827 if (is_array($hashes))
4829 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4834 $hashes = $hashes_parent;
4838 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4840 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4842 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4843 foreach ($temp as $word)
4845 $keywords[] = trim($word);
4849 if (is_array($keywords))
4851 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4854 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4856 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4858 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4859 foreach ($temp as $word)
4861 $keywords[] = trim($word);
4865 if (is_array($keywords))
4867 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4872 $keywords = $keywords_parent;
4876 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4878 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4880 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4882 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4886 $player = $player_parent;
4890 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4892 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4894 $rating_scheme = null;
4895 $rating_value = null;
4896 if (isset($rating['attribs']['']['scheme']))
4898 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4902 $rating_scheme = 'urn:simple';
4904 if (isset($rating['data']))
4906 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4908 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4910 if (is_array($ratings))
4912 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4915 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4917 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4919 $rating_scheme = null;
4920 $rating_value = null;
4921 if (isset($rating['attribs']['']['scheme']))
4923 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4927 $rating_scheme = 'urn:simple';
4929 if (isset($rating['data']))
4931 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4933 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4935 if (is_array($ratings))
4937 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4942 $ratings = $ratings_parent;
4946 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4948 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4950 $restriction_relationship = null;
4951 $restriction_type = null;
4952 $restriction_value = null;
4953 if (isset($restriction['attribs']['']['relationship']))
4955 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4957 if (isset($restriction['attribs']['']['type']))
4959 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4961 if (isset($restriction['data']))
4963 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4965 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4967 if (is_array($restrictions))
4969 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4972 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4974 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4976 $restriction_relationship = null;
4977 $restriction_type = null;
4978 $restriction_value = null;
4979 if (isset($restriction['attribs']['']['relationship']))
4981 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4983 if (isset($restriction['attribs']['']['type']))
4985 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4987 if (isset($restriction['data']))
4989 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4991 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4993 if (is_array($restrictions))
4995 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5000 $restrictions = $restrictions_parent;
5004 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5006 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5008 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5010 if (is_array($thumbnails))
5012 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5015 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5017 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5019 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5021 if (is_array($thumbnails))
5023 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5028 $thumbnails = $thumbnails_parent;
5032 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5034 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5036 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5038 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5042 $title = $title_parent;
5045 $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);
5050 // If we have standalone media:content tags, loop through them.
5051 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5053 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5055 if (isset($content['attribs']['']['url']))
5068 $samplingrate = null;
5078 $description = null;
5083 $restrictions = null;
5087 // Start checking the attributes of media:content
5088 if (isset($content['attribs']['']['bitrate']))
5090 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5092 if (isset($content['attribs']['']['channels']))
5094 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5096 if (isset($content['attribs']['']['duration']))
5098 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5102 $duration = $duration_parent;
5104 if (isset($content['attribs']['']['expression']))
5106 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5108 if (isset($content['attribs']['']['framerate']))
5110 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5112 if (isset($content['attribs']['']['height']))
5114 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5116 if (isset($content['attribs']['']['lang']))
5118 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5120 if (isset($content['attribs']['']['fileSize']))
5122 $length = ceil($content['attribs']['']['fileSize']);
5124 if (isset($content['attribs']['']['medium']))
5126 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5128 if (isset($content['attribs']['']['samplingrate']))
5130 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5132 if (isset($content['attribs']['']['type']))
5134 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5136 if (isset($content['attribs']['']['width']))
5138 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5140 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5142 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5145 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5147 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5149 $caption_type = null;
5150 $caption_lang = null;
5151 $caption_startTime = null;
5152 $caption_endTime = null;
5153 $caption_text = null;
5154 if (isset($caption['attribs']['']['type']))
5156 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5158 if (isset($caption['attribs']['']['lang']))
5160 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5162 if (isset($caption['attribs']['']['start']))
5164 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5166 if (isset($caption['attribs']['']['end']))
5168 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5170 if (isset($caption['data']))
5172 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5174 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5176 if (is_array($captions))
5178 $captions = array_values(SimplePie_Misc::array_unique($captions));
5183 $captions = $captions_parent;
5187 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5189 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5194 if (isset($category['data']))
5196 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5198 if (isset($category['attribs']['']['scheme']))
5200 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5204 $scheme = 'http://search.yahoo.com/mrss/category_schema';
5206 if (isset($category['attribs']['']['label']))
5208 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5210 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5213 if (is_array($categories) && is_array($categories_parent))
5215 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5217 elseif (is_array($categories))
5219 $categories = array_values(SimplePie_Misc::array_unique($categories));
5221 elseif (is_array($categories_parent))
5223 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5231 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5233 $copyright_url = null;
5234 $copyright_label = null;
5235 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5237 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5239 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5241 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5243 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5247 $copyrights = $copyrights_parent;
5251 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5253 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5255 $credit_role = null;
5256 $credit_scheme = null;
5257 $credit_name = null;
5258 if (isset($credit['attribs']['']['role']))
5260 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5262 if (isset($credit['attribs']['']['scheme']))
5264 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5268 $credit_scheme = 'urn:ebu';
5270 if (isset($credit['data']))
5272 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5274 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5276 if (is_array($credits))
5278 $credits = array_values(SimplePie_Misc::array_unique($credits));
5283 $credits = $credits_parent;
5287 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5289 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5293 $description = $description_parent;
5297 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5299 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5303 if (isset($hash['data']))
5305 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5307 if (isset($hash['attribs']['']['algo']))
5309 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5315 $hashes[] = $algo.':'.$value;
5317 if (is_array($hashes))
5319 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5324 $hashes = $hashes_parent;
5328 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5330 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5332 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5333 foreach ($temp as $word)
5335 $keywords[] = trim($word);
5339 if (is_array($keywords))
5341 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5346 $keywords = $keywords_parent;
5350 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5352 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5356 $player = $player_parent;
5360 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5362 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5364 $rating_scheme = null;
5365 $rating_value = null;
5366 if (isset($rating['attribs']['']['scheme']))
5368 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5372 $rating_scheme = 'urn:simple';
5374 if (isset($rating['data']))
5376 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5378 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5380 if (is_array($ratings))
5382 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5387 $ratings = $ratings_parent;
5391 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5393 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5395 $restriction_relationship = null;
5396 $restriction_type = null;
5397 $restriction_value = null;
5398 if (isset($restriction['attribs']['']['relationship']))
5400 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5402 if (isset($restriction['attribs']['']['type']))
5404 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5406 if (isset($restriction['data']))
5408 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5410 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5412 if (is_array($restrictions))
5414 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5419 $restrictions = $restrictions_parent;
5423 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5425 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5427 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5429 if (is_array($thumbnails))
5431 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5436 $thumbnails = $thumbnails_parent;
5440 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5442 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5446 $title = $title_parent;
5449 $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);
5454 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5456 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5469 $samplingrate = null;
5474 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5475 if (isset($link['attribs']['']['type']))
5477 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5479 if (isset($link['attribs']['']['length']))
5481 $length = ceil($link['attribs']['']['length']);
5484 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5485 $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);
5489 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5491 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5504 $samplingrate = null;
5509 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5510 if (isset($link['attribs']['']['type']))
5512 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5514 if (isset($link['attribs']['']['length']))
5516 $length = ceil($link['attribs']['']['length']);
5519 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5520 $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);
5524 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5526 if (isset($enclosure[0]['attribs']['']['url']))
5539 $samplingrate = null;
5544 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5545 if (isset($enclosure[0]['attribs']['']['type']))
5547 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5549 if (isset($enclosure[0]['attribs']['']['length']))
5551 $length = ceil($enclosure[0]['attribs']['']['length']);
5554 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5555 $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);
5559 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))
5561 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5562 $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);
5565 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5567 if (!empty($this->data['enclosures']))
5569 return $this->data['enclosures'];
5577 function get_latitude()
5579 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5581 return (float) $return[0]['data'];
5583 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5585 return (float) $match[1];
5593 function get_longitude()
5595 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5597 return (float) $return[0]['data'];
5599 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5601 return (float) $return[0]['data'];
5603 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
5605 return (float) $match[2];
5613 function get_source()
5615 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5617 return new $this->feed->source_class($this, $return[0]);
5626 * Creates the add_to_* methods' return data
5629 * @param string $item_url String to prefix to the item permalink
5630 * @param string $title_url String to prefix to the item title
5631 * (and suffix to the item permalink)
5632 * @return mixed URL if feed exists, false otherwise
5634 function add_to_service($item_url, $title_url = null, $summary_url = null)
5636 if ($this->get_permalink() !== null)
5638 $return = $item_url . rawurlencode($this->get_permalink());
5639 if ($title_url !== null && $this->get_title() !== null)
5641 $return .= $title_url . rawurlencode($this->get_title());
5643 if ($summary_url !== null && $this->get_description() !== null)
5645 $return .= $summary_url . rawurlencode($this->get_description());
5647 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5655 function add_to_blinklist()
5657 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5660 function add_to_blogmarks()
5662 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5665 function add_to_delicious()
5667 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5670 function add_to_digg()
5672 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5675 function add_to_furl()
5677 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5680 function add_to_magnolia()
5682 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5685 function add_to_myweb20()
5687 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5690 function add_to_newsvine()
5692 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5695 function add_to_reddit()
5697 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5700 function add_to_segnalo()
5702 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5705 function add_to_simpy()
5707 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5710 function add_to_spurl()
5712 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5715 function add_to_wists()
5717 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5720 function search_technorati()
5722 return $this->add_to_service('http://www.technorati.com/search/');
5726 class SimplePie_Source
5729 var $data = array();
5731 function SimplePie_Source($item, $data)
5733 $this->item = $item;
5734 $this->data = $data;
5737 function __toString()
5739 return md5(serialize($this->data));
5742 function get_source_tags($namespace, $tag)
5744 if (isset($this->data['child'][$namespace][$tag]))
5746 return $this->data['child'][$namespace][$tag];
5754 function get_base($element = array())
5756 return $this->item->get_base($element);
5759 function sanitize($data, $type, $base = '')
5761 return $this->item->sanitize($data, $type, $base);
5769 function get_title()
5771 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5773 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5775 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5777 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5779 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5781 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5783 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5785 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5787 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5789 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5791 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5793 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5795 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5797 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5805 function get_category($key = 0)
5807 $categories = $this->get_categories();
5808 if (isset($categories[$key]))
5810 return $categories[$key];
5818 function get_categories()
5820 $categories = array();
5822 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5827 if (isset($category['attribs']['']['term']))
5829 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5831 if (isset($category['attribs']['']['scheme']))
5833 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5835 if (isset($category['attribs']['']['label']))
5837 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5839 $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5841 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5843 // This is really the label, but keep this as the term also for BC.
5844 // Label will also work on retrieving because that falls back to term.
5845 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5846 if (isset($category['attribs']['']['domain']))
5848 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5854 $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5856 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5858 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5860 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5862 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5865 if (!empty($categories))
5867 return SimplePie_Misc::array_unique($categories);
5875 function get_author($key = 0)
5877 $authors = $this->get_authors();
5878 if (isset($authors[$key]))
5880 return $authors[$key];
5888 function get_authors()
5891 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5896 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5898 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5900 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5902 $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]));
5904 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5906 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5908 if ($name !== null || $email !== null || $uri !== null)
5910 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5913 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5918 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5920 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5922 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5924 $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]));
5926 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5928 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5930 if ($name !== null || $email !== null || $url !== null)
5932 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5935 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5937 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5939 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5941 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5943 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5945 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5948 if (!empty($authors))
5950 return SimplePie_Misc::array_unique($authors);
5958 function get_contributor($key = 0)
5960 $contributors = $this->get_contributors();
5961 if (isset($contributors[$key]))
5963 return $contributors[$key];
5971 function get_contributors()
5973 $contributors = array();
5974 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5979 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5981 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5983 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5985 $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]));
5987 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5989 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5991 if ($name !== null || $email !== null || $uri !== null)
5993 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
5996 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6001 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6003 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6005 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6007 $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]));
6009 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6011 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6013 if ($name !== null || $email !== null || $url !== null)
6015 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6019 if (!empty($contributors))
6021 return SimplePie_Misc::array_unique($contributors);
6029 function get_link($key = 0, $rel = 'alternate')
6031 $links = $this->get_links($rel);
6032 if (isset($links[$key]))
6034 return $links[$key];
6043 * Added for parity between the parent-level and the item/entry-level.
6045 function get_permalink()
6047 return $this->get_link(0);
6050 function get_links($rel = 'alternate')
6052 if (!isset($this->data['links']))
6054 $this->data['links'] = array();
6055 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6057 foreach ($links as $link)
6059 if (isset($link['attribs']['']['href']))
6061 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6062 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6066 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6068 foreach ($links as $link)
6070 if (isset($link['attribs']['']['href']))
6072 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6073 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6078 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6080 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6082 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6084 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6086 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6088 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6091 $keys = array_keys($this->data['links']);
6092 foreach ($keys as $key)
6094 if (SimplePie_Misc::is_isegment_nz_nc($key))
6096 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6098 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6099 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6103 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6106 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6108 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6110 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6114 if (isset($this->data['links'][$rel]))
6116 return $this->data['links'][$rel];
6124 function get_description()
6126 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6128 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6130 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6132 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6134 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6136 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6138 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6140 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6142 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6144 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6146 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6148 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6150 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6152 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6154 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6156 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6158 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6160 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6168 function get_copyright()
6170 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6172 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6174 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6176 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6178 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6180 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6182 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6184 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6186 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6188 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6196 function get_language()
6198 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6200 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6202 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6204 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6206 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6208 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6210 elseif (isset($this->data['xml_lang']))
6212 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6220 function get_latitude()
6222 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6224 return (float) $return[0]['data'];
6226 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6228 return (float) $match[1];
6236 function get_longitude()
6238 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6240 return (float) $return[0]['data'];
6242 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6244 return (float) $return[0]['data'];
6246 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
6248 return (float) $match[2];
6256 function get_image_url()
6258 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6260 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6262 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6264 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6266 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6268 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6277 class SimplePie_Author
6283 // Constructor, used to input the data
6284 function SimplePie_Author($name = null, $link = null, $email = null)
6286 $this->name = $name;
6287 $this->link = $link;
6288 $this->email = $email;
6291 function __toString()
6293 // There is no $this->data here
6294 return md5(serialize($this));
6299 if ($this->name !== null)
6311 if ($this->link !== null)
6321 function get_email()
6323 if ($this->email !== null)
6325 return $this->email;
6334 class SimplePie_Category
6340 // Constructor, used to input the data
6341 function SimplePie_Category($term = null, $scheme = null, $label = null)
6343 $this->term = $term;
6344 $this->scheme = $scheme;
6345 $this->label = $label;
6348 function __toString()
6350 // There is no $this->data here
6351 return md5(serialize($this));
6356 if ($this->term !== null)
6366 function get_scheme()
6368 if ($this->scheme !== null)
6370 return $this->scheme;
6378 function get_label()
6380 if ($this->label !== null)
6382 return $this->label;
6386 return $this->get_term();
6391 class SimplePie_Enclosure
6421 // Constructor, used to input the data
6422 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)
6424 $this->bitrate = $bitrate;
6425 $this->captions = $captions;
6426 $this->categories = $categories;
6427 $this->channels = $channels;
6428 $this->copyright = $copyright;
6429 $this->credits = $credits;
6430 $this->description = $description;
6431 $this->duration = $duration;
6432 $this->expression = $expression;
6433 $this->framerate = $framerate;
6434 $this->hashes = $hashes;
6435 $this->height = $height;
6436 $this->javascript = $javascript;
6437 $this->keywords = $keywords;
6438 $this->lang = $lang;
6439 $this->length = $length;
6440 $this->link = $link;
6441 $this->medium = $medium;
6442 $this->player = $player;
6443 $this->ratings = $ratings;
6444 $this->restrictions = $restrictions;
6445 $this->samplingrate = $samplingrate;
6446 $this->thumbnails = $thumbnails;
6447 $this->title = $title;
6448 $this->type = $type;
6449 $this->width = $width;
6450 if (class_exists('idna_convert'))
6452 $idn =& new idna_convert;
6453 $parsed = SimplePie_Misc::parse_url($link);
6454 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6456 $this->handler = $this->get_handler(); // Needs to load last
6459 function __toString()
6461 // There is no $this->data here
6462 return md5(serialize($this));
6465 function get_bitrate()
6467 if ($this->bitrate !== null)
6469 return $this->bitrate;
6477 function get_caption($key = 0)
6479 $captions = $this->get_captions();
6480 if (isset($captions[$key]))
6482 return $captions[$key];
6490 function get_captions()
6492 if ($this->captions !== null)
6494 return $this->captions;
6502 function get_category($key = 0)
6504 $categories = $this->get_categories();
6505 if (isset($categories[$key]))
6507 return $categories[$key];
6515 function get_categories()
6517 if ($this->categories !== null)
6519 return $this->categories;
6527 function get_channels()
6529 if ($this->channels !== null)
6531 return $this->channels;
6539 function get_copyright()
6541 if ($this->copyright !== null)
6543 return $this->copyright;
6551 function get_credit($key = 0)
6553 $credits = $this->get_credits();
6554 if (isset($credits[$key]))
6556 return $credits[$key];
6564 function get_credits()
6566 if ($this->credits !== null)
6568 return $this->credits;
6576 function get_description()
6578 if ($this->description !== null)
6580 return $this->description;
6588 function get_duration($convert = false)
6590 if ($this->duration !== null)
6594 $time = SimplePie_Misc::time_hms($this->duration);
6599 return $this->duration;
6608 function get_expression()
6610 if ($this->expression !== null)
6612 return $this->expression;
6620 function get_extension()
6622 if ($this->link !== null)
6624 $url = SimplePie_Misc::parse_url($this->link);
6625 if ($url['path'] !== '')
6627 return pathinfo($url['path'], PATHINFO_EXTENSION);
6633 function get_framerate()
6635 if ($this->framerate !== null)
6637 return $this->framerate;
6645 function get_handler()
6647 return $this->get_real_type(true);
6650 function get_hash($key = 0)
6652 $hashes = $this->get_hashes();
6653 if (isset($hashes[$key]))
6655 return $hashes[$key];
6663 function get_hashes()
6665 if ($this->hashes !== null)
6667 return $this->hashes;
6675 function get_height()
6677 if ($this->height !== null)
6679 return $this->height;
6687 function get_language()
6689 if ($this->lang !== null)
6699 function get_keyword($key = 0)
6701 $keywords = $this->get_keywords();
6702 if (isset($keywords[$key]))
6704 return $keywords[$key];
6712 function get_keywords()
6714 if ($this->keywords !== null)
6716 return $this->keywords;
6724 function get_length()
6726 if ($this->length !== null)
6728 return $this->length;
6738 if ($this->link !== null)
6740 return urldecode($this->link);
6748 function get_medium()
6750 if ($this->medium !== null)
6752 return $this->medium;
6760 function get_player()
6762 if ($this->player !== null)
6764 return $this->player;
6772 function get_rating($key = 0)
6774 $ratings = $this->get_ratings();
6775 if (isset($ratings[$key]))
6777 return $ratings[$key];
6785 function get_ratings()
6787 if ($this->ratings !== null)
6789 return $this->ratings;
6797 function get_restriction($key = 0)
6799 $restrictions = $this->get_restrictions();
6800 if (isset($restrictions[$key]))
6802 return $restrictions[$key];
6810 function get_restrictions()
6812 if ($this->restrictions !== null)
6814 return $this->restrictions;
6822 function get_sampling_rate()
6824 if ($this->samplingrate !== null)
6826 return $this->samplingrate;
6836 $length = $this->get_length();
6837 if ($length !== null)
6839 return round($length/1048576, 2);
6847 function get_thumbnail($key = 0)
6849 $thumbnails = $this->get_thumbnails();
6850 if (isset($thumbnails[$key]))
6852 return $thumbnails[$key];
6860 function get_thumbnails()
6862 if ($this->thumbnails !== null)
6864 return $this->thumbnails;
6872 function get_title()
6874 if ($this->title !== null)
6876 return $this->title;
6886 if ($this->type !== null)
6896 function get_width()
6898 if ($this->width !== null)
6900 return $this->width;
6908 function native_embed($options='')
6910 return $this->embed($options, true);
6914 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6916 function embed($options = '', $native = false)
6926 $bgcolor = '#ffffff';
6928 $widescreen = false;
6929 $handler = $this->get_handler();
6930 $type = $this->get_real_type();
6932 // Process options and reassign values as necessary
6933 if (is_array($options))
6939 $options = explode(',', $options);
6940 foreach($options as $option)
6942 $opt = explode(':', $option, 2);
6943 if (isset($opt[0], $opt[1]))
6945 $opt[0] = trim($opt[0]);
6946 $opt[1] = trim($opt[1]);
6962 $altclass = $opt[1];
6982 $mediaplayer = $opt[1];
6986 $widescreen = $opt[1];
6993 $mime = explode('/', $type, 2);
6996 // Process values for 'auto'
6997 if ($width === 'auto')
6999 if ($mime === 'video')
7001 if ($height === 'auto')
7005 elseif ($widescreen)
7007 $width = round((intval($height)/9)*16);
7011 $width = round((intval($height)/3)*4);
7020 if ($height === 'auto')
7022 if ($mime === 'audio')
7026 elseif ($mime === 'video')
7028 if ($width === 'auto')
7039 elseif ($widescreen)
7041 $height = round((intval($width)/16)*9);
7045 $height = round((intval($width)/4)*3);
7053 elseif ($mime === 'audio')
7058 // Set proper placeholder value
7059 if ($mime === 'audio')
7061 $placeholder = $audio;
7063 elseif ($mime === 'video')
7065 $placeholder = $video;
7070 // Make sure the JS library is included
7073 static $javascript_outputted = null;
7074 if (!$javascript_outputted && $this->javascript)
7076 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7077 $javascript_outputted = true;
7082 if ($handler === 'odeo')
7086 $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>';
7090 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7095 elseif ($handler === 'flash')
7099 $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>";
7103 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7107 // Flash Media Player file types.
7108 // Preferred handler for MP3 file types.
7109 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7114 $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>";
7118 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7122 // QuickTime 7 file types. Need to test with QuickTime 6.
7123 // Only handle MP3's if the Flash Media Player is not present.
7124 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7129 if ($placeholder !== '')
7131 $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>";
7135 $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>";
7140 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7145 elseif ($handler === 'wmedia')
7150 $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>";
7154 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7159 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7164 function get_real_type($find_handler = false)
7166 // If it's Odeo, let's get it out of the way.
7167 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7172 // Mime-types by handler.
7173 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7174 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7175 $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
7176 $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
7177 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7179 if ($this->get_type() !== null)
7181 $type = strtolower($this->type);
7188 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7189 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7191 switch (strtolower($this->get_extension()))
7196 $type = 'audio/acc';
7203 $type = 'audio/aiff';
7207 $type = 'audio/wav';
7214 $type = 'audio/midi';
7218 $type = 'audio/x-m4a';
7223 $type = 'audio/mp3';
7227 $type = 'audio/wav';
7231 $type = 'audio/x-ms-wax';
7235 $type = 'audio/x-ms-wma';
7241 $type = 'video/3gpp';
7246 $type = 'video/3gpp2';
7250 $type = 'video/x-ms-asf';
7254 $type = 'video/x-flv';
7268 $type = 'video/mpeg';
7272 $type = 'video/x-m4v';
7277 $type = 'video/quicktime';
7282 $type = 'video/mp4';
7286 $type = 'video/sd-video';
7290 $type = 'video/x-ms-wm';
7294 $type = 'video/x-ms-wmv';
7298 $type = 'video/x-ms-wvx';
7303 $type = 'application/futuresplash';
7307 $type = 'application/x-shockwave-flash';
7314 if (in_array($type, $types_flash))
7318 elseif (in_array($type, $types_fmedia))
7322 elseif (in_array($type, $types_quicktime))
7326 elseif (in_array($type, $types_wmedia))
7330 elseif (in_array($type, $types_mp3))
7346 class SimplePie_Caption
7354 // Constructor, used to input the data
7355 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7357 $this->type = $type;
7358 $this->lang = $lang;
7359 $this->startTime = $startTime;
7360 $this->endTime = $endTime;
7361 $this->text = $text;
7364 function __toString()
7366 // There is no $this->data here
7367 return md5(serialize($this));
7370 function get_endtime()
7372 if ($this->endTime !== null)
7374 return $this->endTime;
7382 function get_language()
7384 if ($this->lang !== null)
7394 function get_starttime()
7396 if ($this->startTime !== null)
7398 return $this->startTime;
7408 if ($this->text !== null)
7420 if ($this->type !== null)
7431 class SimplePie_Credit
7437 // Constructor, used to input the data
7438 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7440 $this->role = $role;
7441 $this->scheme = $scheme;
7442 $this->name = $name;
7445 function __toString()
7447 // There is no $this->data here
7448 return md5(serialize($this));
7453 if ($this->role !== null)
7463 function get_scheme()
7465 if ($this->scheme !== null)
7467 return $this->scheme;
7477 if ($this->name !== null)
7488 class SimplePie_Copyright
7493 // Constructor, used to input the data
7494 function SimplePie_Copyright($url = null, $label = null)
7497 $this->label = $label;
7500 function __toString()
7502 // There is no $this->data here
7503 return md5(serialize($this));
7508 if ($this->url !== null)
7518 function get_attribution()
7520 if ($this->label !== null)
7522 return $this->label;
7531 class SimplePie_Rating
7536 // Constructor, used to input the data
7537 function SimplePie_Rating($scheme = null, $value = null)
7539 $this->scheme = $scheme;
7540 $this->value = $value;
7543 function __toString()
7545 // There is no $this->data here
7546 return md5(serialize($this));
7549 function get_scheme()
7551 if ($this->scheme !== null)
7553 return $this->scheme;
7561 function get_value()
7563 if ($this->value !== null)
7565 return $this->value;
7574 class SimplePie_Restriction
7580 // Constructor, used to input the data
7581 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7583 $this->relationship = $relationship;
7584 $this->type = $type;
7585 $this->value = $value;
7588 function __toString()
7590 // There is no $this->data here
7591 return md5(serialize($this));
7594 function get_relationship()
7596 if ($this->relationship !== null)
7598 return $this->relationship;
7608 if ($this->type !== null)
7618 function get_value()
7620 if ($this->value !== null)
7622 return $this->value;
7632 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7634 class SimplePie_File
7638 var $success = true;
7639 var $headers = array();
7644 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7646 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7648 if (class_exists('idna_convert'))
7650 $idn =& new idna_convert;
7651 $parsed = SimplePie_Misc::parse_url($url);
7652 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7655 $this->useragent = $useragent;
7656 if (preg_match('/^http(s)?:\/\//i', $url))
7658 if ($useragent === null)
7660 $useragent = ini_get('user_agent');
7661 $this->useragent = $useragent;
7663 if (!is_array($headers))
7667 if (!$force_fsockopen && function_exists('curl_exec'))
7669 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7671 $headers2 = array();
7672 foreach ($headers as $key => $value)
7674 $headers2[] = "$key: $value";
7676 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7678 curl_setopt($fp, CURLOPT_ENCODING, '');
7680 curl_setopt($fp, CURLOPT_URL, $url);
7681 curl_setopt($fp, CURLOPT_HEADER, 1);
7682 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7683 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7684 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7685 curl_setopt($fp, CURLOPT_REFERER, $url);
7686 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7687 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7688 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7690 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7691 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7694 $this->headers = curl_exec($fp);
7695 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7697 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7698 $this->headers = curl_exec($fp);
7700 if (curl_errno($fp))
7702 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7703 $this->success = false;
7707 $info = curl_getinfo($fp);
7709 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7710 $this->headers = array_pop($this->headers);
7711 $parser =& new SimplePie_HTTP_Parser($this->headers);
7712 if ($parser->parse())
7714 $this->headers = $parser->headers;
7715 $this->body = $parser->body;
7716 $this->status_code = $parser->status_code;
7717 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)
7720 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7721 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7728 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7729 $url_parts = parse_url($url);
7730 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7732 $url_parts['host'] = "ssl://$url_parts[host]";
7733 $url_parts['port'] = 443;
7735 if (!isset($url_parts['port']))
7737 $url_parts['port'] = 80;
7739 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7742 $this->error = 'fsockopen error: ' . $errstr;
7743 $this->success = false;
7747 stream_set_timeout($fp, $timeout);
7748 if (isset($url_parts['path']))
7750 if (isset($url_parts['query']))
7752 $get = "$url_parts[path]?$url_parts[query]";
7756 $get = $url_parts['path'];
7763 $out = "GET $get HTTP/1.0\r\n";
7764 $out .= "Host: $url_parts[host]\r\n";
7765 $out .= "User-Agent: $useragent\r\n";
7766 if (extension_loaded('zlib'))
7768 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7771 if (isset($url_parts['user']) && isset($url_parts['pass']))
7773 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7775 foreach ($headers as $key => $value)
7777 $out .= "$key: $value\r\n";
7779 $out .= "Connection: Close\r\n\r\n";
7782 $info = stream_get_meta_data($fp);
7784 $this->headers = '';
7785 while (!$info['eof'] && !$info['timed_out'])
7787 $this->headers .= fread($fp, 1160);
7788 $info = stream_get_meta_data($fp);
7790 if (!$info['timed_out'])
7792 $parser =& new SimplePie_HTTP_Parser($this->headers);
7793 if ($parser->parse())
7795 $this->headers = $parser->headers;
7796 $this->body = $parser->body;
7797 $this->status_code = $parser->status_code;
7798 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)
7801 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7802 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7804 if (isset($this->headers['content-encoding']))
7806 // Hey, we act dumb elsewhere, so let's do that here too
7807 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7811 $decoder =& new SimplePie_gzdecode($this->body);
7812 if (!$decoder->parse())
7814 $this->error = 'Unable to decode HTTP "gzip" stream';
7815 $this->success = false;
7819 $this->body = $decoder->data;
7824 if (($body = gzuncompress($this->body)) === false)
7826 if (($body = gzinflate($this->body)) === false)
7828 $this->error = 'Unable to decode HTTP "deflate" stream';
7829 $this->success = false;
7832 $this->body = $body;
7836 $this->error = 'Unknown content coding';
7837 $this->success = false;
7844 $this->error = 'fsocket timed out';
7845 $this->success = false;
7853 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7854 if (!$this->body = file_get_contents($url))
7856 $this->error = 'file_get_contents could not read the file';
7857 $this->success = false;
7864 * HTTP Response Parser
7866 * @package SimplePie
7868 class SimplePie_HTTP_Parser
7876 var $http_version = 0.0;
7884 var $status_code = 0;
7895 * Key/value pairs of the headers
7900 var $headers = array();
7903 * Body of the response
7911 * Current state of the state machine
7916 var $state = 'http_version';
7927 * Input data length (to avoid calling strlen() everytime this is needed)
7932 var $data_length = 0;
7935 * Current position of the pointer
7943 * Name of the hedaer currently being parsed
7951 * Value of the hedaer currently being parsed
7959 * Create an instance of the class with the input data
7962 * @param string $data Input data
7964 function SimplePie_HTTP_Parser($data)
7966 $this->data = $data;
7967 $this->data_length = strlen($this->data);
7971 * Parse the input data
7974 * @return bool true on success, false on failure
7978 while ($this->state && $this->state !== 'emit' && $this->has_data())
7980 $state = $this->state;
7984 if ($this->state === 'emit' || $this->state === 'body')
7990 $this->http_version = '';
7991 $this->status_code = '';
7993 $this->headers = array();
8000 * Check whether there is data beyond the pointer
8003 * @return bool true if there is further data, false if not
8007 return (bool) ($this->position < $this->data_length);
8011 * See if the next character is LWS
8014 * @return bool true if the next character is LWS, false if not
8016 function is_linear_whitespace()
8018 return (bool) ($this->data[$this->position] === "\x09"
8019 || $this->data[$this->position] === "\x20"
8020 || ($this->data[$this->position] === "\x0A"
8021 && isset($this->data[$this->position + 1])
8022 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8026 * Parse the HTTP version
8030 function http_version()
8032 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8034 $len = strspn($this->data, '0123456789.', 5);
8035 $this->http_version = substr($this->data, 5, $len);
8036 $this->position += 5 + $len;
8037 if (substr_count($this->http_version, '.') <= 1)
8039 $this->http_version = (float) $this->http_version;
8040 $this->position += strspn($this->data, "\x09\x20", $this->position);
8041 $this->state = 'status';
8045 $this->state = false;
8050 $this->state = false;
8055 * Parse the status code
8061 if ($len = strspn($this->data, '0123456789', $this->position))
8063 $this->status_code = (int) substr($this->data, $this->position, $len);
8064 $this->position += $len;
8065 $this->state = 'reason';
8069 $this->state = false;
8074 * Parse the reason phrase
8080 $len = strcspn($this->data, "\x0A", $this->position);
8081 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8082 $this->position += $len + 1;
8083 $this->state = 'new_line';
8087 * Deal with a new line, shifting data around as needed
8093 $this->value = trim($this->value, "\x0D\x20");
8094 if ($this->name !== '' && $this->value !== '')
8096 $this->name = strtolower($this->name);
8097 if (isset($this->headers[$this->name]))
8099 $this->headers[$this->name] .= ', ' . $this->value;
8103 $this->headers[$this->name] = $this->value;
8108 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8110 $this->position += 2;
8111 $this->state = 'body';
8113 elseif ($this->data[$this->position] === "\x0A")
8116 $this->state = 'body';
8120 $this->state = 'name';
8125 * Parse a header name
8131 $len = strcspn($this->data, "\x0A:", $this->position);
8132 if (isset($this->data[$this->position + $len]))
8134 if ($this->data[$this->position + $len] === "\x0A")
8136 $this->position += $len;
8137 $this->state = 'new_line';
8141 $this->name = substr($this->data, $this->position, $len);
8142 $this->position += $len + 1;
8143 $this->state = 'value';
8148 $this->state = false;
8153 * Parse LWS, replacing consecutive LWS characters with a single space
8157 function linear_whitespace()
8161 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8163 $this->position += 2;
8165 elseif ($this->data[$this->position] === "\x0A")
8169 $this->position += strspn($this->data, "\x09\x20", $this->position);
8170 } while ($this->has_data() && $this->is_linear_whitespace());
8171 $this->value .= "\x20";
8175 * See what state to move to while within non-quoted header values
8181 if ($this->is_linear_whitespace())
8183 $this->linear_whitespace();
8187 switch ($this->data[$this->position])
8191 $this->state = 'quote';
8196 $this->state = 'new_line';
8200 $this->state = 'value_char';
8207 * Parse a header value while outside quotes
8211 function value_char()
8213 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8214 $this->value .= substr($this->data, $this->position, $len);
8215 $this->position += $len;
8216 $this->state = 'value';
8220 * See what state to move to while within quoted header values
8226 if ($this->is_linear_whitespace())
8228 $this->linear_whitespace();
8232 switch ($this->data[$this->position])
8236 $this->state = 'value';
8241 $this->state = 'new_line';
8246 $this->state = 'quote_escaped';
8250 $this->state = 'quote_char';
8257 * Parse a header value while within quotes
8261 function quote_char()
8263 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8264 $this->value .= substr($this->data, $this->position, $len);
8265 $this->position += $len;
8266 $this->state = 'value';
8270 * Parse an escaped character within quotes
8274 function quote_escaped()
8276 $this->value .= $this->data[$this->position];
8278 $this->state = 'quote';
8288 $this->body = substr($this->data, $this->position);
8289 $this->state = 'emit';
8296 * @package SimplePie
8298 class SimplePie_gzdecode
8304 * @see gzdecode::$data
8306 var $compressed_data;
8309 * Size of compressed data
8313 var $compressed_size;
8316 * Minimum size of a valid gzip string
8320 var $min_compressed_size = 18;
8323 * Current position of pointer
8340 * @see gzdecode::$compressed_data
8369 * @see gzdecode::$extra_field
8370 * @see gzdecode::$SI2
8378 * @see gzdecode::$extra_field
8379 * @see gzdecode::$SI1
8384 * Extra field content
8387 * @see gzdecode::$SI1
8388 * @see gzdecode::$SI2
8400 * Human readable comment
8407 * Don't allow anything to be set
8411 function __set($name, $value)
8413 trigger_error("Cannot write property $name", E_USER_ERROR);
8417 * Set the compressed string and related properties
8421 function SimplePie_gzdecode($data)
8423 $this->compressed_data = $data;
8424 $this->compressed_size = strlen($data);
8428 * Decode the GZIP stream
8434 if ($this->compressed_size >= $this->min_compressed_size)
8436 // Check ID1, ID2, and CM
8437 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8442 // Get the FLG (FLaGs)
8443 $this->flags = ord($this->compressed_data[3]);
8445 // FLG bits above (1 << 4) are reserved
8446 if ($this->flags > 0x1F)
8451 // Advance the pointer after the above
8452 $this->position += 4;
8455 $mtime = substr($this->compressed_data, $this->position, 4);
8456 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8457 if (current(unpack('S', "\x00\x01")) === 1)
8459 $mtime = strrev($mtime);
8461 $this->MTIME = current(unpack('l', $mtime));
8462 $this->position += 4;
8464 // Get the XFL (eXtra FLags)
8465 $this->XFL = ord($this->compressed_data[$this->position++]);
8467 // Get the OS (Operating System)
8468 $this->OS = ord($this->compressed_data[$this->position++]);
8471 if ($this->flags & 4)
8473 // Read subfield IDs
8474 $this->SI1 = $this->compressed_data[$this->position++];
8475 $this->SI2 = $this->compressed_data[$this->position++];
8477 // SI2 set to zero is reserved for future use
8478 if ($this->SI2 === "\x00")
8483 // Get the length of the extra field
8484 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8487 // Check the length of the string is still valid
8488 $this->min_compressed_size += $len + 4;
8489 if ($this->compressed_size >= $this->min_compressed_size)
8491 // Set the extra field to the given data
8492 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8493 $this->position += $len;
8502 if ($this->flags & 8)
8504 // Get the length of the filename
8505 $len = strcspn($this->compressed_data, "\x00", $this->position);
8507 // Check the length of the string is still valid
8508 $this->min_compressed_size += $len + 1;
8509 if ($this->compressed_size >= $this->min_compressed_size)
8511 // Set the original filename to the given string
8512 $this->filename = substr($this->compressed_data, $this->position, $len);
8513 $this->position += $len + 1;
8521 // Parse the FCOMMENT
8522 if ($this->flags & 16)
8524 // Get the length of the comment
8525 $len = strcspn($this->compressed_data, "\x00", $this->position);
8527 // Check the length of the string is still valid
8528 $this->min_compressed_size += $len + 1;
8529 if ($this->compressed_size >= $this->min_compressed_size)
8531 // Set the original comment to the given string
8532 $this->comment = substr($this->compressed_data, $this->position, $len);
8533 $this->position += $len + 1;
8542 if ($this->flags & 2)
8544 // Check the length of the string is still valid
8545 $this->min_compressed_size += $len + 2;
8546 if ($this->compressed_size >= $this->min_compressed_size)
8549 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8551 // Check the CRC matches
8552 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8554 $this->position += 2;
8567 // Decompress the actual data
8568 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8574 $this->position = $this->compressed_size - 8;
8577 // Check CRC of data
8578 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8579 $this->position += 4;
8580 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8585 // Check ISIZE of data
8586 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8587 $this->position += 4;
8588 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8593 // Wow, against all odds, we've actually got a valid gzip string
8603 class SimplePie_Cache
8606 * Don't call the constructor. Please.
8610 function SimplePie_Cache()
8612 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8616 * Create a new SimplePie_Cache object
8621 function create($location, $filename, $extension)
8623 $location_iri =& new SimplePie_IRI($location);
8624 switch ($location_iri->get_scheme())
8627 if (extension_loaded('mysql'))
8629 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8634 return new SimplePie_Cache_File($location, $filename, $extension);
8639 class SimplePie_Cache_File
8646 function SimplePie_Cache_File($location, $filename, $extension)
8648 $this->location = $location;
8649 $this->filename = $filename;
8650 $this->extension = $extension;
8651 $this->name = "$this->location/$this->filename.$this->extension";
8654 function save($data)
8656 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8658 if (is_a($data, 'SimplePie'))
8660 $data = $data->data;
8663 $data = serialize($data);
8665 if (function_exists('file_put_contents'))
8667 return (bool) file_put_contents($this->name, $data);
8671 $fp = fopen($this->name, 'wb');
8685 if (file_exists($this->name) && is_readable($this->name))
8687 return unserialize(file_get_contents($this->name));
8694 if (file_exists($this->name))
8696 return filemtime($this->name);
8703 if (file_exists($this->name))
8705 return touch($this->name);
8712 if (file_exists($this->name))
8714 return unlink($this->name);
8720 class SimplePie_Cache_DB
8722 function prepare_simplepie_object_for_cache($data)
8724 $items = $data->get_items();
8725 $items_by_id = array();
8729 foreach ($items as $item)
8731 $items_by_id[$item->get_id()] = $item;
8734 if (count($items_by_id) !== count($items))
8736 $items_by_id = array();
8737 foreach ($items as $item)
8739 $items_by_id[$item->get_id(true)] = $item;
8743 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8745 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8747 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8749 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8751 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8753 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8755 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8757 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8764 if ($channel !== null)
8766 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8768 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8770 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8772 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8774 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8776 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8778 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8780 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8782 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8784 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8787 if (isset($data->data['items']))
8789 unset($data->data['items']);
8791 if (isset($data->data['ordered_items']))
8793 unset($data->data['ordered_items']);
8796 return array(serialize($data->data), $items_by_id);
8800 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8806 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8808 $host = $mysql_location->get_host();
8809 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8811 $server = ':' . substr($host, 5, -1);
8816 if ($mysql_location->get_port() !== null)
8818 $server .= ':' . $mysql_location->get_port();
8822 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8824 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8828 $username = $mysql_location->get_userinfo();
8832 if ($this->mysql = mysql_connect($server, $username, $password))
8834 $this->id = $name . $extension;
8835 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8836 if (!isset($this->options['prefix'][0]))
8838 $this->options['prefix'][0] = '';
8841 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8842 && mysql_query('SET NAMES utf8')
8843 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8846 while ($row = mysql_fetch_row($query))
8851 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8853 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)))'))
8855 $this->mysql = null;
8859 if (!in_array($this->options['prefix'][0] . 'items', $db))
8861 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)))'))
8863 $this->mysql = null;
8869 $this->mysql = null;
8874 function save($data)
8878 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8880 if (is_a($data, 'SimplePie'))
8884 // This keyword needs to defy coding standards for PHP4 compatibility
8885 $data = clone($data);
8888 $prepared = $this->prepare_simplepie_object_for_cache($data);
8890 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8892 if (mysql_num_rows($query))
8894 $items = count($prepared[1]);
8897 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8901 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8904 if (!mysql_query($sql, $this->mysql))
8909 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))
8914 $ids = array_keys($prepared[1]);
8917 foreach ($ids as $id)
8919 $database_ids[] = mysql_real_escape_string($id);
8922 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))
8924 $existing_ids = array();
8925 while ($row = mysql_fetch_row($query))
8927 $existing_ids[] = $row[0];
8930 $new_ids = array_diff($ids, $existing_ids);
8932 foreach ($new_ids as $new_id)
8934 if (!($date = $prepared[1][$new_id]->get_date('U')))
8939 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))
8953 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8955 if (mysql_num_rows($query))
8957 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))
8962 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))
8973 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)))
8975 $data = unserialize($row[1]);
8977 if (isset($this->options['items'][0]))
8979 $items = (int) $this->options['items'][0];
8983 $items = (int) $row[0];
8988 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8990 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8992 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8994 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8996 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8998 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9000 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9002 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9011 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9014 $sql .= ' LIMIT ' . $items;
9017 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9019 while ($row = mysql_fetch_row($query))
9021 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9037 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)))
9049 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))
9061 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)))
9072 class SimplePie_Misc
9074 function time_hms($seconds)
9078 $hours = floor($seconds / 3600);
9079 $remainder = $seconds % 3600;
9082 $time .= $hours.':';
9085 $minutes = floor($remainder / 60);
9086 $seconds = $remainder % 60;
9087 if ($minutes < 10 && $hours > 0)
9089 $minutes = '0' . $minutes;
9093 $seconds = '0' . $seconds;
9096 $time .= $minutes.':';
9102 function absolutize_url($relative, $base)
9104 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9105 return $iri->get_iri();
9108 function remove_dot_segments($input)
9111 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9113 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9114 if (strpos($input, '../') === 0)
9116 $input = substr($input, 3);
9118 elseif (strpos($input, './') === 0)
9120 $input = substr($input, 2);
9122 // 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,
9123 elseif (strpos($input, '/./') === 0)
9125 $input = substr_replace($input, '/', 0, 3);
9127 elseif ($input === '/.')
9131 // 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,
9132 elseif (strpos($input, '/../') === 0)
9134 $input = substr_replace($input, '/', 0, 4);
9135 $output = substr_replace($output, '', strrpos($output, '/'));
9137 elseif ($input === '/..')
9140 $output = substr_replace($output, '', strrpos($output, '/'));
9142 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9143 elseif ($input === '.' || $input === '..')
9147 // 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
9148 elseif (($pos = strpos($input, '/', 1)) !== false)
9150 $output .= substr($input, 0, $pos);
9151 $input = substr_replace($input, '', 0, $pos);
9159 return $output . $input;
9162 function get_element($realname, $string)
9165 $name = preg_quote($realname, '/');
9166 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9168 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9170 $return[$i]['tag'] = $realname;
9171 $return[$i]['full'] = $matches[$i][0][0];
9172 $return[$i]['offset'] = $matches[$i][0][1];
9173 if (strlen($matches[$i][3][0]) <= 2)
9175 $return[$i]['self_closing'] = true;
9179 $return[$i]['self_closing'] = false;
9180 $return[$i]['content'] = $matches[$i][4][0];
9182 $return[$i]['attribs'] = array();
9183 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))
9185 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9187 if (count($attribs[$j]) === 2)
9189 $attribs[$j][2] = $attribs[$j][1];
9191 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9199 function element_implode($element)
9201 $full = "<$element[tag]";
9202 foreach ($element['attribs'] as $key => $value)
9204 $key = strtolower($key);
9205 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9207 if ($element['self_closing'])
9213 $full .= ">$element[content]</$element[tag]>";
9218 function error($message, $level, $file, $line)
9220 if ((ini_get('error_reporting') & $level) > 0)
9225 $note = 'PHP Error';
9227 case E_USER_WARNING:
9228 $note = 'PHP Warning';
9231 $note = 'PHP Notice';
9234 $note = 'Unknown Error';
9237 error_log("$note: $message in $file on line $line", 0);
9243 * If a file has been cached, retrieve and display it.
9245 * This is most useful for caching images (get_favicon(), etc.),
9246 * however it works for all cached files. This WILL NOT display ANY
9247 * file/image/page/whatever, but rather only display what has already
9248 * been cached by SimplePie.
9251 * @see SimplePie::get_favicon()
9252 * @param str $identifier_url URL that is used to identify the content.
9253 * This may or may not be the actual URL of the live content.
9254 * @param str $cache_location Location of SimplePie's cache. Defaults
9256 * @param str $cache_extension The file extension that the file was
9257 * cached with. Defaults to 'spc'.
9258 * @param str $cache_class Name of the cache-handling class being used
9259 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9260 * as-is unless you've overloaded the class.
9261 * @param str $cache_name_function Obsolete. Exists for backwards
9262 * compatibility reasons only.
9264 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9266 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9268 if ($file = $cache->load())
9270 if (isset($file['headers']['content-type']))
9272 header('Content-type:' . $file['headers']['content-type']);
9276 header('Content-type: application/octet-stream');
9278 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9283 die('Cached file for ' . $identifier_url . ' cannot be found.');
9286 function fix_protocol($url, $http = 1)
9288 $url = SimplePie_Misc::normalize_url($url);
9289 $parsed = SimplePie_Misc::parse_url($url);
9290 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9292 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9295 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9297 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9300 if ($http === 2 && $parsed['scheme'] !== '')
9304 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9306 return substr_replace($url, 'podcast', 0, 4);
9308 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9310 return substr_replace($url, 'itpc', 0, 4);
9318 function parse_url($url)
9320 $iri =& new SimplePie_IRI($url);
9322 'scheme' => (string) $iri->get_scheme(),
9323 'authority' => (string) $iri->get_authority(),
9324 'path' => (string) $iri->get_path(),
9325 'query' => (string) $iri->get_query(),
9326 'fragment' => (string) $iri->get_fragment()
9330 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9332 $iri =& new SimplePie_IRI('');
9333 $iri->set_scheme($scheme);
9334 $iri->set_authority($authority);
9335 $iri->set_path($path);
9336 $iri->set_query($query);
9337 $iri->set_fragment($fragment);
9338 return $iri->get_iri();
9341 function normalize_url($url)
9343 $iri =& new SimplePie_IRI($url);
9344 return $iri->get_iri();
9347 function percent_encoding_normalization($match)
9349 $integer = hexdec($match[1]);
9350 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9352 return chr($integer);
9356 return strtoupper($match[0]);
9361 * Remove bad UTF-8 bytes
9363 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9364 * FAQ: Multilingual Forms (modified to include full ASCII range)
9366 * @author Geoffrey Sneddon
9367 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9368 * @param string $str String to remove bad UTF-8 bytes from
9369 * @return string UTF-8 string
9371 function utf8_bad_replace($str)
9373 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9377 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9381 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))
9383 return implode("\xEF\xBF\xBD", $matches[0]);
9385 elseif ($str !== '')
9387 return "\xEF\xBF\xBD";
9396 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9400 * @param string $string Windows-1252 encoded string
9401 * @return string UTF-8 encoded string
9403 function windows_1252_to_utf8($string)
9405 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");
9407 return strtr($string, $convert_table);
9410 function change_encoding($data, $input, $output)
9412 $input = SimplePie_Misc::encoding($input);
9413 $output = SimplePie_Misc::encoding($output);
9415 // We fail to fail on non US-ASCII bytes
9416 if ($input === 'US-ASCII')
9418 static $non_ascii_octects = '';
9419 if (!$non_ascii_octects)
9421 for ($i = 0x80; $i <= 0xFF; $i++)
9423 $non_ascii_octects .= chr($i);
9426 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9429 // This is first, as behaviour of this is completely predictable
9430 if ($input === 'windows-1252' && $output === 'UTF-8')
9432 return SimplePie_Misc::windows_1252_to_utf8($data);
9434 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9435 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9439 // This is last, as behaviour of this varies with OS userland and PHP version
9440 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9444 // If we can't do anything, just fail
9451 function encoding($charset)
9453 // Normalization from UTS #22
9454 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9456 case 'adobestandardencoding':
9457 case 'csadobestandardencoding':
9458 return 'Adobe-Standard-Encoding';
9460 case 'adobesymbolencoding':
9462 return 'Adobe-Symbol-Encoding';
9466 return 'Amiga-1251';
9468 case 'ansix31101983':
9470 case 'csiso99naplps':
9473 return 'ANSI_X3.110-1983';
9477 case 'csiso89asmo449':
9488 return 'Big5-HKSCS';
9499 case 'csiso4unitedkingdom':
9507 case 'csiso47bsviewdata':
9509 return 'BS_viewdata';
9517 case 'csaz243419851':
9518 case 'csiso121canadian1':
9521 return 'CSA_Z243.4-1985-1';
9524 case 'csaz243419852':
9525 case 'csiso122canadian2':
9528 return 'CSA_Z243.4-1985-2';
9530 case 'csaz24341985gr':
9531 case 'csiso123csaz24341985gr':
9533 return 'CSA_Z243.4-1985-gr';
9535 case 'csiso139csn369103':
9538 return 'CSN_369103';
9545 case 'csiso21german':
9556 case 'csiso646danish':
9562 case 'csibmebcdicatde':
9564 return 'EBCDIC-AT-DE';
9566 case 'csebcdicatdea':
9568 return 'EBCDIC-AT-DE-A';
9570 case 'csebcdiccafr':
9572 return 'EBCDIC-CA-FR';
9574 case 'csebcdicdkno':
9576 return 'EBCDIC-DK-NO';
9578 case 'csebcdicdknoa':
9580 return 'EBCDIC-DK-NO-A';
9588 return 'EBCDIC-ES-A';
9592 return 'EBCDIC-ES-S';
9594 case 'csebcdicfise':
9596 return 'EBCDIC-FI-SE';
9598 case 'csebcdicfisea':
9600 return 'EBCDIC-FI-SE-A';
9622 case 'csiso111ecmacyrillic':
9623 case 'ecmacyrillic':
9626 return 'ECMA-cyrillic';
9628 case 'csiso17spanish':
9634 case 'csiso85spanish2':
9640 case 'cseucfixwidjapanese':
9641 case 'extendedunixcodefixedwidthforjapanese':
9642 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9644 case 'cseucpkdfmtjapanese':
9646 case 'extendedunixcodepackedformatforjapanese':
9647 return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
9655 case 'csiso58gb231280':
9665 case 'csiso57gb1988':
9669 return 'GB_1988-80';
9671 case 'csiso153gost1976874':
9675 return 'GOST_19768-74';
9678 case 'csiso150greekccitt':
9681 return 'greek-ccitt';
9683 case 'csiso88greek7':
9688 case 'csiso18greek7old':
9691 return 'greek7-old';
9695 return 'HP-DeskTop';
9707 return 'HP-Pi-font';
9716 return 'HZ-GB-2312';
9718 case 'csibmsymbols':
9720 return 'IBM-Symbols';
9729 case 'pcmultilingual850euro':
9734 case 'ebcdiclatin9euro':
9740 case 'ebcdicus37euro':
9746 case 'ebcdicde273euro':
9752 case 'ebcdicdk277euro':
9753 case 'ebcdicno277euro':
9759 case 'ebcdicfi278euro':
9760 case 'ebcdicse278euro':
9766 case 'ebcdicit280euro':
9772 case 'ebcdices284euro':
9778 case 'ebcdicgb285euro':
9784 case 'ebcdicfr297euro':
9790 case 'ebcdicinternational500euro':
9796 case 'ebcdicis871euro':
9871 case 'ebcdicjpkana':
9901 case 'cspc8codepage437':
9913 case 'cspc775baltic':
9919 case 'cspc850multilingual':
9962 case 'cspc862latinhebrew':
10004 case 'ebcdiccproece':
10017 case 'ebcdiccyrillic':
10045 case 'ebcdiccpar2':
10057 case 'csiso143iecp271':
10060 return 'IEC_P27-1';
10062 case 'csiso49inis':
10067 case 'csiso50inis8':
10072 case 'csiso51iniscyrillic':
10073 case 'iniscyrillic':
10075 return 'INIS-cyrillic';
10077 case 'csinvariant':
10079 return 'INVARIANT';
10082 return 'ISO-2022-CN';
10084 case 'iso2022cnext':
10085 return 'ISO-2022-CN-EXT';
10087 case 'csiso2022jp':
10089 return 'ISO-2022-JP';
10091 case 'csiso2022jp2':
10093 return 'ISO-2022-JP-2';
10095 case 'csiso2022kr':
10097 return 'ISO-2022-KR';
10099 case 'cswindows30latin1':
10100 case 'iso88591windows30latin1':
10101 return 'ISO-8859-1-Windows-3.0-Latin-1';
10103 case 'cswindows31latin1':
10104 case 'iso88591windows31latin1':
10105 return 'ISO-8859-1-Windows-3.1-Latin-1';
10107 case 'csisolatin2':
10109 case 'iso885921987':
10113 return 'ISO-8859-2';
10115 case 'cswindows31latin2':
10116 case 'iso88592windowslatin2':
10117 return 'ISO-8859-2-Windows-Latin-2';
10119 case 'csisolatin3':
10121 case 'iso885931988':
10125 return 'ISO-8859-3';
10127 case 'csisolatin4':
10129 case 'iso885941988':
10133 return 'ISO-8859-4';
10135 case 'csisolatincyrillic':
10138 case 'iso885951988':
10140 return 'ISO-8859-5';
10144 case 'csisolatinarabic':
10147 case 'iso885961987':
10149 return 'ISO-8859-6';
10151 case 'csiso88596e':
10153 return 'ISO-8859-6-E';
10155 case 'csiso88596i':
10157 return 'ISO-8859-6-I';
10159 case 'csisolatingreek':
10165 case 'iso885971987':
10167 return 'ISO-8859-7';
10169 case 'csisolatinhebrew':
10172 case 'iso885981988':
10174 return 'ISO-8859-8';
10176 case 'csiso88598e':
10178 return 'ISO-8859-8-E';
10180 case 'csiso88598i':
10182 return 'ISO-8859-8-I';
10184 case 'cswindows31latin5':
10185 case 'iso88599windowslatin5':
10186 return 'ISO-8859-9-Windows-Latin-5';
10188 case 'csisolatin6':
10190 case 'iso8859101992':
10194 return 'ISO-8859-10';
10197 return 'ISO-8859-13';
10200 case 'iso8859141998':
10205 return 'ISO-8859-14';
10209 return 'ISO-8859-15';
10212 case 'iso8859162001':
10216 return 'ISO-8859-16';
10219 return 'ISO-10646-J-1';
10222 case 'iso10646ucs2':
10223 return 'ISO-10646-UCS-2';
10226 case 'iso10646ucs4':
10227 return 'ISO-10646-UCS-4';
10229 case 'csunicodeascii':
10230 case 'iso10646ucsbasic':
10231 return 'ISO-10646-UCS-Basic';
10233 case 'csunicodelatin1':
10235 case 'iso10646unicodelatin1':
10236 return 'ISO-10646-Unicode-Latin1';
10238 case 'csiso10646utf1':
10239 case 'iso10646utf1':
10240 return 'ISO-10646-UTF-1';
10242 case 'csiso115481':
10244 case 'isotr115481':
10245 return 'ISO-11548-1';
10249 return 'iso-ir-90';
10251 case 'csunicodeibm1261':
10252 case 'isounicodeibm1261':
10253 return 'ISO-Unicode-IBM-1261';
10255 case 'csunicodeibm1264':
10256 case 'isounicodeibm1264':
10257 return 'ISO-Unicode-IBM-1264';
10259 case 'csunicodeibm1265':
10260 case 'isounicodeibm1265':
10261 return 'ISO-Unicode-IBM-1265';
10263 case 'csunicodeibm1268':
10264 case 'isounicodeibm1268':
10265 return 'ISO-Unicode-IBM-1268';
10267 case 'csunicodeibm1276':
10268 case 'isounicodeibm1276':
10269 return 'ISO-Unicode-IBM-1276';
10271 case 'csiso646basic1983':
10272 case 'iso646basic1983':
10274 return 'ISO_646.basic:1983';
10276 case 'csiso2intlrefversion':
10278 case 'iso646irv1983':
10280 return 'ISO_646.irv:1983';
10284 case 'iso20331983':
10286 return 'ISO_2033-1983';
10288 case 'csiso5427cyrillic':
10293 case 'iso5427cyrillic1981':
10294 case 'iso54271981':
10296 return 'ISO_5427:1981';
10298 case 'csiso5428greek':
10299 case 'iso54281980':
10301 return 'ISO_5428:1980';
10303 case 'csiso6937add':
10306 return 'ISO_6937-2-25';
10308 case 'csisotextcomm':
10309 case 'iso69372add':
10311 return 'ISO_6937-2-add';
10313 case 'csiso8859supp':
10314 case 'iso8859supp':
10317 return 'ISO_8859-supp';
10319 case 'csiso10367box':
10320 case 'iso10367box':
10322 return 'ISO_10367-box';
10324 case 'csiso15italian':
10330 case 'csiso13jisc6220jp':
10332 case 'jisc62201969':
10333 case 'jisc62201969jp':
10336 return 'JIS_C6220-1969-jp';
10338 case 'csiso14jisc6220ro':
10341 case 'jisc62201969ro':
10343 return 'JIS_C6220-1969-ro';
10345 case 'csiso42jisc62261978':
10347 case 'jisc62261978':
10348 return 'JIS_C6226-1978';
10350 case 'csiso87jisx208':
10352 case 'jisc62261983':
10353 case 'jisx2081983':
10355 return 'JIS_C6226-1983';
10357 case 'csiso91jisc62291984a':
10359 case 'jisc62291984a':
10361 return 'JIS_C6229-1984-a';
10363 case 'csiso92jisc62991984b':
10364 case 'iso646jpocrb':
10366 case 'jisc62291984b':
10368 return 'JIS_C6229-1984-b';
10370 case 'csiso93jis62291984badd':
10372 case 'jisc62291984badd':
10374 return 'JIS_C6229-1984-b-add';
10376 case 'csiso94jis62291984hand':
10378 case 'jisc62291984hand':
10380 return 'JIS_C6229-1984-hand';
10382 case 'csiso95jis62291984handadd':
10384 case 'jisc62291984handadd':
10385 case 'jpocrhandadd':
10386 return 'JIS_C6229-1984-hand-add';
10388 case 'csiso96jisc62291984kana':
10390 case 'jisc62291984kana':
10391 return 'JIS_C6229-1984-kana';
10393 case 'csjisencoding':
10394 case 'jisencoding':
10395 return 'JIS_Encoding';
10397 case 'cshalfwidthkatakana':
10400 return 'JIS_X0201';
10402 case 'csiso159jisx2121990':
10404 case 'jisx2121990':
10406 return 'JIS_X0212-1990';
10408 case 'csiso141jusib1002':
10414 return 'JUS_I.B1.002';
10416 case 'csiso147macedonian':
10418 case 'jusib1003mac':
10420 return 'JUS_I.B1.003-mac';
10422 case 'csiso146serbian':
10424 case 'jusib1003serb':
10426 return 'JUS_I.B1.003-serb';
10428 case 'koi7switched':
10429 return 'KOI7-switched';
10446 case 'strk10482002':
10449 case 'csiso19latingreek':
10452 return 'latin-greek';
10454 case 'csiso27latingreek1':
10456 case 'latingreek1':
10457 return 'Latin-greek-1';
10459 case 'csiso158lap':
10463 return 'latin-lap';
10465 case 'csmacintosh':
10468 return 'macintosh';
10470 case 'csmicrosoftpublishing':
10471 case 'microsoftpublishing':
10472 return 'Microsoft-Publishing';
10482 case 'csiso86hungarian':
10487 return 'MSZ_7795.3';
10492 return 'NATS-DANO';
10494 case 'csnatsdanoadd':
10496 case 'natsdanoadd':
10497 return 'NATS-DANO-ADD';
10502 return 'NATS-SEFI';
10504 case 'csnatssefiadd':
10506 case 'natssefiadd':
10507 return 'NATS-SEFI-ADD';
10509 case 'csiso151cuba':
10514 return 'NC_NC00-10:81';
10516 case 'csiso69french':
10521 return 'NF_Z_62-010';
10523 case 'csiso25french':
10526 case 'nfz620101973':
10527 return 'NF_Z_62-010_(1973)';
10529 case 'csiso60danishnorwegian':
10530 case 'csiso60norwegian1':
10535 return 'NS_4551-1';
10537 case 'csiso61norwegian2':
10542 return 'NS_4551-2';
10544 case 'osdebcdicdf3irv':
10545 return 'OSD_EBCDIC_DF03_IRV';
10547 case 'osdebcdicdf41':
10548 return 'OSD_EBCDIC_DF04_1';
10550 case 'osdebcdicdf415':
10551 return 'OSD_EBCDIC_DF04_15';
10553 case 'cspc8danishnorwegian':
10554 case 'pc8danishnorwegian':
10555 return 'PC8-Danish-Norwegian';
10557 case 'cspc8turkish':
10559 return 'PC8-Turkish';
10561 case 'csiso16portuguese':
10567 case 'csiso84portuguese2':
10575 case 'cyrillicasian':
10583 case 'csiso10swedish':
10590 return 'SEN_850200_B';
10592 case 'csiso11swedishfornames':
10597 return 'SEN_850200_C';
10602 return 'Shift_JIS';
10604 case 'csiso102t617bit':
10607 return 'T.61-7bit';
10609 case 'csiso103t618bit':
10613 return 'T.61-8bit';
10615 case 'csiso128t101g2':
10624 case 'csunicode11':
10626 return 'UNICODE-1-1';
10628 case 'csunicode11utf7':
10629 case 'unicode11utf7':
10630 return 'UNICODE-1-1-UTF-7';
10632 case 'csunknown8bit':
10633 case 'unknown8bit':
10634 return 'UNKNOWN-8BIT';
10636 case 'ansix341968':
10637 case 'ansix341986':
10642 case 'iso646irv1991':
10677 case 'csventurainternational':
10678 case 'venturainternational':
10679 return 'Ventura-International';
10681 case 'csventuramath':
10682 case 'venturamath':
10683 return 'Ventura-Math';
10685 case 'csventuraus':
10687 return 'Ventura-US';
10689 case 'csiso70videotexsupp1':
10691 case 'videotexsuppl':
10692 return 'videotex-suppl';
10702 case 'cswindows31j':
10704 return 'Windows-31J';
10708 return 'windows-874';
10711 case 'csksc56011987':
10716 case 'ksc56011987':
10717 case 'ksc56011989':
10719 return 'windows-949';
10721 case 'windows1250':
10722 return 'windows-1250';
10724 case 'windows1251':
10725 return 'windows-1251';
10728 case 'csisolatin1':
10731 case 'iso885911987':
10735 case 'windows1252':
10736 return 'windows-1252';
10738 case 'windows1253':
10739 return 'windows-1253';
10741 case 'csisolatin5':
10743 case 'iso885991989':
10747 case 'windows1254':
10748 return 'windows-1254';
10750 case 'windows1255':
10751 return 'windows-1255';
10753 case 'windows1256':
10754 return 'windows-1256';
10756 case 'windows1257':
10757 return 'windows-1257';
10759 case 'windows1258':
10760 return 'windows-1258';
10767 function get_curl_version()
10769 if (is_array($curl = curl_version()))
10771 $curl = $curl['version'];
10773 elseif (substr($curl, 0, 5) === 'curl/')
10775 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10777 elseif (substr($curl, 0, 8) === 'libcurl/')
10779 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10788 function is_subclass_of($class1, $class2)
10790 if (func_num_args() !== 2)
10792 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10794 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10796 return is_subclass_of($class1, $class2);
10798 elseif (is_string($class1) && is_string($class2))
10800 if (class_exists($class1))
10802 if (class_exists($class2))
10804 $class2 = strtolower($class2);
10805 while ($class1 = strtolower(get_parent_class($class1)))
10807 if ($class1 === $class2)
10816 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10823 * Strip HTML comments
10826 * @param string $data Data to strip comments from
10827 * @return string Comment stripped string
10829 function strip_comments($data)
10832 while (($start = strpos($data, '<!--')) !== false)
10834 $output .= substr($data, 0, $start);
10835 if (($end = strpos($data, '-->', $start)) !== false)
10837 $data = substr_replace($data, '', 0, $end + 3);
10844 return $output . $data;
10847 function parse_date($dt)
10849 $parser = SimplePie_Parse_Date::get();
10850 return $parser->parse($dt);
10854 * Decode HTML entities
10858 * @param string $data Input data
10859 * @return string Output data
10861 function entities_decode($data)
10863 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10864 return $decoder->parse();
10868 * Remove RFC822 comments
10871 * @param string $data Data to strip comments from
10872 * @return string Comment stripped string
10874 function uncomment_rfc822($string)
10876 $string = (string) $string;
10878 $length = strlen($string);
10883 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10885 $output .= substr($string, $position, $pos - $position);
10886 $position = $pos + 1;
10887 if ($string[$pos - 1] !== '\\')
10890 while ($depth && $position < $length)
10892 $position += strcspn($string, '()', $position);
10893 if ($string[$position - 1] === '\\')
10898 elseif (isset($string[$position]))
10900 switch ($string[$position])
10923 $output .= substr($string, $position);
10928 function parse_mime($mime)
10930 if (($pos = strpos($mime, ';')) === false)
10932 return trim($mime);
10936 return trim(substr($mime, 0, $pos));
10940 function htmlspecialchars_decode($string, $quote_style)
10942 if (function_exists('htmlspecialchars_decode'))
10944 return htmlspecialchars_decode($string, $quote_style);
10948 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10952 function atom_03_construct_type($attribs)
10954 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10956 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10960 $mode = SIMPLEPIE_CONSTRUCT_NONE;
10962 if (isset($attribs['']['type']))
10964 switch (strtolower(trim($attribs['']['type'])))
10968 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10972 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10975 case 'application/xhtml+xml':
10976 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10979 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10984 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10988 function atom_10_construct_type($attribs)
10990 if (isset($attribs['']['type']))
10992 switch (strtolower(trim($attribs['']['type'])))
10995 return SIMPLEPIE_CONSTRUCT_TEXT;
10998 return SIMPLEPIE_CONSTRUCT_HTML;
11001 return SIMPLEPIE_CONSTRUCT_XHTML;
11004 return SIMPLEPIE_CONSTRUCT_NONE;
11007 return SIMPLEPIE_CONSTRUCT_TEXT;
11010 function atom_10_content_construct_type($attribs)
11012 if (isset($attribs['']['type']))
11014 $type = strtolower(trim($attribs['']['type']));
11018 return SIMPLEPIE_CONSTRUCT_TEXT;
11021 return SIMPLEPIE_CONSTRUCT_HTML;
11024 return SIMPLEPIE_CONSTRUCT_XHTML;
11026 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11028 return SIMPLEPIE_CONSTRUCT_NONE;
11032 return SIMPLEPIE_CONSTRUCT_BASE64;
11037 return SIMPLEPIE_CONSTRUCT_TEXT;
11041 function is_isegment_nz_nc($string)
11043 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);
11046 function space_seperated_tokens($string)
11048 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11049 $string_length = strlen($string);
11051 $position = strspn($string, $space_characters);
11054 while ($position < $string_length)
11056 $len = strcspn($string, $space_characters, $position);
11057 $tokens[] = substr($string, $position, $len);
11059 $position += strspn($string, $space_characters, $position);
11065 function array_unique($array)
11067 if (version_compare(PHP_VERSION, '5.2', '>='))
11069 return array_unique($array);
11073 $array = (array) $array;
11074 $new_array = array();
11075 $new_array_strings = array();
11076 foreach ($array as $key => $value)
11078 if (is_object($value))
11080 if (method_exists($value, '__toString'))
11082 $cmp = $value->__toString();
11086 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11089 elseif (is_array($value))
11091 $cmp = (string) reset($value);
11095 $cmp = (string) $value;
11097 if (!in_array($cmp, $new_array_strings))
11099 $new_array[$key] = $value;
11100 $new_array_strings[] = $cmp;
11108 * Converts a unicode codepoint to a UTF-8 character
11112 * @param int $codepoint Unicode codepoint
11113 * @return string UTF-8 character
11115 function codepoint_to_utf8($codepoint)
11117 $codepoint = (int) $codepoint;
11118 if ($codepoint < 0)
11122 else if ($codepoint <= 0x7f)
11124 return chr($codepoint);
11126 else if ($codepoint <= 0x7ff)
11128 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11130 else if ($codepoint <= 0xffff)
11132 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11134 else if ($codepoint <= 0x10ffff)
11136 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11140 // U+FFFD REPLACEMENT CHARACTER
11141 return "\xEF\xBF\xBD";
11146 * Re-implementation of PHP 5's stripos()
11148 * Returns the numeric position of the first occurrence of needle in the
11153 * @param object $haystack
11154 * @param string $needle Note that the needle may be a string of one or more
11155 * characters. If needle is not a string, it is converted to an integer
11156 * and applied as the ordinal value of a character.
11157 * @param int $offset The optional offset parameter allows you to specify which
11158 * character in haystack to start searching. The position returned is still
11159 * relative to the beginning of haystack.
11160 * @return bool If needle is not found, stripos() will return boolean false.
11162 function stripos($haystack, $needle, $offset = 0)
11164 if (function_exists('stripos'))
11166 return stripos($haystack, $needle, $offset);
11170 if (is_string($needle))
11172 $needle = strtolower($needle);
11174 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11176 $needle = strtolower(chr($needle));
11180 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11184 return strpos(strtolower($haystack), $needle, $offset);
11189 * Similar to parse_str()
11191 * Returns an associative array of name/value pairs, where the value is an
11192 * array of values that have used the same name
11196 * @param string $str The input string.
11199 function parse_str($str)
11202 $str = explode('&', $str);
11204 foreach ($str as $section)
11206 if (strpos($section, '=') !== false)
11208 list($name, $value) = explode('=', $section, 2);
11209 $return[urldecode($name)][] = urldecode($value);
11213 $return[urldecode($section)][] = null;
11221 * Detect XML encoding, as per XML 1.0 Appendix F.1
11223 * @todo Add support for EBCDIC
11224 * @param string $data XML data
11225 * @return array Possible encodings
11227 function xml_encoding($data)
11229 // UTF-32 Big Endian BOM
11230 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11232 $encoding[] = 'UTF-32BE';
11234 // UTF-32 Little Endian BOM
11235 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11237 $encoding[] = 'UTF-32LE';
11239 // UTF-16 Big Endian BOM
11240 elseif (substr($data, 0, 2) === "\xFE\xFF")
11242 $encoding[] = 'UTF-16BE';
11244 // UTF-16 Little Endian BOM
11245 elseif (substr($data, 0, 2) === "\xFF\xFE")
11247 $encoding[] = 'UTF-16LE';
11250 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11252 $encoding[] = 'UTF-8';
11254 // UTF-32 Big Endian Without BOM
11255 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")
11257 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11259 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11260 if ($parser->parse())
11262 $encoding[] = $parser->encoding;
11265 $encoding[] = 'UTF-32BE';
11267 // UTF-32 Little Endian Without BOM
11268 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")
11270 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11272 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11273 if ($parser->parse())
11275 $encoding[] = $parser->encoding;
11278 $encoding[] = 'UTF-32LE';
11280 // UTF-16 Big Endian Without BOM
11281 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11283 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11285 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11286 if ($parser->parse())
11288 $encoding[] = $parser->encoding;
11291 $encoding[] = 'UTF-16BE';
11293 // UTF-16 Little Endian Without BOM
11294 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11296 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11298 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11299 if ($parser->parse())
11301 $encoding[] = $parser->encoding;
11304 $encoding[] = 'UTF-16LE';
11306 // US-ASCII (or superset)
11307 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11309 if ($pos = strpos($data, "\x3F\x3E"))
11311 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11312 if ($parser->parse())
11314 $encoding[] = $parser->encoding;
11317 $encoding[] = 'UTF-8';
11319 // Fallback to UTF-8
11322 $encoding[] = 'UTF-8';
11327 function output_javascript()
11329 if (function_exists('ob_gzhandler'))
11331 ob_start('ob_gzhandler');
11333 header('Content-type: text/javascript; charset: UTF-8');
11334 header('Cache-Control: must-revalidate');
11335 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11337 function embed_odeo(link) {
11338 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>');
11341 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11342 if (placeholder != '') {
11343 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>');
11346 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>');
11350 function embed_flash(bgcolor, width, height, link, loop, type) {
11351 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>');
11354 function embed_flv(width, height, link, placeholder, loop, player) {
11355 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>');
11358 function embed_wmedia(width, height, link) {
11359 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11366 * Decode HTML Entities
11368 * This implements HTML5 as of revision 967 (2007-06-28)
11370 * @package SimplePie
11372 class SimplePie_Decode_HTML_Entities
11375 * Data to be parsed
11383 * Currently consumed bytes
11388 var $consumed = '';
11391 * Position of the current byte being parsed
11399 * Create an instance of the class with the input data
11402 * @param string $data Input data
11404 function SimplePie_Decode_HTML_Entities($data)
11406 $this->data = $data;
11410 * Parse the input data
11413 * @return string Output data
11417 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11421 $this->consumed = '';
11423 return $this->data;
11427 * Consume the next byte
11430 * @return mixed The next byte, or false, if there is no more data
11434 if (isset($this->data[$this->position]))
11436 $this->consumed .= $this->data[$this->position];
11437 return $this->data[$this->position++];
11446 * Consume a range of characters
11449 * @param string $chars Characters to consume
11450 * @return mixed A series of characters that match the range, or false
11452 function consume_range($chars)
11454 if ($len = strspn($this->data, $chars, $this->position))
11456 $data = substr($this->data, $this->position, $len);
11457 $this->consumed .= $data;
11458 $this->position += $len;
11468 * Unconsume one byte
11472 function unconsume()
11474 $this->consumed = substr($this->consumed, 0, -1);
11485 switch ($this->consume())
11499 switch ($this->consume())
11503 $range = '0123456789ABCDEFabcdef';
11508 $range = '0123456789';
11510 $this->unconsume();
11514 if ($codepoint = $this->consume_range($range))
11516 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");
11520 $codepoint = hexdec($codepoint);
11524 $codepoint = intval($codepoint);
11527 if (isset($windows_1252_specials[$codepoint]))
11529 $replacement = $windows_1252_specials[$codepoint];
11533 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11536 if (!in_array($this->consume(), array(';', false), true))
11538 $this->unconsume();
11541 $consumed_length = strlen($this->consumed);
11542 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11543 $this->position += strlen($replacement) - $consumed_length;
11548 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");
11550 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11552 $consumed = substr($this->consumed, 1);
11553 if (isset($entities[$consumed]))
11555 $match = $consumed;
11559 if ($match !== null)
11561 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11562 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11570 * IRI parser/serialiser
11572 * @package SimplePie
11574 class SimplePie_IRI
11633 * Whether the object represents a valid IRI
11638 var $valid = array();
11641 * Return the entire IRI when you try and read the object as a string
11646 function __toString()
11648 return $this->get_iri();
11652 * Create a new IRI object, from a specified string
11655 * @param string $iri
11656 * @return SimplePie_IRI
11658 function SimplePie_IRI($iri)
11660 $iri = (string) $iri;
11663 $parsed = $this->parse_iri($iri);
11664 $this->set_scheme($parsed['scheme']);
11665 $this->set_authority($parsed['authority']);
11666 $this->set_path($parsed['path']);
11667 $this->set_query($parsed['query']);
11668 $this->set_fragment($parsed['fragment']);
11673 * Create a new IRI object by resolving a relative IRI
11677 * @param SimplePie_IRI $base Base IRI
11678 * @param string $relative Relative IRI
11679 * @return SimplePie_IRI
11681 function absolutize($base, $relative)
11683 $relative = (string) $relative;
11684 if ($relative !== '')
11686 $relative =& new SimplePie_IRI($relative);
11687 if ($relative->get_scheme() !== null)
11689 $target = $relative;
11691 elseif ($base->get_iri() !== null)
11693 if ($relative->get_authority() !== null)
11695 $target = $relative;
11696 $target->set_scheme($base->get_scheme());
11700 $target =& new SimplePie_IRI('');
11701 $target->set_scheme($base->get_scheme());
11702 $target->set_userinfo($base->get_userinfo());
11703 $target->set_host($base->get_host());
11704 $target->set_port($base->get_port());
11705 if ($relative->get_path() !== null)
11707 if (strpos($relative->get_path(), '/') === 0)
11709 $target->set_path($relative->get_path());
11711 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11713 $target->set_path('/' . $relative->get_path());
11715 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11717 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11721 $target->set_path($relative->get_path());
11723 $target->set_query($relative->get_query());
11727 $target->set_path($base->get_path());
11728 if ($relative->get_query() !== null)
11730 $target->set_query($relative->get_query());
11732 elseif ($base->get_query() !== null)
11734 $target->set_query($base->get_query());
11738 $target->set_fragment($relative->get_fragment());
11742 // No base URL, just return the relative URL
11743 $target = $relative;
11754 * Parse an IRI into scheme/authority/path/query/fragment segments
11757 * @param string $iri
11760 function parse_iri($iri)
11762 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11763 for ($i = count($match); $i <= 9; $i++)
11767 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11771 * Remove dot segments from a path
11774 * @param string $input
11777 function remove_dot_segments($input)
11780 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11782 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11783 if (strpos($input, '../') === 0)
11785 $input = substr($input, 3);
11787 elseif (strpos($input, './') === 0)
11789 $input = substr($input, 2);
11791 // 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,
11792 elseif (strpos($input, '/./') === 0)
11794 $input = substr_replace($input, '/', 0, 3);
11796 elseif ($input === '/.')
11800 // 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,
11801 elseif (strpos($input, '/../') === 0)
11803 $input = substr_replace($input, '/', 0, 4);
11804 $output = substr_replace($output, '', strrpos($output, '/'));
11806 elseif ($input === '/..')
11809 $output = substr_replace($output, '', strrpos($output, '/'));
11811 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11812 elseif ($input === '.' || $input === '..')
11816 // 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
11817 elseif (($pos = strpos($input, '/', 1)) !== false)
11819 $output .= substr($input, 0, $pos);
11820 $input = substr_replace($input, '', 0, $pos);
11828 return $output . $input;
11832 * Replace invalid character with percent encoding
11835 * @param string $string Input string
11836 * @param string $valid_chars Valid characters
11837 * @param int $case Normalise case
11840 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11843 if ($case & SIMPLEPIE_LOWERCASE)
11845 $string = strtolower($string);
11847 elseif ($case & SIMPLEPIE_UPPERCASE)
11849 $string = strtoupper($string);
11852 // Store position and string length (to avoid constantly recalculating this)
11854 $strlen = strlen($string);
11856 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11857 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11859 // If we have a % character
11860 if ($string[$position] === '%')
11862 // If we have a pct-encoded section
11863 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11865 // Get the the represented character
11866 $chr = chr(hexdec(substr($string, $position + 1, 2)));
11868 // If the character is valid, replace the pct-encoded with the actual character while normalising case
11869 if (strpos($valid_chars, $chr) !== false)
11871 if ($case & SIMPLEPIE_LOWERCASE)
11873 $chr = strtolower($chr);
11875 elseif ($case & SIMPLEPIE_UPPERCASE)
11877 $chr = strtoupper($chr);
11879 $string = substr_replace($string, $chr, $position, 3);
11884 // Otherwise just normalise the pct-encoded to uppercase
11887 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11891 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11894 $string = substr_replace($string, '%25', $position, 1);
11899 // If we have an invalid character, change into its pct-encoded form
11902 $replacement = sprintf("%%%02X", ord($string[$position]));
11903 $string = str_replace($string[$position], $replacement, $string);
11904 $strlen = strlen($string);
11911 * Check if the object represents a valid IRI
11916 function is_valid()
11918 return array_sum($this->valid) === count($this->valid);
11922 * Set the scheme. Returns true on success, false on failure (if there are
11923 * any invalid characters).
11926 * @param string $scheme
11929 function set_scheme($scheme)
11931 if ($scheme === null || $scheme === '')
11933 $this->scheme = null;
11937 $len = strlen($scheme);
11941 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11943 $this->scheme = null;
11944 $this->valid[__FUNCTION__] = false;
11949 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11951 $this->scheme = null;
11952 $this->valid[__FUNCTION__] = false;
11956 $this->scheme = strtolower($scheme);
11958 $this->valid[__FUNCTION__] = true;
11963 * Set the authority. Returns true on success, false on failure (if there are
11964 * any invalid characters).
11967 * @param string $authority
11970 function set_authority($authority)
11972 if (($userinfo_end = strrpos($authority, '@')) !== false)
11974 $userinfo = substr($authority, 0, $userinfo_end);
11975 $authority = substr($authority, $userinfo_end + 1);
11982 if (($port_start = strpos($authority, ':')) !== false)
11984 $port = substr($authority, $port_start + 1);
11985 $authority = substr($authority, 0, $port_start);
11992 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
11996 * Set the userinfo.
11999 * @param string $userinfo
12002 function set_userinfo($userinfo)
12004 if ($userinfo === null || $userinfo === '')
12006 $this->userinfo = null;
12010 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12012 $this->valid[__FUNCTION__] = true;
12017 * Set the host. Returns true on success, false on failure (if there are
12018 * any invalid characters).
12021 * @param string $host
12024 function set_host($host)
12026 if ($host === null || $host === '')
12028 $this->host = null;
12029 $this->valid[__FUNCTION__] = true;
12032 elseif ($host[0] === '[' && substr($host, -1) === ']')
12034 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12036 $this->host = $host;
12037 $this->valid[__FUNCTION__] = true;
12042 $this->host = null;
12043 $this->valid[__FUNCTION__] = false;
12049 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12050 $this->valid[__FUNCTION__] = true;
12056 * Set the port. Returns true on success, false on failure (if there are
12057 * any invalid characters).
12060 * @param string $port
12063 function set_port($port)
12065 if ($port === null || $port === '')
12067 $this->port = null;
12068 $this->valid[__FUNCTION__] = true;
12071 elseif (strspn($port, '0123456789') === strlen($port))
12073 $this->port = (int) $port;
12074 $this->valid[__FUNCTION__] = true;
12079 $this->port = null;
12080 $this->valid[__FUNCTION__] = false;
12089 * @param string $path
12092 function set_path($path)
12094 if ($path === null || $path === '')
12096 $this->path = null;
12097 $this->valid[__FUNCTION__] = true;
12100 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12102 $this->path = null;
12103 $this->valid[__FUNCTION__] = false;
12108 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12109 if ($this->scheme !== null)
12111 $this->path = $this->remove_dot_segments($this->path);
12113 $this->valid[__FUNCTION__] = true;
12122 * @param string $query
12125 function set_query($query)
12127 if ($query === null || $query === '')
12129 $this->query = null;
12133 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12135 $this->valid[__FUNCTION__] = true;
12140 * Set the fragment.
12143 * @param string $fragment
12146 function set_fragment($fragment)
12148 if ($fragment === null || $fragment === '')
12150 $this->fragment = null;
12154 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12156 $this->valid[__FUNCTION__] = true;
12161 * Get the complete IRI
12169 if ($this->scheme !== null)
12171 $iri .= $this->scheme . ':';
12173 if (($authority = $this->get_authority()) !== null)
12175 $iri .= '//' . $authority;
12177 if ($this->path !== null)
12179 $iri .= $this->path;
12181 if ($this->query !== null)
12183 $iri .= '?' . $this->query;
12185 if ($this->fragment !== null)
12187 $iri .= '#' . $this->fragment;
12206 function get_scheme()
12208 return $this->scheme;
12212 * Get the complete authority
12217 function get_authority()
12220 if ($this->userinfo !== null)
12222 $authority .= $this->userinfo . '@';
12224 if ($this->host !== null)
12226 $authority .= $this->host;
12228 if ($this->port !== null)
12230 $authority .= ':' . $this->port;
12233 if ($authority !== '')
12244 * Get the user information
12249 function get_userinfo()
12251 return $this->userinfo;
12260 function get_host()
12262 return $this->host;
12271 function get_port()
12273 return $this->port;
12282 function get_path()
12284 return $this->path;
12293 function get_query()
12295 return $this->query;
12304 function get_fragment()
12306 return $this->fragment;
12311 * Class to validate and to work with IPv6 addresses.
12313 * @package SimplePie
12314 * @copyright 2003-2005 The PHP Group
12315 * @license http://www.opensource.org/licenses/bsd-license.php
12316 * @link http://pear.php.net/package/Net_IPv6
12317 * @author Alexander Merz <alexander.merz@web.de>
12318 * @author elfrink at introweb dot nl
12319 * @author Josh Peck <jmp at joshpeck dot org>
12320 * @author Geoffrey Sneddon <geoffers@gmail.com>
12322 class SimplePie_Net_IPv6
12325 * Removes a possible existing netmask specification of an IP address.
12327 * @param string $ip the (compressed) IP as Hex representation
12328 * @return string the IP the without netmask
12333 function removeNetmaskSpec($ip)
12335 if (strpos($ip, '/') !== false)
12337 list($addr, $nm) = explode('/', $ip);
12347 * Uncompresses an IPv6 address
12349 * RFC 2373 allows you to compress zeros in an address to '::'. This
12350 * function expects an valid IPv6 address and expands the '::' to
12351 * the required zeros.
12353 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12354 * ::1 -> 0:0:0:0:0:0:0:1
12358 * @param string $ip a valid IPv6-address (hex format)
12359 * @return string the uncompressed IPv6-address (hex format)
12361 function Uncompress($ip)
12363 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12366 if (strpos($ip, '::') !== false)
12368 list($ip1, $ip2) = explode('::', $ip);
12376 if (($pos = substr_count($ip1, ':')) > 0)
12392 if (($pos = substr_count($ip2, ':')) > 0)
12401 if (strstr($ip2, '.'))
12406 if ($c1 === -1 && $c2 === -1)
12408 $uip = '0:0:0:0:0:0:0:0';
12411 else if ($c1 === -1)
12413 $fill = str_repeat('0:', 7 - $c2);
12414 $uip = str_replace('::', $fill, $uip);
12417 else if ($c2 === -1)
12419 $fill = str_repeat(':0', 7 - $c1);
12420 $uip = str_replace('::', $fill, $uip);
12425 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12426 $uip = str_replace('::', $fill, $uip);
12427 $uip = str_replace('::', ':', $uip);
12434 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12436 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12437 * an IPv4 compatible address
12439 * Example: 0:0:0:0:0:0:13.1.68.3
12440 * 0:0:0:0:0:FFFF:129.144.52.38
12444 * @param string $ip a valid IPv6-address (hex format)
12445 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12447 function SplitV64($ip)
12449 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12450 if (strstr($ip, '.'))
12452 $pos = strrpos($ip, ':');
12454 $ipPart = explode('_', $ip);
12459 return array($ip, '');
12464 * Checks an IPv6 address
12466 * Checks if the given IP is IPv6-compatible
12470 * @param string $ip a valid IPv6-address
12471 * @return bool true if $ip is an IPv6 address
12473 function checkIPv6($ip)
12475 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12477 if (!empty($ipPart[0]))
12479 $ipv6 = explode(':', $ipPart[0]);
12480 for ($i = 0; $i < count($ipv6); $i++)
12482 $dec = hexdec($ipv6[$i]);
12483 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12484 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12493 elseif ($count === 6 && !empty($ipPart[1]))
12495 $ipv4 = explode('.', $ipPart[1]);
12497 foreach ($ipv4 as $ipv4_part)
12499 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12525 * @package SimplePie
12527 class SimplePie_Parse_Date
12532 * @access protected
12538 * List of days, calendar day name => ordinal day number in the week
12540 * @access protected
12603 'keskiviikko' => 3,
12627 * List of months, calendar month name => calendar month number
12629 * @access protected
12632 var $month = array(
12643 // No long form of May
12772 * List of timezones, abbreviation => offset from UTC
12774 * @access protected
12777 var $timezone = array(
12980 * Cached PCRE for SimplePie_Parse_Date::$day
12982 * @access protected
12988 * Cached PCRE for SimplePie_Parse_Date::$month
12990 * @access protected
12996 * Array of user-added callback methods
13001 var $built_in = array();
13004 * Array of user-added callback methods
13009 var $user = array();
13012 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13013 * self::month_pcre, and self::built_in
13017 function SimplePie_Parse_Date()
13019 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13020 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13023 if (!isset($cache[get_class($this)]))
13025 $all_methods = get_class_methods($this);
13027 foreach ($all_methods as $method)
13029 if (strtolower(substr($method, 0, 5)) === 'date_')
13031 $cache[get_class($this)][] = $method;
13036 foreach ($cache[get_class($this)] as $method)
13038 $this->built_in[] = $method;
13052 $object =& new SimplePie_Parse_Date;
13062 * @param string $date Date to parse
13063 * @return int Timestamp corresponding to date string, or false on failure
13065 function parse($date)
13067 foreach ($this->user as $method)
13069 if (($returned = call_user_func($method, $date)) !== false)
13075 foreach ($this->built_in as $method)
13077 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13087 * Add a callback method to parse a date
13091 * @param callback $callback
13093 function add_callback($callback)
13095 if (is_callable($callback))
13097 $this->user[] = $callback;
13101 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13106 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13107 * well as allowing any of upper or lower case "T", horizontal tabs, or
13108 * spaces to be used as the time seperator (including more than one))
13110 * @access protected
13111 * @return int Timestamp
13113 function date_w3cdtf($date)
13118 $year = '([0-9]{4})';
13119 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13120 $decimal = '([0-9]*)';
13121 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13122 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13124 if (preg_match($pcre, $date, $match))
13127 Capturing subpatterns:
13134 7: Decimal fraction of a second
13138 11: Timezone minutes
13141 // Fill in empty matches
13142 for ($i = count($match); $i <= 3; $i++)
13147 for ($i = count($match); $i <= 7; $i++)
13152 // Numeric timezone
13153 if (isset($match[9]) && $match[9] !== '')
13155 $timezone = $match[10] * 3600;
13156 $timezone += $match[11] * 60;
13157 if ($match[9] === '-')
13159 $timezone = 0 - $timezone;
13167 // Convert the number of seconds to an integer, taking decimals into account
13168 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13170 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13179 * Remove RFC822 comments
13181 * @access protected
13182 * @param string $data Data to strip comments from
13183 * @return string Comment stripped string
13185 function remove_rfc2822_comments($string)
13187 $string = (string) $string;
13189 $length = strlen($string);
13194 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13196 $output .= substr($string, $position, $pos - $position);
13197 $position = $pos + 1;
13198 if ($string[$pos - 1] !== '\\')
13201 while ($depth && $position < $length)
13203 $position += strcspn($string, '()', $position);
13204 if ($string[$position - 1] === '\\')
13209 elseif (isset($string[$position]))
13211 switch ($string[$position])
13234 $output .= substr($string, $position);
13240 * Parse RFC2822's date format
13242 * @access protected
13243 * @return int Timestamp
13245 function date_rfc2822($date)
13250 $wsp = '[\x09\x20]';
13251 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13252 $optional_fws = $fws . '?';
13253 $day_name = $this->day_pcre;
13254 $month = $this->month_pcre;
13255 $day = '([0-9]{1,2})';
13256 $hour = $minute = $second = '([0-9]{2})';
13257 $year = '([0-9]{2,4})';
13258 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13259 $character_zone = '([A-Z]{1,5})';
13260 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13261 $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';
13263 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13266 Capturing subpatterns:
13276 10: Timezone minutes
13277 11: Alphabetic timezone
13280 // Find the month number
13281 $month = $this->month[strtolower($match[3])];
13283 // Numeric timezone
13284 if ($match[8] !== '')
13286 $timezone = $match[9] * 3600;
13287 $timezone += $match[10] * 60;
13288 if ($match[8] === '-')
13290 $timezone = 0 - $timezone;
13293 // Character timezone
13294 elseif (isset($this->timezone[strtoupper($match[11])]))
13296 $timezone = $this->timezone[strtoupper($match[11])];
13298 // Assume everything else to be -0000
13304 // Deal with 2/3 digit years
13305 if ($match[4] < 50)
13309 elseif ($match[4] < 1000)
13314 // Second is optional, if it is empty set it to zero
13315 if ($match[7] !== '')
13317 $second = $match[7];
13324 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13333 * Parse RFC850's date format
13335 * @access protected
13336 * @return int Timestamp
13338 function date_rfc850($date)
13343 $space = '[\x09\x20]+';
13344 $day_name = $this->day_pcre;
13345 $month = $this->month_pcre;
13346 $day = '([0-9]{1,2})';
13347 $year = $hour = $minute = $second = '([0-9]{2})';
13348 $zone = '([A-Z]{1,5})';
13349 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13351 if (preg_match($pcre, $date, $match))
13354 Capturing subpatterns:
13366 $month = $this->month[strtolower($match[3])];
13368 // Character timezone
13369 if (isset($this->timezone[strtoupper($match[8])]))
13371 $timezone = $this->timezone[strtoupper($match[8])];
13373 // Assume everything else to be -0000
13379 // Deal with 2 digit year
13380 if ($match[4] < 50)
13389 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13398 * Parse C99's asctime()'s date format
13400 * @access protected
13401 * @return int Timestamp
13403 function date_asctime($date)
13408 $space = '[\x09\x20]+';
13409 $wday_name = $this->day_pcre;
13410 $mon_name = $this->month_pcre;
13411 $day = '([0-9]{1,2})';
13412 $hour = $sec = $min = '([0-9]{2})';
13413 $year = '([0-9]{4})';
13414 $terminator = '\x0A?\x00?';
13415 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13417 if (preg_match($pcre, $date, $match))
13420 Capturing subpatterns:
13430 $month = $this->month[strtolower($match[2])];
13431 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13440 * Parse dates using strtotime()
13442 * @access protected
13443 * @return int Timestamp
13445 function date_strtotime($date)
13447 $strtotime = strtotime($date);
13448 if ($strtotime === -1 || $strtotime === false)
13460 * Content-type sniffing
13462 * @package SimplePie
13464 class SimplePie_Content_Type_Sniffer
13469 * @var SimplePie_File
13475 * Create an instance of the class with the input file
13478 * @param SimplePie_Content_Type_Sniffer $file Input file
13480 function SimplePie_Content_Type_Sniffer($file)
13482 $this->file = $file;
13486 * Get the Content-Type of the specified file
13489 * @return string Actual Content-Type
13491 function get_type()
13493 if (isset($this->file->headers['content-type']))
13495 if (!isset($this->file->headers['content-encoding'])
13496 && ($this->file->headers['content-type'] === 'text/plain'
13497 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13498 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13500 return $this->text_or_binary();
13503 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13505 $official = substr($this->file->headers['content-type'], 0, $pos);
13509 $official = $this->file->headers['content-type'];
13511 $official = strtolower($official);
13513 if ($official === 'unknown/unknown'
13514 || $official === 'application/unknown')
13516 return $this->unknown();
13518 elseif (substr($official, -4) === '+xml'
13519 || $official === 'text/xml'
13520 || $official === 'application/xml')
13524 elseif (substr($official, 0, 6) === 'image/')
13526 if ($return = $this->image())
13535 elseif ($official === 'text/html')
13537 return $this->feed_or_html();
13546 return $this->unknown();
13551 * Sniff text or binary
13554 * @return string Actual Content-Type
13556 function text_or_binary()
13558 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13559 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13560 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13561 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13563 return 'text/plain';
13565 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13567 return 'application/octect-stream';
13571 return 'text/plain';
13579 * @return string Actual Content-Type
13583 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13584 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13585 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13586 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13588 return 'text/html';
13590 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13592 return 'application/pdf';
13594 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13596 return 'application/postscript';
13598 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13599 || substr($this->file->body, 0, 6) === 'GIF89a')
13601 return 'image/gif';
13603 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13605 return 'image/png';
13607 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13609 return 'image/jpeg';
13611 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13613 return 'image/bmp';
13617 return $this->text_or_binary();
13625 * @return string Actual Content-Type
13629 if (substr($this->file->body, 0, 6) === 'GIF87a'
13630 || substr($this->file->body, 0, 6) === 'GIF89a')
13632 return 'image/gif';
13634 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13636 return 'image/png';
13638 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13640 return 'image/jpeg';
13642 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13644 return 'image/bmp';
13656 * @return string Actual Content-Type
13658 function feed_or_html()
13660 $len = strlen($this->file->body);
13661 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13663 while ($pos < $len)
13665 switch ($this->file->body[$pos])
13671 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13679 return 'text/html';
13682 if (substr($this->file->body, $pos, 3) === '!--')
13685 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13691 return 'text/html';
13694 elseif (substr($this->file->body, $pos, 1) === '!')
13696 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13702 return 'text/html';
13705 elseif (substr($this->file->body, $pos, 1) === '?')
13707 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13713 return 'text/html';
13716 elseif (substr($this->file->body, $pos, 3) === 'rss'
13717 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13719 return 'application/rss+xml';
13721 elseif (substr($this->file->body, $pos, 4) === 'feed')
13723 return 'application/atom+xml';
13727 return 'text/html';
13731 return 'text/html';
13736 * Parses the XML Declaration
13738 * @package SimplePie
13740 class SimplePie_XML_Declaration_Parser
13748 var $version = '1.0';
13756 var $encoding = 'UTF-8';
13764 var $standalone = false;
13767 * Current state of the state machine
13772 var $state = 'before_version_name';
13783 * Input data length (to avoid calling strlen() everytime this is needed)
13788 var $data_length = 0;
13791 * Current position of the pointer
13799 * Create an instance of the class with the input data
13802 * @param string $data Input data
13804 function SimplePie_XML_Declaration_Parser($data)
13806 $this->data = $data;
13807 $this->data_length = strlen($this->data);
13811 * Parse the input data
13814 * @return bool true on success, false on failure
13818 while ($this->state && $this->state !== 'emit' && $this->has_data())
13820 $state = $this->state;
13824 if ($this->state === 'emit')
13830 $this->version = '';
13831 $this->encoding = '';
13832 $this->standalone = '';
13838 * Check whether there is data beyond the pointer
13841 * @return bool true if there is further data, false if not
13843 function has_data()
13845 return (bool) ($this->position < $this->data_length);
13849 * Advance past any whitespace
13851 * @return int Number of whitespace characters passed
13853 function skip_whitespace()
13855 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13856 $this->position += $whitespace;
13857 return $whitespace;
13863 function get_value()
13865 $quote = substr($this->data, $this->position, 1);
13866 if ($quote === '"' || $quote === "'")
13869 $len = strcspn($this->data, $quote, $this->position);
13870 if ($this->has_data())
13872 $value = substr($this->data, $this->position, $len);
13873 $this->position += $len + 1;
13880 function before_version_name()
13882 if ($this->skip_whitespace())
13884 $this->state = 'version_name';
13888 $this->state = false;
13892 function version_name()
13894 if (substr($this->data, $this->position, 7) === 'version')
13896 $this->position += 7;
13897 $this->skip_whitespace();
13898 $this->state = 'version_equals';
13902 $this->state = false;
13906 function version_equals()
13908 if (substr($this->data, $this->position, 1) === '=')
13911 $this->skip_whitespace();
13912 $this->state = 'version_value';
13916 $this->state = false;
13920 function version_value()
13922 if ($this->version = $this->get_value())
13924 $this->skip_whitespace();
13925 if ($this->has_data())
13927 $this->state = 'encoding_name';
13931 $this->state = 'emit';
13936 $this->state = 'standalone_name';
13940 function encoding_name()
13942 if (substr($this->data, $this->position, 8) === 'encoding')
13944 $this->position += 8;
13945 $this->skip_whitespace();
13946 $this->state = 'encoding_equals';
13950 $this->state = false;
13954 function encoding_equals()
13956 if (substr($this->data, $this->position, 1) === '=')
13959 $this->skip_whitespace();
13960 $this->state = 'encoding_value';
13964 $this->state = false;
13968 function encoding_value()
13970 if ($this->encoding = $this->get_value())
13972 $this->skip_whitespace();
13973 if ($this->has_data())
13975 $this->state = 'standalone_name';
13979 $this->state = 'emit';
13984 $this->state = false;
13988 function standalone_name()
13990 if (substr($this->data, $this->position, 10) === 'standalone')
13992 $this->position += 10;
13993 $this->skip_whitespace();
13994 $this->state = 'standalone_equals';
13998 $this->state = false;
14002 function standalone_equals()
14004 if (substr($this->data, $this->position, 1) === '=')
14007 $this->skip_whitespace();
14008 $this->state = 'standalone_value';
14012 $this->state = false;
14016 function standalone_value()
14018 if ($standalone = $this->get_value())
14020 switch ($standalone)
14023 $this->standalone = true;
14027 $this->standalone = false;
14031 $this->state = false;
14035 $this->skip_whitespace();
14036 if ($this->has_data())
14038 $this->state = false;
14042 $this->state = 'emit';
14047 $this->state = false;
14052 class SimplePie_Locator
14057 var $local = array();
14058 var $elsewhere = array();
14059 var $file_class = 'SimplePie_File';
14060 var $cached_entities = array();
14063 var $base_location = 0;
14064 var $checked_feeds = 0;
14065 var $max_checked_feeds = 10;
14066 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14068 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14070 $this->file =& $file;
14071 $this->file_class = $file_class;
14072 $this->useragent = $useragent;
14073 $this->timeout = $timeout;
14074 $this->max_checked_feeds = $max_checked_feeds;
14075 $this->content_type_sniffer_class = $content_type_sniffer_class;
14078 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14080 if ($this->is_feed($this->file))
14082 return $this->file;
14085 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14087 $sniffer =& new $this->content_type_sniffer_class($this->file);
14088 if ($sniffer->get_type() !== 'text/html')
14094 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14099 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14101 return $working[0];
14104 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14106 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14111 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14116 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14121 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14129 function is_feed(&$file)
14131 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14133 $sniffer =& new $this->content_type_sniffer_class($file);
14134 $sniffed = $sniffer->get_type();
14135 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14144 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14154 function get_base()
14156 $this->http_base = $this->file->url;
14157 $this->base = $this->http_base;
14158 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14159 foreach ($elements as $element)
14161 if ($element['attribs']['href']['data'] !== '')
14163 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14164 $this->base_location = $element['offset'];
14170 function autodiscovery()
14172 $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));
14175 foreach ($links as $link)
14177 if ($this->checked_feeds === $this->max_checked_feeds)
14181 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14183 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14185 if ($this->base_location < $link['offset'])
14187 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14191 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14194 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]))
14196 $this->checked_feeds++;
14197 $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14198 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))
14200 $feeds[$href] = $feed;
14207 if (!empty($feeds))
14209 return array_values($feeds);
14216 function get_links()
14218 $links = SimplePie_Misc::get_element('a', $this->file->body);
14219 foreach ($links as $link)
14221 if (isset($link['attribs']['href']['data']))
14223 $href = trim($link['attribs']['href']['data']);
14224 $parsed = SimplePie_Misc::parse_url($href);
14225 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14227 if ($this->base_location < $link['offset'])
14229 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14233 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14236 $current = SimplePie_Misc::parse_url($this->file->url);
14238 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14240 $this->local[] = $href;
14244 $this->elsewhere[] = $href;
14249 $this->local = array_unique($this->local);
14250 $this->elsewhere = array_unique($this->elsewhere);
14251 if (!empty($this->local) || !empty($this->elsewhere))
14258 function extension(&$array)
14260 foreach ($array as $key => $value)
14262 if ($this->checked_feeds === $this->max_checked_feeds)
14266 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14268 $this->checked_feeds++;
14269 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14270 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))
14276 unset($array[$key]);
14283 function body(&$array)
14285 foreach ($array as $key => $value)
14287 if ($this->checked_feeds === $this->max_checked_feeds)
14291 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14293 $this->checked_feeds++;
14294 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14295 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))
14301 unset($array[$key]);
14309 class SimplePie_Parser
14314 var $current_column;
14316 var $separator = ' ';
14317 var $namespace = array('');
14318 var $element = array('');
14319 var $xml_base = array('');
14320 var $xml_base_explicit = array(false);
14321 var $xml_lang = array('');
14322 var $data = array();
14323 var $datas = array(array());
14324 var $current_xhtml_construct = -1;
14327 function parse(&$data, $encoding)
14329 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14330 if (strtoupper($encoding) === 'US-ASCII')
14332 $this->encoding = 'UTF-8';
14336 $this->encoding = $encoding;
14340 // UTF-32 Big Endian BOM
14341 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14343 $data = substr($data, 4);
14345 // UTF-32 Little Endian BOM
14346 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14348 $data = substr($data, 4);
14350 // UTF-16 Big Endian BOM
14351 elseif (substr($data, 0, 2) === "\xFE\xFF")
14353 $data = substr($data, 2);
14355 // UTF-16 Little Endian BOM
14356 elseif (substr($data, 0, 2) === "\xFF\xFE")
14358 $data = substr($data, 2);
14361 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14363 $data = substr($data, 3);
14366 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14368 $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14369 if ($declaration->parse())
14371 $data = substr($data, $pos + 2);
14372 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14376 $this->error_string = 'SimplePie bug! Please report this!';
14383 static $xml_is_sane = null;
14384 if ($xml_is_sane === null)
14386 $parser_check = xml_parser_create();
14387 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
14388 xml_parser_free($parser_check);
14389 $xml_is_sane = isset($values[0]['value']);
14392 // Create the parser
14395 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14396 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14397 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14398 xml_set_object($xml, $this);
14399 xml_set_character_data_handler($xml, 'cdata');
14400 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14403 if (!xml_parse($xml, $data, true))
14405 $this->error_code = xml_get_error_code($xml);
14406 $this->error_string = xml_error_string($this->error_code);
14409 $this->current_line = xml_get_current_line_number($xml);
14410 $this->current_column = xml_get_current_column_number($xml);
14411 $this->current_byte = xml_get_current_byte_index($xml);
14412 xml_parser_free($xml);
14417 libxml_clear_errors();
14418 $xml =& new XMLReader();
14420 while (@$xml->read())
14422 switch ($xml->nodeType)
14425 case constant('XMLReader::END_ELEMENT'):
14426 if ($xml->namespaceURI !== '')
14428 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14432 $tagName = $xml->localName;
14434 $this->tag_close(null, $tagName);
14436 case constant('XMLReader::ELEMENT'):
14437 $empty = $xml->isEmptyElement;
14438 if ($xml->namespaceURI !== '')
14440 $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14444 $tagName = $xml->localName;
14446 $attributes = array();
14447 while ($xml->moveToNextAttribute())
14449 if ($xml->namespaceURI !== '')
14451 $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
14455 $attrName = $xml->localName;
14457 $attributes[$attrName] = $xml->value;
14459 $this->tag_open(null, $tagName, $attributes);
14462 $this->tag_close(null, $tagName);
14465 case constant('XMLReader::TEXT'):
14467 case constant('XMLReader::CDATA'):
14468 $this->cdata(null, $xml->value);
14472 if ($error = libxml_get_last_error())
14474 $this->error_code = $error->code;
14475 $this->error_string = $error->message;
14476 $this->current_line = $error->line;
14477 $this->current_column = $error->column;
14487 function get_error_code()
14489 return $this->error_code;
14492 function get_error_string()
14494 return $this->error_string;
14497 function get_current_line()
14499 return $this->current_line;
14502 function get_current_column()
14504 return $this->current_column;
14507 function get_current_byte()
14509 return $this->current_byte;
14512 function get_data()
14514 return $this->data;
14517 function tag_open($parser, $tag, $attributes)
14519 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14521 $attribs = array();
14522 foreach ($attributes as $name => $value)
14524 list($attrib_namespace, $attribute) = $this->split_ns($name);
14525 $attribs[$attrib_namespace][$attribute] = $value;
14528 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14530 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14531 $this->xml_base_explicit[] = true;
14535 $this->xml_base[] = end($this->xml_base);
14536 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14539 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14541 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14545 $this->xml_lang[] = end($this->xml_lang);
14548 if ($this->current_xhtml_construct >= 0)
14550 $this->current_xhtml_construct++;
14551 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14553 $this->data['data'] .= '<' . end($this->element);
14554 if (isset($attribs['']))
14556 foreach ($attribs[''] as $name => $value)
14558 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14561 $this->data['data'] .= '>';
14566 $this->datas[] =& $this->data;
14567 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14568 $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));
14569 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')
14570 || (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'))
14572 $this->current_xhtml_construct = 0;
14577 function cdata($parser, $cdata)
14579 if ($this->current_xhtml_construct >= 0)
14581 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14585 $this->data['data'] .= $cdata;
14589 function tag_close($parser, $tag)
14591 if ($this->current_xhtml_construct >= 0)
14593 $this->current_xhtml_construct--;
14594 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')))
14596 $this->data['data'] .= '</' . end($this->element) . '>';
14599 if ($this->current_xhtml_construct === -1)
14601 $this->data =& $this->datas[count($this->datas) - 1];
14602 array_pop($this->datas);
14605 array_pop($this->element);
14606 array_pop($this->namespace);
14607 array_pop($this->xml_base);
14608 array_pop($this->xml_base_explicit);
14609 array_pop($this->xml_lang);
14612 function split_ns($string)
14614 static $cache = array();
14615 if (!isset($cache[$string]))
14617 if ($pos = strpos($string, $this->separator))
14619 static $separator_length;
14620 if (!$separator_length)
14622 $separator_length = strlen($this->separator);
14624 $namespace = substr($string, 0, $pos);
14625 $local_name = substr($string, $pos + $separator_length);
14626 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14628 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14631 // Normalize the Media RSS namespaces
14632 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14634 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14636 $cache[$string] = array($namespace, $local_name);
14640 $cache[$string] = array('', $string);
14643 return $cache[$string];
14648 * @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
14650 class SimplePie_Sanitize
14656 var $remove_div = true;
14657 var $image_handler = '';
14658 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14659 var $encode_instead_of_strip = false;
14660 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14661 var $strip_comments = false;
14662 var $output_encoding = 'UTF-8';
14663 var $enable_cache = true;
14664 var $cache_location = './cache';
14665 var $cache_name_function = 'md5';
14666 var $cache_class = 'SimplePie_Cache';
14667 var $file_class = 'SimplePie_File';
14669 var $useragent = '';
14670 var $force_fsockopen = false;
14672 var $replace_url_attributes = array(
14675 'blockquote' => 'cite',
14677 'form' => 'action',
14678 'img' => array('longdesc', 'src'),
14684 function remove_div($enable = true)
14686 $this->remove_div = (bool) $enable;
14689 function set_image_handler($page = false)
14693 $this->image_handler = (string) $page;
14697 $this->image_handler = false;
14701 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14703 if (isset($enable_cache))
14705 $this->enable_cache = (bool) $enable_cache;
14708 if ($cache_location)
14710 $this->cache_location = (string) $cache_location;
14713 if ($cache_name_function)
14715 $this->cache_name_function = (string) $cache_name_function;
14720 $this->cache_class = (string) $cache_class;
14724 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14728 $this->file_class = (string) $file_class;
14733 $this->timeout = (string) $timeout;
14738 $this->useragent = (string) $useragent;
14741 if ($force_fsockopen)
14743 $this->force_fsockopen = (string) $force_fsockopen;
14747 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
14751 if (is_array($tags))
14753 $this->strip_htmltags = $tags;
14757 $this->strip_htmltags = explode(',', $tags);
14762 $this->strip_htmltags = false;
14766 function encode_instead_of_strip($encode = false)
14768 $this->encode_instead_of_strip = (bool) $encode;
14771 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14775 if (is_array($attribs))
14777 $this->strip_attributes = $attribs;
14781 $this->strip_attributes = explode(',', $attribs);
14786 $this->strip_attributes = false;
14790 function strip_comments($strip = false)
14792 $this->strip_comments = (bool) $strip;
14795 function set_output_encoding($encoding = 'UTF-8')
14797 $this->output_encoding = (string) $encoding;
14801 * Set element/attribute key/value pairs of HTML attributes
14802 * containing URLs that need to be resolved relative to the feed
14806 * @param array $element_attribute Element/attribute key/value pairs
14808 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'))
14810 $this->replace_url_attributes = (array) $element_attribute;
14813 function sanitize($data, $type, $base = '')
14815 $data = trim($data);
14816 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14818 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14820 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))
14822 $type |= SIMPLEPIE_CONSTRUCT_HTML;
14826 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14830 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14832 $data = base64_decode($data);
14835 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14837 if ($this->remove_div)
14839 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14840 $data = preg_replace('/<\/div>$/', '', $data);
14844 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14848 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14851 if ($this->strip_comments)
14853 $data = SimplePie_Misc::strip_comments($data);
14856 // Strip out HTML tags and attributes that might cause various security problems.
14857 // Based on recommendations by Mark Pilgrim at:
14858 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14859 if ($this->strip_htmltags)
14861 foreach ($this->strip_htmltags as $tag)
14863 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14864 while (preg_match($pcre, $data))
14866 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14871 if ($this->strip_attributes)
14873 foreach ($this->strip_attributes as $attrib)
14875 $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);
14879 // Replace relative URLs
14880 $this->base = $base;
14881 foreach ($this->replace_url_attributes as $element => $attributes)
14883 $data = $this->replace_urls($data, $element, $attributes);
14886 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14887 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14889 $images = SimplePie_Misc::get_element('img', $data);
14890 foreach ($images as $img)
14892 if (isset($img['attribs']['src']['data']))
14894 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14895 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14897 if ($cache->load())
14899 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14900 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14904 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14905 $headers = $file->headers;
14907 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14909 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14911 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14912 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14916 trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
14924 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14925 $data = trim($data);
14928 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14930 $data = SimplePie_Misc::absolutize_url($data, $base);
14933 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14935 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14938 if ($this->output_encoding !== 'UTF-8')
14940 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14946 function replace_urls($data, $tag, $attributes)
14948 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14950 $elements = SimplePie_Misc::get_element($tag, $data);
14951 foreach ($elements as $element)
14953 if (is_array($attributes))
14955 foreach ($attributes as $attribute)
14957 if (isset($element['attribs'][$attribute]['data']))
14959 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14960 $new_element = SimplePie_Misc::element_implode($element);
14961 $data = str_replace($element['full'], $new_element, $data);
14962 $element['full'] = $new_element;
14966 elseif (isset($element['attribs'][$attributes]['data']))
14968 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14969 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14976 function do_strip_htmltags($match)
14978 if ($this->encode_instead_of_strip)
14980 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14982 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
14983 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
14984 return "<$match[1]$match[2]>$match[3]</$match[1]>";
14988 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
14991 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))