5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
8 * Copyright (c) 2004-2011, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright notice, this list
18 * of conditions and the following disclaimer in the documentation and/or other materials
19 * provided with the distribution.
21 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * to endorse or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
37 * @copyright 2004-2011 Ryan Parman, Geoffrey Sneddon, Ryan McCue
39 * @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.1-dev');
60 define('SIMPLEPIE_BUILD', '20111015034325');
63 * SimplePie Website URL
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
69 * @see SimplePie::set_useragent()
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
80 * @see SimplePie::set_autodiscovery_level()
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
85 * Feed Link Element Autodiscovery
86 * @see SimplePie::set_autodiscovery_level()
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
91 * Local Feed Extension Autodiscovery
92 * @see SimplePie::set_autodiscovery_level()
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
97 * Local Feed Body Autodiscovery
98 * @see SimplePie::set_autodiscovery_level()
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
103 * Remote Feed Extension Autodiscovery
104 * @see SimplePie::set_autodiscovery_level()
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
109 * Remote Feed Body Autodiscovery
110 * @see SimplePie::set_autodiscovery_level()
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
115 * All Feed Autodiscovery
116 * @see SimplePie::set_autodiscovery_level()
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
123 define('SIMPLEPIE_TYPE_NONE', 0);
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
131 * RSS 0.91 (Netscape)
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
136 * RSS 0.91 (Userland)
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
141 * RSS 0.91 (both Netscape and Userland)
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
176 * Non-RDF-based RSS (truly intended as syndication format)
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
203 define('SIMPLEPIE_TYPE_ALL', 1023);
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
226 * base64-encoded construct
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
236 * A construct that might be HTML
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
248 define('SIMPLEPIE_SAME_CASE', 1);
251 * Change to lowercase
253 define('SIMPLEPIE_LOWERCASE', 2);
256 * Change to uppercase
258 define('SIMPLEPIE_UPPERCASE', 4);
261 * PCRE for HTML attributes
263 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
266 * PCRE for XML attributes
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
301 * RSS 1.0 Content Module Namespace
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
307 * (Stupid, I know, but I'm certain it will confuse people less with support.)
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
322 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
332 * Media RSS Namespace
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
337 * Wrong Media RSS Namespace
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
342 * iTunes RSS Namespace
344 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
349 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
352 * IANA Link Relations Registry
354 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
357 * Whether we're running on PHP5
359 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
364 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
369 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
374 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
377 * fsockopen() file source
379 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
384 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
387 * file_get_contents() file source
389 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
399 * @var array Raw data
405 * @var mixed Error string
411 * @var object Instance of SimplePie_Sanitize (or other class)
412 * @see SimplePie::set_sanitize_class()
418 * @var string SimplePie Useragent
419 * @see SimplePie::set_useragent()
422 var $useragent = SIMPLEPIE_USERAGENT;
425 * @var string Feed URL
426 * @see SimplePie::set_feed_url()
432 * @var object Instance of SimplePie_File to use as a feed
433 * @see SimplePie::set_file()
439 * @var string Raw feed data
440 * @see SimplePie::set_raw_data()
446 * @var int Timeout for fetching remote files
447 * @see SimplePie::set_timeout()
453 * @var bool Forces fsockopen() to be used for remote files instead
454 * of cURL, even if a new enough version is installed
455 * @see SimplePie::force_fsockopen()
458 var $force_fsockopen = false;
461 * @var bool Force the given data/URL to be treated as a feed no matter what
463 * @see SimplePie::force_feed()
466 var $force_feed = false;
469 * @var bool Enable/Disable XML dump
470 * @see SimplePie::enable_xml_dump()
473 var $xml_dump = false;
476 * @var bool Enable/Disable Caching
477 * @see SimplePie::enable_cache()
483 * @var int Cache duration (in seconds)
484 * @see SimplePie::set_cache_duration()
487 var $cache_duration = 3600;
490 * @var int Auto-discovery cache duration (in seconds)
491 * @see SimplePie::set_autodiscovery_cache_duration()
494 var $autodiscovery_cache_duration = 604800; // 7 Days.
497 * @var string Cache location (relative to executing script)
498 * @see SimplePie::set_cache_location()
501 var $cache_location = './cache';
504 * @var string Function that creates the cache filename
505 * @see SimplePie::set_cache_name_function()
508 var $cache_name_function = 'md5';
511 * @var bool Reorder feed by date descending
512 * @see SimplePie::enable_order_by_date()
515 var $order_by_date = true;
518 * @var mixed Force input encoding to be set to the follow value
519 * (false, or anything type-cast to false, disables this feature)
520 * @see SimplePie::set_input_encoding()
523 var $input_encoding = false;
526 * @var int Feed Autodiscovery Level
527 * @see SimplePie::set_autodiscovery_level()
530 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
533 * @var string Class used for caching feeds
534 * @see SimplePie::set_cache_class()
537 var $cache_class = 'SimplePie_Cache';
540 * @var string Class used for locating feeds
541 * @see SimplePie::set_locator_class()
544 var $locator_class = 'SimplePie_Locator';
547 * @var string Class used for parsing feeds
548 * @see SimplePie::set_parser_class()
551 var $parser_class = 'SimplePie_Parser';
554 * @var string Class used for fetching feeds
555 * @see SimplePie::set_file_class()
558 var $file_class = 'SimplePie_File';
561 * @var string Class used for items
562 * @see SimplePie::set_item_class()
565 var $item_class = 'SimplePie_Item';
568 * @var string Class used for authors
569 * @see SimplePie::set_author_class()
572 var $author_class = 'SimplePie_Author';
575 * @var string Class used for categories
576 * @see SimplePie::set_category_class()
579 var $category_class = 'SimplePie_Category';
582 * @var string Class used for enclosures
583 * @see SimplePie::set_enclosures_class()
586 var $enclosure_class = 'SimplePie_Enclosure';
589 * @var string Class used for Media RSS <media:text> captions
590 * @see SimplePie::set_caption_class()
593 var $caption_class = 'SimplePie_Caption';
596 * @var string Class used for Media RSS <media:copyright>
597 * @see SimplePie::set_copyright_class()
600 var $copyright_class = 'SimplePie_Copyright';
603 * @var string Class used for Media RSS <media:credit>
604 * @see SimplePie::set_credit_class()
607 var $credit_class = 'SimplePie_Credit';
610 * @var string Class used for Media RSS <media:rating>
611 * @see SimplePie::set_rating_class()
614 var $rating_class = 'SimplePie_Rating';
617 * @var string Class used for Media RSS <media:restriction>
618 * @see SimplePie::set_restriction_class()
621 var $restriction_class = 'SimplePie_Restriction';
624 * @var string Class used for content-type sniffing
625 * @see SimplePie::set_content_type_sniffer_class()
628 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
631 * @var string Class used for item sources.
632 * @see SimplePie::set_source_class()
635 var $source_class = 'SimplePie_Source';
638 * @var mixed Set javascript query string parameter (false, or
639 * anything type-cast to false, disables this feature)
640 * @see SimplePie::set_javascript()
643 var $javascript = 'js';
646 * @var int Maximum number of feeds to check with autodiscovery
647 * @see SimplePie::set_max_checked_feeds()
650 var $max_checked_feeds = 10;
653 * @var array All the feeds found during the autodiscovery process
654 * @see SimplePie::get_all_discovered_feeds()
657 var $all_discovered_feeds = array();
660 * @var string Web-accessible path to the handler_favicon.php file.
661 * @see SimplePie::set_favicon_handler()
664 var $favicon_handler = '';
667 * @var string Web-accessible path to the handler_image.php file.
668 * @see SimplePie::set_image_handler()
671 var $image_handler = '';
674 * @var array Stores the URLs when multiple feeds are being initialized.
675 * @see SimplePie::set_feed_url()
678 var $multifeed_url = array();
681 * @var array Stores SimplePie objects when multiple feeds initialized.
684 var $multifeed_objects = array();
687 * @var array Stores the get_object_vars() array for use with multifeeds.
688 * @see SimplePie::set_feed_url()
691 var $config_settings = null;
694 * @var integer Stores the number of items to return per-feed with multifeeds.
695 * @see SimplePie::set_item_limit()
701 * @var array Stores the default attributes to be stripped by strip_attributes().
702 * @see SimplePie::strip_attributes()
705 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
708 * @var array Stores the default tags to be stripped by strip_htmltags().
709 * @see SimplePie::strip_htmltags()
712 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
715 * The SimplePie class contains feed level data and options
717 * There are two ways that you can create a new SimplePie object. The first
718 * is by passing a feed URL as a parameter to the SimplePie constructor
719 * (as well as optionally setting the cache location and cache expiry). This
720 * will initialise the whole feed with all of the default settings, and you
721 * can begin accessing methods and properties immediately.
723 * The second way is to create the SimplePie object with no parameters
724 * at all. This will enable you to set configuration options. After setting
725 * them, you must initialise the feed using $feed->init(). At that point the
726 * object's methods and properties will be available to you. This format is
727 * what is used throughout this documentation.
730 * @since 1.0 Preview Release
731 * @param string $feed_url This is the URL you want to parse.
732 * @param string $cache_location This is where you want the cache to be stored.
733 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
735 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
737 // Other objects, instances created here so we can set options on them
738 $this->sanitize =& new SimplePie_Sanitize;
740 // Set options if they're passed to the constructor
741 if ($cache_location !== null)
743 $this->set_cache_location($cache_location);
746 if ($cache_duration !== null)
748 $this->set_cache_duration($cache_duration);
751 // Only init the script if we're passed a feed URL
752 if ($feed_url !== null)
754 $this->set_feed_url($feed_url);
760 * Used for converting object to a string
762 function __toString()
764 return md5(serialize($this->data));
768 * Remove items that link back to this before destroying this object
770 function __destruct()
772 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
774 if (!empty($this->data['items']))
776 foreach ($this->data['items'] as $item)
780 unset($item, $this->data['items']);
782 if (!empty($this->data['ordered_items']))
784 foreach ($this->data['ordered_items'] as $item)
788 unset($item, $this->data['ordered_items']);
794 * Force the given data/URL to be treated as a feed no matter what it
799 * @param bool $enable Force the given data/URL to be treated as a feed
801 function force_feed($enable = false)
803 $this->force_feed = (bool) $enable;
807 * This is the URL of the feed you want to parse.
809 * This allows you to enter the URL of the feed you want to parse, or the
810 * website you want to try to use auto-discovery on. This takes priority
811 * over any set raw data.
813 * You can set multiple feeds to mash together by passing an array instead
814 * of a string for the $url. Remember that with each additional feed comes
815 * additional processing and resources.
818 * @since 1.0 Preview Release
819 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
820 * @see SimplePie::set_raw_data()
822 function set_feed_url($url)
826 $this->multifeed_url = array();
827 foreach ($url as $value)
829 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
834 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
839 * Provides an instance of SimplePie_File to use as a feed
842 * @param object &$file Instance of SimplePie_File (or subclass)
843 * @return bool True on success, false on failure
845 function set_file(&$file)
847 if (is_a($file, 'SimplePie_File'))
849 $this->feed_url = $file->url;
850 $this->file =& $file;
857 * Allows you to use a string of RSS/Atom data instead of a remote feed.
859 * If you have a feed available as a string in PHP, you can tell SimplePie
860 * to parse that data string instead of a remote feed. Any set feed URL
865 * @param string $data RSS or Atom data as a string.
866 * @see SimplePie::set_feed_url()
868 function set_raw_data($data)
870 $this->raw_data = $data;
874 * Allows you to override the default timeout for fetching remote feeds.
876 * This allows you to change the maximum time the feed's server to respond
877 * and send the feed back.
881 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
883 function set_timeout($timeout = 10)
885 $this->timeout = (int) $timeout;
889 * Forces SimplePie to use fsockopen() instead of the preferred cURL
894 * @param bool $enable Force fsockopen() to be used
896 function force_fsockopen($enable = false)
898 $this->force_fsockopen = (bool) $enable;
902 * Outputs the raw XML content of the feed, after it has gone through
903 * SimplePie's filters.
905 * Used only for debugging, this function will output the XML content as
906 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
907 * before trying to parse it. Many parts of the feed are re-written in
908 * memory, and in the end, you have a parsable feed. XML dump shows you the
909 * actual XML that SimplePie tries to parse, which may or may not be very
910 * different from the original feed.
913 * @since 1.0 Preview Release
914 * @param bool $enable Enable XML dump
916 function enable_xml_dump($enable = false)
918 $this->xml_dump = (bool) $enable;
922 * Enables/disables caching in SimplePie.
924 * This option allows you to disable caching all-together in SimplePie.
925 * However, disabling the cache can lead to longer load times.
928 * @since 1.0 Preview Release
929 * @param bool $enable Enable caching
931 function enable_cache($enable = true)
933 $this->cache = (bool) $enable;
937 * Set the length of time (in seconds) that the contents of a feed
941 * @param int $seconds The feed content cache duration.
943 function set_cache_duration($seconds = 3600)
945 $this->cache_duration = (int) $seconds;
949 * Set the length of time (in seconds) that the autodiscovered feed
950 * URL will be cached.
953 * @param int $seconds The autodiscovered feed URL cache duration.
955 function set_autodiscovery_cache_duration($seconds = 604800)
957 $this->autodiscovery_cache_duration = (int) $seconds;
961 * Set the file system location where the cached files should be stored.
964 * @param string $location The file system location.
966 function set_cache_location($location = './cache')
968 $this->cache_location = (string) $location;
972 * Determines whether feed items should be sorted into reverse chronological order.
975 * @param bool $enable Sort as reverse chronological order.
977 function enable_order_by_date($enable = true)
979 $this->order_by_date = (bool) $enable;
983 * Allows you to override the character encoding reported by the feed.
986 * @param string $encoding Character encoding.
988 function set_input_encoding($encoding = false)
992 $this->input_encoding = (string) $encoding;
996 $this->input_encoding = false;
1001 * Set how much feed autodiscovery to do
1004 * @see SIMPLEPIE_LOCATOR_NONE
1005 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1006 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1007 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1008 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1009 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1010 * @see SIMPLEPIE_LOCATOR_ALL
1011 * @param int $level Feed Autodiscovery Level (level can be a
1012 * combination of the above constants, see bitwise OR operator)
1014 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1016 $this->autodiscovery = (int) $level;
1020 * Allows you to change which class SimplePie uses for caching.
1021 * Useful when you are overloading or extending SimplePie's default classes.
1024 * @param string $class Name of custom class.
1025 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1026 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1028 function set_cache_class($class = 'SimplePie_Cache')
1030 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1032 $this->cache_class = $class;
1039 * Allows you to change which class SimplePie uses for auto-discovery.
1040 * Useful when you are overloading or extending SimplePie's default classes.
1043 * @param string $class Name of custom class.
1044 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1045 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1047 function set_locator_class($class = 'SimplePie_Locator')
1049 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1051 $this->locator_class = $class;
1058 * Allows you to change which class SimplePie uses for XML parsing.
1059 * Useful when you are overloading or extending SimplePie's default classes.
1062 * @param string $class Name of custom class.
1063 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1064 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1066 function set_parser_class($class = 'SimplePie_Parser')
1068 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1070 $this->parser_class = $class;
1077 * Allows you to change which class SimplePie uses for remote file fetching.
1078 * Useful when you are overloading or extending SimplePie's default classes.
1081 * @param string $class Name of custom class.
1082 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1083 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1085 function set_file_class($class = 'SimplePie_File')
1087 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1089 $this->file_class = $class;
1096 * Allows you to change which class SimplePie uses for data sanitization.
1097 * Useful when you are overloading or extending SimplePie's default classes.
1100 * @param string $class Name of custom class.
1101 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1102 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1104 function set_sanitize_class($class = 'SimplePie_Sanitize')
1106 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1108 $this->sanitize =& new $class;
1115 * Allows you to change which class SimplePie uses for handling feed items.
1116 * Useful when you are overloading or extending SimplePie's default classes.
1119 * @param string $class Name of custom class.
1120 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1121 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1123 function set_item_class($class = 'SimplePie_Item')
1125 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1127 $this->item_class = $class;
1134 * Allows you to change which class SimplePie uses for handling author data.
1135 * Useful when you are overloading or extending SimplePie's default classes.
1138 * @param string $class Name of custom class.
1139 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1140 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1142 function set_author_class($class = 'SimplePie_Author')
1144 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1146 $this->author_class = $class;
1153 * Allows you to change which class SimplePie uses for handling category data.
1154 * Useful when you are overloading or extending SimplePie's default classes.
1157 * @param string $class Name of custom class.
1158 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1159 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1161 function set_category_class($class = 'SimplePie_Category')
1163 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1165 $this->category_class = $class;
1172 * Allows you to change which class SimplePie uses for feed enclosures.
1173 * Useful when you are overloading or extending SimplePie's default classes.
1176 * @param string $class Name of custom class.
1177 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1178 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1180 function set_enclosure_class($class = 'SimplePie_Enclosure')
1182 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1184 $this->enclosure_class = $class;
1191 * Allows you to change which class SimplePie uses for <media:text> captions
1192 * Useful when you are overloading or extending SimplePie's default classes.
1195 * @param string $class Name of custom class.
1196 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1197 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1199 function set_caption_class($class = 'SimplePie_Caption')
1201 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1203 $this->caption_class = $class;
1210 * Allows you to change which class SimplePie uses for <media:copyright>
1211 * Useful when you are overloading or extending SimplePie's default classes.
1214 * @param string $class Name of custom class.
1215 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1216 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1218 function set_copyright_class($class = 'SimplePie_Copyright')
1220 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1222 $this->copyright_class = $class;
1229 * Allows you to change which class SimplePie uses for <media:credit>
1230 * Useful when you are overloading or extending SimplePie's default classes.
1233 * @param string $class Name of custom class.
1234 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1235 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1237 function set_credit_class($class = 'SimplePie_Credit')
1239 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1241 $this->credit_class = $class;
1248 * Allows you to change which class SimplePie uses for <media:rating>
1249 * Useful when you are overloading or extending SimplePie's default classes.
1252 * @param string $class Name of custom class.
1253 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1254 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1256 function set_rating_class($class = 'SimplePie_Rating')
1258 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1260 $this->rating_class = $class;
1267 * Allows you to change which class SimplePie uses for <media:restriction>
1268 * Useful when you are overloading or extending SimplePie's default classes.
1271 * @param string $class Name of custom class.
1272 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1273 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1275 function set_restriction_class($class = 'SimplePie_Restriction')
1277 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1279 $this->restriction_class = $class;
1286 * Allows you to change which class SimplePie uses for content-type sniffing.
1287 * Useful when you are overloading or extending SimplePie's default classes.
1290 * @param string $class Name of custom class.
1291 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1292 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1294 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1296 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1298 $this->content_type_sniffer_class = $class;
1305 * Allows you to change which class SimplePie uses item sources.
1306 * Useful when you are overloading or extending SimplePie's default classes.
1309 * @param string $class Name of custom class.
1310 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1311 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1313 function set_source_class($class = 'SimplePie_Source')
1315 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1317 $this->source_class = $class;
1324 * Allows you to override the default user agent string.
1327 * @param string $ua New user agent string.
1329 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1331 $this->useragent = (string) $ua;
1335 * Set callback function to create cache filename with
1338 * @param mixed $function Callback function
1340 function set_cache_name_function($function = 'md5')
1342 if (is_callable($function))
1344 $this->cache_name_function = $function;
1349 * Set javascript query string parameter
1352 * @param mixed $get Javascript query string parameter
1354 function set_javascript($get = 'js')
1358 $this->javascript = (string) $get;
1362 $this->javascript = false;
1367 * Set options to make SP as fast as possible. Forgoes a
1368 * substantial amount of data sanitization in favor of speed.
1371 * @param bool $set Whether to set them or not
1373 function set_stupidly_fast($set = false)
1377 $this->enable_order_by_date(false);
1378 $this->remove_div(false);
1379 $this->strip_comments(false);
1380 $this->strip_htmltags(false);
1381 $this->strip_attributes(false);
1382 $this->set_image_handler(false);
1387 * Set maximum number of feeds to check with autodiscovery
1390 * @param int $max Maximum number of feeds to check
1392 function set_max_checked_feeds($max = 10)
1394 $this->max_checked_feeds = (int) $max;
1397 function remove_div($enable = true)
1399 $this->sanitize->remove_div($enable);
1402 function strip_htmltags($tags = '', $encode = null)
1406 $tags = $this->strip_htmltags;
1408 $this->sanitize->strip_htmltags($tags);
1409 if ($encode !== null)
1411 $this->sanitize->encode_instead_of_strip($tags);
1415 function encode_instead_of_strip($enable = true)
1417 $this->sanitize->encode_instead_of_strip($enable);
1420 function strip_attributes($attribs = '')
1422 if ($attribs === '')
1424 $attribs = $this->strip_attributes;
1426 $this->sanitize->strip_attributes($attribs);
1429 function set_output_encoding($encoding = 'UTF-8')
1431 $this->sanitize->set_output_encoding($encoding);
1434 function strip_comments($strip = false)
1436 $this->sanitize->strip_comments($strip);
1440 * Set element/attribute key/value pairs of HTML attributes
1441 * containing URLs that need to be resolved relative to the feed
1445 * @param array $element_attribute Element/attribute key/value pairs
1447 function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1449 $this->sanitize->set_url_replacements($element_attribute);
1453 * Set the handler to enable the display of cached favicons.
1456 * @param str $page Web-accessible path to the handler_favicon.php file.
1457 * @param str $qs The query string that the value should be passed to.
1459 function set_favicon_handler($page = false, $qs = 'i')
1461 if ($page !== false)
1463 $this->favicon_handler = $page . '?' . $qs . '=';
1467 $this->favicon_handler = '';
1472 * Set the handler to enable the display of cached images.
1475 * @param str $page Web-accessible path to the handler_image.php file.
1476 * @param str $qs The query string that the value should be passed to.
1478 function set_image_handler($page = false, $qs = 'i')
1480 if ($page !== false)
1482 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1486 $this->image_handler = '';
1491 * Set the limit for items returned per-feed with multifeeds.
1494 * @param integer $limit The maximum number of items to return.
1496 function set_item_limit($limit = 0)
1498 $this->item_limit = (int) $limit;
1503 // Check absolute bare minimum requirements.
1504 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1508 // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1509 elseif (!extension_loaded('xmlreader'))
1511 static $xml_is_sane = null;
1512 if ($xml_is_sane === null)
1514 $parser_check = xml_parser_create();
1515 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
1516 xml_parser_free($parser_check);
1517 $xml_is_sane = isset($values[0]['value']);
1525 if (isset($_GET[$this->javascript]))
1527 SimplePie_Misc::output_javascript();
1531 // Pass whatever was set with config options over to the sanitizer.
1532 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1533 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1535 if ($this->feed_url !== null || $this->raw_data !== null)
1537 $this->data = array();
1538 $this->multifeed_objects = array();
1541 if ($this->feed_url !== null)
1543 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1544 // Decide whether to enable caching
1545 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1547 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1549 // If it's enabled and we don't want an XML dump, use the cache
1550 if ($cache && !$this->xml_dump)
1553 $this->data = $cache->load();
1554 if (!empty($this->data))
1556 // If the cache is for an outdated build of SimplePie
1557 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1560 $this->data = array();
1562 // If we've hit a collision just rerun it with caching disabled
1563 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1566 $this->data = array();
1568 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1569 elseif (isset($this->data['feed_url']))
1571 // If the autodiscovery cache is still valid use it.
1572 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1574 // Do not need to do feed autodiscovery yet.
1575 if ($this->data['feed_url'] === $this->data['url'])
1578 $this->data = array();
1582 $this->set_feed_url($this->data['feed_url']);
1583 return $this->init();
1587 // Check if the cache has been updated
1588 elseif ($cache->mtime() + $this->cache_duration < time())
1590 // If we have last-modified and/or etag set
1591 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1594 if (isset($this->data['headers']['last-modified']))
1596 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1598 if (isset($this->data['headers']['etag']))
1600 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1602 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1605 if ($file->status_code === 304)
1612 $headers = $file->headers;
1621 // If the cache is still valid, just return true
1627 // If the cache is empty, delete it
1631 $this->data = array();
1634 // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
1637 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1639 $file =& $this->file;
1643 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1646 // If the file connection has an error, set SimplePie::error to that and quit
1647 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1649 $this->error = $file->error;
1650 if (!empty($this->data))
1660 if (!$this->force_feed)
1662 // Check if the supplied URL is a feed, if it isn't, look for it.
1663 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1664 if (!$locate->is_feed($file))
1666 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1668 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1672 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1673 if (!$cache->save($this))
1675 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1677 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1679 $this->feed_url = $file->url;
1683 $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1684 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1691 $headers = $file->headers;
1692 $data = $file->body;
1693 $sniffer =& new $this->content_type_sniffer_class($file);
1694 $sniffed = $sniffer->get_type();
1698 $data = $this->raw_data;
1701 // Set up array of possible encodings
1702 $encodings = array();
1704 // First check to see if input has been overridden.
1705 if ($this->input_encoding !== false)
1707 $encodings[] = $this->input_encoding;
1710 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1711 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1713 // RFC 3023 (only applies to sniffed content)
1714 if (isset($sniffed))
1716 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1718 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1720 $encodings[] = strtoupper($charset[1]);
1722 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1723 $encodings[] = 'UTF-8';
1725 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1727 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1729 $encodings[] = $charset[1];
1731 $encodings[] = 'US-ASCII';
1733 // Text MIME-type default
1734 elseif (substr($sniffed, 0, 5) === 'text/')
1736 $encodings[] = 'US-ASCII';
1740 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1741 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1742 $encodings[] = 'UTF-8';
1743 $encodings[] = 'ISO-8859-1';
1745 // There's no point in trying an encoding twice
1746 $encodings = array_unique($encodings);
1748 // If we want the XML, just output that with the most likely encoding and quit
1749 if ($this->xml_dump)
1751 header('Content-type: text/xml; charset=' . $encodings[0]);
1756 // Loop through each possible encoding, till we return something, or run out of possibilities
1757 foreach ($encodings as $encoding)
1759 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1760 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1762 // Create new parser
1763 $parser =& new $this->parser_class();
1765 // If it's parsed fine
1766 if ($parser->parse($utf8_data, 'UTF-8'))
1768 $this->data = $parser->get_data();
1769 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1771 if (isset($headers))
1773 $this->data['headers'] = $headers;
1775 $this->data['build'] = SIMPLEPIE_BUILD;
1777 // Cache the file if caching is enabled
1778 if ($cache && !$cache->save($this))
1780 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1786 $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1787 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1795 // We have an error, just set SimplePie_Misc::error to it and quit
1796 $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1800 $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1802 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1805 elseif (!empty($this->multifeed_url))
1809 $this->multifeed_objects = array();
1810 foreach ($this->multifeed_url as $url)
1814 // This keyword needs to defy coding standards for PHP4 compatibility
1815 $this->multifeed_objects[$i] = clone($this);
1819 $this->multifeed_objects[$i] = $this;
1821 $this->multifeed_objects[$i]->set_feed_url($url);
1822 $success |= $this->multifeed_objects[$i]->init();
1825 return (bool) $success;
1834 * Return the error message for the occured error
1837 * @return string Error message
1841 return $this->error;
1844 function get_encoding()
1846 return $this->sanitize->output_encoding;
1849 function handle_content_type($mime = 'text/html')
1851 if (!headers_sent())
1853 $header = "Content-type: $mime;";
1854 if ($this->get_encoding())
1856 $header .= ' charset=' . $this->get_encoding();
1860 $header .= ' charset=UTF-8';
1868 if (!isset($this->data['type']))
1870 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1871 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1873 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1875 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1877 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1879 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1881 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1882 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1883 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1884 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1886 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1888 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1889 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1890 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1891 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1893 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1896 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1898 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1899 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1901 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1904 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1905 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1907 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1910 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1914 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1921 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1925 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1929 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1933 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1940 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1943 return $this->data['type'];
1947 * Returns the URL for the favicon of the feed's website.
1949 * @todo Cache atom:icon
1953 function get_favicon()
1955 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1957 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1959 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1961 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1963 if ($this->cache && $this->favicon_handler)
1965 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1966 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1970 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1974 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1976 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
1978 $sniffer =& new $this->content_type_sniffer_class($file);
1979 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1981 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1983 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1987 trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1988 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2001 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2008 * @todo If we have a perm redirect we should return the new URL
2009 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2010 * @todo Also, |atom:link|@rel=self
2012 function subscribe_url()
2014 if ($this->feed_url !== null)
2016 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2024 function subscribe_feed()
2026 if ($this->feed_url !== null)
2028 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2036 function subscribe_outlook()
2038 if ($this->feed_url !== null)
2040 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2048 function subscribe_podcast()
2050 if ($this->feed_url !== null)
2052 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2060 function subscribe_itunes()
2062 if ($this->feed_url !== null)
2064 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2073 * Creates the subscribe_* methods' return data
2076 * @param string $feed_url String to prefix to the feed URL
2077 * @param string $site_url String to prefix to the site URL (and
2078 * suffix to the feed URL)
2079 * @return mixed URL if feed exists, false otherwise
2081 function subscribe_service($feed_url, $site_url = null)
2083 if ($this->subscribe_url())
2085 $return = $feed_url . rawurlencode($this->feed_url);
2086 if ($site_url !== null && $this->get_link() !== null)
2088 $return .= $site_url . rawurlencode($this->get_link());
2090 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2098 function subscribe_aol()
2100 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2103 function subscribe_bloglines()
2105 return $this->subscribe_service('http://www.bloglines.com/sub/');
2108 function subscribe_eskobo()
2110 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2113 function subscribe_feedfeeds()
2115 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2118 function subscribe_feedster()
2120 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2123 function subscribe_google()
2125 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2128 function subscribe_gritwire()
2130 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2133 function subscribe_msn()
2135 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2138 function subscribe_netvibes()
2140 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2143 function subscribe_newsburst()
2145 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2148 function subscribe_newsgator()
2150 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2153 function subscribe_odeo()
2155 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2158 function subscribe_podnova()
2160 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2163 function subscribe_rojo()
2165 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2168 function subscribe_yahoo()
2170 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2173 function get_feed_tags($namespace, $tag)
2175 $type = $this->get_type();
2176 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2178 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2180 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2183 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2185 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2187 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2190 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2192 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2194 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2197 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2199 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2201 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2207 function get_channel_tags($namespace, $tag)
2209 $type = $this->get_type();
2210 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2212 if ($return = $this->get_feed_tags($namespace, $tag))
2217 if ($type & SIMPLEPIE_TYPE_RSS_10)
2219 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2221 if (isset($channel[0]['child'][$namespace][$tag]))
2223 return $channel[0]['child'][$namespace][$tag];
2227 if ($type & SIMPLEPIE_TYPE_RSS_090)
2229 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2231 if (isset($channel[0]['child'][$namespace][$tag]))
2233 return $channel[0]['child'][$namespace][$tag];
2237 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2239 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2241 if (isset($channel[0]['child'][$namespace][$tag]))
2243 return $channel[0]['child'][$namespace][$tag];
2250 function get_image_tags($namespace, $tag)
2252 $type = $this->get_type();
2253 if ($type & SIMPLEPIE_TYPE_RSS_10)
2255 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2257 if (isset($image[0]['child'][$namespace][$tag]))
2259 return $image[0]['child'][$namespace][$tag];
2263 if ($type & SIMPLEPIE_TYPE_RSS_090)
2265 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2267 if (isset($image[0]['child'][$namespace][$tag]))
2269 return $image[0]['child'][$namespace][$tag];
2273 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2275 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2277 if (isset($image[0]['child'][$namespace][$tag]))
2279 return $image[0]['child'][$namespace][$tag];
2286 function get_base($element = array())
2288 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2290 return $element['xml_base'];
2292 elseif ($this->get_link() !== null)
2294 return $this->get_link();
2298 return $this->subscribe_url();
2302 function sanitize($data, $type, $base = '')
2304 return $this->sanitize->sanitize($data, $type, $base);
2307 function get_title()
2309 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2311 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2313 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2315 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2317 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2319 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2321 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2323 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2325 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2327 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2329 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2331 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2333 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2335 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2343 function get_category($key = 0)
2345 $categories = $this->get_categories();
2346 if (isset($categories[$key]))
2348 return $categories[$key];
2356 function get_categories()
2358 $categories = array();
2360 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2365 if (isset($category['attribs']['']['term']))
2367 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2369 if (isset($category['attribs']['']['scheme']))
2371 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2373 if (isset($category['attribs']['']['label']))
2375 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2377 $categories[] =& new $this->category_class($term, $scheme, $label);
2379 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2381 // This is really the label, but keep this as the term also for BC.
2382 // Label will also work on retrieving because that falls back to term.
2383 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2384 if (isset($category['attribs']['']['domain']))
2386 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2392 $categories[] =& new $this->category_class($term, $scheme, null);
2394 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2396 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2398 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2400 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2403 if (!empty($categories))
2405 return SimplePie_Misc::array_unique($categories);
2413 function get_author($key = 0)
2415 $authors = $this->get_authors();
2416 if (isset($authors[$key]))
2418 return $authors[$key];
2426 function get_authors()
2429 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
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()
2778 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2780 return (float) $return[0]['data'];
2782 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2784 return (float) $match[1];
2792 function get_longitude()
2794 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2796 return (float) $return[0]['data'];
2798 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2800 return (float) $return[0]['data'];
2802 elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2804 return (float) $match[2];
2812 function get_image_title()
2814 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2816 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2818 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2820 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2822 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2824 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2826 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2828 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2830 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2832 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2840 function get_image_url()
2842 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2844 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2846 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2848 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2850 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2852 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2854 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2856 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2858 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2860 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2862 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2864 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2872 function get_image_link()
2874 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2876 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2878 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2880 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2882 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2884 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2892 function get_image_width()
2894 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2896 return round($return[0]['data']);
2898 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2908 function get_image_height()
2910 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2912 return round($return[0]['data']);
2914 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2924 function get_item_quantity($max = 0)
2927 $qty = count($this->get_items());
2934 return ($qty > $max) ? $max : $qty;
2938 function get_item($key = 0)
2940 $items = $this->get_items();
2941 if (isset($items[$key]))
2943 return $items[$key];
2951 function get_items($start = 0, $end = 0)
2953 if (!isset($this->data['items']))
2955 if (!empty($this->multifeed_objects))
2957 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2961 $this->data['items'] = array();
2962 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2964 $keys = array_keys($items);
2965 foreach ($keys as $key)
2967 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2970 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2972 $keys = array_keys($items);
2973 foreach ($keys as $key)
2975 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2978 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2980 $keys = array_keys($items);
2981 foreach ($keys as $key)
2983 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2986 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2988 $keys = array_keys($items);
2989 foreach ($keys as $key)
2991 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2994 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2996 $keys = array_keys($items);
2997 foreach ($keys as $key)
2999 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
3005 if (!empty($this->data['items']))
3007 // If we want to order it by date, check if all items have a date, and then sort it
3008 if ($this->order_by_date && empty($this->multifeed_objects))
3010 if (!isset($this->data['ordered_items']))
3013 foreach ($this->data['items'] as $item)
3015 if (!$item->get_date('U'))
3022 $this->data['ordered_items'] = $this->data['items'];
3025 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3028 $items = $this->data['ordered_items'];
3032 $items = $this->data['items'];
3035 // Slice the data as desired
3038 return array_slice($items, $start);
3042 return array_slice($items, $start, $end);
3054 function sort_items($a, $b)
3056 return $a->get_date('U') <= $b->get_date('U');
3062 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3064 if (is_array($urls) && sizeof($urls) > 0)
3067 foreach ($urls as $arg)
3069 if (is_a($arg, 'SimplePie'))
3071 $items = array_merge($items, $arg->get_items(0, $limit));
3075 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3080 foreach ($items as $item)
3082 if (!$item->get_date('U'))
3091 usort($items, array('SimplePie', 'sort_items'));
3096 return array_slice($items, $start);
3100 return array_slice($items, $start, $end);
3105 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3111 class SimplePie_Item
3114 var $data = array();
3116 function SimplePie_Item($feed, $data)
3118 $this->feed = $feed;
3119 $this->data = $data;
3122 function __toString()
3124 return md5(serialize($this->data));
3128 * Remove items that link back to this before destroying this object
3130 function __destruct()
3132 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3138 function get_item_tags($namespace, $tag)
3140 if (isset($this->data['child'][$namespace][$tag]))
3142 return $this->data['child'][$namespace][$tag];
3150 function get_base($element = array())
3152 return $this->feed->get_base($element);
3155 function sanitize($data, $type, $base = '')
3157 return $this->feed->sanitize($data, $type, $base);
3165 function get_id($hash = false)
3169 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3171 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3173 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3175 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3177 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3179 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3181 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3183 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3185 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3187 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3189 elseif (($return = $this->get_permalink()) !== null)
3193 elseif (($return = $this->get_title()) !== null)
3198 if ($this->get_permalink() !== null || $this->get_title() !== null)
3200 return md5($this->get_permalink() . $this->get_title());
3204 return md5(serialize($this->data));
3208 function get_title()
3210 if (!isset($this->data['title']))
3212 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3214 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3216 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3218 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3220 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3222 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3224 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3226 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3228 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3230 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3232 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3234 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3236 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3238 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3242 $this->data['title'] = null;
3245 return $this->data['title'];
3248 function get_description($description_only = false)
3250 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3252 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3254 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3256 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3258 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3260 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3262 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3264 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3266 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3268 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3270 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3272 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3274 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3276 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3278 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3280 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3282 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
3284 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
3287 elseif (!$description_only)
3289 return $this->get_content(true);
3297 function get_content($content_only = false)
3299 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3301 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3303 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3305 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3307 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3309 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3311 elseif (!$content_only)
3313 return $this->get_description(true);
3321 function get_category($key = 0)
3323 $categories = $this->get_categories();
3324 if (isset($categories[$key]))
3326 return $categories[$key];
3334 function get_categories()
3336 $categories = array();
3338 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3343 if (isset($category['attribs']['']['term']))
3345 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3347 if (isset($category['attribs']['']['scheme']))
3349 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3351 if (isset($category['attribs']['']['label']))
3353 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3355 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3357 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3359 // This is really the label, but keep this as the term also for BC.
3360 // Label will also work on retrieving because that falls back to term.
3361 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3362 if (isset($category['attribs']['']['domain']))
3364 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3370 $categories[] =& new $this->feed->category_class($term, $scheme, null);
3372 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3374 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3376 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3378 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3381 if (!empty($categories))
3383 return SimplePie_Misc::array_unique($categories);
3391 function get_author($key = 0)
3393 $authors = $this->get_authors();
3394 if (isset($authors[$key]))
3396 return $authors[$key];
3404 function get_contributor($key = 0)
3406 $contributors = $this->get_contributors();
3407 if (isset($contributors[$key]))
3409 return $contributors[$key];
3417 function get_contributors()
3419 $contributors = array();
3420 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3425 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3427 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3429 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3431 $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]));
3433 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3435 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3437 if ($name !== null || $email !== null || $uri !== null)
3439 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3442 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3447 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3449 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3451 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3453 $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]));
3455 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3457 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3459 if ($name !== null || $email !== null || $url !== null)
3461 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3465 if (!empty($contributors))
3467 return SimplePie_Misc::array_unique($contributors);
3475 function get_authors()
3478 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3483 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3485 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3487 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3489 $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]));
3491 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3493 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3495 if ($name !== null || $email !== null || $uri !== null)
3497 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3500 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3505 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3507 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3509 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3511 $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]));
3513 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3515 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3517 if ($name !== null || $email !== null || $url !== null)
3519 $authors[] =& new $this->feed->author_class($name, $url, $email);
3522 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3524 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3526 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3528 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3530 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3532 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3534 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3536 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3539 if (!empty($authors))
3541 return SimplePie_Misc::array_unique($authors);
3543 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3547 elseif ($authors = $this->feed->get_authors())
3557 function get_copyright()
3559 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3561 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3563 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3565 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3567 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3569 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3577 function get_date($date_format = 'j F Y, g:i a')
3579 if (!isset($this->data['date']))
3581 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3583 $this->data['date']['raw'] = $return[0]['data'];
3585 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3587 $this->data['date']['raw'] = $return[0]['data'];
3589 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3591 $this->data['date']['raw'] = $return[0]['data'];
3593 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3595 $this->data['date']['raw'] = $return[0]['data'];
3597 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3599 $this->data['date']['raw'] = $return[0]['data'];
3601 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3603 $this->data['date']['raw'] = $return[0]['data'];
3605 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3607 $this->data['date']['raw'] = $return[0]['data'];
3609 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3611 $this->data['date']['raw'] = $return[0]['data'];
3614 if (!empty($this->data['date']['raw']))
3616 $parser = SimplePie_Parse_Date::get();
3617 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3621 $this->data['date'] = null;
3624 if ($this->data['date'])
3626 $date_format = (string) $date_format;
3627 switch ($date_format)
3630 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3633 return $this->data['date']['parsed'];
3636 return date($date_format, $this->data['date']['parsed']);
3645 function get_local_date($date_format = '%c')
3649 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3651 elseif (($date = $this->get_date('U')) !== null && $date !== false)
3653 return strftime($date_format, $date);
3661 function get_permalink()
3663 $link = $this->get_link();
3664 $enclosure = $this->get_enclosure(0);
3669 elseif ($enclosure !== null)
3671 return $enclosure->get_link();
3679 function get_link($key = 0, $rel = 'alternate')
3681 $links = $this->get_links($rel);
3682 if ($links[$key] !== null)
3684 return $links[$key];
3692 function get_links($rel = 'alternate')
3694 if (!isset($this->data['links']))
3696 $this->data['links'] = array();
3697 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3699 if (isset($link['attribs']['']['href']))
3701 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3702 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3706 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3708 if (isset($link['attribs']['']['href']))
3710 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3711 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3714 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3716 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3718 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3720 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3722 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3724 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3726 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3728 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3730 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3734 $keys = array_keys($this->data['links']);
3735 foreach ($keys as $key)
3737 if (SimplePie_Misc::is_isegment_nz_nc($key))
3739 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3741 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3742 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3746 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3749 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3751 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3753 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3756 if (isset($this->data['links'][$rel]))
3758 return $this->data['links'][$rel];
3767 * @todo Add ability to prefer one type of content over another (in a media group).
3769 function get_enclosure($key = 0, $prefer = null)
3771 $enclosures = $this->get_enclosures();
3772 if (isset($enclosures[$key]))
3774 return $enclosures[$key];
3783 * Grabs all available enclosures (podcasts, etc.)
3785 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3787 * 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.
3789 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3790 * @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).
3792 function get_enclosures()
3794 if (!isset($this->data['enclosures']))
3796 $this->data['enclosures'] = array();
3799 $captions_parent = null;
3800 $categories_parent = null;
3801 $copyrights_parent = null;
3802 $credits_parent = null;
3803 $description_parent = null;
3804 $duration_parent = null;
3805 $hashes_parent = null;
3806 $keywords_parent = null;
3807 $player_parent = null;
3808 $ratings_parent = null;
3809 $restrictions_parent = null;
3810 $thumbnails_parent = null;
3811 $title_parent = null;
3813 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3814 $parent = $this->get_feed();
3817 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3819 foreach ($captions as $caption)
3821 $caption_type = null;
3822 $caption_lang = null;
3823 $caption_startTime = null;
3824 $caption_endTime = null;
3825 $caption_text = null;
3826 if (isset($caption['attribs']['']['type']))
3828 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3830 if (isset($caption['attribs']['']['lang']))
3832 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3834 if (isset($caption['attribs']['']['start']))
3836 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3838 if (isset($caption['attribs']['']['end']))
3840 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3842 if (isset($caption['data']))
3844 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3846 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3849 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3851 foreach ($captions as $caption)
3853 $caption_type = null;
3854 $caption_lang = null;
3855 $caption_startTime = null;
3856 $caption_endTime = null;
3857 $caption_text = null;
3858 if (isset($caption['attribs']['']['type']))
3860 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3862 if (isset($caption['attribs']['']['lang']))
3864 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3866 if (isset($caption['attribs']['']['start']))
3868 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3870 if (isset($caption['attribs']['']['end']))
3872 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3874 if (isset($caption['data']))
3876 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3878 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3881 if (is_array($captions_parent))
3883 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3887 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3892 if (isset($category['data']))
3894 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3896 if (isset($category['attribs']['']['scheme']))
3898 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3902 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3904 if (isset($category['attribs']['']['label']))
3906 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3908 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3910 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3915 if (isset($category['data']))
3917 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3919 if (isset($category['attribs']['']['scheme']))
3921 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3925 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3927 if (isset($category['attribs']['']['label']))
3929 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3931 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3933 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3936 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3938 if (isset($category['attribs']['']['text']))
3940 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3942 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3944 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3946 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3948 if (isset($subcategory['attribs']['']['text']))
3950 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3952 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3956 if (is_array($categories_parent))
3958 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3962 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3964 $copyright_url = null;
3965 $copyright_label = null;
3966 if (isset($copyright[0]['attribs']['']['url']))
3968 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3970 if (isset($copyright[0]['data']))
3972 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3974 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3976 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3978 $copyright_url = null;
3979 $copyright_label = null;
3980 if (isset($copyright[0]['attribs']['']['url']))
3982 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3984 if (isset($copyright[0]['data']))
3986 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3988 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3992 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3994 foreach ($credits as $credit)
3996 $credit_role = null;
3997 $credit_scheme = null;
3998 $credit_name = null;
3999 if (isset($credit['attribs']['']['role']))
4001 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4003 if (isset($credit['attribs']['']['scheme']))
4005 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4009 $credit_scheme = 'urn:ebu';
4011 if (isset($credit['data']))
4013 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4015 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4018 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4020 foreach ($credits as $credit)
4022 $credit_role = null;
4023 $credit_scheme = null;
4024 $credit_name = null;
4025 if (isset($credit['attribs']['']['role']))
4027 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4029 if (isset($credit['attribs']['']['scheme']))
4031 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4035 $credit_scheme = 'urn:ebu';
4037 if (isset($credit['data']))
4039 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4041 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4044 if (is_array($credits_parent))
4046 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4050 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4052 if (isset($description_parent[0]['data']))
4054 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4057 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4059 if (isset($description_parent[0]['data']))
4061 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4066 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4071 if (isset($duration_parent[0]['data']))
4073 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4074 if (sizeof($temp) > 0)
4076 $seconds = (int) array_pop($temp);
4078 if (sizeof($temp) > 0)
4080 $minutes = (int) array_pop($temp);
4081 $seconds += $minutes * 60;
4083 if (sizeof($temp) > 0)
4085 $hours = (int) array_pop($temp);
4086 $seconds += $hours * 3600;
4089 $duration_parent = $seconds;
4094 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4096 foreach ($hashes_iterator as $hash)
4100 if (isset($hash['data']))
4102 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4104 if (isset($hash['attribs']['']['algo']))
4106 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4112 $hashes_parent[] = $algo.':'.$value;
4115 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4117 foreach ($hashes_iterator as $hash)
4121 if (isset($hash['data']))
4123 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4125 if (isset($hash['attribs']['']['algo']))
4127 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4133 $hashes_parent[] = $algo.':'.$value;
4136 if (is_array($hashes_parent))
4138 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4142 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4144 if (isset($keywords[0]['data']))
4146 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4147 foreach ($temp as $word)
4149 $keywords_parent[] = trim($word);
4154 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4156 if (isset($keywords[0]['data']))
4158 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4159 foreach ($temp as $word)
4161 $keywords_parent[] = trim($word);
4166 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4168 if (isset($keywords[0]['data']))
4170 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4171 foreach ($temp as $word)
4173 $keywords_parent[] = trim($word);
4178 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4180 if (isset($keywords[0]['data']))
4182 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4183 foreach ($temp as $word)
4185 $keywords_parent[] = trim($word);
4190 if (is_array($keywords_parent))
4192 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4196 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4198 if (isset($player_parent[0]['attribs']['']['url']))
4200 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4203 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4205 if (isset($player_parent[0]['attribs']['']['url']))
4207 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4212 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4214 foreach ($ratings as $rating)
4216 $rating_scheme = null;
4217 $rating_value = null;
4218 if (isset($rating['attribs']['']['scheme']))
4220 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4224 $rating_scheme = 'urn:simple';
4226 if (isset($rating['data']))
4228 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4230 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4233 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4235 foreach ($ratings as $rating)
4237 $rating_scheme = 'urn:itunes';
4238 $rating_value = null;
4239 if (isset($rating['data']))
4241 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4243 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4246 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4248 foreach ($ratings as $rating)
4250 $rating_scheme = null;
4251 $rating_value = null;
4252 if (isset($rating['attribs']['']['scheme']))
4254 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4258 $rating_scheme = 'urn:simple';
4260 if (isset($rating['data']))
4262 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4264 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4267 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4269 foreach ($ratings as $rating)
4271 $rating_scheme = 'urn:itunes';
4272 $rating_value = null;
4273 if (isset($rating['data']))
4275 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4277 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4280 if (is_array($ratings_parent))
4282 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4286 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4288 foreach ($restrictions as $restriction)
4290 $restriction_relationship = null;
4291 $restriction_type = null;
4292 $restriction_value = null;
4293 if (isset($restriction['attribs']['']['relationship']))
4295 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4297 if (isset($restriction['attribs']['']['type']))
4299 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4301 if (isset($restriction['data']))
4303 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4305 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4308 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4310 foreach ($restrictions as $restriction)
4312 $restriction_relationship = 'allow';
4313 $restriction_type = null;
4314 $restriction_value = 'itunes';
4315 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4317 $restriction_relationship = 'deny';
4319 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4322 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4324 foreach ($restrictions as $restriction)
4326 $restriction_relationship = null;
4327 $restriction_type = null;
4328 $restriction_value = null;
4329 if (isset($restriction['attribs']['']['relationship']))
4331 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4333 if (isset($restriction['attribs']['']['type']))
4335 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4337 if (isset($restriction['data']))
4339 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4341 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4344 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4346 foreach ($restrictions as $restriction)
4348 $restriction_relationship = 'allow';
4349 $restriction_type = null;
4350 $restriction_value = 'itunes';
4351 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4353 $restriction_relationship = 'deny';
4355 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4358 if (is_array($restrictions_parent))
4360 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4364 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4366 foreach ($thumbnails as $thumbnail)
4368 if (isset($thumbnail['attribs']['']['url']))
4370 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4374 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4376 foreach ($thumbnails as $thumbnail)
4378 if (isset($thumbnail['attribs']['']['url']))
4380 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4386 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4388 if (isset($title_parent[0]['data']))
4390 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4393 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4395 if (isset($title_parent[0]['data']))
4397 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4415 $samplingrate = null;
4425 $description = null;
4430 $restrictions = null;
4434 // If we have media:group tags, loop through them.
4435 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4437 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4439 // If we have media:content tags, loop through them.
4440 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4442 if (isset($content['attribs']['']['url']))
4455 $samplingrate = null;
4465 $description = null;
4470 $restrictions = null;
4474 // Start checking the attributes of media:content
4475 if (isset($content['attribs']['']['bitrate']))
4477 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4479 if (isset($content['attribs']['']['channels']))
4481 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4483 if (isset($content['attribs']['']['duration']))
4485 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4489 $duration = $duration_parent;
4491 if (isset($content['attribs']['']['expression']))
4493 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4495 if (isset($content['attribs']['']['framerate']))
4497 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4499 if (isset($content['attribs']['']['height']))
4501 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4503 if (isset($content['attribs']['']['lang']))
4505 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4507 if (isset($content['attribs']['']['fileSize']))
4509 $length = ceil($content['attribs']['']['fileSize']);
4511 if (isset($content['attribs']['']['medium']))
4513 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4515 if (isset($content['attribs']['']['samplingrate']))
4517 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4519 if (isset($content['attribs']['']['type']))
4521 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4523 if (isset($content['attribs']['']['width']))
4525 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4527 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4529 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4532 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4534 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4536 $caption_type = null;
4537 $caption_lang = null;
4538 $caption_startTime = null;
4539 $caption_endTime = null;
4540 $caption_text = null;
4541 if (isset($caption['attribs']['']['type']))
4543 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4545 if (isset($caption['attribs']['']['lang']))
4547 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4549 if (isset($caption['attribs']['']['start']))
4551 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4553 if (isset($caption['attribs']['']['end']))
4555 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4557 if (isset($caption['data']))
4559 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4561 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4563 if (is_array($captions))
4565 $captions = array_values(SimplePie_Misc::array_unique($captions));
4568 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4570 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4572 $caption_type = null;
4573 $caption_lang = null;
4574 $caption_startTime = null;
4575 $caption_endTime = null;
4576 $caption_text = null;
4577 if (isset($caption['attribs']['']['type']))
4579 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4581 if (isset($caption['attribs']['']['lang']))
4583 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4585 if (isset($caption['attribs']['']['start']))
4587 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4589 if (isset($caption['attribs']['']['end']))
4591 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4593 if (isset($caption['data']))
4595 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4597 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4599 if (is_array($captions))
4601 $captions = array_values(SimplePie_Misc::array_unique($captions));
4606 $captions = $captions_parent;
4610 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4612 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4617 if (isset($category['data']))
4619 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4621 if (isset($category['attribs']['']['scheme']))
4623 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4627 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4629 if (isset($category['attribs']['']['label']))
4631 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4633 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4636 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4638 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4643 if (isset($category['data']))
4645 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4647 if (isset($category['attribs']['']['scheme']))
4649 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4653 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4655 if (isset($category['attribs']['']['label']))
4657 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4659 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4662 if (is_array($categories) && is_array($categories_parent))
4664 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4666 elseif (is_array($categories))
4668 $categories = array_values(SimplePie_Misc::array_unique($categories));
4670 elseif (is_array($categories_parent))
4672 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4676 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4678 $copyright_url = null;
4679 $copyright_label = null;
4680 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4682 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4684 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4686 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4688 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4690 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4692 $copyright_url = null;
4693 $copyright_label = null;
4694 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4696 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4698 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4700 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4702 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4706 $copyrights = $copyrights_parent;
4710 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4712 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4714 $credit_role = null;
4715 $credit_scheme = null;
4716 $credit_name = null;
4717 if (isset($credit['attribs']['']['role']))
4719 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4721 if (isset($credit['attribs']['']['scheme']))
4723 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4727 $credit_scheme = 'urn:ebu';
4729 if (isset($credit['data']))
4731 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4733 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4735 if (is_array($credits))
4737 $credits = array_values(SimplePie_Misc::array_unique($credits));
4740 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4742 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4744 $credit_role = null;
4745 $credit_scheme = null;
4746 $credit_name = null;
4747 if (isset($credit['attribs']['']['role']))
4749 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4751 if (isset($credit['attribs']['']['scheme']))
4753 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4757 $credit_scheme = 'urn:ebu';
4759 if (isset($credit['data']))
4761 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4763 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4765 if (is_array($credits))
4767 $credits = array_values(SimplePie_Misc::array_unique($credits));
4772 $credits = $credits_parent;
4776 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4778 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4780 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4782 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4786 $description = $description_parent;
4790 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4792 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4796 if (isset($hash['data']))
4798 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4800 if (isset($hash['attribs']['']['algo']))
4802 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4808 $hashes[] = $algo.':'.$value;
4810 if (is_array($hashes))
4812 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4815 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4817 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4821 if (isset($hash['data']))
4823 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4825 if (isset($hash['attribs']['']['algo']))
4827 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4833 $hashes[] = $algo.':'.$value;
4835 if (is_array($hashes))
4837 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4842 $hashes = $hashes_parent;
4846 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4848 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4850 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4851 foreach ($temp as $word)
4853 $keywords[] = trim($word);
4857 if (is_array($keywords))
4859 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4862 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4864 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4866 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4867 foreach ($temp as $word)
4869 $keywords[] = trim($word);
4873 if (is_array($keywords))
4875 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4880 $keywords = $keywords_parent;
4884 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4886 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4888 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4890 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4894 $player = $player_parent;
4898 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4900 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4902 $rating_scheme = null;
4903 $rating_value = null;
4904 if (isset($rating['attribs']['']['scheme']))
4906 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4910 $rating_scheme = 'urn:simple';
4912 if (isset($rating['data']))
4914 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4916 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4918 if (is_array($ratings))
4920 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4923 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4925 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4927 $rating_scheme = null;
4928 $rating_value = null;
4929 if (isset($rating['attribs']['']['scheme']))
4931 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4935 $rating_scheme = 'urn:simple';
4937 if (isset($rating['data']))
4939 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4941 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4943 if (is_array($ratings))
4945 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4950 $ratings = $ratings_parent;
4954 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4956 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4958 $restriction_relationship = null;
4959 $restriction_type = null;
4960 $restriction_value = null;
4961 if (isset($restriction['attribs']['']['relationship']))
4963 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4965 if (isset($restriction['attribs']['']['type']))
4967 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4969 if (isset($restriction['data']))
4971 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4973 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4975 if (is_array($restrictions))
4977 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4980 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4982 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4984 $restriction_relationship = null;
4985 $restriction_type = null;
4986 $restriction_value = null;
4987 if (isset($restriction['attribs']['']['relationship']))
4989 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4991 if (isset($restriction['attribs']['']['type']))
4993 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4995 if (isset($restriction['data']))
4997 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4999 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5001 if (is_array($restrictions))
5003 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5008 $restrictions = $restrictions_parent;
5012 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5014 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5016 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5018 if (is_array($thumbnails))
5020 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5023 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5025 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5027 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5029 if (is_array($thumbnails))
5031 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5036 $thumbnails = $thumbnails_parent;
5040 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5042 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5044 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5046 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5050 $title = $title_parent;
5053 $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);
5059 // If we have standalone media:content tags, loop through them.
5060 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5062 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5064 if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5077 $samplingrate = null;
5087 $description = null;
5092 $restrictions = null;
5096 // Start checking the attributes of media:content
5097 if (isset($content['attribs']['']['bitrate']))
5099 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5101 if (isset($content['attribs']['']['channels']))
5103 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5105 if (isset($content['attribs']['']['duration']))
5107 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5111 $duration = $duration_parent;
5113 if (isset($content['attribs']['']['expression']))
5115 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5117 if (isset($content['attribs']['']['framerate']))
5119 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5121 if (isset($content['attribs']['']['height']))
5123 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5125 if (isset($content['attribs']['']['lang']))
5127 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5129 if (isset($content['attribs']['']['fileSize']))
5131 $length = ceil($content['attribs']['']['fileSize']);
5133 if (isset($content['attribs']['']['medium']))
5135 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5137 if (isset($content['attribs']['']['samplingrate']))
5139 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5141 if (isset($content['attribs']['']['type']))
5143 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5145 if (isset($content['attribs']['']['width']))
5147 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5149 if (isset($content['attribs']['']['url']))
5151 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5153 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5156 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5158 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5160 $caption_type = null;
5161 $caption_lang = null;
5162 $caption_startTime = null;
5163 $caption_endTime = null;
5164 $caption_text = null;
5165 if (isset($caption['attribs']['']['type']))
5167 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5169 if (isset($caption['attribs']['']['lang']))
5171 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5173 if (isset($caption['attribs']['']['start']))
5175 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5177 if (isset($caption['attribs']['']['end']))
5179 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5181 if (isset($caption['data']))
5183 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5185 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5187 if (is_array($captions))
5189 $captions = array_values(SimplePie_Misc::array_unique($captions));
5194 $captions = $captions_parent;
5198 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5200 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5205 if (isset($category['data']))
5207 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5209 if (isset($category['attribs']['']['scheme']))
5211 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5215 $scheme = 'http://search.yahoo.com/mrss/category_schema';
5217 if (isset($category['attribs']['']['label']))
5219 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5221 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5224 if (is_array($categories) && is_array($categories_parent))
5226 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5228 elseif (is_array($categories))
5230 $categories = array_values(SimplePie_Misc::array_unique($categories));
5232 elseif (is_array($categories_parent))
5234 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5242 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5244 $copyright_url = null;
5245 $copyright_label = null;
5246 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5248 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5250 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5252 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5254 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5258 $copyrights = $copyrights_parent;
5262 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5264 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5266 $credit_role = null;
5267 $credit_scheme = null;
5268 $credit_name = null;
5269 if (isset($credit['attribs']['']['role']))
5271 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5273 if (isset($credit['attribs']['']['scheme']))
5275 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5279 $credit_scheme = 'urn:ebu';
5281 if (isset($credit['data']))
5283 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5285 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5287 if (is_array($credits))
5289 $credits = array_values(SimplePie_Misc::array_unique($credits));
5294 $credits = $credits_parent;
5298 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5300 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5304 $description = $description_parent;
5308 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5310 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5314 if (isset($hash['data']))
5316 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5318 if (isset($hash['attribs']['']['algo']))
5320 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5326 $hashes[] = $algo.':'.$value;
5328 if (is_array($hashes))
5330 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5335 $hashes = $hashes_parent;
5339 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5341 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5343 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5344 foreach ($temp as $word)
5346 $keywords[] = trim($word);
5350 if (is_array($keywords))
5352 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5357 $keywords = $keywords_parent;
5361 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5363 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5367 $player = $player_parent;
5371 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5373 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5375 $rating_scheme = null;
5376 $rating_value = null;
5377 if (isset($rating['attribs']['']['scheme']))
5379 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5383 $rating_scheme = 'urn:simple';
5385 if (isset($rating['data']))
5387 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5389 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5391 if (is_array($ratings))
5393 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5398 $ratings = $ratings_parent;
5402 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5404 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5406 $restriction_relationship = null;
5407 $restriction_type = null;
5408 $restriction_value = null;
5409 if (isset($restriction['attribs']['']['relationship']))
5411 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5413 if (isset($restriction['attribs']['']['type']))
5415 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5417 if (isset($restriction['data']))
5419 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5421 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5423 if (is_array($restrictions))
5425 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5430 $restrictions = $restrictions_parent;
5434 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5436 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5438 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5440 if (is_array($thumbnails))
5442 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5447 $thumbnails = $thumbnails_parent;
5451 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5453 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5457 $title = $title_parent;
5460 $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);
5465 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5467 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5480 $samplingrate = null;
5485 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5486 if (isset($link['attribs']['']['type']))
5488 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5490 if (isset($link['attribs']['']['length']))
5492 $length = ceil($link['attribs']['']['length']);
5495 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5496 $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);
5500 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5502 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5515 $samplingrate = null;
5520 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5521 if (isset($link['attribs']['']['type']))
5523 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5525 if (isset($link['attribs']['']['length']))
5527 $length = ceil($link['attribs']['']['length']);
5530 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5531 $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);
5535 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5537 if (isset($enclosure[0]['attribs']['']['url']))
5550 $samplingrate = null;
5555 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5556 if (isset($enclosure[0]['attribs']['']['type']))
5558 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5560 if (isset($enclosure[0]['attribs']['']['length']))
5562 $length = ceil($enclosure[0]['attribs']['']['length']);
5565 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5566 $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);
5570 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))
5572 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5573 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5576 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5578 if (!empty($this->data['enclosures']))
5580 return $this->data['enclosures'];
5588 function get_latitude()
5590 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5592 return (float) $return[0]['data'];
5594 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5596 return (float) $match[1];
5604 function get_longitude()
5606 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5608 return (float) $return[0]['data'];
5610 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5612 return (float) $return[0]['data'];
5614 elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
5616 return (float) $match[2];
5624 function get_source()
5626 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5628 return new $this->feed->source_class($this, $return[0]);
5637 * Creates the add_to_* methods' return data
5640 * @param string $item_url String to prefix to the item permalink
5641 * @param string $title_url String to prefix to the item title
5642 * (and suffix to the item permalink)
5643 * @return mixed URL if feed exists, false otherwise
5645 function add_to_service($item_url, $title_url = null, $summary_url = null)
5647 if ($this->get_permalink() !== null)
5649 $return = $item_url . rawurlencode($this->get_permalink());
5650 if ($title_url !== null && $this->get_title() !== null)
5652 $return .= $title_url . rawurlencode($this->get_title());
5654 if ($summary_url !== null && $this->get_description() !== null)
5656 $return .= $summary_url . rawurlencode($this->get_description());
5658 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5666 function add_to_blinklist()
5668 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5671 function add_to_blogmarks()
5673 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5676 function add_to_delicious()
5678 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5681 function add_to_digg()
5683 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5686 function add_to_furl()
5688 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5691 function add_to_magnolia()
5693 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5696 function add_to_myweb20()
5698 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5701 function add_to_newsvine()
5703 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5706 function add_to_reddit()
5708 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5711 function add_to_segnalo()
5713 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5716 function add_to_simpy()
5718 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5721 function add_to_spurl()
5723 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5726 function add_to_wists()
5728 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5731 function search_technorati()
5733 return $this->add_to_service('http://www.technorati.com/search/');
5737 class SimplePie_Source
5740 var $data = array();
5742 function SimplePie_Source($item, $data)
5744 $this->item = $item;
5745 $this->data = $data;
5748 function __toString()
5750 return md5(serialize($this->data));
5753 function get_source_tags($namespace, $tag)
5755 if (isset($this->data['child'][$namespace][$tag]))
5757 return $this->data['child'][$namespace][$tag];
5765 function get_base($element = array())
5767 return $this->item->get_base($element);
5770 function sanitize($data, $type, $base = '')
5772 return $this->item->sanitize($data, $type, $base);
5780 function get_title()
5782 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5784 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5786 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5788 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5790 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5792 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5794 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5796 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5798 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5800 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5802 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5804 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5806 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5808 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5816 function get_category($key = 0)
5818 $categories = $this->get_categories();
5819 if (isset($categories[$key]))
5821 return $categories[$key];
5829 function get_categories()
5831 $categories = array();
5833 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5838 if (isset($category['attribs']['']['term']))
5840 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5842 if (isset($category['attribs']['']['scheme']))
5844 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5846 if (isset($category['attribs']['']['label']))
5848 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5850 $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5852 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5854 // This is really the label, but keep this as the term also for BC.
5855 // Label will also work on retrieving because that falls back to term.
5856 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5857 if (isset($category['attribs']['']['domain']))
5859 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5865 $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5867 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5869 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5871 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5873 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5876 if (!empty($categories))
5878 return SimplePie_Misc::array_unique($categories);
5886 function get_author($key = 0)
5888 $authors = $this->get_authors();
5889 if (isset($authors[$key]))
5891 return $authors[$key];
5899 function get_authors()
5902 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5907 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5909 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5911 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5913 $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]));
5915 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5917 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5919 if ($name !== null || $email !== null || $uri !== null)
5921 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5924 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5929 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5931 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5933 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5935 $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]));
5937 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5939 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5941 if ($name !== null || $email !== null || $url !== null)
5943 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5946 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5948 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5950 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5952 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5954 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5956 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5959 if (!empty($authors))
5961 return SimplePie_Misc::array_unique($authors);
5969 function get_contributor($key = 0)
5971 $contributors = $this->get_contributors();
5972 if (isset($contributors[$key]))
5974 return $contributors[$key];
5982 function get_contributors()
5984 $contributors = array();
5985 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5990 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5992 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5994 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5996 $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]));
5998 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6000 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6002 if ($name !== null || $email !== null || $uri !== null)
6004 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
6007 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6012 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6014 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6016 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6018 $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]));
6020 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6022 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6024 if ($name !== null || $email !== null || $url !== null)
6026 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6030 if (!empty($contributors))
6032 return SimplePie_Misc::array_unique($contributors);
6040 function get_link($key = 0, $rel = 'alternate')
6042 $links = $this->get_links($rel);
6043 if (isset($links[$key]))
6045 return $links[$key];
6054 * Added for parity between the parent-level and the item/entry-level.
6056 function get_permalink()
6058 return $this->get_link(0);
6061 function get_links($rel = 'alternate')
6063 if (!isset($this->data['links']))
6065 $this->data['links'] = array();
6066 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, '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));
6077 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6079 foreach ($links as $link)
6081 if (isset($link['attribs']['']['href']))
6083 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6084 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6089 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6091 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6093 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6095 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6097 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6099 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6102 $keys = array_keys($this->data['links']);
6103 foreach ($keys as $key)
6105 if (SimplePie_Misc::is_isegment_nz_nc($key))
6107 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6109 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6110 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6114 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6117 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6119 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6121 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6125 if (isset($this->data['links'][$rel]))
6127 return $this->data['links'][$rel];
6135 function get_description()
6137 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6139 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6141 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6143 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6145 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6147 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6149 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6151 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6153 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6155 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6157 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6159 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6161 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6163 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6165 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6167 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6169 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6171 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6179 function get_copyright()
6181 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6183 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6185 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6187 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6189 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6191 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6193 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6195 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6197 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6199 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6207 function get_language()
6209 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6211 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6213 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6215 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6217 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6219 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6221 elseif (isset($this->data['xml_lang']))
6223 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6231 function get_latitude()
6233 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6235 return (float) $return[0]['data'];
6237 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6239 return (float) $match[1];
6247 function get_longitude()
6249 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6251 return (float) $return[0]['data'];
6253 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6255 return (float) $return[0]['data'];
6257 elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
6259 return (float) $match[2];
6267 function get_image_url()
6269 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6271 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6273 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6275 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6277 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6279 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6288 class SimplePie_Author
6294 // Constructor, used to input the data
6295 function SimplePie_Author($name = null, $link = null, $email = null)
6297 $this->name = $name;
6298 $this->link = $link;
6299 $this->email = $email;
6302 function __toString()
6304 // There is no $this->data here
6305 return md5(serialize($this));
6310 if ($this->name !== null)
6322 if ($this->link !== null)
6332 function get_email()
6334 if ($this->email !== null)
6336 return $this->email;
6345 class SimplePie_Category
6351 // Constructor, used to input the data
6352 function SimplePie_Category($term = null, $scheme = null, $label = null)
6354 $this->term = $term;
6355 $this->scheme = $scheme;
6356 $this->label = $label;
6359 function __toString()
6361 // There is no $this->data here
6362 return md5(serialize($this));
6367 if ($this->term !== null)
6377 function get_scheme()
6379 if ($this->scheme !== null)
6381 return $this->scheme;
6389 function get_label()
6391 if ($this->label !== null)
6393 return $this->label;
6397 return $this->get_term();
6402 class SimplePie_Enclosure
6432 // Constructor, used to input the data
6433 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)
6435 $this->bitrate = $bitrate;
6436 $this->captions = $captions;
6437 $this->categories = $categories;
6438 $this->channels = $channels;
6439 $this->copyright = $copyright;
6440 $this->credits = $credits;
6441 $this->description = $description;
6442 $this->duration = $duration;
6443 $this->expression = $expression;
6444 $this->framerate = $framerate;
6445 $this->hashes = $hashes;
6446 $this->height = $height;
6447 $this->javascript = $javascript;
6448 $this->keywords = $keywords;
6449 $this->lang = $lang;
6450 $this->length = $length;
6451 $this->link = $link;
6452 $this->medium = $medium;
6453 $this->player = $player;
6454 $this->ratings = $ratings;
6455 $this->restrictions = $restrictions;
6456 $this->samplingrate = $samplingrate;
6457 $this->thumbnails = $thumbnails;
6458 $this->title = $title;
6459 $this->type = $type;
6460 $this->width = $width;
6461 if (class_exists('idna_convert'))
6463 $idn =& new idna_convert;
6464 $parsed = SimplePie_Misc::parse_url($link);
6465 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6467 $this->handler = $this->get_handler(); // Needs to load last
6470 function __toString()
6472 // There is no $this->data here
6473 return md5(serialize($this));
6476 function get_bitrate()
6478 if ($this->bitrate !== null)
6480 return $this->bitrate;
6488 function get_caption($key = 0)
6490 $captions = $this->get_captions();
6491 if (isset($captions[$key]))
6493 return $captions[$key];
6501 function get_captions()
6503 if ($this->captions !== null)
6505 return $this->captions;
6513 function get_category($key = 0)
6515 $categories = $this->get_categories();
6516 if (isset($categories[$key]))
6518 return $categories[$key];
6526 function get_categories()
6528 if ($this->categories !== null)
6530 return $this->categories;
6538 function get_channels()
6540 if ($this->channels !== null)
6542 return $this->channels;
6550 function get_copyright()
6552 if ($this->copyright !== null)
6554 return $this->copyright;
6562 function get_credit($key = 0)
6564 $credits = $this->get_credits();
6565 if (isset($credits[$key]))
6567 return $credits[$key];
6575 function get_credits()
6577 if ($this->credits !== null)
6579 return $this->credits;
6587 function get_description()
6589 if ($this->description !== null)
6591 return $this->description;
6599 function get_duration($convert = false)
6601 if ($this->duration !== null)
6605 $time = SimplePie_Misc::time_hms($this->duration);
6610 return $this->duration;
6619 function get_expression()
6621 if ($this->expression !== null)
6623 return $this->expression;
6631 function get_extension()
6633 if ($this->link !== null)
6635 $url = SimplePie_Misc::parse_url($this->link);
6636 if ($url['path'] !== '')
6638 return pathinfo($url['path'], PATHINFO_EXTENSION);
6644 function get_framerate()
6646 if ($this->framerate !== null)
6648 return $this->framerate;
6656 function get_handler()
6658 return $this->get_real_type(true);
6661 function get_hash($key = 0)
6663 $hashes = $this->get_hashes();
6664 if (isset($hashes[$key]))
6666 return $hashes[$key];
6674 function get_hashes()
6676 if ($this->hashes !== null)
6678 return $this->hashes;
6686 function get_height()
6688 if ($this->height !== null)
6690 return $this->height;
6698 function get_language()
6700 if ($this->lang !== null)
6710 function get_keyword($key = 0)
6712 $keywords = $this->get_keywords();
6713 if (isset($keywords[$key]))
6715 return $keywords[$key];
6723 function get_keywords()
6725 if ($this->keywords !== null)
6727 return $this->keywords;
6735 function get_length()
6737 if ($this->length !== null)
6739 return $this->length;
6749 if ($this->link !== null)
6751 return urldecode($this->link);
6759 function get_medium()
6761 if ($this->medium !== null)
6763 return $this->medium;
6771 function get_player()
6773 if ($this->player !== null)
6775 return $this->player;
6783 function get_rating($key = 0)
6785 $ratings = $this->get_ratings();
6786 if (isset($ratings[$key]))
6788 return $ratings[$key];
6796 function get_ratings()
6798 if ($this->ratings !== null)
6800 return $this->ratings;
6808 function get_restriction($key = 0)
6810 $restrictions = $this->get_restrictions();
6811 if (isset($restrictions[$key]))
6813 return $restrictions[$key];
6821 function get_restrictions()
6823 if ($this->restrictions !== null)
6825 return $this->restrictions;
6833 function get_sampling_rate()
6835 if ($this->samplingrate !== null)
6837 return $this->samplingrate;
6847 $length = $this->get_length();
6848 if ($length !== null)
6850 return round($length/1048576, 2);
6858 function get_thumbnail($key = 0)
6860 $thumbnails = $this->get_thumbnails();
6861 if (isset($thumbnails[$key]))
6863 return $thumbnails[$key];
6871 function get_thumbnails()
6873 if ($this->thumbnails !== null)
6875 return $this->thumbnails;
6883 function get_title()
6885 if ($this->title !== null)
6887 return $this->title;
6897 if ($this->type !== null)
6907 function get_width()
6909 if ($this->width !== null)
6911 return $this->width;
6919 function native_embed($options='')
6921 return $this->embed($options, true);
6925 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6927 function embed($options = '', $native = false)
6937 $bgcolor = '#ffffff';
6939 $widescreen = false;
6940 $handler = $this->get_handler();
6941 $type = $this->get_real_type();
6943 // Process options and reassign values as necessary
6944 if (is_array($options))
6950 $options = explode(',', $options);
6951 foreach($options as $option)
6953 $opt = explode(':', $option, 2);
6954 if (isset($opt[0], $opt[1]))
6956 $opt[0] = trim($opt[0]);
6957 $opt[1] = trim($opt[1]);
6973 $altclass = $opt[1];
6993 $mediaplayer = $opt[1];
6997 $widescreen = $opt[1];
7004 $mime = explode('/', $type, 2);
7007 // Process values for 'auto'
7008 if ($width === 'auto')
7010 if ($mime === 'video')
7012 if ($height === 'auto')
7016 elseif ($widescreen)
7018 $width = round((intval($height)/9)*16);
7022 $width = round((intval($height)/3)*4);
7031 if ($height === 'auto')
7033 if ($mime === 'audio')
7037 elseif ($mime === 'video')
7039 if ($width === 'auto')
7050 elseif ($widescreen)
7052 $height = round((intval($width)/16)*9);
7056 $height = round((intval($width)/4)*3);
7064 elseif ($mime === 'audio')
7069 // Set proper placeholder value
7070 if ($mime === 'audio')
7072 $placeholder = $audio;
7074 elseif ($mime === 'video')
7076 $placeholder = $video;
7081 // Make sure the JS library is included
7084 static $javascript_outputted = null;
7085 if (!$javascript_outputted && $this->javascript)
7087 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7088 $javascript_outputted = true;
7093 if ($handler === 'odeo')
7097 $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>';
7101 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7106 elseif ($handler === 'flash')
7110 $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>";
7114 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7118 // Flash Media Player file types.
7119 // Preferred handler for MP3 file types.
7120 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7125 $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>";
7129 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7133 // QuickTime 7 file types. Need to test with QuickTime 6.
7134 // Only handle MP3's if the Flash Media Player is not present.
7135 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7140 if ($placeholder !== '')
7142 $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>";
7146 $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>";
7151 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7156 elseif ($handler === 'wmedia')
7161 $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>";
7165 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7170 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7175 function get_real_type($find_handler = false)
7177 // If it's Odeo, let's get it out of the way.
7178 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7183 // Mime-types by handler.
7184 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7185 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7186 $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
7187 $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
7188 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7190 if ($this->get_type() !== null)
7192 $type = strtolower($this->type);
7199 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7200 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7202 switch (strtolower($this->get_extension()))
7207 $type = 'audio/acc';
7214 $type = 'audio/aiff';
7218 $type = 'audio/wav';
7225 $type = 'audio/midi';
7229 $type = 'audio/x-m4a';
7234 $type = 'audio/mp3';
7238 $type = 'audio/wav';
7242 $type = 'audio/x-ms-wax';
7246 $type = 'audio/x-ms-wma';
7252 $type = 'video/3gpp';
7257 $type = 'video/3gpp2';
7261 $type = 'video/x-ms-asf';
7265 $type = 'video/x-flv';
7279 $type = 'video/mpeg';
7283 $type = 'video/x-m4v';
7288 $type = 'video/quicktime';
7293 $type = 'video/mp4';
7297 $type = 'video/sd-video';
7301 $type = 'video/x-ms-wm';
7305 $type = 'video/x-ms-wmv';
7309 $type = 'video/x-ms-wvx';
7314 $type = 'application/futuresplash';
7318 $type = 'application/x-shockwave-flash';
7325 if (in_array($type, $types_flash))
7329 elseif (in_array($type, $types_fmedia))
7333 elseif (in_array($type, $types_quicktime))
7337 elseif (in_array($type, $types_wmedia))
7341 elseif (in_array($type, $types_mp3))
7357 class SimplePie_Caption
7365 // Constructor, used to input the data
7366 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7368 $this->type = $type;
7369 $this->lang = $lang;
7370 $this->startTime = $startTime;
7371 $this->endTime = $endTime;
7372 $this->text = $text;
7375 function __toString()
7377 // There is no $this->data here
7378 return md5(serialize($this));
7381 function get_endtime()
7383 if ($this->endTime !== null)
7385 return $this->endTime;
7393 function get_language()
7395 if ($this->lang !== null)
7405 function get_starttime()
7407 if ($this->startTime !== null)
7409 return $this->startTime;
7419 if ($this->text !== null)
7431 if ($this->type !== null)
7442 class SimplePie_Credit
7448 // Constructor, used to input the data
7449 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7451 $this->role = $role;
7452 $this->scheme = $scheme;
7453 $this->name = $name;
7456 function __toString()
7458 // There is no $this->data here
7459 return md5(serialize($this));
7464 if ($this->role !== null)
7474 function get_scheme()
7476 if ($this->scheme !== null)
7478 return $this->scheme;
7488 if ($this->name !== null)
7499 class SimplePie_Copyright
7504 // Constructor, used to input the data
7505 function SimplePie_Copyright($url = null, $label = null)
7508 $this->label = $label;
7511 function __toString()
7513 // There is no $this->data here
7514 return md5(serialize($this));
7519 if ($this->url !== null)
7529 function get_attribution()
7531 if ($this->label !== null)
7533 return $this->label;
7542 class SimplePie_Rating
7547 // Constructor, used to input the data
7548 function SimplePie_Rating($scheme = null, $value = null)
7550 $this->scheme = $scheme;
7551 $this->value = $value;
7554 function __toString()
7556 // There is no $this->data here
7557 return md5(serialize($this));
7560 function get_scheme()
7562 if ($this->scheme !== null)
7564 return $this->scheme;
7572 function get_value()
7574 if ($this->value !== null)
7576 return $this->value;
7585 class SimplePie_Restriction
7591 // Constructor, used to input the data
7592 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7594 $this->relationship = $relationship;
7595 $this->type = $type;
7596 $this->value = $value;
7599 function __toString()
7601 // There is no $this->data here
7602 return md5(serialize($this));
7605 function get_relationship()
7607 if ($this->relationship !== null)
7609 return $this->relationship;
7619 if ($this->type !== null)
7629 function get_value()
7631 if ($this->value !== null)
7633 return $this->value;
7643 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7645 class SimplePie_File
7649 var $success = true;
7650 var $headers = array();
7655 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7657 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7659 if (class_exists('idna_convert'))
7661 $idn =& new idna_convert;
7662 $parsed = SimplePie_Misc::parse_url($url);
7663 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7666 $this->useragent = $useragent;
7667 if (preg_match('/^http(s)?:\/\//i', $url))
7669 if ($useragent === null)
7671 $useragent = ini_get('user_agent');
7672 $this->useragent = $useragent;
7674 if (!is_array($headers))
7678 if (!$force_fsockopen && function_exists('curl_exec'))
7680 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7682 $headers2 = array();
7683 foreach ($headers as $key => $value)
7685 $headers2[] = "$key: $value";
7687 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7689 curl_setopt($fp, CURLOPT_ENCODING, '');
7691 curl_setopt($fp, CURLOPT_URL, $url);
7692 curl_setopt($fp, CURLOPT_HEADER, 1);
7693 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7694 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7695 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7696 curl_setopt($fp, CURLOPT_REFERER, $url);
7697 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7698 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7699 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7701 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7702 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7705 /* Enable Digest authentication and SSL -fox */
7706 curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false);
7707 curl_setopt($fp, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
7709 $this->headers = curl_exec($fp);
7710 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7712 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7713 $this->headers = curl_exec($fp);
7715 if (curl_errno($fp))
7717 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7718 $this->success = false;
7722 $info = curl_getinfo($fp);
7724 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7725 $this->headers = array_pop($this->headers);
7726 $parser =& new SimplePie_HTTP_Parser($this->headers);
7727 if ($parser->parse())
7729 $this->headers = $parser->headers;
7730 $this->body = $parser->body;
7731 $this->status_code = $parser->status_code;
7732 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)
7735 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7736 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7743 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7744 $url_parts = parse_url($url);
7745 $socket_host = $url_parts['host'];
7746 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7748 $socket_host = "ssl://$url_parts[host]";
7749 $url_parts['port'] = 443;
7751 if (!isset($url_parts['port']))
7753 $url_parts['port'] = 80;
7755 $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
7758 $this->error = 'fsockopen error: ' . $errstr;
7759 $this->success = false;
7763 stream_set_timeout($fp, $timeout);
7764 if (isset($url_parts['path']))
7766 if (isset($url_parts['query']))
7768 $get = "$url_parts[path]?$url_parts[query]";
7772 $get = $url_parts['path'];
7779 $out = "GET $get HTTP/1.0\r\n";
7780 $out .= "Host: $url_parts[host]\r\n";
7781 $out .= "User-Agent: $useragent\r\n";
7782 if (extension_loaded('zlib'))
7784 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7787 if (isset($url_parts['user']) && isset($url_parts['pass']))
7789 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7791 foreach ($headers as $key => $value)
7793 $out .= "$key: $value\r\n";
7795 $out .= "Connection: Close\r\n\r\n";
7798 $info = stream_get_meta_data($fp);
7800 $this->headers = '';
7801 while (!$info['eof'] && !$info['timed_out'])
7803 $this->headers .= fread($fp, 1160);
7804 $info = stream_get_meta_data($fp);
7806 if (!$info['timed_out'])
7808 $parser =& new SimplePie_HTTP_Parser($this->headers);
7809 if ($parser->parse())
7811 $this->headers = $parser->headers;
7812 $this->body = $parser->body;
7813 $this->status_code = $parser->status_code;
7814 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)
7817 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7818 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7820 if (isset($this->headers['content-encoding']))
7822 // Hey, we act dumb elsewhere, so let's do that here too
7823 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7827 $decoder =& new SimplePie_gzdecode($this->body);
7828 if (!$decoder->parse())
7830 $this->error = 'Unable to decode HTTP "gzip" stream';
7831 $this->success = false;
7835 $this->body = $decoder->data;
7840 if (($body = gzuncompress($this->body)) === false)
7842 if (($body = gzinflate($this->body)) === false)
7844 $this->error = 'Unable to decode HTTP "deflate" stream';
7845 $this->success = false;
7848 $this->body = $body;
7852 $this->error = 'Unknown content coding';
7853 $this->success = false;
7860 $this->error = 'fsocket timed out';
7861 $this->success = false;
7869 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7870 if (!$this->body = file_get_contents($url))
7872 $this->error = 'file_get_contents could not read the file';
7873 $this->success = false;
7880 * HTTP Response Parser
7882 * @package SimplePie
7884 class SimplePie_HTTP_Parser
7892 var $http_version = 0.0;
7900 var $status_code = 0;
7911 * Key/value pairs of the headers
7916 var $headers = array();
7919 * Body of the response
7927 * Current state of the state machine
7932 var $state = 'http_version';
7943 * Input data length (to avoid calling strlen() everytime this is needed)
7948 var $data_length = 0;
7951 * Current position of the pointer
7959 * Name of the hedaer currently being parsed
7967 * Value of the hedaer currently being parsed
7975 * Create an instance of the class with the input data
7978 * @param string $data Input data
7980 function SimplePie_HTTP_Parser($data)
7982 $this->data = $data;
7983 $this->data_length = strlen($this->data);
7987 * Parse the input data
7990 * @return bool true on success, false on failure
7994 while ($this->state && $this->state !== 'emit' && $this->has_data())
7996 $state = $this->state;
8000 if ($this->state === 'emit' || $this->state === 'body')
8006 $this->http_version = '';
8007 $this->status_code = '';
8009 $this->headers = array();
8016 * Check whether there is data beyond the pointer
8019 * @return bool true if there is further data, false if not
8023 return (bool) ($this->position < $this->data_length);
8027 * See if the next character is LWS
8030 * @return bool true if the next character is LWS, false if not
8032 function is_linear_whitespace()
8034 return (bool) ($this->data[$this->position] === "\x09"
8035 || $this->data[$this->position] === "\x20"
8036 || ($this->data[$this->position] === "\x0A"
8037 && isset($this->data[$this->position + 1])
8038 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8042 * Parse the HTTP version
8046 function http_version()
8048 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8050 $len = strspn($this->data, '0123456789.', 5);
8051 $this->http_version = substr($this->data, 5, $len);
8052 $this->position += 5 + $len;
8053 if (substr_count($this->http_version, '.') <= 1)
8055 $this->http_version = (float) $this->http_version;
8056 $this->position += strspn($this->data, "\x09\x20", $this->position);
8057 $this->state = 'status';
8061 $this->state = false;
8066 $this->state = false;
8071 * Parse the status code
8077 if ($len = strspn($this->data, '0123456789', $this->position))
8079 $this->status_code = (int) substr($this->data, $this->position, $len);
8080 $this->position += $len;
8081 $this->state = 'reason';
8085 $this->state = false;
8090 * Parse the reason phrase
8096 $len = strcspn($this->data, "\x0A", $this->position);
8097 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8098 $this->position += $len + 1;
8099 $this->state = 'new_line';
8103 * Deal with a new line, shifting data around as needed
8109 $this->value = trim($this->value, "\x0D\x20");
8110 if ($this->name !== '' && $this->value !== '')
8112 $this->name = strtolower($this->name);
8113 if (isset($this->headers[$this->name]))
8115 $this->headers[$this->name] .= ', ' . $this->value;
8119 $this->headers[$this->name] = $this->value;
8124 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8126 $this->position += 2;
8127 $this->state = 'body';
8129 elseif ($this->data[$this->position] === "\x0A")
8132 $this->state = 'body';
8136 $this->state = 'name';
8141 * Parse a header name
8147 $len = strcspn($this->data, "\x0A:", $this->position);
8148 if (isset($this->data[$this->position + $len]))
8150 if ($this->data[$this->position + $len] === "\x0A")
8152 $this->position += $len;
8153 $this->state = 'new_line';
8157 $this->name = substr($this->data, $this->position, $len);
8158 $this->position += $len + 1;
8159 $this->state = 'value';
8164 $this->state = false;
8169 * Parse LWS, replacing consecutive LWS characters with a single space
8173 function linear_whitespace()
8177 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8179 $this->position += 2;
8181 elseif ($this->data[$this->position] === "\x0A")
8185 $this->position += strspn($this->data, "\x09\x20", $this->position);
8186 } while ($this->has_data() && $this->is_linear_whitespace());
8187 $this->value .= "\x20";
8191 * See what state to move to while within non-quoted header values
8197 if ($this->is_linear_whitespace())
8199 $this->linear_whitespace();
8203 switch ($this->data[$this->position])
8207 $this->state = 'quote';
8212 $this->state = 'new_line';
8216 $this->state = 'value_char';
8223 * Parse a header value while outside quotes
8227 function value_char()
8229 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8230 $this->value .= substr($this->data, $this->position, $len);
8231 $this->position += $len;
8232 $this->state = 'value';
8236 * See what state to move to while within quoted header values
8242 if ($this->is_linear_whitespace())
8244 $this->linear_whitespace();
8248 switch ($this->data[$this->position])
8252 $this->state = 'value';
8257 $this->state = 'new_line';
8262 $this->state = 'quote_escaped';
8266 $this->state = 'quote_char';
8273 * Parse a header value while within quotes
8277 function quote_char()
8279 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8280 $this->value .= substr($this->data, $this->position, $len);
8281 $this->position += $len;
8282 $this->state = 'value';
8286 * Parse an escaped character within quotes
8290 function quote_escaped()
8292 $this->value .= $this->data[$this->position];
8294 $this->state = 'quote';
8304 $this->body = substr($this->data, $this->position);
8305 $this->state = 'emit';
8312 * @package SimplePie
8314 class SimplePie_gzdecode
8320 * @see gzdecode::$data
8322 var $compressed_data;
8325 * Size of compressed data
8329 var $compressed_size;
8332 * Minimum size of a valid gzip string
8336 var $min_compressed_size = 18;
8339 * Current position of pointer
8356 * @see gzdecode::$compressed_data
8385 * @see gzdecode::$extra_field
8386 * @see gzdecode::$SI2
8394 * @see gzdecode::$extra_field
8395 * @see gzdecode::$SI1
8400 * Extra field content
8403 * @see gzdecode::$SI1
8404 * @see gzdecode::$SI2
8416 * Human readable comment
8423 * Don't allow anything to be set
8427 function __set($name, $value)
8429 trigger_error("Cannot write property $name", E_USER_ERROR);
8433 * Set the compressed string and related properties
8437 function SimplePie_gzdecode($data)
8439 $this->compressed_data = $data;
8440 $this->compressed_size = strlen($data);
8444 * Decode the GZIP stream
8450 if ($this->compressed_size >= $this->min_compressed_size)
8452 // Check ID1, ID2, and CM
8453 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8458 // Get the FLG (FLaGs)
8459 $this->flags = ord($this->compressed_data[3]);
8461 // FLG bits above (1 << 4) are reserved
8462 if ($this->flags > 0x1F)
8467 // Advance the pointer after the above
8468 $this->position += 4;
8471 $mtime = substr($this->compressed_data, $this->position, 4);
8472 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8473 if (current(unpack('S', "\x00\x01")) === 1)
8475 $mtime = strrev($mtime);
8477 $this->MTIME = current(unpack('l', $mtime));
8478 $this->position += 4;
8480 // Get the XFL (eXtra FLags)
8481 $this->XFL = ord($this->compressed_data[$this->position++]);
8483 // Get the OS (Operating System)
8484 $this->OS = ord($this->compressed_data[$this->position++]);
8487 if ($this->flags & 4)
8489 // Read subfield IDs
8490 $this->SI1 = $this->compressed_data[$this->position++];
8491 $this->SI2 = $this->compressed_data[$this->position++];
8493 // SI2 set to zero is reserved for future use
8494 if ($this->SI2 === "\x00")
8499 // Get the length of the extra field
8500 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8501 $this->position += 2;
8503 // Check the length of the string is still valid
8504 $this->min_compressed_size += $len + 4;
8505 if ($this->compressed_size >= $this->min_compressed_size)
8507 // Set the extra field to the given data
8508 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8509 $this->position += $len;
8518 if ($this->flags & 8)
8520 // Get the length of the filename
8521 $len = strcspn($this->compressed_data, "\x00", $this->position);
8523 // Check the length of the string is still valid
8524 $this->min_compressed_size += $len + 1;
8525 if ($this->compressed_size >= $this->min_compressed_size)
8527 // Set the original filename to the given string
8528 $this->filename = substr($this->compressed_data, $this->position, $len);
8529 $this->position += $len + 1;
8537 // Parse the FCOMMENT
8538 if ($this->flags & 16)
8540 // Get the length of the comment
8541 $len = strcspn($this->compressed_data, "\x00", $this->position);
8543 // Check the length of the string is still valid
8544 $this->min_compressed_size += $len + 1;
8545 if ($this->compressed_size >= $this->min_compressed_size)
8547 // Set the original comment to the given string
8548 $this->comment = substr($this->compressed_data, $this->position, $len);
8549 $this->position += $len + 1;
8558 if ($this->flags & 2)
8560 // Check the length of the string is still valid
8561 $this->min_compressed_size += $len + 2;
8562 if ($this->compressed_size >= $this->min_compressed_size)
8565 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8567 // Check the CRC matches
8568 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8570 $this->position += 2;
8583 // Decompress the actual data
8584 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8590 $this->position = $this->compressed_size - 8;
8593 // Check CRC of data
8594 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8595 $this->position += 4;
8596 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8601 // Check ISIZE of data
8602 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8603 $this->position += 4;
8604 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8609 // Wow, against all odds, we've actually got a valid gzip string
8619 class SimplePie_Cache
8622 * Don't call the constructor. Please.
8626 function SimplePie_Cache()
8628 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8632 * Create a new SimplePie_Cache object
8637 function create($location, $filename, $extension)
8639 $location_iri =& new SimplePie_IRI($location);
8640 switch ($location_iri->get_scheme())
8643 if (extension_loaded('mysql'))
8645 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8650 return new SimplePie_Cache_File($location, $filename, $extension);
8655 class SimplePie_Cache_File
8662 function SimplePie_Cache_File($location, $filename, $extension)
8664 $this->location = $location;
8665 $this->filename = $filename;
8666 $this->extension = $extension;
8667 $this->name = "$this->location/$this->filename.$this->extension";
8670 function save($data)
8672 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8674 if (is_a($data, 'SimplePie'))
8676 $data = $data->data;
8679 $data = serialize($data);
8681 if (function_exists('file_put_contents'))
8683 return (bool) file_put_contents($this->name, $data);
8687 $fp = fopen($this->name, 'wb');
8701 if (file_exists($this->name) && is_readable($this->name))
8703 return unserialize(file_get_contents($this->name));
8710 if (file_exists($this->name))
8712 return filemtime($this->name);
8719 if (file_exists($this->name))
8721 return touch($this->name);
8728 if (file_exists($this->name))
8730 return unlink($this->name);
8736 class SimplePie_Cache_DB
8738 function prepare_simplepie_object_for_cache($data)
8740 $items = $data->get_items();
8741 $items_by_id = array();
8745 foreach ($items as $item)
8747 $items_by_id[$item->get_id()] = $item;
8750 if (count($items_by_id) !== count($items))
8752 $items_by_id = array();
8753 foreach ($items as $item)
8755 $items_by_id[$item->get_id(true)] = $item;
8759 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8761 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8763 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8765 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8767 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8769 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8771 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8773 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8780 if ($channel !== null)
8782 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8784 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8786 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8788 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8790 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8792 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8794 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8796 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8798 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8800 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8803 if (isset($data->data['items']))
8805 unset($data->data['items']);
8807 if (isset($data->data['ordered_items']))
8809 unset($data->data['ordered_items']);
8812 return array(serialize($data->data), $items_by_id);
8816 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8822 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8824 $host = $mysql_location->get_host();
8825 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8827 $server = ':' . substr($host, 5, -1);
8832 if ($mysql_location->get_port() !== null)
8834 $server .= ':' . $mysql_location->get_port();
8838 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8840 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8844 $username = $mysql_location->get_userinfo();
8848 if ($this->mysql = mysql_connect($server, $username, $password))
8850 $this->id = $name . $extension;
8851 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8852 if (!isset($this->options['prefix'][0]))
8854 $this->options['prefix'][0] = '';
8857 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8858 && mysql_query('SET NAMES utf8')
8859 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8862 while ($row = mysql_fetch_row($query))
8867 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8869 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)))'))
8871 $this->mysql = null;
8875 if (!in_array($this->options['prefix'][0] . 'items', $db))
8877 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)))'))
8879 $this->mysql = null;
8885 $this->mysql = null;
8890 function save($data)
8894 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8896 if (is_a($data, 'SimplePie'))
8900 // This keyword needs to defy coding standards for PHP4 compatibility
8901 $data = clone($data);
8904 $prepared = $this->prepare_simplepie_object_for_cache($data);
8906 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8908 if (mysql_num_rows($query))
8910 $items = count($prepared[1]);
8913 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8917 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8920 if (!mysql_query($sql, $this->mysql))
8925 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))
8930 $ids = array_keys($prepared[1]);
8933 foreach ($ids as $id)
8935 $database_ids[] = mysql_real_escape_string($id);
8938 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))
8940 $existing_ids = array();
8941 while ($row = mysql_fetch_row($query))
8943 $existing_ids[] = $row[0];
8946 $new_ids = array_diff($ids, $existing_ids);
8948 foreach ($new_ids as $new_id)
8950 if (!($date = $prepared[1][$new_id]->get_date('U')))
8955 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))
8969 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8971 if (mysql_num_rows($query))
8973 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))
8978 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))
8989 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)))
8991 $data = unserialize($row[1]);
8993 if (isset($this->options['items'][0]))
8995 $items = (int) $this->options['items'][0];
8999 $items = (int) $row[0];
9004 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9006 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9008 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9010 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9012 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9014 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9016 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9018 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9027 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9030 $sql .= ' LIMIT ' . $items;
9033 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9035 while ($row = mysql_fetch_row($query))
9037 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9053 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)))
9065 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))
9077 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)))
9088 class SimplePie_Misc
9090 function time_hms($seconds)
9094 $hours = floor($seconds / 3600);
9095 $remainder = $seconds % 3600;
9098 $time .= $hours.':';
9101 $minutes = floor($remainder / 60);
9102 $seconds = $remainder % 60;
9103 if ($minutes < 10 && $hours > 0)
9105 $minutes = '0' . $minutes;
9109 $seconds = '0' . $seconds;
9112 $time .= $minutes.':';
9118 function absolutize_url($relative, $base)
9120 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9121 return $iri->get_iri();
9124 function remove_dot_segments($input)
9127 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9129 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9130 if (strpos($input, '../') === 0)
9132 $input = substr($input, 3);
9134 elseif (strpos($input, './') === 0)
9136 $input = substr($input, 2);
9138 // 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,
9139 elseif (strpos($input, '/./') === 0)
9141 $input = substr_replace($input, '/', 0, 3);
9143 elseif ($input === '/.')
9147 // 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,
9148 elseif (strpos($input, '/../') === 0)
9150 $input = substr_replace($input, '/', 0, 4);
9151 $output = substr_replace($output, '', strrpos($output, '/'));
9153 elseif ($input === '/..')
9156 $output = substr_replace($output, '', strrpos($output, '/'));
9158 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9159 elseif ($input === '.' || $input === '..')
9163 // 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
9164 elseif (($pos = strpos($input, '/', 1)) !== false)
9166 $output .= substr($input, 0, $pos);
9167 $input = substr_replace($input, '', 0, $pos);
9175 return $output . $input;
9178 function get_element($realname, $string)
9181 $name = preg_quote($realname, '/');
9182 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9184 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9186 $return[$i]['tag'] = $realname;
9187 $return[$i]['full'] = $matches[$i][0][0];
9188 $return[$i]['offset'] = $matches[$i][0][1];
9189 if (strlen($matches[$i][3][0]) <= 2)
9191 $return[$i]['self_closing'] = true;
9195 $return[$i]['self_closing'] = false;
9196 $return[$i]['content'] = $matches[$i][4][0];
9198 $return[$i]['attribs'] = array();
9199 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))
9201 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9203 if (count($attribs[$j]) === 2)
9205 $attribs[$j][2] = $attribs[$j][1];
9207 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9215 function element_implode($element)
9217 $full = "<$element[tag]";
9218 foreach ($element['attribs'] as $key => $value)
9220 $key = strtolower($key);
9221 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9223 if ($element['self_closing'])
9229 $full .= ">$element[content]</$element[tag]>";
9234 function error($message, $level, $file, $line)
9236 if ((ini_get('error_reporting') & $level) > 0)
9241 $note = 'PHP Error';
9243 case E_USER_WARNING:
9244 $note = 'PHP Warning';
9247 $note = 'PHP Notice';
9250 $note = 'Unknown Error';
9255 if (!function_exists('error_log'))
9260 $log_file = @ini_get('error_log');
9261 if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9268 @error_log("$note: $message in $file on line $line", 0);
9276 * If a file has been cached, retrieve and display it.
9278 * This is most useful for caching images (get_favicon(), etc.),
9279 * however it works for all cached files. This WILL NOT display ANY
9280 * file/image/page/whatever, but rather only display what has already
9281 * been cached by SimplePie.
9284 * @see SimplePie::get_favicon()
9285 * @param str $identifier_url URL that is used to identify the content.
9286 * This may or may not be the actual URL of the live content.
9287 * @param str $cache_location Location of SimplePie's cache. Defaults
9289 * @param str $cache_extension The file extension that the file was
9290 * cached with. Defaults to 'spc'.
9291 * @param str $cache_class Name of the cache-handling class being used
9292 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9293 * as-is unless you've overloaded the class.
9294 * @param str $cache_name_function Obsolete. Exists for backwards
9295 * compatibility reasons only.
9297 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9299 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9301 if ($file = $cache->load())
9303 if (isset($file['headers']['content-type']))
9305 header('Content-type:' . $file['headers']['content-type']);
9309 header('Content-type: application/octet-stream');
9311 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9316 die('Cached file for ' . $identifier_url . ' cannot be found.');
9319 function fix_protocol($url, $http = 1)
9321 $url = SimplePie_Misc::normalize_url($url);
9322 $parsed = SimplePie_Misc::parse_url($url);
9323 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9325 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9328 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9330 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9333 if ($http === 2 && $parsed['scheme'] !== '')
9337 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9339 return substr_replace($url, 'podcast', 0, 4);
9341 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9343 return substr_replace($url, 'itpc', 0, 4);
9351 function parse_url($url)
9353 $iri =& new SimplePie_IRI($url);
9355 'scheme' => (string) $iri->get_scheme(),
9356 'authority' => (string) $iri->get_authority(),
9357 'path' => (string) $iri->get_path(),
9358 'query' => (string) $iri->get_query(),
9359 'fragment' => (string) $iri->get_fragment()
9363 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9365 $iri =& new SimplePie_IRI('');
9366 $iri->set_scheme($scheme);
9367 $iri->set_authority($authority);
9368 $iri->set_path($path);
9369 $iri->set_query($query);
9370 $iri->set_fragment($fragment);
9371 return $iri->get_iri();
9374 function normalize_url($url)
9376 $iri =& new SimplePie_IRI($url);
9377 return $iri->get_iri();
9380 function percent_encoding_normalization($match)
9382 $integer = hexdec($match[1]);
9383 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9385 return chr($integer);
9389 return strtoupper($match[0]);
9394 * Remove bad UTF-8 bytes
9396 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9397 * FAQ: Multilingual Forms (modified to include full ASCII range)
9399 * @author Geoffrey Sneddon
9400 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9401 * @param string $str String to remove bad UTF-8 bytes from
9402 * @return string UTF-8 string
9404 function utf8_bad_replace($str)
9406 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9410 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9414 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))
9416 return implode("\xEF\xBF\xBD", $matches[0]);
9418 elseif ($str !== '')
9420 return "\xEF\xBF\xBD";
9429 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9433 * @param string $string Windows-1252 encoded string
9434 * @return string UTF-8 encoded string
9436 function windows_1252_to_utf8($string)
9438 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");
9440 return strtr($string, $convert_table);
9443 function change_encoding($data, $input, $output)
9445 $input = SimplePie_Misc::encoding($input);
9446 $output = SimplePie_Misc::encoding($output);
9448 // We fail to fail on non US-ASCII bytes
9449 if ($input === 'US-ASCII')
9451 static $non_ascii_octects = '';
9452 if (!$non_ascii_octects)
9454 for ($i = 0x80; $i <= 0xFF; $i++)
9456 $non_ascii_octects .= chr($i);
9459 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9462 // This is first, as behaviour of this is completely predictable
9463 if ($input === 'windows-1252' && $output === 'UTF-8')
9465 return SimplePie_Misc::windows_1252_to_utf8($data);
9467 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9468 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && in_array($input, mb_list_encodings()) && ($return = @mb_convert_encoding($data, $output, $input)))
9472 // This is last, as behaviour of this varies with OS userland and PHP version
9473 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9477 // If we can't do anything, just fail
9485 * Normalize an encoding name
9487 * This is automatically generated by create.php
9489 * To generate it, run `php create.php` on the command line, and copy the
9490 * output to replace this function.
9492 * @param string $charset Character set to standardise
9493 * @return string Standardised name
9495 function encoding($charset)
9497 // Normalization from UTS #22
9498 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9500 case 'adobestandardencoding':
9501 case 'csadobestandardencoding':
9502 return 'Adobe-Standard-Encoding';
9504 case 'adobesymbolencoding':
9506 return 'Adobe-Symbol-Encoding';
9510 return 'Amiga-1251';
9512 case 'ansix31101983':
9514 case 'csiso99naplps':
9517 return 'ANSI_X3.110-1983';
9521 case 'csiso89asmo449':
9531 return 'Big5-HKSCS';
9542 case 'csiso4unitedkingdom':
9550 case 'csiso47bsviewdata':
9552 return 'BS_viewdata';
9560 case 'csaz243419851':
9561 case 'csiso121canadian1':
9564 return 'CSA_Z243.4-1985-1';
9567 case 'csaz243419852':
9568 case 'csiso122canadian2':
9571 return 'CSA_Z243.4-1985-2';
9573 case 'csaz24341985gr':
9574 case 'csiso123csaz24341985gr':
9576 return 'CSA_Z243.4-1985-gr';
9578 case 'csiso139csn369103':
9581 return 'CSN_369103';
9588 case 'csiso21german':
9599 case 'csiso646danish':
9605 case 'csibmebcdicatde':
9607 return 'EBCDIC-AT-DE';
9609 case 'csebcdicatdea':
9611 return 'EBCDIC-AT-DE-A';
9613 case 'csebcdiccafr':
9615 return 'EBCDIC-CA-FR';
9617 case 'csebcdicdkno':
9619 return 'EBCDIC-DK-NO';
9621 case 'csebcdicdknoa':
9623 return 'EBCDIC-DK-NO-A';
9631 return 'EBCDIC-ES-A';
9635 return 'EBCDIC-ES-S';
9637 case 'csebcdicfise':
9639 return 'EBCDIC-FI-SE';
9641 case 'csebcdicfisea':
9643 return 'EBCDIC-FI-SE-A';
9665 case 'csiso111ecmacyrillic':
9666 case 'ecmacyrillic':
9669 return 'ECMA-cyrillic';
9671 case 'csiso17spanish':
9677 case 'csiso85spanish2':
9683 case 'cseucpkdfmtjapanese':
9685 case 'extendedunixcodepackedformatforjapanese':
9688 case 'cseucfixwidjapanese':
9689 case 'extendedunixcodefixedwidthforjapanese':
9690 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9698 case 'csiso58gb231280':
9708 case 'csiso57gb1988':
9712 return 'GB_1988-80';
9714 case 'csiso153gost1976874':
9718 return 'GOST_19768-74';
9721 case 'csiso150greekccitt':
9724 return 'greek-ccitt';
9726 case 'csiso88greek7':
9731 case 'csiso18greek7old':
9734 return 'greek7-old';
9738 return 'HP-DeskTop';
9750 return 'HP-Pi-font';
9759 return 'HZ-GB-2312';
9761 case 'csibmsymbols':
9763 return 'IBM-Symbols';
9840 case 'ebcdicjpkana':
9870 case 'cspc8codepage437':
9882 case 'cspc775baltic':
9888 case 'cspc850multilingual':
9919 case 'pcmultilingual850euro':
9937 case 'cspc862latinhebrew':
9979 case 'ebcdiccproece':
9992 case 'ebcdiccyrillic':
10020 case 'ebcdiccpar2':
10026 case 'ebcdiclatin9euro':
10040 case 'ebcdicus37euro':
10046 case 'ebcdicde273euro':
10052 case 'ebcdicdk277euro':
10053 case 'ebcdicno277euro':
10059 case 'ebcdicfi278euro':
10060 case 'ebcdicse278euro':
10066 case 'ebcdicit280euro':
10072 case 'ebcdices284euro':
10078 case 'ebcdicgb285euro':
10084 case 'ebcdicfr297euro':
10090 case 'ebcdicinternational500euro':
10096 case 'ebcdicis871euro':
10100 case 'csiso143iecp271':
10103 return 'IEC_P27-1';
10105 case 'csiso49inis':
10110 case 'csiso50inis8':
10115 case 'csiso51iniscyrillic':
10116 case 'iniscyrillic':
10118 return 'INIS-cyrillic';
10120 case 'csinvariant':
10122 return 'INVARIANT';
10125 return 'ISO-2022-CN';
10127 case 'iso2022cnext':
10128 return 'ISO-2022-CN-EXT';
10130 case 'csiso2022jp':
10132 return 'ISO-2022-JP';
10134 case 'csiso2022jp2':
10136 return 'ISO-2022-JP-2';
10138 case 'csiso2022kr':
10140 return 'ISO-2022-KR';
10142 case 'cswindows30latin1':
10143 case 'iso88591windows30latin1':
10144 return 'ISO-8859-1-Windows-3.0-Latin-1';
10146 case 'cswindows31latin1':
10147 case 'iso88591windows31latin1':
10148 return 'ISO-8859-1-Windows-3.1-Latin-1';
10150 case 'csisolatin2':
10152 case 'iso885921987':
10156 return 'ISO-8859-2';
10158 case 'cswindows31latin2':
10159 case 'iso88592windowslatin2':
10160 return 'ISO-8859-2-Windows-Latin-2';
10162 case 'csisolatin3':
10164 case 'iso885931988':
10168 return 'ISO-8859-3';
10170 case 'csisolatin4':
10172 case 'iso885941988':
10176 return 'ISO-8859-4';
10178 case 'csisolatincyrillic':
10181 case 'iso885951988':
10183 return 'ISO-8859-5';
10187 case 'csisolatinarabic':
10190 case 'iso885961987':
10192 return 'ISO-8859-6';
10194 case 'csiso88596e':
10196 return 'ISO-8859-6-E';
10198 case 'csiso88596i':
10200 return 'ISO-8859-6-I';
10202 case 'csisolatingreek':
10208 case 'iso885971987':
10210 return 'ISO-8859-7';
10212 case 'csisolatinhebrew':
10215 case 'iso885981988':
10217 return 'ISO-8859-8';
10219 case 'csiso88598e':
10221 return 'ISO-8859-8-E';
10223 case 'csiso88598i':
10225 return 'ISO-8859-8-I';
10227 case 'cswindows31latin5':
10228 case 'iso88599windowslatin5':
10229 return 'ISO-8859-9-Windows-Latin-5';
10231 case 'csisolatin6':
10233 case 'iso8859101992':
10237 return 'ISO-8859-10';
10240 return 'ISO-8859-13';
10243 case 'iso8859141998':
10248 return 'ISO-8859-14';
10252 return 'ISO-8859-15';
10255 case 'iso8859162001':
10259 return 'ISO-8859-16';
10262 return 'ISO-10646-J-1';
10265 case 'iso10646ucs2':
10266 return 'ISO-10646-UCS-2';
10269 case 'iso10646ucs4':
10270 return 'ISO-10646-UCS-4';
10272 case 'csunicodeascii':
10273 case 'iso10646ucsbasic':
10274 return 'ISO-10646-UCS-Basic';
10276 case 'csunicodelatin1':
10278 case 'iso10646unicodelatin1':
10279 return 'ISO-10646-Unicode-Latin1';
10281 case 'csiso10646utf1':
10282 case 'iso10646utf1':
10283 return 'ISO-10646-UTF-1';
10285 case 'csiso115481':
10287 case 'isotr115481':
10288 return 'ISO-11548-1';
10292 return 'iso-ir-90';
10294 case 'csunicodeibm1261':
10295 case 'isounicodeibm1261':
10296 return 'ISO-Unicode-IBM-1261';
10298 case 'csunicodeibm1264':
10299 case 'isounicodeibm1264':
10300 return 'ISO-Unicode-IBM-1264';
10302 case 'csunicodeibm1265':
10303 case 'isounicodeibm1265':
10304 return 'ISO-Unicode-IBM-1265';
10306 case 'csunicodeibm1268':
10307 case 'isounicodeibm1268':
10308 return 'ISO-Unicode-IBM-1268';
10310 case 'csunicodeibm1276':
10311 case 'isounicodeibm1276':
10312 return 'ISO-Unicode-IBM-1276';
10314 case 'csiso646basic1983':
10315 case 'iso646basic1983':
10317 return 'ISO_646.basic:1983';
10319 case 'csiso2intlrefversion':
10321 case 'iso646irv1983':
10323 return 'ISO_646.irv:1983';
10327 case 'iso20331983':
10329 return 'ISO_2033-1983';
10331 case 'csiso5427cyrillic':
10336 case 'iso5427cyrillic1981':
10337 case 'iso54271981':
10339 return 'ISO_5427:1981';
10341 case 'csiso5428greek':
10342 case 'iso54281980':
10344 return 'ISO_5428:1980';
10346 case 'csiso6937add':
10349 return 'ISO_6937-2-25';
10351 case 'csisotextcomm':
10352 case 'iso69372add':
10354 return 'ISO_6937-2-add';
10356 case 'csiso8859supp':
10357 case 'iso8859supp':
10360 return 'ISO_8859-supp';
10362 case 'csiso10367box':
10363 case 'iso10367box':
10365 return 'ISO_10367-box';
10367 case 'csiso15italian':
10373 case 'csiso13jisc6220jp':
10375 case 'jisc62201969':
10376 case 'jisc62201969jp':
10379 return 'JIS_C6220-1969-jp';
10381 case 'csiso14jisc6220ro':
10384 case 'jisc62201969ro':
10386 return 'JIS_C6220-1969-ro';
10388 case 'csiso42jisc62261978':
10390 case 'jisc62261978':
10391 return 'JIS_C6226-1978';
10393 case 'csiso87jisx208':
10395 case 'jisc62261983':
10396 case 'jisx2081983':
10398 return 'JIS_C6226-1983';
10400 case 'csiso91jisc62291984a':
10402 case 'jisc62291984a':
10404 return 'JIS_C6229-1984-a';
10406 case 'csiso92jisc62991984b':
10407 case 'iso646jpocrb':
10409 case 'jisc62291984b':
10411 return 'JIS_C6229-1984-b';
10413 case 'csiso93jis62291984badd':
10415 case 'jisc62291984badd':
10417 return 'JIS_C6229-1984-b-add';
10419 case 'csiso94jis62291984hand':
10421 case 'jisc62291984hand':
10423 return 'JIS_C6229-1984-hand';
10425 case 'csiso95jis62291984handadd':
10427 case 'jisc62291984handadd':
10428 case 'jpocrhandadd':
10429 return 'JIS_C6229-1984-hand-add';
10431 case 'csiso96jisc62291984kana':
10433 case 'jisc62291984kana':
10434 return 'JIS_C6229-1984-kana';
10436 case 'csjisencoding':
10437 case 'jisencoding':
10438 return 'JIS_Encoding';
10440 case 'cshalfwidthkatakana':
10443 return 'JIS_X0201';
10445 case 'csiso159jisx2121990':
10447 case 'jisx2121990':
10449 return 'JIS_X0212-1990';
10451 case 'csiso141jusib1002':
10457 return 'JUS_I.B1.002';
10459 case 'csiso147macedonian':
10461 case 'jusib1003mac':
10463 return 'JUS_I.B1.003-mac';
10465 case 'csiso146serbian':
10467 case 'jusib1003serb':
10469 return 'JUS_I.B1.003-serb';
10471 case 'koi7switched':
10472 return 'KOI7-switched';
10489 case 'strk10482002':
10492 case 'csiso19latingreek':
10495 return 'latin-greek';
10497 case 'csiso27latingreek1':
10499 case 'latingreek1':
10500 return 'Latin-greek-1';
10502 case 'csiso158lap':
10506 return 'latin-lap';
10508 case 'csmacintosh':
10511 return 'macintosh';
10513 case 'csmicrosoftpublishing':
10514 case 'microsoftpublishing':
10515 return 'Microsoft-Publishing';
10525 case 'csiso86hungarian':
10530 return 'MSZ_7795.3';
10535 return 'NATS-DANO';
10537 case 'csnatsdanoadd':
10539 case 'natsdanoadd':
10540 return 'NATS-DANO-ADD';
10545 return 'NATS-SEFI';
10547 case 'csnatssefiadd':
10549 case 'natssefiadd':
10550 return 'NATS-SEFI-ADD';
10552 case 'csiso151cuba':
10557 return 'NC_NC00-10:81';
10559 case 'csiso69french':
10564 return 'NF_Z_62-010';
10566 case 'csiso25french':
10569 case 'nfz620101973':
10570 return 'NF_Z_62-010_(1973)';
10572 case 'csiso60danishnorwegian':
10573 case 'csiso60norwegian1':
10578 return 'NS_4551-1';
10580 case 'csiso61norwegian2':
10585 return 'NS_4551-2';
10587 case 'osdebcdicdf3irv':
10588 return 'OSD_EBCDIC_DF03_IRV';
10590 case 'osdebcdicdf41':
10591 return 'OSD_EBCDIC_DF04_1';
10593 case 'osdebcdicdf415':
10594 return 'OSD_EBCDIC_DF04_15';
10596 case 'cspc8danishnorwegian':
10597 case 'pc8danishnorwegian':
10598 return 'PC8-Danish-Norwegian';
10600 case 'cspc8turkish':
10602 return 'PC8-Turkish';
10604 case 'csiso16portuguese':
10610 case 'csiso84portuguese2':
10618 case 'cyrillicasian':
10626 case 'csiso10swedish':
10633 return 'SEN_850200_B';
10635 case 'csiso11swedishfornames':
10640 return 'SEN_850200_C';
10642 case 'csiso102t617bit':
10645 return 'T.61-7bit';
10647 case 'csiso103t618bit':
10651 return 'T.61-8bit';
10653 case 'csiso128t101g2':
10662 case 'csunicode11':
10664 return 'UNICODE-1-1';
10666 case 'csunicode11utf7':
10667 case 'unicode11utf7':
10668 return 'UNICODE-1-1-UTF-7';
10670 case 'csunknown8bit':
10671 case 'unknown8bit':
10672 return 'UNKNOWN-8BIT';
10674 case 'ansix341968':
10675 case 'ansix341986':
10680 case 'iso646irv1991':
10715 case 'csventurainternational':
10716 case 'venturainternational':
10717 return 'Ventura-International';
10719 case 'csventuramath':
10720 case 'venturamath':
10721 return 'Ventura-Math';
10723 case 'csventuraus':
10725 return 'Ventura-US';
10727 case 'csiso70videotexsupp1':
10729 case 'videotexsuppl':
10730 return 'videotex-suppl';
10741 case 'cswindows31j':
10745 return 'Windows-31J';
10749 return 'windows-874';
10752 case 'csksc56011987':
10757 case 'ksc56011987':
10758 case 'ksc56011989':
10760 return 'windows-949';
10762 case 'windows1250':
10763 return 'windows-1250';
10765 case 'windows1251':
10766 return 'windows-1251';
10769 case 'csisolatin1':
10772 case 'iso885911987':
10776 case 'windows1252':
10777 return 'windows-1252';
10779 case 'windows1253':
10780 return 'windows-1253';
10782 case 'csisolatin5':
10784 case 'iso885991989':
10788 case 'windows1254':
10789 return 'windows-1254';
10791 case 'windows1255':
10792 return 'windows-1255';
10794 case 'windows1256':
10795 return 'windows-1256';
10797 case 'windows1257':
10798 return 'windows-1257';
10800 case 'windows1258':
10801 return 'windows-1258';
10808 function get_curl_version()
10810 if (is_array($curl = curl_version()))
10812 $curl = $curl['version'];
10814 elseif (substr($curl, 0, 5) === 'curl/')
10816 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10818 elseif (substr($curl, 0, 8) === 'libcurl/')
10820 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10829 function is_subclass_of($class1, $class2)
10831 if (func_num_args() !== 2)
10833 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10835 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10837 return is_subclass_of($class1, $class2);
10839 elseif (is_string($class1) && is_string($class2))
10841 if (class_exists($class1))
10843 if (class_exists($class2))
10845 $class2 = strtolower($class2);
10846 while ($class1 = strtolower(get_parent_class($class1)))
10848 if ($class1 === $class2)
10857 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10864 * Strip HTML comments
10867 * @param string $data Data to strip comments from
10868 * @return string Comment stripped string
10870 function strip_comments($data)
10873 while (($start = strpos($data, '<!--')) !== false)
10875 $output .= substr($data, 0, $start);
10876 if (($end = strpos($data, '-->', $start)) !== false)
10878 $data = substr_replace($data, '', 0, $end + 3);
10885 return $output . $data;
10888 function parse_date($dt)
10890 $parser = SimplePie_Parse_Date::get();
10891 return $parser->parse($dt);
10895 * Decode HTML entities
10899 * @param string $data Input data
10900 * @return string Output data
10902 function entities_decode($data)
10904 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10905 return $decoder->parse();
10909 * Remove RFC822 comments
10912 * @param string $data Data to strip comments from
10913 * @return string Comment stripped string
10915 function uncomment_rfc822($string)
10917 $string = (string) $string;
10919 $length = strlen($string);
10924 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10926 $output .= substr($string, $position, $pos - $position);
10927 $position = $pos + 1;
10928 if ($string[$pos - 1] !== '\\')
10931 while ($depth && $position < $length)
10933 $position += strcspn($string, '()', $position);
10934 if ($string[$position - 1] === '\\')
10939 elseif (isset($string[$position]))
10941 switch ($string[$position])
10964 $output .= substr($string, $position);
10969 function parse_mime($mime)
10971 if (($pos = strpos($mime, ';')) === false)
10973 return trim($mime);
10977 return trim(substr($mime, 0, $pos));
10981 function htmlspecialchars_decode($string, $quote_style)
10983 if (function_exists('htmlspecialchars_decode'))
10985 return htmlspecialchars_decode($string, $quote_style);
10989 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10993 function atom_03_construct_type($attribs)
10995 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10997 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
11001 $mode = SIMPLEPIE_CONSTRUCT_NONE;
11003 if (isset($attribs['']['type']))
11005 switch (strtolower(trim($attribs['']['type'])))
11009 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11013 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11016 case 'application/xhtml+xml':
11017 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11020 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11025 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11029 function atom_10_construct_type($attribs)
11031 if (isset($attribs['']['type']))
11033 switch (strtolower(trim($attribs['']['type'])))
11036 return SIMPLEPIE_CONSTRUCT_TEXT;
11039 return SIMPLEPIE_CONSTRUCT_HTML;
11042 return SIMPLEPIE_CONSTRUCT_XHTML;
11045 return SIMPLEPIE_CONSTRUCT_NONE;
11048 return SIMPLEPIE_CONSTRUCT_TEXT;
11051 function atom_10_content_construct_type($attribs)
11053 if (isset($attribs['']['type']))
11055 $type = strtolower(trim($attribs['']['type']));
11059 return SIMPLEPIE_CONSTRUCT_TEXT;
11062 return SIMPLEPIE_CONSTRUCT_HTML;
11065 return SIMPLEPIE_CONSTRUCT_XHTML;
11067 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11069 return SIMPLEPIE_CONSTRUCT_NONE;
11073 return SIMPLEPIE_CONSTRUCT_BASE64;
11078 return SIMPLEPIE_CONSTRUCT_TEXT;
11082 function is_isegment_nz_nc($string)
11084 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);
11087 function space_seperated_tokens($string)
11089 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11090 $string_length = strlen($string);
11092 $position = strspn($string, $space_characters);
11095 while ($position < $string_length)
11097 $len = strcspn($string, $space_characters, $position);
11098 $tokens[] = substr($string, $position, $len);
11100 $position += strspn($string, $space_characters, $position);
11106 function array_unique($array)
11108 if (version_compare(PHP_VERSION, '5.2', '>='))
11110 return array_unique($array);
11114 $array = (array) $array;
11115 $new_array = array();
11116 $new_array_strings = array();
11117 foreach ($array as $key => $value)
11119 if (is_object($value))
11121 if (method_exists($value, '__toString'))
11123 $cmp = $value->__toString();
11127 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11130 elseif (is_array($value))
11132 $cmp = (string) reset($value);
11136 $cmp = (string) $value;
11138 if (!in_array($cmp, $new_array_strings))
11140 $new_array[$key] = $value;
11141 $new_array_strings[] = $cmp;
11149 * Converts a unicode codepoint to a UTF-8 character
11153 * @param int $codepoint Unicode codepoint
11154 * @return string UTF-8 character
11156 function codepoint_to_utf8($codepoint)
11158 $codepoint = (int) $codepoint;
11159 if ($codepoint < 0)
11163 else if ($codepoint <= 0x7f)
11165 return chr($codepoint);
11167 else if ($codepoint <= 0x7ff)
11169 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11171 else if ($codepoint <= 0xffff)
11173 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11175 else if ($codepoint <= 0x10ffff)
11177 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11181 // U+FFFD REPLACEMENT CHARACTER
11182 return "\xEF\xBF\xBD";
11187 * Re-implementation of PHP 5's stripos()
11189 * Returns the numeric position of the first occurrence of needle in the
11194 * @param object $haystack
11195 * @param string $needle Note that the needle may be a string of one or more
11196 * characters. If needle is not a string, it is converted to an integer
11197 * and applied as the ordinal value of a character.
11198 * @param int $offset The optional offset parameter allows you to specify which
11199 * character in haystack to start searching. The position returned is still
11200 * relative to the beginning of haystack.
11201 * @return bool If needle is not found, stripos() will return boolean false.
11203 function stripos($haystack, $needle, $offset = 0)
11205 if (function_exists('stripos'))
11207 return stripos($haystack, $needle, $offset);
11211 if (is_string($needle))
11213 $needle = strtolower($needle);
11215 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11217 $needle = strtolower(chr($needle));
11221 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11225 return strpos(strtolower($haystack), $needle, $offset);
11230 * Similar to parse_str()
11232 * Returns an associative array of name/value pairs, where the value is an
11233 * array of values that have used the same name
11237 * @param string $str The input string.
11240 function parse_str($str)
11243 $str = explode('&', $str);
11245 foreach ($str as $section)
11247 if (strpos($section, '=') !== false)
11249 list($name, $value) = explode('=', $section, 2);
11250 $return[urldecode($name)][] = urldecode($value);
11254 $return[urldecode($section)][] = null;
11262 * Detect XML encoding, as per XML 1.0 Appendix F.1
11264 * @todo Add support for EBCDIC
11265 * @param string $data XML data
11266 * @return array Possible encodings
11268 function xml_encoding($data)
11270 // UTF-32 Big Endian BOM
11271 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11273 $encoding[] = 'UTF-32BE';
11275 // UTF-32 Little Endian BOM
11276 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11278 $encoding[] = 'UTF-32LE';
11280 // UTF-16 Big Endian BOM
11281 elseif (substr($data, 0, 2) === "\xFE\xFF")
11283 $encoding[] = 'UTF-16BE';
11285 // UTF-16 Little Endian BOM
11286 elseif (substr($data, 0, 2) === "\xFF\xFE")
11288 $encoding[] = 'UTF-16LE';
11291 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11293 $encoding[] = 'UTF-8';
11295 // UTF-32 Big Endian Without BOM
11296 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")
11298 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11300 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11301 if ($parser->parse())
11303 $encoding[] = $parser->encoding;
11306 $encoding[] = 'UTF-32BE';
11308 // UTF-32 Little Endian Without BOM
11309 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")
11311 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11313 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11314 if ($parser->parse())
11316 $encoding[] = $parser->encoding;
11319 $encoding[] = 'UTF-32LE';
11321 // UTF-16 Big Endian Without BOM
11322 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11324 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11326 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11327 if ($parser->parse())
11329 $encoding[] = $parser->encoding;
11332 $encoding[] = 'UTF-16BE';
11334 // UTF-16 Little Endian Without BOM
11335 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11337 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11339 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11340 if ($parser->parse())
11342 $encoding[] = $parser->encoding;
11345 $encoding[] = 'UTF-16LE';
11347 // US-ASCII (or superset)
11348 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11350 if ($pos = strpos($data, "\x3F\x3E"))
11352 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11353 if ($parser->parse())
11355 $encoding[] = $parser->encoding;
11358 $encoding[] = 'UTF-8';
11360 // Fallback to UTF-8
11363 $encoding[] = 'UTF-8';
11368 function output_javascript()
11370 if (function_exists('ob_gzhandler'))
11372 ob_start('ob_gzhandler');
11374 header('Content-type: text/javascript; charset: UTF-8');
11375 header('Cache-Control: must-revalidate');
11376 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11378 function embed_odeo(link) {
11379 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>');
11382 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11383 if (placeholder != '') {
11384 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>');
11387 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>');
11391 function embed_flash(bgcolor, width, height, link, loop, type) {
11392 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>');
11395 function embed_flv(width, height, link, placeholder, loop, player) {
11396 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>');
11399 function embed_wmedia(width, height, link) {
11400 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11408 * Format debugging information
11410 function debug($sp)
11412 $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
11413 $info .= 'PHP ' . PHP_VERSION . "\n";
11414 if ($sp->error() !== null)
11416 $info .= 'Error occurred: ' . $sp->error() . "\n";
11420 $info .= "No error found.\n";
11422 $info .= "Extensions:\n";
11423 $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
11424 foreach ($extensions as $ext)
11426 if (extension_loaded($ext))
11428 $info .= " $ext loaded\n";
11432 $info .= ' Version ' . PCRE_VERSION . "\n";
11435 $version = curl_version();
11436 $info .= ' Version ' . $version['version'] . "\n";
11439 $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
11442 $info .= ' Version ' . ICONV_VERSION . "\n";
11445 $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n";
11451 $info .= " $ext not loaded\n";
11459 * Decode HTML Entities
11461 * This implements HTML5 as of revision 967 (2007-06-28)
11463 * @package SimplePie
11465 class SimplePie_Decode_HTML_Entities
11468 * Data to be parsed
11476 * Currently consumed bytes
11481 var $consumed = '';
11484 * Position of the current byte being parsed
11492 * Create an instance of the class with the input data
11495 * @param string $data Input data
11497 function SimplePie_Decode_HTML_Entities($data)
11499 $this->data = $data;
11503 * Parse the input data
11506 * @return string Output data
11510 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11514 $this->consumed = '';
11516 return $this->data;
11520 * Consume the next byte
11523 * @return mixed The next byte, or false, if there is no more data
11527 if (isset($this->data[$this->position]))
11529 $this->consumed .= $this->data[$this->position];
11530 return $this->data[$this->position++];
11539 * Consume a range of characters
11542 * @param string $chars Characters to consume
11543 * @return mixed A series of characters that match the range, or false
11545 function consume_range($chars)
11547 if ($len = strspn($this->data, $chars, $this->position))
11549 $data = substr($this->data, $this->position, $len);
11550 $this->consumed .= $data;
11551 $this->position += $len;
11561 * Unconsume one byte
11565 function unconsume()
11567 $this->consumed = substr($this->consumed, 0, -1);
11578 switch ($this->consume())
11592 switch ($this->consume())
11596 $range = '0123456789ABCDEFabcdef';
11601 $range = '0123456789';
11603 $this->unconsume();
11607 if ($codepoint = $this->consume_range($range))
11609 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");
11613 $codepoint = hexdec($codepoint);
11617 $codepoint = intval($codepoint);
11620 if (isset($windows_1252_specials[$codepoint]))
11622 $replacement = $windows_1252_specials[$codepoint];
11626 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11629 if (!in_array($this->consume(), array(';', false), true))
11631 $this->unconsume();
11634 $consumed_length = strlen($this->consumed);
11635 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11636 $this->position += strlen($replacement) - $consumed_length;
11641 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");
11643 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11645 $consumed = substr($this->consumed, 1);
11646 if (isset($entities[$consumed]))
11648 $match = $consumed;
11652 if ($match !== null)
11654 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11655 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11663 * IRI parser/serialiser
11665 * @package SimplePie
11667 class SimplePie_IRI
11726 * Whether the object represents a valid IRI
11731 var $valid = array();
11734 * Return the entire IRI when you try and read the object as a string
11739 function __toString()
11741 return $this->get_iri();
11745 * Create a new IRI object, from a specified string
11748 * @param string $iri
11749 * @return SimplePie_IRI
11751 function SimplePie_IRI($iri)
11753 $iri = (string) $iri;
11756 $parsed = $this->parse_iri($iri);
11757 $this->set_scheme($parsed['scheme']);
11758 $this->set_authority($parsed['authority']);
11759 $this->set_path($parsed['path']);
11760 $this->set_query($parsed['query']);
11761 $this->set_fragment($parsed['fragment']);
11766 * Create a new IRI object by resolving a relative IRI
11770 * @param SimplePie_IRI $base Base IRI
11771 * @param string $relative Relative IRI
11772 * @return SimplePie_IRI
11774 function absolutize($base, $relative)
11776 $relative = (string) $relative;
11777 if ($relative !== '')
11779 $relative =& new SimplePie_IRI($relative);
11780 if ($relative->get_scheme() !== null)
11782 $target = $relative;
11784 elseif ($base->get_iri() !== null)
11786 if ($relative->get_authority() !== null)
11788 $target = $relative;
11789 $target->set_scheme($base->get_scheme());
11793 $target =& new SimplePie_IRI('');
11794 $target->set_scheme($base->get_scheme());
11795 $target->set_userinfo($base->get_userinfo());
11796 $target->set_host($base->get_host());
11797 $target->set_port($base->get_port());
11798 if ($relative->get_path() !== null)
11800 if (strpos($relative->get_path(), '/') === 0)
11802 $target->set_path($relative->get_path());
11804 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11806 $target->set_path('/' . $relative->get_path());
11808 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11810 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11814 $target->set_path($relative->get_path());
11816 $target->set_query($relative->get_query());
11820 $target->set_path($base->get_path());
11821 if ($relative->get_query() !== null)
11823 $target->set_query($relative->get_query());
11825 elseif ($base->get_query() !== null)
11827 $target->set_query($base->get_query());
11831 $target->set_fragment($relative->get_fragment());
11835 // No base URL, just return the relative URL
11836 $target = $relative;
11847 * Parse an IRI into scheme/authority/path/query/fragment segments
11850 * @param string $iri
11853 function parse_iri($iri)
11855 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11856 for ($i = count($match); $i <= 9; $i++)
11860 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11864 * Remove dot segments from a path
11867 * @param string $input
11870 function remove_dot_segments($input)
11873 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11875 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11876 if (strpos($input, '../') === 0)
11878 $input = substr($input, 3);
11880 elseif (strpos($input, './') === 0)
11882 $input = substr($input, 2);
11884 // 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,
11885 elseif (strpos($input, '/./') === 0)
11887 $input = substr_replace($input, '/', 0, 3);
11889 elseif ($input === '/.')
11893 // 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,
11894 elseif (strpos($input, '/../') === 0)
11896 $input = substr_replace($input, '/', 0, 4);
11897 $output = substr_replace($output, '', strrpos($output, '/'));
11899 elseif ($input === '/..')
11902 $output = substr_replace($output, '', strrpos($output, '/'));
11904 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11905 elseif ($input === '.' || $input === '..')
11909 // 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
11910 elseif (($pos = strpos($input, '/', 1)) !== false)
11912 $output .= substr($input, 0, $pos);
11913 $input = substr_replace($input, '', 0, $pos);
11921 return $output . $input;
11925 * Replace invalid character with percent encoding
11927 * @param string $string Input string
11928 * @param string $valid_chars Valid characters
11929 * @param int $case Normalise case
11932 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false)
11934 // Normalize as many pct-encoded sections as possible
11935 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
11937 // Replace invalid percent characters
11938 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
11940 // Add unreserved and % to $valid_chars (the latter is safe because all
11941 // pct-encoded sections are now valid).
11942 $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
11944 // Now replace any bytes that aren't allowed with their pct-encoded versions
11946 $strlen = strlen($string);
11947 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11949 $value = ord($string[$position]);
11952 $start = $position;
11954 // By default we are valid
11957 // No one byte sequences are valid due to the while.
11958 // Two byte sequence:
11959 if (($value & 0xE0) === 0xC0)
11961 $character = ($value & 0x1F) << 6;
11965 // Three byte sequence:
11966 elseif (($value & 0xF0) === 0xE0)
11968 $character = ($value & 0x0F) << 12;
11972 // Four byte sequence:
11973 elseif (($value & 0xF8) === 0xF0)
11975 $character = ($value & 0x07) << 18;
11989 if ($position + $length <= $strlen)
11991 for ($position++; $remaining; $position++)
11993 $value = ord($string[$position]);
11995 // Check that the byte is valid, then add it to the character:
11996 if (($value & 0xC0) === 0x80)
11998 $character |= ($value & 0x3F) << (--$remaining * 6);
12000 // If it is invalid, count the sequence as invalid and reprocess the current byte:
12011 $position = $strlen - 1;
12016 // Percent encode anything invalid or not in ucschar
12018 // Invalid sequences
12020 // Non-shortest form sequences are invalid
12021 || $length > 1 && $character <= 0x7F
12022 || $length > 2 && $character <= 0x7FF
12023 || $length > 3 && $character <= 0xFFFF
12024 // Outside of range of ucschar codepoints
12026 || ($character & 0xFFFE) === 0xFFFE
12027 || $character >= 0xFDD0 && $character <= 0xFDEF
12029 // Everything else not in ucschar
12030 $character > 0xD7FF && $character < 0xF900
12031 || $character < 0xA0
12032 || $character > 0xEFFFD
12035 // Everything not in iprivate, if it applies
12037 || $character < 0xE000
12038 || $character > 0x10FFFD
12042 // If we were a character, pretend we weren't, but rather an error.
12046 for ($j = $start; $j <= $position; $j++)
12048 $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
12057 if ($case & SIMPLEPIE_LOWERCASE)
12059 $string = strtolower($string);
12061 elseif ($case & SIMPLEPIE_UPPERCASE)
12063 $string = strtoupper($string);
12070 * Callback function for preg_replace_callback.
12072 * Removes sequences of percent encoded bytes that represent UTF-8
12073 * encoded characters in iunreserved
12076 * @param array $match PCRE match
12077 * @return string Replacement
12079 function remove_iunreserved_percent_encoded($match)
12081 // As we just have valid percent encoded sequences we can just explode
12082 // and ignore the first member of the returned array (an empty string).
12083 $bytes = explode('%', $match[0]);
12085 // Initialize the new string (this is what will be returned) and that
12086 // there are no bytes remaining in the current sequence (unsurprising
12087 // at the first byte!).
12091 // Loop over each and every byte, and set $value to its value
12092 for ($i = 1, $len = count($bytes); $i < $len; $i++)
12094 $value = hexdec($bytes[$i]);
12096 // If we're the first byte of sequence:
12102 // By default we are valid
12105 // One byte sequence:
12106 if ($value <= 0x7F)
12108 $character = $value;
12111 // Two byte sequence:
12112 elseif (($value & 0xE0) === 0xC0)
12114 $character = ($value & 0x1F) << 6;
12118 // Three byte sequence:
12119 elseif (($value & 0xF0) === 0xE0)
12121 $character = ($value & 0x0F) << 12;
12125 // Four byte sequence:
12126 elseif (($value & 0xF8) === 0xF0)
12128 $character = ($value & 0x07) << 18;
12139 // Continuation byte:
12142 // Check that the byte is valid, then add it to the character:
12143 if (($value & 0xC0) === 0x80)
12146 $character |= ($value & 0x3F) << ($remaining * 6);
12148 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
12157 // If we've reached the end of the current byte sequence, append it to Unicode::$data
12160 // Percent encode anything invalid or not in iunreserved
12162 // Invalid sequences
12164 // Non-shortest form sequences are invalid
12165 || $length > 1 && $character <= 0x7F
12166 || $length > 2 && $character <= 0x7FF
12167 || $length > 3 && $character <= 0xFFFF
12168 // Outside of range of iunreserved codepoints
12169 || $character < 0x2D
12170 || $character > 0xEFFFD
12172 || ($character & 0xFFFE) === 0xFFFE
12173 || $character >= 0xFDD0 && $character <= 0xFDEF
12174 // Everything else not in iunreserved (this is all BMP)
12175 || $character === 0x2F
12176 || $character > 0x39 && $character < 0x41
12177 || $character > 0x5A && $character < 0x61
12178 || $character > 0x7A && $character < 0x7E
12179 || $character > 0x7E && $character < 0xA0
12180 || $character > 0xD7FF && $character < 0xF900
12183 for ($j = $start; $j <= $i; $j++)
12185 $string .= '%' . strtoupper($bytes[$j]);
12190 for ($j = $start; $j <= $i; $j++)
12192 $string .= chr(hexdec($bytes[$j]));
12198 // If we have any bytes left over they are invalid (i.e., we are
12199 // mid-way through a multi-byte sequence)
12202 for ($j = $start; $j < $len; $j++)
12204 $string .= '%' . strtoupper($bytes[$j]);
12212 * Check if the object represents a valid IRI
12217 function is_valid()
12219 return array_sum($this->valid) === count($this->valid);
12223 * Set the scheme. Returns true on success, false on failure (if there are
12224 * any invalid characters).
12227 * @param string $scheme
12230 function set_scheme($scheme)
12232 if ($scheme === null || $scheme === '')
12234 $this->scheme = null;
12238 $len = strlen($scheme);
12242 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12244 $this->scheme = null;
12245 $this->valid[__FUNCTION__] = false;
12250 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12252 $this->scheme = null;
12253 $this->valid[__FUNCTION__] = false;
12257 $this->scheme = strtolower($scheme);
12259 $this->valid[__FUNCTION__] = true;
12264 * Set the authority. Returns true on success, false on failure (if there are
12265 * any invalid characters).
12268 * @param string $authority
12271 function set_authority($authority)
12273 if (($userinfo_end = strrpos($authority, '@')) !== false)
12275 $userinfo = substr($authority, 0, $userinfo_end);
12276 $authority = substr($authority, $userinfo_end + 1);
12283 if (($port_start = strpos($authority, ':')) !== false)
12285 $port = substr($authority, $port_start + 1);
12286 $authority = substr($authority, 0, $port_start);
12293 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12297 * Set the userinfo.
12300 * @param string $userinfo
12303 function set_userinfo($userinfo)
12305 if ($userinfo === null || $userinfo === '')
12307 $this->userinfo = null;
12311 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12313 $this->valid[__FUNCTION__] = true;
12318 * Set the host. Returns true on success, false on failure (if there are
12319 * any invalid characters).
12322 * @param string $host
12325 function set_host($host)
12327 if ($host === null || $host === '')
12329 $this->host = null;
12330 $this->valid[__FUNCTION__] = true;
12333 elseif ($host[0] === '[' && substr($host, -1) === ']')
12335 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
12337 $this->host = $host;
12338 $this->valid[__FUNCTION__] = true;
12343 $this->host = null;
12344 $this->valid[__FUNCTION__] = false;
12350 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12351 $this->valid[__FUNCTION__] = true;
12357 * Set the port. Returns true on success, false on failure (if there are
12358 * any invalid characters).
12361 * @param string $port
12364 function set_port($port)
12366 if ($port === null || $port === '')
12368 $this->port = null;
12369 $this->valid[__FUNCTION__] = true;
12372 elseif (strspn($port, '0123456789') === strlen($port))
12374 $this->port = (int) $port;
12375 $this->valid[__FUNCTION__] = true;
12380 $this->port = null;
12381 $this->valid[__FUNCTION__] = false;
12390 * @param string $path
12393 function set_path($path)
12395 if ($path === null || $path === '')
12397 $this->path = null;
12398 $this->valid[__FUNCTION__] = true;
12401 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12403 $this->path = null;
12404 $this->valid[__FUNCTION__] = false;
12409 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12410 if ($this->scheme !== null)
12412 $this->path = $this->remove_dot_segments($this->path);
12414 $this->valid[__FUNCTION__] = true;
12423 * @param string $query
12426 function set_query($query)
12428 if ($query === null || $query === '')
12430 $this->query = null;
12434 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
12436 $this->valid[__FUNCTION__] = true;
12441 * Set the fragment.
12444 * @param string $fragment
12447 function set_fragment($fragment)
12449 if ($fragment === null || $fragment === '')
12451 $this->fragment = null;
12455 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12457 $this->valid[__FUNCTION__] = true;
12462 * Get the complete IRI
12470 if ($this->scheme !== null)
12472 $iri .= $this->scheme . ':';
12474 if (($authority = $this->get_authority()) !== null)
12476 $iri .= '//' . $authority;
12478 if ($this->path !== null)
12480 $iri .= $this->path;
12482 if ($this->query !== null)
12484 $iri .= '?' . $this->query;
12486 if ($this->fragment !== null)
12488 $iri .= '#' . $this->fragment;
12507 function get_scheme()
12509 return $this->scheme;
12513 * Get the complete authority
12518 function get_authority()
12521 if ($this->userinfo !== null)
12523 $authority .= $this->userinfo . '@';
12525 if ($this->host !== null)
12527 $authority .= $this->host;
12529 if ($this->port !== null)
12531 $authority .= ':' . $this->port;
12534 if ($authority !== '')
12545 * Get the user information
12550 function get_userinfo()
12552 return $this->userinfo;
12561 function get_host()
12563 return $this->host;
12572 function get_port()
12574 return $this->port;
12583 function get_path()
12585 return $this->path;
12594 function get_query()
12596 return $this->query;
12605 function get_fragment()
12607 return $this->fragment;
12612 * Class to validate and to work with IPv6 addresses.
12614 * @package SimplePie
12615 * @copyright 2003-2005 The PHP Group
12616 * @license http://www.opensource.org/licenses/bsd-license.php
12617 * @link http://pear.php.net/package/Net_IPv6
12618 * @author Alexander Merz <alexander.merz@web.de>
12619 * @author elfrink at introweb dot nl
12620 * @author Josh Peck <jmp at joshpeck dot org>
12621 * @author Geoffrey Sneddon <geoffers@gmail.com>
12623 class SimplePie_Net_IPv6
12626 * Removes a possible existing netmask specification of an IP address.
12628 * @param string $ip the (compressed) IP as Hex representation
12629 * @return string the IP the without netmask
12634 function removeNetmaskSpec($ip)
12636 if (strpos($ip, '/') !== false)
12638 list($addr, $nm) = explode('/', $ip);
12648 * Uncompresses an IPv6 address
12650 * RFC 2373 allows you to compress zeros in an address to '::'. This
12651 * function expects an valid IPv6 address and expands the '::' to
12652 * the required zeros.
12654 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12655 * ::1 -> 0:0:0:0:0:0:0:1
12659 * @param string $ip a valid IPv6-address (hex format)
12660 * @return string the uncompressed IPv6-address (hex format)
12662 function Uncompress($ip)
12664 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12667 if (strpos($ip, '::') !== false)
12669 list($ip1, $ip2) = explode('::', $ip);
12677 if (($pos = substr_count($ip1, ':')) > 0)
12693 if (($pos = substr_count($ip2, ':')) > 0)
12702 if (strstr($ip2, '.'))
12707 if ($c1 === -1 && $c2 === -1)
12709 $uip = '0:0:0:0:0:0:0:0';
12712 else if ($c1 === -1)
12714 $fill = str_repeat('0:', 7 - $c2);
12715 $uip = str_replace('::', $fill, $uip);
12718 else if ($c2 === -1)
12720 $fill = str_repeat(':0', 7 - $c1);
12721 $uip = str_replace('::', $fill, $uip);
12726 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12727 $uip = str_replace('::', $fill, $uip);
12728 $uip = str_replace('::', ':', $uip);
12735 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12737 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12738 * an IPv4 compatible address
12740 * Example: 0:0:0:0:0:0:13.1.68.3
12741 * 0:0:0:0:0:FFFF:129.144.52.38
12745 * @param string $ip a valid IPv6-address (hex format)
12746 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12748 function SplitV64($ip)
12750 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12751 if (strstr($ip, '.'))
12753 $pos = strrpos($ip, ':');
12755 $ipPart = explode('_', $ip);
12760 return array($ip, '');
12765 * Checks an IPv6 address
12767 * Checks if the given IP is IPv6-compatible
12771 * @param string $ip a valid IPv6-address
12772 * @return bool true if $ip is an IPv6 address
12774 function checkIPv6($ip)
12776 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12778 if (!empty($ipPart[0]))
12780 $ipv6 = explode(':', $ipPart[0]);
12781 for ($i = 0; $i < count($ipv6); $i++)
12783 $dec = hexdec($ipv6[$i]);
12784 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12785 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12794 elseif ($count === 6 && !empty($ipPart[1]))
12796 $ipv4 = explode('.', $ipPart[1]);
12798 foreach ($ipv4 as $ipv4_part)
12800 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12826 * @package SimplePie
12828 class SimplePie_Parse_Date
12833 * @access protected
12839 * List of days, calendar day name => ordinal day number in the week
12841 * @access protected
12904 'keskiviikko' => 3,
12928 * List of months, calendar month name => calendar month number
12930 * @access protected
12933 var $month = array(
12944 // No long form of May
13073 * List of timezones, abbreviation => offset from UTC
13075 * @access protected
13078 var $timezone = array(
13281 * Cached PCRE for SimplePie_Parse_Date::$day
13283 * @access protected
13289 * Cached PCRE for SimplePie_Parse_Date::$month
13291 * @access protected
13297 * Array of user-added callback methods
13302 var $built_in = array();
13305 * Array of user-added callback methods
13310 var $user = array();
13313 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13314 * self::month_pcre, and self::built_in
13318 function SimplePie_Parse_Date()
13320 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13321 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13324 if (!isset($cache[get_class($this)]))
13326 $all_methods = get_class_methods($this);
13328 foreach ($all_methods as $method)
13330 if (strtolower(substr($method, 0, 5)) === 'date_')
13332 $cache[get_class($this)][] = $method;
13337 foreach ($cache[get_class($this)] as $method)
13339 $this->built_in[] = $method;
13353 $object =& new SimplePie_Parse_Date;
13363 * @param string $date Date to parse
13364 * @return int Timestamp corresponding to date string, or false on failure
13366 function parse($date)
13368 foreach ($this->user as $method)
13370 if (($returned = call_user_func($method, $date)) !== false)
13376 foreach ($this->built_in as $method)
13378 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13388 * Add a callback method to parse a date
13392 * @param callback $callback
13394 function add_callback($callback)
13396 if (is_callable($callback))
13398 $this->user[] = $callback;
13402 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13407 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13408 * well as allowing any of upper or lower case "T", horizontal tabs, or
13409 * spaces to be used as the time seperator (including more than one))
13411 * @access protected
13412 * @return int Timestamp
13414 function date_w3cdtf($date)
13419 $year = '([0-9]{4})';
13420 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13421 $decimal = '([0-9]*)';
13422 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13423 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13425 if (preg_match($pcre, $date, $match))
13428 Capturing subpatterns:
13435 7: Decimal fraction of a second
13439 11: Timezone minutes
13442 // Fill in empty matches
13443 for ($i = count($match); $i <= 3; $i++)
13448 for ($i = count($match); $i <= 7; $i++)
13453 // Numeric timezone
13454 if (isset($match[9]) && $match[9] !== '')
13456 $timezone = $match[10] * 3600;
13457 $timezone += $match[11] * 60;
13458 if ($match[9] === '-')
13460 $timezone = 0 - $timezone;
13468 // Convert the number of seconds to an integer, taking decimals into account
13469 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13471 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13480 * Remove RFC822 comments
13482 * @access protected
13483 * @param string $data Data to strip comments from
13484 * @return string Comment stripped string
13486 function remove_rfc2822_comments($string)
13488 $string = (string) $string;
13490 $length = strlen($string);
13495 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13497 $output .= substr($string, $position, $pos - $position);
13498 $position = $pos + 1;
13499 if ($string[$pos - 1] !== '\\')
13502 while ($depth && $position < $length)
13504 $position += strcspn($string, '()', $position);
13505 if ($string[$position - 1] === '\\')
13510 elseif (isset($string[$position]))
13512 switch ($string[$position])
13535 $output .= substr($string, $position);
13541 * Parse RFC2822's date format
13543 * @access protected
13544 * @return int Timestamp
13546 function date_rfc2822($date)
13551 $wsp = '[\x09\x20]';
13552 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13553 $optional_fws = $fws . '?';
13554 $day_name = $this->day_pcre;
13555 $month = $this->month_pcre;
13556 $day = '([0-9]{1,2})';
13557 $hour = $minute = $second = '([0-9]{2})';
13558 $year = '([0-9]{2,4})';
13559 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13560 $character_zone = '([A-Z]{1,5})';
13561 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13562 $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';
13564 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13567 Capturing subpatterns:
13577 10: Timezone minutes
13578 11: Alphabetic timezone
13581 // Find the month number
13582 $month = $this->month[strtolower($match[3])];
13584 // Numeric timezone
13585 if ($match[8] !== '')
13587 $timezone = $match[9] * 3600;
13588 $timezone += $match[10] * 60;
13589 if ($match[8] === '-')
13591 $timezone = 0 - $timezone;
13594 // Character timezone
13595 elseif (isset($this->timezone[strtoupper($match[11])]))
13597 $timezone = $this->timezone[strtoupper($match[11])];
13599 // Assume everything else to be -0000
13605 // Deal with 2/3 digit years
13606 if ($match[4] < 50)
13610 elseif ($match[4] < 1000)
13615 // Second is optional, if it is empty set it to zero
13616 if ($match[7] !== '')
13618 $second = $match[7];
13625 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13634 * Parse RFC850's date format
13636 * @access protected
13637 * @return int Timestamp
13639 function date_rfc850($date)
13644 $space = '[\x09\x20]+';
13645 $day_name = $this->day_pcre;
13646 $month = $this->month_pcre;
13647 $day = '([0-9]{1,2})';
13648 $year = $hour = $minute = $second = '([0-9]{2})';
13649 $zone = '([A-Z]{1,5})';
13650 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13652 if (preg_match($pcre, $date, $match))
13655 Capturing subpatterns:
13667 $month = $this->month[strtolower($match[3])];
13669 // Character timezone
13670 if (isset($this->timezone[strtoupper($match[8])]))
13672 $timezone = $this->timezone[strtoupper($match[8])];
13674 // Assume everything else to be -0000
13680 // Deal with 2 digit year
13681 if ($match[4] < 50)
13690 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13699 * Parse C99's asctime()'s date format
13701 * @access protected
13702 * @return int Timestamp
13704 function date_asctime($date)
13709 $space = '[\x09\x20]+';
13710 $wday_name = $this->day_pcre;
13711 $mon_name = $this->month_pcre;
13712 $day = '([0-9]{1,2})';
13713 $hour = $sec = $min = '([0-9]{2})';
13714 $year = '([0-9]{4})';
13715 $terminator = '\x0A?\x00?';
13716 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13718 if (preg_match($pcre, $date, $match))
13721 Capturing subpatterns:
13731 $month = $this->month[strtolower($match[2])];
13732 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13741 * Parse dates using strtotime()
13743 * @access protected
13744 * @return int Timestamp
13746 function date_strtotime($date)
13748 $strtotime = strtotime($date);
13749 if ($strtotime === -1 || $strtotime === false)
13761 * Content-type sniffing
13763 * @package SimplePie
13765 class SimplePie_Content_Type_Sniffer
13770 * @var SimplePie_File
13776 * Create an instance of the class with the input file
13779 * @param SimplePie_Content_Type_Sniffer $file Input file
13781 function SimplePie_Content_Type_Sniffer($file)
13783 $this->file = $file;
13787 * Get the Content-Type of the specified file
13790 * @return string Actual Content-Type
13792 function get_type()
13794 if (isset($this->file->headers['content-type']))
13796 if (!isset($this->file->headers['content-encoding'])
13797 && ($this->file->headers['content-type'] === 'text/plain'
13798 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13799 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13801 return $this->text_or_binary();
13804 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13806 $official = substr($this->file->headers['content-type'], 0, $pos);
13810 $official = $this->file->headers['content-type'];
13812 $official = strtolower($official);
13814 if ($official === 'unknown/unknown'
13815 || $official === 'application/unknown')
13817 return $this->unknown();
13819 elseif (substr($official, -4) === '+xml'
13820 || $official === 'text/xml'
13821 || $official === 'application/xml')
13825 elseif (substr($official, 0, 6) === 'image/')
13827 if ($return = $this->image())
13836 elseif ($official === 'text/html')
13838 return $this->feed_or_html();
13847 return $this->unknown();
13852 * Sniff text or binary
13855 * @return string Actual Content-Type
13857 function text_or_binary()
13859 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13860 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13861 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13862 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13864 return 'text/plain';
13866 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13868 return 'application/octect-stream';
13872 return 'text/plain';
13880 * @return string Actual Content-Type
13884 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13885 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13886 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13887 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13889 return 'text/html';
13891 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13893 return 'application/pdf';
13895 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13897 return 'application/postscript';
13899 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13900 || substr($this->file->body, 0, 6) === 'GIF89a')
13902 return 'image/gif';
13904 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13906 return 'image/png';
13908 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13910 return 'image/jpeg';
13912 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13914 return 'image/bmp';
13918 return $this->text_or_binary();
13926 * @return string Actual Content-Type
13930 if (substr($this->file->body, 0, 6) === 'GIF87a'
13931 || substr($this->file->body, 0, 6) === 'GIF89a')
13933 return 'image/gif';
13935 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13937 return 'image/png';
13939 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13941 return 'image/jpeg';
13943 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13945 return 'image/bmp';
13957 * @return string Actual Content-Type
13959 function feed_or_html()
13961 $len = strlen($this->file->body);
13962 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13964 while ($pos < $len)
13966 switch ($this->file->body[$pos])
13972 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13980 return 'text/html';
13983 if (substr($this->file->body, $pos, 3) === '!--')
13986 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13992 return 'text/html';
13995 elseif (substr($this->file->body, $pos, 1) === '!')
13997 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
14003 return 'text/html';
14006 elseif (substr($this->file->body, $pos, 1) === '?')
14008 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
14014 return 'text/html';
14017 elseif (substr($this->file->body, $pos, 3) === 'rss'
14018 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
14020 return 'application/rss+xml';
14022 elseif (substr($this->file->body, $pos, 4) === 'feed')
14024 return 'application/atom+xml';
14028 return 'text/html';
14032 return 'text/html';
14037 * Parses the XML Declaration
14039 * @package SimplePie
14041 class SimplePie_XML_Declaration_Parser
14049 var $version = '1.0';
14057 var $encoding = 'UTF-8';
14065 var $standalone = false;
14068 * Current state of the state machine
14073 var $state = 'before_version_name';
14084 * Input data length (to avoid calling strlen() everytime this is needed)
14089 var $data_length = 0;
14092 * Current position of the pointer
14100 * Create an instance of the class with the input data
14103 * @param string $data Input data
14105 function SimplePie_XML_Declaration_Parser($data)
14107 $this->data = $data;
14108 $this->data_length = strlen($this->data);
14112 * Parse the input data
14115 * @return bool true on success, false on failure
14119 while ($this->state && $this->state !== 'emit' && $this->has_data())
14121 $state = $this->state;
14125 if ($this->state === 'emit')
14131 $this->version = '';
14132 $this->encoding = '';
14133 $this->standalone = '';
14139 * Check whether there is data beyond the pointer
14142 * @return bool true if there is further data, false if not
14144 function has_data()
14146 return (bool) ($this->position < $this->data_length);
14150 * Advance past any whitespace
14152 * @return int Number of whitespace characters passed
14154 function skip_whitespace()
14156 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14157 $this->position += $whitespace;
14158 return $whitespace;
14164 function get_value()
14166 $quote = substr($this->data, $this->position, 1);
14167 if ($quote === '"' || $quote === "'")
14170 $len = strcspn($this->data, $quote, $this->position);
14171 if ($this->has_data())
14173 $value = substr($this->data, $this->position, $len);
14174 $this->position += $len + 1;
14181 function before_version_name()
14183 if ($this->skip_whitespace())
14185 $this->state = 'version_name';
14189 $this->state = false;
14193 function version_name()
14195 if (substr($this->data, $this->position, 7) === 'version')
14197 $this->position += 7;
14198 $this->skip_whitespace();
14199 $this->state = 'version_equals';
14203 $this->state = false;
14207 function version_equals()
14209 if (substr($this->data, $this->position, 1) === '=')
14212 $this->skip_whitespace();
14213 $this->state = 'version_value';
14217 $this->state = false;
14221 function version_value()
14223 if ($this->version = $this->get_value())
14225 $this->skip_whitespace();
14226 if ($this->has_data())
14228 $this->state = 'encoding_name';
14232 $this->state = 'emit';
14237 $this->state = false;
14241 function encoding_name()
14243 if (substr($this->data, $this->position, 8) === 'encoding')
14245 $this->position += 8;
14246 $this->skip_whitespace();
14247 $this->state = 'encoding_equals';
14251 $this->state = 'standalone_name';
14255 function encoding_equals()
14257 if (substr($this->data, $this->position, 1) === '=')
14260 $this->skip_whitespace();
14261 $this->state = 'encoding_value';
14265 $this->state = false;
14269 function encoding_value()
14271 if ($this->encoding = $this->get_value())
14273 $this->skip_whitespace();
14274 if ($this->has_data())
14276 $this->state = 'standalone_name';
14280 $this->state = 'emit';
14285 $this->state = false;
14289 function standalone_name()
14291 if (substr($this->data, $this->position, 10) === 'standalone')
14293 $this->position += 10;
14294 $this->skip_whitespace();
14295 $this->state = 'standalone_equals';
14299 $this->state = false;
14303 function standalone_equals()
14305 if (substr($this->data, $this->position, 1) === '=')
14308 $this->skip_whitespace();
14309 $this->state = 'standalone_value';
14313 $this->state = false;
14317 function standalone_value()
14319 if ($standalone = $this->get_value())
14321 switch ($standalone)
14324 $this->standalone = true;
14328 $this->standalone = false;
14332 $this->state = false;
14336 $this->skip_whitespace();
14337 if ($this->has_data())
14339 $this->state = false;
14343 $this->state = 'emit';
14348 $this->state = false;
14353 class SimplePie_Locator
14358 var $local = array();
14359 var $elsewhere = array();
14360 var $file_class = 'SimplePie_File';
14361 var $cached_entities = array();
14364 var $base_location = 0;
14365 var $checked_feeds = 0;
14366 var $max_checked_feeds = 10;
14367 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14369 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14371 $this->file =& $file;
14372 $this->file_class = $file_class;
14373 $this->useragent = $useragent;
14374 $this->timeout = $timeout;
14375 $this->max_checked_feeds = $max_checked_feeds;
14376 $this->content_type_sniffer_class = $content_type_sniffer_class;
14379 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14381 if ($this->is_feed($this->file))
14383 return $this->file;
14386 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14388 $sniffer =& new $this->content_type_sniffer_class($this->file);
14389 if ($sniffer->get_type() !== 'text/html')
14395 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14400 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14402 return $working[0];
14405 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14407 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14412 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14417 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14422 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14430 function is_feed(&$file)
14432 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14434 $sniffer =& new $this->content_type_sniffer_class($file);
14435 $sniffed = $sniffer->get_type();
14436 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14445 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14455 function get_base()
14457 $this->http_base = $this->file->url;
14458 $this->base = $this->http_base;
14459 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14460 foreach ($elements as $element)
14462 if ($element['attribs']['href']['data'] !== '')
14464 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14465 $this->base_location = $element['offset'];
14471 function autodiscovery()
14473 $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));
14476 foreach ($links as $link)
14478 if ($this->checked_feeds === $this->max_checked_feeds)
14482 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14484 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14486 if ($this->base_location < $link['offset'])
14488 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14492 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14495 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]))
14497 $this->checked_feeds++;
14498 $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14499 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))
14501 $feeds[$href] = $feed;
14508 if (!empty($feeds))
14510 return array_values($feeds);
14517 function get_links()
14519 $links = SimplePie_Misc::get_element('a', $this->file->body);
14520 foreach ($links as $link)
14522 if (isset($link['attribs']['href']['data']))
14524 $href = trim($link['attribs']['href']['data']);
14525 $parsed = SimplePie_Misc::parse_url($href);
14526 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14528 if ($this->base_location < $link['offset'])
14530 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14534 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14537 $current = SimplePie_Misc::parse_url($this->file->url);
14539 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14541 $this->local[] = $href;
14545 $this->elsewhere[] = $href;
14550 $this->local = array_unique($this->local);
14551 $this->elsewhere = array_unique($this->elsewhere);
14552 if (!empty($this->local) || !empty($this->elsewhere))
14559 function extension(&$array)
14561 foreach ($array as $key => $value)
14563 if ($this->checked_feeds === $this->max_checked_feeds)
14567 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14569 $this->checked_feeds++;
14570 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14571 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))
14577 unset($array[$key]);
14584 function body(&$array)
14586 foreach ($array as $key => $value)
14588 if ($this->checked_feeds === $this->max_checked_feeds)
14592 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14594 $this->checked_feeds++;
14595 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14596 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))
14602 unset($array[$key]);
14610 class SimplePie_Parser
14615 var $current_column;
14617 var $separator = ' ';
14618 var $namespace = array('');
14619 var $element = array('');
14620 var $xml_base = array('');
14621 var $xml_base_explicit = array(false);
14622 var $xml_lang = array('');
14623 var $data = array();
14624 var $datas = array(array());
14625 var $current_xhtml_construct = -1;
14628 function parse(&$data, $encoding)
14630 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14631 if (strtoupper($encoding) === 'US-ASCII')
14633 $this->encoding = 'UTF-8';
14637 $this->encoding = $encoding;
14641 // UTF-32 Big Endian BOM
14642 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14644 $data = substr($data, 4);
14646 // UTF-32 Little Endian BOM
14647 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14649 $data = substr($data, 4);
14651 // UTF-16 Big Endian BOM
14652 elseif (substr($data, 0, 2) === "\xFE\xFF")
14654 $data = substr($data, 2);
14656 // UTF-16 Little Endian BOM
14657 elseif (substr($data, 0, 2) === "\xFF\xFE")
14659 $data = substr($data, 2);
14662 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14664 $data = substr($data, 3);
14667 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14669 $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14670 if ($declaration->parse())
14672 $data = substr($data, $pos + 2);
14673 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14677 $this->error_string = 'SimplePie bug! Please report this!';
14684 static $xml_is_sane = null;
14685 if ($xml_is_sane === null)
14687 $parser_check = xml_parser_create();
14688 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
14689 xml_parser_free($parser_check);
14690 $xml_is_sane = isset($values[0]['value']);
14693 // Create the parser
14696 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14697 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14698 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14699 xml_set_object($xml, $this);
14700 xml_set_character_data_handler($xml, 'cdata');
14701 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14704 if (!xml_parse($xml, $data, true))
14706 $this->error_code = xml_get_error_code($xml);
14707 $this->error_string = xml_error_string($this->error_code);
14710 $this->current_line = xml_get_current_line_number($xml);
14711 $this->current_column = xml_get_current_column_number($xml);
14712 $this->current_byte = xml_get_current_byte_index($xml);
14713 xml_parser_free($xml);
14718 libxml_clear_errors();
14719 $xml =& new XMLReader();
14721 while (@$xml->read())
14723 switch ($xml->nodeType)
14726 case constant('XMLReader::END_ELEMENT'):
14727 if ($xml->namespaceURI !== '')
14729 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14733 $tagName = $xml->localName;
14735 $this->tag_close(null, $tagName);
14737 case constant('XMLReader::ELEMENT'):
14738 $empty = $xml->isEmptyElement;
14739 if ($xml->namespaceURI !== '')
14741 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14745 $tagName = $xml->localName;
14747 $attributes = array();
14748 while ($xml->moveToNextAttribute())
14750 if ($xml->namespaceURI !== '')
14752 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
14756 $attrName = $xml->localName;
14758 $attributes[$attrName] = $xml->value;
14760 $this->tag_open(null, $tagName, $attributes);
14763 $this->tag_close(null, $tagName);
14766 case constant('XMLReader::TEXT'):
14768 case constant('XMLReader::CDATA'):
14769 $this->cdata(null, $xml->value);
14773 if ($error = libxml_get_last_error())
14775 $this->error_code = $error->code;
14776 $this->error_string = $error->message;
14777 $this->current_line = $error->line;
14778 $this->current_column = $error->column;
14788 function get_error_code()
14790 return $this->error_code;
14793 function get_error_string()
14795 return $this->error_string;
14798 function get_current_line()
14800 return $this->current_line;
14803 function get_current_column()
14805 return $this->current_column;
14808 function get_current_byte()
14810 return $this->current_byte;
14813 function get_data()
14815 return $this->data;
14818 function tag_open($parser, $tag, $attributes)
14820 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14822 $attribs = array();
14823 foreach ($attributes as $name => $value)
14825 list($attrib_namespace, $attribute) = $this->split_ns($name);
14826 $attribs[$attrib_namespace][$attribute] = $value;
14829 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14831 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14832 $this->xml_base_explicit[] = true;
14836 $this->xml_base[] = end($this->xml_base);
14837 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14840 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14842 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14846 $this->xml_lang[] = end($this->xml_lang);
14849 if ($this->current_xhtml_construct >= 0)
14851 $this->current_xhtml_construct++;
14852 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14854 $this->data['data'] .= '<' . end($this->element);
14855 if (isset($attribs['']))
14857 foreach ($attribs[''] as $name => $value)
14859 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14862 $this->data['data'] .= '>';
14867 $this->datas[] =& $this->data;
14868 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14869 $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));
14870 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')
14871 || (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'))
14873 $this->current_xhtml_construct = 0;
14878 function cdata($parser, $cdata)
14880 if ($this->current_xhtml_construct >= 0)
14882 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14886 $this->data['data'] .= $cdata;
14890 function tag_close($parser, $tag)
14892 if ($this->current_xhtml_construct >= 0)
14894 $this->current_xhtml_construct--;
14895 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')))
14897 $this->data['data'] .= '</' . end($this->element) . '>';
14900 if ($this->current_xhtml_construct === -1)
14902 $this->data =& $this->datas[count($this->datas) - 1];
14903 array_pop($this->datas);
14906 array_pop($this->element);
14907 array_pop($this->namespace);
14908 array_pop($this->xml_base);
14909 array_pop($this->xml_base_explicit);
14910 array_pop($this->xml_lang);
14913 function split_ns($string)
14915 static $cache = array();
14916 if (!isset($cache[$string]))
14918 if ($pos = strpos($string, $this->separator))
14920 static $separator_length;
14921 if (!$separator_length)
14923 $separator_length = strlen($this->separator);
14925 $namespace = substr($string, 0, $pos);
14926 $local_name = substr($string, $pos + $separator_length);
14927 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14929 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14932 // Normalize the Media RSS namespaces
14933 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14935 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14937 $cache[$string] = array($namespace, $local_name);
14941 $cache[$string] = array('', $string);
14944 return $cache[$string];
14949 * @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
14951 class SimplePie_Sanitize
14957 var $remove_div = true;
14958 var $image_handler = '';
14959 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14960 var $encode_instead_of_strip = false;
14961 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14962 var $strip_comments = false;
14963 var $output_encoding = 'UTF-8';
14964 var $enable_cache = true;
14965 var $cache_location = './cache';
14966 var $cache_name_function = 'md5';
14967 var $cache_class = 'SimplePie_Cache';
14968 var $file_class = 'SimplePie_File';
14970 var $useragent = '';
14971 var $force_fsockopen = false;
14973 var $replace_url_attributes = array(
14976 'blockquote' => 'cite',
14978 'form' => 'action',
14979 'img' => array('longdesc', 'src'),
14985 function remove_div($enable = true)
14987 $this->remove_div = (bool) $enable;
14990 function set_image_handler($page = false)
14994 $this->image_handler = (string) $page;
14998 $this->image_handler = false;
15002 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
15004 if (isset($enable_cache))
15006 $this->enable_cache = (bool) $enable_cache;
15009 if ($cache_location)
15011 $this->cache_location = (string) $cache_location;
15014 if ($cache_name_function)
15016 $this->cache_name_function = (string) $cache_name_function;
15021 $this->cache_class = (string) $cache_class;
15025 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
15029 $this->file_class = (string) $file_class;
15034 $this->timeout = (string) $timeout;
15039 $this->useragent = (string) $useragent;
15042 if ($force_fsockopen)
15044 $this->force_fsockopen = (string) $force_fsockopen;
15048 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
15052 if (is_array($tags))
15054 $this->strip_htmltags = $tags;
15058 $this->strip_htmltags = explode(',', $tags);
15063 $this->strip_htmltags = false;
15067 function encode_instead_of_strip($encode = false)
15069 $this->encode_instead_of_strip = (bool) $encode;
15072 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
15076 if (is_array($attribs))
15078 $this->strip_attributes = $attribs;
15082 $this->strip_attributes = explode(',', $attribs);
15087 $this->strip_attributes = false;
15091 function strip_comments($strip = false)
15093 $this->strip_comments = (bool) $strip;
15096 function set_output_encoding($encoding = 'UTF-8')
15098 $this->output_encoding = (string) $encoding;
15102 * Set element/attribute key/value pairs of HTML attributes
15103 * containing URLs that need to be resolved relative to the feed
15107 * @param array $element_attribute Element/attribute key/value pairs
15109 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'))
15111 $this->replace_url_attributes = (array) $element_attribute;
15114 function sanitize($data, $type, $base = '')
15116 $data = trim($data);
15117 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
15119 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
15121 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))
15123 $type |= SIMPLEPIE_CONSTRUCT_HTML;
15127 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
15131 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
15133 $data = base64_decode($data);
15136 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
15138 if ($this->remove_div)
15140 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
15141 $data = preg_replace('/<\/div>$/', '', $data);
15145 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
15149 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
15152 if ($this->strip_comments)
15154 $data = SimplePie_Misc::strip_comments($data);
15157 // Strip out HTML tags and attributes that might cause various security problems.
15158 // Based on recommendations by Mark Pilgrim at:
15159 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15160 if ($this->strip_htmltags)
15162 foreach ($this->strip_htmltags as $tag)
15164 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15165 while (preg_match($pcre, $data))
15167 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15172 if ($this->strip_attributes)
15174 foreach ($this->strip_attributes as $attrib)
15176 $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);
15180 // Replace relative URLs
15181 $this->base = $base;
15182 foreach ($this->replace_url_attributes as $element => $attributes)
15184 $data = $this->replace_urls($data, $element, $attributes);
15187 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15188 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15190 $images = SimplePie_Misc::get_element('img', $data);
15191 foreach ($images as $img)
15193 if (isset($img['attribs']['src']['data']))
15195 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15196 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15198 if ($cache->load())
15200 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15201 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15205 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15206 $headers = $file->headers;
15208 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15210 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15212 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15213 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15217 trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
15225 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15226 $data = trim($data);
15229 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15231 $data = SimplePie_Misc::absolutize_url($data, $base);
15234 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15236 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15239 if ($this->output_encoding !== 'UTF-8')
15241 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15247 function replace_urls($data, $tag, $attributes)
15249 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15251 $elements = SimplePie_Misc::get_element($tag, $data);
15252 foreach ($elements as $element)
15254 if (is_array($attributes))
15256 foreach ($attributes as $attribute)
15258 if (isset($element['attribs'][$attribute]['data']))
15260 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15261 $new_element = SimplePie_Misc::element_implode($element);
15262 $data = str_replace($element['full'], $new_element, $data);
15263 $element['full'] = $new_element;
15267 elseif (isset($element['attribs'][$attributes]['data']))
15269 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15270 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15277 function do_strip_htmltags($match)
15279 if ($this->encode_instead_of_strip)
15281 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15283 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15284 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15285 return "<$match[1]$match[2]>$match[3]</$match[1]>";
15289 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15292 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))