2 if ( ! class_exists( 'SimplePie' ) ) :
6 * A PHP-Based RSS and Atom Feed Framework.
7 * Takes the hard work out of managing a complete RSS/Atom solution.
9 * Copyright (c) 2004-2011, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without modification, are
13 * permitted provided that the following conditions are met:
15 * * Redistributions of source code must retain the above copyright notice, this list of
16 * conditions and the following disclaimer.
18 * * Redistributions in binary form must reproduce the above copyright notice, this list
19 * of conditions and the following disclaimer in the documentation and/or other materials
20 * provided with the distribution.
22 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
23 * to endorse or promote products derived from this software without specific prior
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
27 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
28 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
29 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
38 * @copyright 2004-2011 Ryan Parman, Geoffrey Sneddon, Ryan McCue
40 * @author Geoffrey Sneddon
42 * @link http://simplepie.org/ SimplePie
43 * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
44 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
45 * @todo phpDoc comments
51 define('SIMPLEPIE_NAME', 'SimplePie');
56 define('SIMPLEPIE_VERSION', '1.2.1');
61 define('SIMPLEPIE_BUILD', '20111015034325');
64 * SimplePie Website URL
66 define('SIMPLEPIE_URL', 'http://simplepie.org');
70 * @see SimplePie::set_useragent()
72 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
77 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
81 * @see SimplePie::set_autodiscovery_level()
83 define('SIMPLEPIE_LOCATOR_NONE', 0);
86 * Feed Link Element Autodiscovery
87 * @see SimplePie::set_autodiscovery_level()
89 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
92 * Local Feed Extension Autodiscovery
93 * @see SimplePie::set_autodiscovery_level()
95 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
98 * Local Feed Body Autodiscovery
99 * @see SimplePie::set_autodiscovery_level()
101 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
104 * Remote Feed Extension Autodiscovery
105 * @see SimplePie::set_autodiscovery_level()
107 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
110 * Remote Feed Body Autodiscovery
111 * @see SimplePie::set_autodiscovery_level()
113 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
116 * All Feed Autodiscovery
117 * @see SimplePie::set_autodiscovery_level()
119 define('SIMPLEPIE_LOCATOR_ALL', 31);
124 define('SIMPLEPIE_TYPE_NONE', 0);
129 define('SIMPLEPIE_TYPE_RSS_090', 1);
132 * RSS 0.91 (Netscape)
134 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
137 * RSS 0.91 (Userland)
139 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
142 * RSS 0.91 (both Netscape and Userland)
144 define('SIMPLEPIE_TYPE_RSS_091', 6);
149 define('SIMPLEPIE_TYPE_RSS_092', 8);
154 define('SIMPLEPIE_TYPE_RSS_093', 16);
159 define('SIMPLEPIE_TYPE_RSS_094', 32);
164 define('SIMPLEPIE_TYPE_RSS_10', 64);
169 define('SIMPLEPIE_TYPE_RSS_20', 128);
174 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
177 * Non-RDF-based RSS (truly intended as syndication format)
179 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
184 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
189 define('SIMPLEPIE_TYPE_ATOM_03', 256);
194 define('SIMPLEPIE_TYPE_ATOM_10', 512);
199 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
204 define('SIMPLEPIE_TYPE_ALL', 1023);
209 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
214 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
219 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
224 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
227 * base64-encoded construct
229 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
234 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
237 * A construct that might be HTML
239 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
244 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
249 define('SIMPLEPIE_SAME_CASE', 1);
252 * Change to lowercase
254 define('SIMPLEPIE_LOWERCASE', 2);
257 * Change to uppercase
259 define('SIMPLEPIE_UPPERCASE', 4);
262 * PCRE for HTML attributes
264 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]*');
267 * PCRE for XML attributes
269 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
274 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
279 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
284 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
289 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
294 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
299 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
302 * RSS 1.0 Content Module Namespace
304 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
308 * (Stupid, I know, but I'm certain it will confuse people less with support.)
310 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
315 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
320 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
323 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
325 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
330 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
333 * Media RSS Namespace
335 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
338 * Wrong Media RSS Namespace
340 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
343 * iTunes RSS Namespace
345 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
350 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
353 * IANA Link Relations Registry
355 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
358 * Whether we're running on PHP5
360 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
365 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
370 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
375 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
378 * fsockopen() file source
380 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
385 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
388 * file_get_contents() file source
390 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
400 * @var array Raw data
406 * @var mixed Error string
412 * @var object Instance of SimplePie_Sanitize (or other class)
413 * @see SimplePie::set_sanitize_class()
419 * @var string SimplePie Useragent
420 * @see SimplePie::set_useragent()
423 var $useragent = SIMPLEPIE_USERAGENT;
426 * @var string Feed URL
427 * @see SimplePie::set_feed_url()
433 * @var object Instance of SimplePie_File to use as a feed
434 * @see SimplePie::set_file()
440 * @var string Raw feed data
441 * @see SimplePie::set_raw_data()
447 * @var int Timeout for fetching remote files
448 * @see SimplePie::set_timeout()
454 * @var bool Forces fsockopen() to be used for remote files instead
455 * of cURL, even if a new enough version is installed
456 * @see SimplePie::force_fsockopen()
459 var $force_fsockopen = false;
462 * @var bool Force the given data/URL to be treated as a feed no matter what
464 * @see SimplePie::force_feed()
467 var $force_feed = false;
470 * @var bool Enable/Disable XML dump
471 * @see SimplePie::enable_xml_dump()
474 var $xml_dump = false;
477 * @var bool Enable/Disable Caching
478 * @see SimplePie::enable_cache()
484 * @var int Cache duration (in seconds)
485 * @see SimplePie::set_cache_duration()
488 var $cache_duration = 3600;
491 * @var int Auto-discovery cache duration (in seconds)
492 * @see SimplePie::set_autodiscovery_cache_duration()
495 var $autodiscovery_cache_duration = 604800; // 7 Days.
498 * @var string Cache location (relative to executing script)
499 * @see SimplePie::set_cache_location()
502 var $cache_location = './cache';
505 * @var string Function that creates the cache filename
506 * @see SimplePie::set_cache_name_function()
509 var $cache_name_function = 'md5';
512 * @var bool Reorder feed by date descending
513 * @see SimplePie::enable_order_by_date()
516 var $order_by_date = true;
519 * @var mixed Force input encoding to be set to the follow value
520 * (false, or anything type-cast to false, disables this feature)
521 * @see SimplePie::set_input_encoding()
524 var $input_encoding = false;
527 * @var int Feed Autodiscovery Level
528 * @see SimplePie::set_autodiscovery_level()
531 var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
534 * @var string Class used for caching feeds
535 * @see SimplePie::set_cache_class()
538 var $cache_class = 'SimplePie_Cache';
541 * @var string Class used for locating feeds
542 * @see SimplePie::set_locator_class()
545 var $locator_class = 'SimplePie_Locator';
548 * @var string Class used for parsing feeds
549 * @see SimplePie::set_parser_class()
552 var $parser_class = 'SimplePie_Parser';
555 * @var string Class used for fetching feeds
556 * @see SimplePie::set_file_class()
559 var $file_class = 'SimplePie_File';
562 * @var string Class used for items
563 * @see SimplePie::set_item_class()
566 var $item_class = 'SimplePie_Item';
569 * @var string Class used for authors
570 * @see SimplePie::set_author_class()
573 var $author_class = 'SimplePie_Author';
576 * @var string Class used for categories
577 * @see SimplePie::set_category_class()
580 var $category_class = 'SimplePie_Category';
583 * @var string Class used for enclosures
584 * @see SimplePie::set_enclosures_class()
587 var $enclosure_class = 'SimplePie_Enclosure';
590 * @var string Class used for Media RSS <media:text> captions
591 * @see SimplePie::set_caption_class()
594 var $caption_class = 'SimplePie_Caption';
597 * @var string Class used for Media RSS <media:copyright>
598 * @see SimplePie::set_copyright_class()
601 var $copyright_class = 'SimplePie_Copyright';
604 * @var string Class used for Media RSS <media:credit>
605 * @see SimplePie::set_credit_class()
608 var $credit_class = 'SimplePie_Credit';
611 * @var string Class used for Media RSS <media:rating>
612 * @see SimplePie::set_rating_class()
615 var $rating_class = 'SimplePie_Rating';
618 * @var string Class used for Media RSS <media:restriction>
619 * @see SimplePie::set_restriction_class()
622 var $restriction_class = 'SimplePie_Restriction';
625 * @var string Class used for content-type sniffing
626 * @see SimplePie::set_content_type_sniffer_class()
629 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
632 * @var string Class used for item sources.
633 * @see SimplePie::set_source_class()
636 var $source_class = 'SimplePie_Source';
639 * @var mixed Set javascript query string parameter (false, or
640 * anything type-cast to false, disables this feature)
641 * @see SimplePie::set_javascript()
644 var $javascript = 'js';
647 * @var int Maximum number of feeds to check with autodiscovery
648 * @see SimplePie::set_max_checked_feeds()
651 var $max_checked_feeds = 10;
654 * @var array All the feeds found during the autodiscovery process
655 * @see SimplePie::get_all_discovered_feeds()
658 var $all_discovered_feeds = array();
661 * @var string Web-accessible path to the handler_favicon.php file.
662 * @see SimplePie::set_favicon_handler()
665 var $favicon_handler = '';
668 * @var string Web-accessible path to the handler_image.php file.
669 * @see SimplePie::set_image_handler()
672 var $image_handler = '';
675 * @var array Stores the URLs when multiple feeds are being initialized.
676 * @see SimplePie::set_feed_url()
679 var $multifeed_url = array();
682 * @var array Stores SimplePie objects when multiple feeds initialized.
685 var $multifeed_objects = array();
688 * @var array Stores the get_object_vars() array for use with multifeeds.
689 * @see SimplePie::set_feed_url()
692 var $config_settings = null;
695 * @var integer Stores the number of items to return per-feed with multifeeds.
696 * @see SimplePie::set_item_limit()
702 * @var array Stores the default attributes to be stripped by strip_attributes().
703 * @see SimplePie::strip_attributes()
706 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
709 * @var array Stores the default tags to be stripped by strip_htmltags().
710 * @see SimplePie::strip_htmltags()
713 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
716 * The SimplePie class contains feed level data and options
718 * There are two ways that you can create a new SimplePie object. The first
719 * is by passing a feed URL as a parameter to the SimplePie constructor
720 * (as well as optionally setting the cache location and cache expiry). This
721 * will initialise the whole feed with all of the default settings, and you
722 * can begin accessing methods and properties immediately.
724 * The second way is to create the SimplePie object with no parameters
725 * at all. This will enable you to set configuration options. After setting
726 * them, you must initialise the feed using $feed->init(). At that point the
727 * object's methods and properties will be available to you. This format is
728 * what is used throughout this documentation.
731 * @since 1.0 Preview Release
732 * @param string $feed_url This is the URL you want to parse.
733 * @param string $cache_location This is where you want the cache to be stored.
734 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
736 function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
738 // Other objects, instances created here so we can set options on them
739 $this->sanitize =& new SimplePie_Sanitize;
741 // Set options if they're passed to the constructor
742 if ($cache_location !== null)
744 $this->set_cache_location($cache_location);
747 if ($cache_duration !== null)
749 $this->set_cache_duration($cache_duration);
752 // Only init the script if we're passed a feed URL
753 if ($feed_url !== null)
755 $this->set_feed_url($feed_url);
761 * Used for converting object to a string
763 function __toString()
765 return md5(serialize($this->data));
769 * Remove items that link back to this before destroying this object
771 function __destruct()
773 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
775 if (!empty($this->data['items']))
777 foreach ($this->data['items'] as $item)
781 unset($item, $this->data['items']);
783 if (!empty($this->data['ordered_items']))
785 foreach ($this->data['ordered_items'] as $item)
789 unset($item, $this->data['ordered_items']);
795 * Force the given data/URL to be treated as a feed no matter what it
800 * @param bool $enable Force the given data/URL to be treated as a feed
802 function force_feed($enable = false)
804 $this->force_feed = (bool) $enable;
808 * This is the URL of the feed you want to parse.
810 * This allows you to enter the URL of the feed you want to parse, or the
811 * website you want to try to use auto-discovery on. This takes priority
812 * over any set raw data.
814 * You can set multiple feeds to mash together by passing an array instead
815 * of a string for the $url. Remember that with each additional feed comes
816 * additional processing and resources.
819 * @since 1.0 Preview Release
820 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
821 * @see SimplePie::set_raw_data()
823 function set_feed_url($url)
827 $this->multifeed_url = array();
828 foreach ($url as $value)
830 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
835 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
840 * Provides an instance of SimplePie_File to use as a feed
843 * @param object &$file Instance of SimplePie_File (or subclass)
844 * @return bool True on success, false on failure
846 function set_file(&$file)
848 if (is_a($file, 'SimplePie_File'))
850 $this->feed_url = $file->url;
851 $this->file =& $file;
858 * Allows you to use a string of RSS/Atom data instead of a remote feed.
860 * If you have a feed available as a string in PHP, you can tell SimplePie
861 * to parse that data string instead of a remote feed. Any set feed URL
866 * @param string $data RSS or Atom data as a string.
867 * @see SimplePie::set_feed_url()
869 function set_raw_data($data)
871 $this->raw_data = $data;
875 * Allows you to override the default timeout for fetching remote feeds.
877 * This allows you to change the maximum time the feed's server to respond
878 * and send the feed back.
882 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
884 function set_timeout($timeout = 10)
886 $this->timeout = (int) $timeout;
890 * Forces SimplePie to use fsockopen() instead of the preferred cURL
895 * @param bool $enable Force fsockopen() to be used
897 function force_fsockopen($enable = false)
899 $this->force_fsockopen = (bool) $enable;
903 * Outputs the raw XML content of the feed, after it has gone through
904 * SimplePie's filters.
906 * Used only for debugging, this function will output the XML content as
907 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
908 * before trying to parse it. Many parts of the feed are re-written in
909 * memory, and in the end, you have a parsable feed. XML dump shows you the
910 * actual XML that SimplePie tries to parse, which may or may not be very
911 * different from the original feed.
914 * @since 1.0 Preview Release
915 * @param bool $enable Enable XML dump
917 function enable_xml_dump($enable = false)
919 $this->xml_dump = (bool) $enable;
923 * Enables/disables caching in SimplePie.
925 * This option allows you to disable caching all-together in SimplePie.
926 * However, disabling the cache can lead to longer load times.
929 * @since 1.0 Preview Release
930 * @param bool $enable Enable caching
932 function enable_cache($enable = true)
934 $this->cache = (bool) $enable;
938 * Set the length of time (in seconds) that the contents of a feed
942 * @param int $seconds The feed content cache duration.
944 function set_cache_duration($seconds = 3600)
946 $this->cache_duration = (int) $seconds;
950 * Set the length of time (in seconds) that the autodiscovered feed
951 * URL will be cached.
954 * @param int $seconds The autodiscovered feed URL cache duration.
956 function set_autodiscovery_cache_duration($seconds = 604800)
958 $this->autodiscovery_cache_duration = (int) $seconds;
962 * Set the file system location where the cached files should be stored.
965 * @param string $location The file system location.
967 function set_cache_location($location = './cache')
969 $this->cache_location = (string) $location;
973 * Determines whether feed items should be sorted into reverse chronological order.
976 * @param bool $enable Sort as reverse chronological order.
978 function enable_order_by_date($enable = true)
980 $this->order_by_date = (bool) $enable;
984 * Allows you to override the character encoding reported by the feed.
987 * @param string $encoding Character encoding.
989 function set_input_encoding($encoding = false)
993 $this->input_encoding = (string) $encoding;
997 $this->input_encoding = false;
1002 * Set how much feed autodiscovery to do
1005 * @see SIMPLEPIE_LOCATOR_NONE
1006 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
1007 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
1008 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
1009 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
1010 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
1011 * @see SIMPLEPIE_LOCATOR_ALL
1012 * @param int $level Feed Autodiscovery Level (level can be a
1013 * combination of the above constants, see bitwise OR operator)
1015 function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
1017 $this->autodiscovery = (int) $level;
1021 * Allows you to change which class SimplePie uses for caching.
1022 * Useful when you are overloading or extending SimplePie's default classes.
1025 * @param string $class Name of custom class.
1026 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1027 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1029 function set_cache_class($class = 'SimplePie_Cache')
1031 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1033 $this->cache_class = $class;
1040 * Allows you to change which class SimplePie uses for auto-discovery.
1041 * Useful when you are overloading or extending SimplePie's default classes.
1044 * @param string $class Name of custom class.
1045 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1046 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1048 function set_locator_class($class = 'SimplePie_Locator')
1050 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1052 $this->locator_class = $class;
1059 * Allows you to change which class SimplePie uses for XML parsing.
1060 * Useful when you are overloading or extending SimplePie's default classes.
1063 * @param string $class Name of custom class.
1064 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1065 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1067 function set_parser_class($class = 'SimplePie_Parser')
1069 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1071 $this->parser_class = $class;
1078 * Allows you to change which class SimplePie uses for remote file fetching.
1079 * Useful when you are overloading or extending SimplePie's default classes.
1082 * @param string $class Name of custom class.
1083 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1084 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1086 function set_file_class($class = 'SimplePie_File')
1088 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1090 $this->file_class = $class;
1097 * Allows you to change which class SimplePie uses for data sanitization.
1098 * Useful when you are overloading or extending SimplePie's default classes.
1101 * @param string $class Name of custom class.
1102 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1103 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1105 function set_sanitize_class($class = 'SimplePie_Sanitize')
1107 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1109 $this->sanitize =& new $class;
1116 * Allows you to change which class SimplePie uses for handling feed items.
1117 * Useful when you are overloading or extending SimplePie's default classes.
1120 * @param string $class Name of custom class.
1121 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1122 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1124 function set_item_class($class = 'SimplePie_Item')
1126 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1128 $this->item_class = $class;
1135 * Allows you to change which class SimplePie uses for handling author data.
1136 * Useful when you are overloading or extending SimplePie's default classes.
1139 * @param string $class Name of custom class.
1140 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1141 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1143 function set_author_class($class = 'SimplePie_Author')
1145 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1147 $this->author_class = $class;
1154 * Allows you to change which class SimplePie uses for handling category data.
1155 * Useful when you are overloading or extending SimplePie's default classes.
1158 * @param string $class Name of custom class.
1159 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1160 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1162 function set_category_class($class = 'SimplePie_Category')
1164 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1166 $this->category_class = $class;
1173 * Allows you to change which class SimplePie uses for feed enclosures.
1174 * Useful when you are overloading or extending SimplePie's default classes.
1177 * @param string $class Name of custom class.
1178 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1179 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1181 function set_enclosure_class($class = 'SimplePie_Enclosure')
1183 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1185 $this->enclosure_class = $class;
1192 * Allows you to change which class SimplePie uses for <media:text> captions
1193 * Useful when you are overloading or extending SimplePie's default classes.
1196 * @param string $class Name of custom class.
1197 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1198 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1200 function set_caption_class($class = 'SimplePie_Caption')
1202 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1204 $this->caption_class = $class;
1211 * Allows you to change which class SimplePie uses for <media:copyright>
1212 * Useful when you are overloading or extending SimplePie's default classes.
1215 * @param string $class Name of custom class.
1216 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1217 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1219 function set_copyright_class($class = 'SimplePie_Copyright')
1221 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1223 $this->copyright_class = $class;
1230 * Allows you to change which class SimplePie uses for <media:credit>
1231 * Useful when you are overloading or extending SimplePie's default classes.
1234 * @param string $class Name of custom class.
1235 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1236 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1238 function set_credit_class($class = 'SimplePie_Credit')
1240 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1242 $this->credit_class = $class;
1249 * Allows you to change which class SimplePie uses for <media:rating>
1250 * Useful when you are overloading or extending SimplePie's default classes.
1253 * @param string $class Name of custom class.
1254 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1255 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1257 function set_rating_class($class = 'SimplePie_Rating')
1259 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1261 $this->rating_class = $class;
1268 * Allows you to change which class SimplePie uses for <media:restriction>
1269 * Useful when you are overloading or extending SimplePie's default classes.
1272 * @param string $class Name of custom class.
1273 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1274 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1276 function set_restriction_class($class = 'SimplePie_Restriction')
1278 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1280 $this->restriction_class = $class;
1287 * Allows you to change which class SimplePie uses for content-type sniffing.
1288 * Useful when you are overloading or extending SimplePie's default classes.
1291 * @param string $class Name of custom class.
1292 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1293 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1295 function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1297 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1299 $this->content_type_sniffer_class = $class;
1306 * Allows you to change which class SimplePie uses item sources.
1307 * Useful when you are overloading or extending SimplePie's default classes.
1310 * @param string $class Name of custom class.
1311 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
1312 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1314 function set_source_class($class = 'SimplePie_Source')
1316 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1318 $this->source_class = $class;
1325 * Allows you to override the default user agent string.
1328 * @param string $ua New user agent string.
1330 function set_useragent($ua = SIMPLEPIE_USERAGENT)
1332 $this->useragent = (string) $ua;
1336 * Set callback function to create cache filename with
1339 * @param mixed $function Callback function
1341 function set_cache_name_function($function = 'md5')
1343 if (is_callable($function))
1345 $this->cache_name_function = $function;
1350 * Set javascript query string parameter
1353 * @param mixed $get Javascript query string parameter
1355 function set_javascript($get = 'js')
1359 $this->javascript = (string) $get;
1363 $this->javascript = false;
1368 * Set options to make SP as fast as possible. Forgoes a
1369 * substantial amount of data sanitization in favor of speed.
1372 * @param bool $set Whether to set them or not
1374 function set_stupidly_fast($set = false)
1378 $this->enable_order_by_date(false);
1379 $this->remove_div(false);
1380 $this->strip_comments(false);
1381 $this->strip_htmltags(false);
1382 $this->strip_attributes(false);
1383 $this->set_image_handler(false);
1388 * Set maximum number of feeds to check with autodiscovery
1391 * @param int $max Maximum number of feeds to check
1393 function set_max_checked_feeds($max = 10)
1395 $this->max_checked_feeds = (int) $max;
1398 function remove_div($enable = true)
1400 $this->sanitize->remove_div($enable);
1403 function strip_htmltags($tags = '', $encode = null)
1407 $tags = $this->strip_htmltags;
1409 $this->sanitize->strip_htmltags($tags);
1410 if ($encode !== null)
1412 $this->sanitize->encode_instead_of_strip($tags);
1416 function encode_instead_of_strip($enable = true)
1418 $this->sanitize->encode_instead_of_strip($enable);
1421 function strip_attributes($attribs = '')
1423 if ($attribs === '')
1425 $attribs = $this->strip_attributes;
1427 $this->sanitize->strip_attributes($attribs);
1430 function set_output_encoding($encoding = 'UTF-8')
1432 $this->sanitize->set_output_encoding($encoding);
1435 function strip_comments($strip = false)
1437 $this->sanitize->strip_comments($strip);
1441 * Set element/attribute key/value pairs of HTML attributes
1442 * containing URLs that need to be resolved relative to the feed
1446 * @param array $element_attribute Element/attribute key/value pairs
1448 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'))
1450 $this->sanitize->set_url_replacements($element_attribute);
1454 * Set the handler to enable the display of cached favicons.
1457 * @param str $page Web-accessible path to the handler_favicon.php file.
1458 * @param str $qs The query string that the value should be passed to.
1460 function set_favicon_handler($page = false, $qs = 'i')
1462 if ($page !== false)
1464 $this->favicon_handler = $page . '?' . $qs . '=';
1468 $this->favicon_handler = '';
1473 * Set the handler to enable the display of cached images.
1476 * @param str $page Web-accessible path to the handler_image.php file.
1477 * @param str $qs The query string that the value should be passed to.
1479 function set_image_handler($page = false, $qs = 'i')
1481 if ($page !== false)
1483 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1487 $this->image_handler = '';
1492 * Set the limit for items returned per-feed with multifeeds.
1495 * @param integer $limit The maximum number of items to return.
1497 function set_item_limit($limit = 0)
1499 $this->item_limit = (int) $limit;
1504 // Check absolute bare minimum requirements.
1505 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1509 // 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.
1510 elseif (!extension_loaded('xmlreader'))
1512 static $xml_is_sane = null;
1513 if ($xml_is_sane === null)
1515 $parser_check = xml_parser_create();
1516 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
1517 xml_parser_free($parser_check);
1518 $xml_is_sane = isset($values[0]['value']);
1526 if (isset($_GET[$this->javascript]))
1528 SimplePie_Misc::output_javascript();
1532 // Pass whatever was set with config options over to the sanitizer.
1533 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1534 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1536 if ($this->feed_url !== null || $this->raw_data !== null)
1538 $this->data = array();
1539 $this->multifeed_objects = array();
1542 if ($this->feed_url !== null)
1544 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1545 // Decide whether to enable caching
1546 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1548 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1550 // If it's enabled and we don't want an XML dump, use the cache
1551 if ($cache && !$this->xml_dump)
1554 $this->data = $cache->load();
1555 if (!empty($this->data))
1557 // If the cache is for an outdated build of SimplePie
1558 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1561 $this->data = array();
1563 // If we've hit a collision just rerun it with caching disabled
1564 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1567 $this->data = array();
1569 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1570 elseif (isset($this->data['feed_url']))
1572 // If the autodiscovery cache is still valid use it.
1573 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1575 // Do not need to do feed autodiscovery yet.
1576 if ($this->data['feed_url'] === $this->data['url'])
1579 $this->data = array();
1583 $this->set_feed_url($this->data['feed_url']);
1584 return $this->init();
1588 // Check if the cache has been updated
1589 elseif ($cache->mtime() + $this->cache_duration < time())
1591 // If we have last-modified and/or etag set
1592 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1595 if (isset($this->data['headers']['last-modified']))
1597 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1599 if (isset($this->data['headers']['etag']))
1601 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1603 $file =& new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1606 if ($file->status_code === 304)
1613 $headers = $file->headers;
1622 // If the cache is still valid, just return true
1628 // If the cache is empty, delete it
1632 $this->data = array();
1635 // 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.
1638 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1640 $file =& $this->file;
1644 $file =& new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1647 // If the file connection has an error, set SimplePie::error to that and quit
1648 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1650 $this->error = $file->error;
1651 if (!empty($this->data))
1661 if (!$this->force_feed)
1663 // Check if the supplied URL is a feed, if it isn't, look for it.
1664 $locate =& new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1665 if (!$locate->is_feed($file))
1667 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1669 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1673 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1674 if (!$cache->save($this))
1676 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);
1678 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1680 $this->feed_url = $file->url;
1684 $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.";
1685 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1692 $headers = $file->headers;
1693 $data = $file->body;
1694 $sniffer =& new $this->content_type_sniffer_class($file);
1695 $sniffed = $sniffer->get_type();
1699 $data = $this->raw_data;
1702 // Set up array of possible encodings
1703 $encodings = array();
1705 // First check to see if input has been overridden.
1706 if ($this->input_encoding !== false)
1708 $encodings[] = $this->input_encoding;
1711 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1712 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1714 // RFC 3023 (only applies to sniffed content)
1715 if (isset($sniffed))
1717 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1719 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1721 $encodings[] = strtoupper($charset[1]);
1723 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1724 $encodings[] = 'UTF-8';
1726 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1728 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1730 $encodings[] = $charset[1];
1732 $encodings[] = 'US-ASCII';
1734 // Text MIME-type default
1735 elseif (substr($sniffed, 0, 5) === 'text/')
1737 $encodings[] = 'US-ASCII';
1741 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1742 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1743 $encodings[] = 'UTF-8';
1744 $encodings[] = 'ISO-8859-1';
1746 // There's no point in trying an encoding twice
1747 $encodings = array_unique($encodings);
1749 // If we want the XML, just output that with the most likely encoding and quit
1750 if ($this->xml_dump)
1752 header('Content-type: text/xml; charset=' . $encodings[0]);
1757 // Loop through each possible encoding, till we return something, or run out of possibilities
1758 foreach ($encodings as $encoding)
1760 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1761 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1763 // Create new parser
1764 $parser =& new $this->parser_class();
1766 // If it's parsed fine
1767 if ($parser->parse($utf8_data, 'UTF-8'))
1769 $this->data = $parser->get_data();
1770 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1772 if (isset($headers))
1774 $this->data['headers'] = $headers;
1776 $this->data['build'] = SIMPLEPIE_BUILD;
1778 // Cache the file if caching is enabled
1779 if ($cache && !$cache->save($this))
1781 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);
1787 $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1788 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1796 // We have an error, just set SimplePie_Misc::error to it and quit
1797 $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());
1801 $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.';
1803 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1806 elseif (!empty($this->multifeed_url))
1810 $this->multifeed_objects = array();
1811 foreach ($this->multifeed_url as $url)
1815 // This keyword needs to defy coding standards for PHP4 compatibility
1816 $this->multifeed_objects[$i] = clone($this);
1820 $this->multifeed_objects[$i] = $this;
1822 $this->multifeed_objects[$i]->set_feed_url($url);
1823 $success |= $this->multifeed_objects[$i]->init();
1826 return (bool) $success;
1835 * Return the error message for the occured error
1838 * @return string Error message
1842 return $this->error;
1845 function get_encoding()
1847 return $this->sanitize->output_encoding;
1850 function handle_content_type($mime = 'text/html')
1852 if (!headers_sent())
1854 $header = "Content-type: $mime;";
1855 if ($this->get_encoding())
1857 $header .= ' charset=' . $this->get_encoding();
1861 $header .= ' charset=UTF-8';
1869 if (!isset($this->data['type']))
1871 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1872 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1874 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1876 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1878 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1880 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1882 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1883 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1884 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1885 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1887 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1889 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1890 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1891 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1892 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1894 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1897 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1899 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1900 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1902 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1905 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1906 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1908 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1911 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1915 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1922 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1926 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1930 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1934 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1941 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1944 return $this->data['type'];
1948 * Returns the URL for the favicon of the feed's website.
1950 * @todo Cache atom:icon
1954 function get_favicon()
1956 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
1958 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
1960 elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
1962 $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
1964 if ($this->cache && $this->favicon_handler)
1966 $favicon_filename = call_user_func($this->cache_name_function, $favicon);
1967 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
1971 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1975 $file =& new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
1977 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)
1979 $sniffer =& new $this->content_type_sniffer_class($file);
1980 if (substr($sniffer->get_type(), 0, 6) === 'image/')
1982 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
1984 return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
1988 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);
1989 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2002 return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
2009 * @todo If we have a perm redirect we should return the new URL
2010 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
2011 * @todo Also, |atom:link|@rel=self
2013 function subscribe_url()
2015 if ($this->feed_url !== null)
2017 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
2025 function subscribe_feed()
2027 if ($this->feed_url !== null)
2029 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2037 function subscribe_outlook()
2039 if ($this->feed_url !== null)
2041 return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
2049 function subscribe_podcast()
2051 if ($this->feed_url !== null)
2053 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
2061 function subscribe_itunes()
2063 if ($this->feed_url !== null)
2065 return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
2074 * Creates the subscribe_* methods' return data
2077 * @param string $feed_url String to prefix to the feed URL
2078 * @param string $site_url String to prefix to the site URL (and
2079 * suffix to the feed URL)
2080 * @return mixed URL if feed exists, false otherwise
2082 function subscribe_service($feed_url, $site_url = null)
2084 if ($this->subscribe_url())
2086 $return = $feed_url . rawurlencode($this->feed_url);
2087 if ($site_url !== null && $this->get_link() !== null)
2089 $return .= $site_url . rawurlencode($this->get_link());
2091 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
2099 function subscribe_aol()
2101 return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
2104 function subscribe_bloglines()
2106 return $this->subscribe_service('http://www.bloglines.com/sub/');
2109 function subscribe_eskobo()
2111 return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
2114 function subscribe_feedfeeds()
2116 return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
2119 function subscribe_feedster()
2121 return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
2124 function subscribe_google()
2126 return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
2129 function subscribe_gritwire()
2131 return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
2134 function subscribe_msn()
2136 return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
2139 function subscribe_netvibes()
2141 return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
2144 function subscribe_newsburst()
2146 return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
2149 function subscribe_newsgator()
2151 return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
2154 function subscribe_odeo()
2156 return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
2159 function subscribe_podnova()
2161 return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
2164 function subscribe_rojo()
2166 return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
2169 function subscribe_yahoo()
2171 return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
2174 function get_feed_tags($namespace, $tag)
2176 $type = $this->get_type();
2177 if ($type & SIMPLEPIE_TYPE_ATOM_10)
2179 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
2181 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
2184 if ($type & SIMPLEPIE_TYPE_ATOM_03)
2186 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
2188 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
2191 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
2193 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
2195 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
2198 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2200 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
2202 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
2208 function get_channel_tags($namespace, $tag)
2210 $type = $this->get_type();
2211 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
2213 if ($return = $this->get_feed_tags($namespace, $tag))
2218 if ($type & SIMPLEPIE_TYPE_RSS_10)
2220 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
2222 if (isset($channel[0]['child'][$namespace][$tag]))
2224 return $channel[0]['child'][$namespace][$tag];
2228 if ($type & SIMPLEPIE_TYPE_RSS_090)
2230 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
2232 if (isset($channel[0]['child'][$namespace][$tag]))
2234 return $channel[0]['child'][$namespace][$tag];
2238 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2240 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
2242 if (isset($channel[0]['child'][$namespace][$tag]))
2244 return $channel[0]['child'][$namespace][$tag];
2251 function get_image_tags($namespace, $tag)
2253 $type = $this->get_type();
2254 if ($type & SIMPLEPIE_TYPE_RSS_10)
2256 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
2258 if (isset($image[0]['child'][$namespace][$tag]))
2260 return $image[0]['child'][$namespace][$tag];
2264 if ($type & SIMPLEPIE_TYPE_RSS_090)
2266 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2268 if (isset($image[0]['child'][$namespace][$tag]))
2270 return $image[0]['child'][$namespace][$tag];
2274 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2276 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2278 if (isset($image[0]['child'][$namespace][$tag]))
2280 return $image[0]['child'][$namespace][$tag];
2287 function get_base($element = array())
2289 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2291 return $element['xml_base'];
2293 elseif ($this->get_link() !== null)
2295 return $this->get_link();
2299 return $this->subscribe_url();
2303 function sanitize($data, $type, $base = '')
2305 return $this->sanitize->sanitize($data, $type, $base);
2308 function get_title()
2310 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2312 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2314 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2316 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2318 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2320 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2322 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2324 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2326 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2328 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2330 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2332 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2334 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2336 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2344 function get_category($key = 0)
2346 $categories = $this->get_categories();
2347 if (isset($categories[$key]))
2349 return $categories[$key];
2357 function get_categories()
2359 $categories = array();
2361 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2366 if (isset($category['attribs']['']['term']))
2368 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2370 if (isset($category['attribs']['']['scheme']))
2372 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2374 if (isset($category['attribs']['']['label']))
2376 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2378 $categories[] =& new $this->category_class($term, $scheme, $label);
2380 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2382 // This is really the label, but keep this as the term also for BC.
2383 // Label will also work on retrieving because that falls back to term.
2384 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2385 if (isset($category['attribs']['']['domain']))
2387 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2393 $categories[] =& new $this->category_class($term, $scheme, null);
2395 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2397 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2399 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2401 $categories[] =& new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2404 if (!empty($categories))
2406 return SimplePie_Misc::array_unique($categories);
2414 function get_author($key = 0)
2416 $authors = $this->get_authors();
2417 if (isset($authors[$key]))
2419 return $authors[$key];
2427 function get_authors()
2430 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2435 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2437 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2439 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2441 $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]));
2443 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2445 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2447 if ($name !== null || $email !== null || $uri !== null)
2449 $authors[] =& new $this->author_class($name, $uri, $email);
2452 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2457 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2459 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2461 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2463 $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]));
2465 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2467 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2469 if ($name !== null || $email !== null || $url !== null)
2471 $authors[] =& new $this->author_class($name, $url, $email);
2474 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2476 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2478 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2480 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2482 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2484 $authors[] =& new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2487 if (!empty($authors))
2489 return SimplePie_Misc::array_unique($authors);
2497 function get_contributor($key = 0)
2499 $contributors = $this->get_contributors();
2500 if (isset($contributors[$key]))
2502 return $contributors[$key];
2510 function get_contributors()
2512 $contributors = array();
2513 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2518 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2520 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2522 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2524 $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]));
2526 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2528 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2530 if ($name !== null || $email !== null || $uri !== null)
2532 $contributors[] =& new $this->author_class($name, $uri, $email);
2535 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2540 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2542 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2544 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2546 $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]));
2548 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2550 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2552 if ($name !== null || $email !== null || $url !== null)
2554 $contributors[] =& new $this->author_class($name, $url, $email);
2558 if (!empty($contributors))
2560 return SimplePie_Misc::array_unique($contributors);
2568 function get_link($key = 0, $rel = 'alternate')
2570 $links = $this->get_links($rel);
2571 if (isset($links[$key]))
2573 return $links[$key];
2582 * Added for parity between the parent-level and the item/entry-level.
2584 function get_permalink()
2586 return $this->get_link(0);
2589 function get_links($rel = 'alternate')
2591 if (!isset($this->data['links']))
2593 $this->data['links'] = array();
2594 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2596 foreach ($links as $link)
2598 if (isset($link['attribs']['']['href']))
2600 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2601 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2605 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2607 foreach ($links as $link)
2609 if (isset($link['attribs']['']['href']))
2611 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2612 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2617 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2619 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2621 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2623 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2625 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2627 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2630 $keys = array_keys($this->data['links']);
2631 foreach ($keys as $key)
2633 if (SimplePie_Misc::is_isegment_nz_nc($key))
2635 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2637 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2638 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2642 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2645 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2647 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2649 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2653 if (isset($this->data['links'][$rel]))
2655 return $this->data['links'][$rel];
2663 function get_all_discovered_feeds()
2665 return $this->all_discovered_feeds;
2668 function get_description()
2670 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2672 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2674 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2676 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2678 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2680 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2682 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2684 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2686 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2688 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2690 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2692 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2694 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2696 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2698 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2700 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2702 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2704 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2712 function get_copyright()
2714 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2716 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2718 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2720 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2722 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2724 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2726 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2728 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2730 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2732 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2740 function get_language()
2742 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2744 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2746 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2748 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2750 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2752 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2754 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2756 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2758 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2760 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2762 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2764 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2766 elseif (isset($this->data['headers']['content-language']))
2768 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2776 function get_latitude()
2779 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2781 return (float) $return[0]['data'];
2783 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))
2785 return (float) $match[1];
2793 function get_longitude()
2795 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2797 return (float) $return[0]['data'];
2799 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2801 return (float) $return[0]['data'];
2803 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))
2805 return (float) $match[2];
2813 function get_image_title()
2815 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2817 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2819 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2821 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2823 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2825 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2827 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2829 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2831 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2833 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2841 function get_image_url()
2843 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2845 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2847 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2849 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2851 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2853 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2855 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2857 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2859 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2861 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2863 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2865 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2873 function get_image_link()
2875 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2877 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2879 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2881 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2883 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2885 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2893 function get_image_width()
2895 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2897 return round($return[0]['data']);
2899 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2909 function get_image_height()
2911 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2913 return round($return[0]['data']);
2915 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2925 function get_item_quantity($max = 0)
2928 $qty = count($this->get_items());
2935 return ($qty > $max) ? $max : $qty;
2939 function get_item($key = 0)
2941 $items = $this->get_items();
2942 if (isset($items[$key]))
2944 return $items[$key];
2952 function get_items($start = 0, $end = 0)
2954 if (!isset($this->data['items']))
2956 if (!empty($this->multifeed_objects))
2958 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2962 $this->data['items'] = array();
2963 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2965 $keys = array_keys($items);
2966 foreach ($keys as $key)
2968 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2971 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2973 $keys = array_keys($items);
2974 foreach ($keys as $key)
2976 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2979 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2981 $keys = array_keys($items);
2982 foreach ($keys as $key)
2984 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2987 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2989 $keys = array_keys($items);
2990 foreach ($keys as $key)
2992 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
2995 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2997 $keys = array_keys($items);
2998 foreach ($keys as $key)
3000 $this->data['items'][] =& new $this->item_class($this, $items[$key]);
3006 if (!empty($this->data['items']))
3008 // If we want to order it by date, check if all items have a date, and then sort it
3009 if ($this->order_by_date && empty($this->multifeed_objects))
3011 if (!isset($this->data['ordered_items']))
3014 foreach ($this->data['items'] as $item)
3016 if (!$item->get_date('U'))
3023 $this->data['ordered_items'] = $this->data['items'];
3026 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
3029 $items = $this->data['ordered_items'];
3033 $items = $this->data['items'];
3036 // Slice the data as desired
3039 return array_slice($items, $start);
3043 return array_slice($items, $start, $end);
3055 function sort_items($a, $b)
3057 return $a->get_date('U') <= $b->get_date('U');
3063 function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3065 if (is_array($urls) && sizeof($urls) > 0)
3068 foreach ($urls as $arg)
3070 if (is_a($arg, 'SimplePie'))
3072 $items = array_merge($items, $arg->get_items(0, $limit));
3076 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3081 foreach ($items as $item)
3083 if (!$item->get_date('U'))
3092 usort($items, array('SimplePie', 'sort_items'));
3097 return array_slice($items, $start);
3101 return array_slice($items, $start, $end);
3106 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3112 class SimplePie_Item
3115 var $data = array();
3117 function SimplePie_Item($feed, $data)
3119 $this->feed = $feed;
3120 $this->data = $data;
3123 function __toString()
3125 return md5(serialize($this->data));
3129 * Remove items that link back to this before destroying this object
3131 function __destruct()
3133 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
3139 function get_item_tags($namespace, $tag)
3141 if (isset($this->data['child'][$namespace][$tag]))
3143 return $this->data['child'][$namespace][$tag];
3151 function get_base($element = array())
3153 return $this->feed->get_base($element);
3156 function sanitize($data, $type, $base = '')
3158 return $this->feed->sanitize($data, $type, $base);
3166 function get_id($hash = false)
3170 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
3172 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3174 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
3176 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3178 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3180 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3182 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
3184 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3186 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
3188 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3190 elseif (($return = $this->get_permalink()) !== null)
3194 elseif (($return = $this->get_title()) !== null)
3199 if ($this->get_permalink() !== null || $this->get_title() !== null)
3201 return md5($this->get_permalink() . $this->get_title());
3205 return md5(serialize($this->data));
3209 function get_title()
3211 if (!isset($this->data['title']))
3213 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
3215 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3217 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
3219 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3221 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
3223 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3225 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
3227 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3229 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
3231 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3233 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
3235 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3237 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
3239 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3243 $this->data['title'] = null;
3246 return $this->data['title'];
3249 function get_description($description_only = false)
3251 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
3253 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3255 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
3257 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3259 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
3261 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
3263 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3265 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3267 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3269 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3271 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3273 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3275 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3277 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3279 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3281 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3283 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
3285 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
3288 elseif (!$description_only)
3290 return $this->get_content(true);
3298 function get_content($content_only = false)
3300 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3302 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3304 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3306 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3308 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3310 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3312 elseif (!$content_only)
3314 return $this->get_description(true);
3322 function get_category($key = 0)
3324 $categories = $this->get_categories();
3325 if (isset($categories[$key]))
3327 return $categories[$key];
3335 function get_categories()
3337 $categories = array();
3339 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3344 if (isset($category['attribs']['']['term']))
3346 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3348 if (isset($category['attribs']['']['scheme']))
3350 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3352 if (isset($category['attribs']['']['label']))
3354 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3356 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
3358 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3360 // This is really the label, but keep this as the term also for BC.
3361 // Label will also work on retrieving because that falls back to term.
3362 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3363 if (isset($category['attribs']['']['domain']))
3365 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3371 $categories[] =& new $this->feed->category_class($term, $scheme, null);
3373 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3375 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3377 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3379 $categories[] =& new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3382 if (!empty($categories))
3384 return SimplePie_Misc::array_unique($categories);
3392 function get_author($key = 0)
3394 $authors = $this->get_authors();
3395 if (isset($authors[$key]))
3397 return $authors[$key];
3405 function get_contributor($key = 0)
3407 $contributors = $this->get_contributors();
3408 if (isset($contributors[$key]))
3410 return $contributors[$key];
3418 function get_contributors()
3420 $contributors = array();
3421 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3426 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3428 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3430 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3432 $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]));
3434 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3436 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3438 if ($name !== null || $email !== null || $uri !== null)
3440 $contributors[] =& new $this->feed->author_class($name, $uri, $email);
3443 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3448 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3450 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3452 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3454 $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]));
3456 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3458 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3460 if ($name !== null || $email !== null || $url !== null)
3462 $contributors[] =& new $this->feed->author_class($name, $url, $email);
3466 if (!empty($contributors))
3468 return SimplePie_Misc::array_unique($contributors);
3476 function get_authors()
3479 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3484 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3486 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3488 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3490 $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]));
3492 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3494 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3496 if ($name !== null || $email !== null || $uri !== null)
3498 $authors[] =& new $this->feed->author_class($name, $uri, $email);
3501 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3506 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3508 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3510 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3512 $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]));
3514 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3516 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3518 if ($name !== null || $email !== null || $url !== null)
3520 $authors[] =& new $this->feed->author_class($name, $url, $email);
3523 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3525 $authors[] =& new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3527 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3529 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3531 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3533 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3535 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3537 $authors[] =& new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3540 if (!empty($authors))
3542 return SimplePie_Misc::array_unique($authors);
3544 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3548 elseif ($authors = $this->feed->get_authors())
3558 function get_copyright()
3560 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3562 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3564 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3566 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3568 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3570 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3578 function get_date($date_format = 'j F Y, g:i a')
3580 if (!isset($this->data['date']))
3582 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3584 $this->data['date']['raw'] = $return[0]['data'];
3586 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3588 $this->data['date']['raw'] = $return[0]['data'];
3590 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3592 $this->data['date']['raw'] = $return[0]['data'];
3594 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3596 $this->data['date']['raw'] = $return[0]['data'];
3598 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3600 $this->data['date']['raw'] = $return[0]['data'];
3602 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3604 $this->data['date']['raw'] = $return[0]['data'];
3606 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3608 $this->data['date']['raw'] = $return[0]['data'];
3610 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3612 $this->data['date']['raw'] = $return[0]['data'];
3615 if (!empty($this->data['date']['raw']))
3617 $parser = SimplePie_Parse_Date::get();
3618 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3622 $this->data['date'] = null;
3625 if ($this->data['date'])
3627 $date_format = (string) $date_format;
3628 switch ($date_format)
3631 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3634 return $this->data['date']['parsed'];
3637 return date($date_format, $this->data['date']['parsed']);
3646 function get_local_date($date_format = '%c')
3650 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3652 elseif (($date = $this->get_date('U')) !== null && $date !== false)
3654 return strftime($date_format, $date);
3662 function get_permalink()
3664 $link = $this->get_link();
3665 $enclosure = $this->get_enclosure(0);
3670 elseif ($enclosure !== null)
3672 return $enclosure->get_link();
3680 function get_link($key = 0, $rel = 'alternate')
3682 $links = $this->get_links($rel);
3683 if ($links[$key] !== null)
3685 return $links[$key];
3693 function get_links($rel = 'alternate')
3695 if (!isset($this->data['links']))
3697 $this->data['links'] = array();
3698 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3700 if (isset($link['attribs']['']['href']))
3702 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3703 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3707 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3709 if (isset($link['attribs']['']['href']))
3711 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3712 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3715 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3717 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3719 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3721 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3723 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3725 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3727 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3729 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3731 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3735 $keys = array_keys($this->data['links']);
3736 foreach ($keys as $key)
3738 if (SimplePie_Misc::is_isegment_nz_nc($key))
3740 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3742 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3743 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3747 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3750 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3752 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3754 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3757 if (isset($this->data['links'][$rel]))
3759 return $this->data['links'][$rel];
3768 * @todo Add ability to prefer one type of content over another (in a media group).
3770 function get_enclosure($key = 0, $prefer = null)
3772 $enclosures = $this->get_enclosures();
3773 if (isset($enclosures[$key]))
3775 return $enclosures[$key];
3784 * Grabs all available enclosures (podcasts, etc.)
3786 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3788 * 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.
3790 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3791 * @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).
3793 function get_enclosures()
3795 if (!isset($this->data['enclosures']))
3797 $this->data['enclosures'] = array();
3800 $captions_parent = null;
3801 $categories_parent = null;
3802 $copyrights_parent = null;
3803 $credits_parent = null;
3804 $description_parent = null;
3805 $duration_parent = null;
3806 $hashes_parent = null;
3807 $keywords_parent = null;
3808 $player_parent = null;
3809 $ratings_parent = null;
3810 $restrictions_parent = null;
3811 $thumbnails_parent = null;
3812 $title_parent = null;
3814 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3815 $parent = $this->get_feed();
3818 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3820 foreach ($captions as $caption)
3822 $caption_type = null;
3823 $caption_lang = null;
3824 $caption_startTime = null;
3825 $caption_endTime = null;
3826 $caption_text = null;
3827 if (isset($caption['attribs']['']['type']))
3829 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3831 if (isset($caption['attribs']['']['lang']))
3833 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3835 if (isset($caption['attribs']['']['start']))
3837 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3839 if (isset($caption['attribs']['']['end']))
3841 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3843 if (isset($caption['data']))
3845 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3847 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3850 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3852 foreach ($captions as $caption)
3854 $caption_type = null;
3855 $caption_lang = null;
3856 $caption_startTime = null;
3857 $caption_endTime = null;
3858 $caption_text = null;
3859 if (isset($caption['attribs']['']['type']))
3861 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3863 if (isset($caption['attribs']['']['lang']))
3865 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3867 if (isset($caption['attribs']['']['start']))
3869 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3871 if (isset($caption['attribs']['']['end']))
3873 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3875 if (isset($caption['data']))
3877 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3879 $captions_parent[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3882 if (is_array($captions_parent))
3884 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3888 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3893 if (isset($category['data']))
3895 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3897 if (isset($category['attribs']['']['scheme']))
3899 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3903 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3905 if (isset($category['attribs']['']['label']))
3907 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3909 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3911 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3916 if (isset($category['data']))
3918 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3920 if (isset($category['attribs']['']['scheme']))
3922 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3926 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3928 if (isset($category['attribs']['']['label']))
3930 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3932 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3934 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3937 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3939 if (isset($category['attribs']['']['text']))
3941 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3943 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3945 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3947 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3949 if (isset($subcategory['attribs']['']['text']))
3951 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3953 $categories_parent[] =& new $this->feed->category_class($term, $scheme, $label);
3957 if (is_array($categories_parent))
3959 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3963 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3965 $copyright_url = null;
3966 $copyright_label = null;
3967 if (isset($copyright[0]['attribs']['']['url']))
3969 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3971 if (isset($copyright[0]['data']))
3973 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3975 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3977 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3979 $copyright_url = null;
3980 $copyright_label = null;
3981 if (isset($copyright[0]['attribs']['']['url']))
3983 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3985 if (isset($copyright[0]['data']))
3987 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3989 $copyrights_parent =& new $this->feed->copyright_class($copyright_url, $copyright_label);
3993 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3995 foreach ($credits as $credit)
3997 $credit_role = null;
3998 $credit_scheme = null;
3999 $credit_name = null;
4000 if (isset($credit['attribs']['']['role']))
4002 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4004 if (isset($credit['attribs']['']['scheme']))
4006 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4010 $credit_scheme = 'urn:ebu';
4012 if (isset($credit['data']))
4014 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4016 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4019 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
4021 foreach ($credits as $credit)
4023 $credit_role = null;
4024 $credit_scheme = null;
4025 $credit_name = null;
4026 if (isset($credit['attribs']['']['role']))
4028 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4030 if (isset($credit['attribs']['']['scheme']))
4032 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4036 $credit_scheme = 'urn:ebu';
4038 if (isset($credit['data']))
4040 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4042 $credits_parent[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4045 if (is_array($credits_parent))
4047 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
4051 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4053 if (isset($description_parent[0]['data']))
4055 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4058 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
4060 if (isset($description_parent[0]['data']))
4062 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4067 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
4072 if (isset($duration_parent[0]['data']))
4074 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4075 if (sizeof($temp) > 0)
4077 $seconds = (int) array_pop($temp);
4079 if (sizeof($temp) > 0)
4081 $minutes = (int) array_pop($temp);
4082 $seconds += $minutes * 60;
4084 if (sizeof($temp) > 0)
4086 $hours = (int) array_pop($temp);
4087 $seconds += $hours * 3600;
4090 $duration_parent = $seconds;
4095 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4097 foreach ($hashes_iterator as $hash)
4101 if (isset($hash['data']))
4103 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4105 if (isset($hash['attribs']['']['algo']))
4107 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4113 $hashes_parent[] = $algo.':'.$value;
4116 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
4118 foreach ($hashes_iterator as $hash)
4122 if (isset($hash['data']))
4124 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4126 if (isset($hash['attribs']['']['algo']))
4128 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4134 $hashes_parent[] = $algo.':'.$value;
4137 if (is_array($hashes_parent))
4139 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
4143 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4145 if (isset($keywords[0]['data']))
4147 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4148 foreach ($temp as $word)
4150 $keywords_parent[] = trim($word);
4155 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4157 if (isset($keywords[0]['data']))
4159 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4160 foreach ($temp as $word)
4162 $keywords_parent[] = trim($word);
4167 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
4169 if (isset($keywords[0]['data']))
4171 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4172 foreach ($temp as $word)
4174 $keywords_parent[] = trim($word);
4179 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
4181 if (isset($keywords[0]['data']))
4183 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4184 foreach ($temp as $word)
4186 $keywords_parent[] = trim($word);
4191 if (is_array($keywords_parent))
4193 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
4197 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4199 if (isset($player_parent[0]['attribs']['']['url']))
4201 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4204 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
4206 if (isset($player_parent[0]['attribs']['']['url']))
4208 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4213 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4215 foreach ($ratings as $rating)
4217 $rating_scheme = null;
4218 $rating_value = null;
4219 if (isset($rating['attribs']['']['scheme']))
4221 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4225 $rating_scheme = 'urn:simple';
4227 if (isset($rating['data']))
4229 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4231 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4234 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4236 foreach ($ratings as $rating)
4238 $rating_scheme = 'urn:itunes';
4239 $rating_value = null;
4240 if (isset($rating['data']))
4242 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4244 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4247 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
4249 foreach ($ratings as $rating)
4251 $rating_scheme = null;
4252 $rating_value = null;
4253 if (isset($rating['attribs']['']['scheme']))
4255 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4259 $rating_scheme = 'urn:simple';
4261 if (isset($rating['data']))
4263 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4265 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4268 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4270 foreach ($ratings as $rating)
4272 $rating_scheme = 'urn:itunes';
4273 $rating_value = null;
4274 if (isset($rating['data']))
4276 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4278 $ratings_parent[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4281 if (is_array($ratings_parent))
4283 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4287 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4289 foreach ($restrictions as $restriction)
4291 $restriction_relationship = null;
4292 $restriction_type = null;
4293 $restriction_value = null;
4294 if (isset($restriction['attribs']['']['relationship']))
4296 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4298 if (isset($restriction['attribs']['']['type']))
4300 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4302 if (isset($restriction['data']))
4304 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4306 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4309 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4311 foreach ($restrictions as $restriction)
4313 $restriction_relationship = 'allow';
4314 $restriction_type = null;
4315 $restriction_value = 'itunes';
4316 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4318 $restriction_relationship = 'deny';
4320 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4323 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4325 foreach ($restrictions as $restriction)
4327 $restriction_relationship = null;
4328 $restriction_type = null;
4329 $restriction_value = null;
4330 if (isset($restriction['attribs']['']['relationship']))
4332 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4334 if (isset($restriction['attribs']['']['type']))
4336 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4338 if (isset($restriction['data']))
4340 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4342 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4345 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4347 foreach ($restrictions as $restriction)
4349 $restriction_relationship = 'allow';
4350 $restriction_type = null;
4351 $restriction_value = 'itunes';
4352 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4354 $restriction_relationship = 'deny';
4356 $restrictions_parent[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4359 if (is_array($restrictions_parent))
4361 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4365 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4367 foreach ($thumbnails as $thumbnail)
4369 if (isset($thumbnail['attribs']['']['url']))
4371 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4375 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4377 foreach ($thumbnails as $thumbnail)
4379 if (isset($thumbnail['attribs']['']['url']))
4381 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4387 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4389 if (isset($title_parent[0]['data']))
4391 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4394 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4396 if (isset($title_parent[0]['data']))
4398 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4416 $samplingrate = null;
4426 $description = null;
4431 $restrictions = null;
4435 // If we have media:group tags, loop through them.
4436 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4438 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4440 // If we have media:content tags, loop through them.
4441 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4443 if (isset($content['attribs']['']['url']))
4456 $samplingrate = null;
4466 $description = null;
4471 $restrictions = null;
4475 // Start checking the attributes of media:content
4476 if (isset($content['attribs']['']['bitrate']))
4478 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4480 if (isset($content['attribs']['']['channels']))
4482 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4484 if (isset($content['attribs']['']['duration']))
4486 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4490 $duration = $duration_parent;
4492 if (isset($content['attribs']['']['expression']))
4494 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4496 if (isset($content['attribs']['']['framerate']))
4498 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4500 if (isset($content['attribs']['']['height']))
4502 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4504 if (isset($content['attribs']['']['lang']))
4506 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4508 if (isset($content['attribs']['']['fileSize']))
4510 $length = ceil($content['attribs']['']['fileSize']);
4512 if (isset($content['attribs']['']['medium']))
4514 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4516 if (isset($content['attribs']['']['samplingrate']))
4518 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4520 if (isset($content['attribs']['']['type']))
4522 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4524 if (isset($content['attribs']['']['width']))
4526 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4528 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4530 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4533 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4535 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4537 $caption_type = null;
4538 $caption_lang = null;
4539 $caption_startTime = null;
4540 $caption_endTime = null;
4541 $caption_text = null;
4542 if (isset($caption['attribs']['']['type']))
4544 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4546 if (isset($caption['attribs']['']['lang']))
4548 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4550 if (isset($caption['attribs']['']['start']))
4552 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4554 if (isset($caption['attribs']['']['end']))
4556 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4558 if (isset($caption['data']))
4560 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4562 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4564 if (is_array($captions))
4566 $captions = array_values(SimplePie_Misc::array_unique($captions));
4569 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4571 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4573 $caption_type = null;
4574 $caption_lang = null;
4575 $caption_startTime = null;
4576 $caption_endTime = null;
4577 $caption_text = null;
4578 if (isset($caption['attribs']['']['type']))
4580 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4582 if (isset($caption['attribs']['']['lang']))
4584 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4586 if (isset($caption['attribs']['']['start']))
4588 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4590 if (isset($caption['attribs']['']['end']))
4592 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4594 if (isset($caption['data']))
4596 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4598 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4600 if (is_array($captions))
4602 $captions = array_values(SimplePie_Misc::array_unique($captions));
4607 $captions = $captions_parent;
4611 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4613 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4618 if (isset($category['data']))
4620 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4622 if (isset($category['attribs']['']['scheme']))
4624 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4628 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4630 if (isset($category['attribs']['']['label']))
4632 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4634 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4637 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4639 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4644 if (isset($category['data']))
4646 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4648 if (isset($category['attribs']['']['scheme']))
4650 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4654 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4656 if (isset($category['attribs']['']['label']))
4658 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4660 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
4663 if (is_array($categories) && is_array($categories_parent))
4665 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4667 elseif (is_array($categories))
4669 $categories = array_values(SimplePie_Misc::array_unique($categories));
4671 elseif (is_array($categories_parent))
4673 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4677 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4679 $copyright_url = null;
4680 $copyright_label = null;
4681 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4683 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4685 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4687 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4689 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4691 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4693 $copyright_url = null;
4694 $copyright_label = null;
4695 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4697 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4699 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4701 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4703 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
4707 $copyrights = $copyrights_parent;
4711 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4713 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4715 $credit_role = null;
4716 $credit_scheme = null;
4717 $credit_name = null;
4718 if (isset($credit['attribs']['']['role']))
4720 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4722 if (isset($credit['attribs']['']['scheme']))
4724 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4728 $credit_scheme = 'urn:ebu';
4730 if (isset($credit['data']))
4732 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4734 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4736 if (is_array($credits))
4738 $credits = array_values(SimplePie_Misc::array_unique($credits));
4741 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4743 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4745 $credit_role = null;
4746 $credit_scheme = null;
4747 $credit_name = null;
4748 if (isset($credit['attribs']['']['role']))
4750 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4752 if (isset($credit['attribs']['']['scheme']))
4754 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4758 $credit_scheme = 'urn:ebu';
4760 if (isset($credit['data']))
4762 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4764 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4766 if (is_array($credits))
4768 $credits = array_values(SimplePie_Misc::array_unique($credits));
4773 $credits = $credits_parent;
4777 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4779 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4781 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4783 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4787 $description = $description_parent;
4791 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4793 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4797 if (isset($hash['data']))
4799 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4801 if (isset($hash['attribs']['']['algo']))
4803 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4809 $hashes[] = $algo.':'.$value;
4811 if (is_array($hashes))
4813 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4816 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4818 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4822 if (isset($hash['data']))
4824 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4826 if (isset($hash['attribs']['']['algo']))
4828 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4834 $hashes[] = $algo.':'.$value;
4836 if (is_array($hashes))
4838 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4843 $hashes = $hashes_parent;
4847 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4849 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4851 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4852 foreach ($temp as $word)
4854 $keywords[] = trim($word);
4858 if (is_array($keywords))
4860 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4863 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4865 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4867 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4868 foreach ($temp as $word)
4870 $keywords[] = trim($word);
4874 if (is_array($keywords))
4876 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4881 $keywords = $keywords_parent;
4885 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4887 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4889 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4891 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4895 $player = $player_parent;
4899 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4901 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4903 $rating_scheme = null;
4904 $rating_value = null;
4905 if (isset($rating['attribs']['']['scheme']))
4907 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4911 $rating_scheme = 'urn:simple';
4913 if (isset($rating['data']))
4915 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4917 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4919 if (is_array($ratings))
4921 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4924 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4926 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4928 $rating_scheme = null;
4929 $rating_value = null;
4930 if (isset($rating['attribs']['']['scheme']))
4932 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4936 $rating_scheme = 'urn:simple';
4938 if (isset($rating['data']))
4940 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4942 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
4944 if (is_array($ratings))
4946 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4951 $ratings = $ratings_parent;
4955 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4957 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4959 $restriction_relationship = null;
4960 $restriction_type = null;
4961 $restriction_value = null;
4962 if (isset($restriction['attribs']['']['relationship']))
4964 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4966 if (isset($restriction['attribs']['']['type']))
4968 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4970 if (isset($restriction['data']))
4972 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4974 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4976 if (is_array($restrictions))
4978 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4981 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4983 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4985 $restriction_relationship = null;
4986 $restriction_type = null;
4987 $restriction_value = null;
4988 if (isset($restriction['attribs']['']['relationship']))
4990 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4992 if (isset($restriction['attribs']['']['type']))
4994 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4996 if (isset($restriction['data']))
4998 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5000 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5002 if (is_array($restrictions))
5004 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5009 $restrictions = $restrictions_parent;
5013 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5015 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5017 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5019 if (is_array($thumbnails))
5021 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5024 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5026 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5028 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5030 if (is_array($thumbnails))
5032 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5037 $thumbnails = $thumbnails_parent;
5041 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5043 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5045 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5047 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5051 $title = $title_parent;
5054 $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);
5060 // If we have standalone media:content tags, loop through them.
5061 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
5063 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
5065 if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5078 $samplingrate = null;
5088 $description = null;
5093 $restrictions = null;
5097 // Start checking the attributes of media:content
5098 if (isset($content['attribs']['']['bitrate']))
5100 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5102 if (isset($content['attribs']['']['channels']))
5104 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
5106 if (isset($content['attribs']['']['duration']))
5108 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
5112 $duration = $duration_parent;
5114 if (isset($content['attribs']['']['expression']))
5116 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
5118 if (isset($content['attribs']['']['framerate']))
5120 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
5122 if (isset($content['attribs']['']['height']))
5124 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
5126 if (isset($content['attribs']['']['lang']))
5128 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5130 if (isset($content['attribs']['']['fileSize']))
5132 $length = ceil($content['attribs']['']['fileSize']);
5134 if (isset($content['attribs']['']['medium']))
5136 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
5138 if (isset($content['attribs']['']['samplingrate']))
5140 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
5142 if (isset($content['attribs']['']['type']))
5144 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5146 if (isset($content['attribs']['']['width']))
5148 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
5150 if (isset($content['attribs']['']['url']))
5152 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5154 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
5157 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
5159 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
5161 $caption_type = null;
5162 $caption_lang = null;
5163 $caption_startTime = null;
5164 $caption_endTime = null;
5165 $caption_text = null;
5166 if (isset($caption['attribs']['']['type']))
5168 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5170 if (isset($caption['attribs']['']['lang']))
5172 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5174 if (isset($caption['attribs']['']['start']))
5176 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
5178 if (isset($caption['attribs']['']['end']))
5180 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
5182 if (isset($caption['data']))
5184 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5186 $captions[] =& new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
5188 if (is_array($captions))
5190 $captions = array_values(SimplePie_Misc::array_unique($captions));
5195 $captions = $captions_parent;
5199 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
5201 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
5206 if (isset($category['data']))
5208 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5210 if (isset($category['attribs']['']['scheme']))
5212 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5216 $scheme = 'http://search.yahoo.com/mrss/category_schema';
5218 if (isset($category['attribs']['']['label']))
5220 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5222 $categories[] =& new $this->feed->category_class($term, $scheme, $label);
5225 if (is_array($categories) && is_array($categories_parent))
5227 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
5229 elseif (is_array($categories))
5231 $categories = array_values(SimplePie_Misc::array_unique($categories));
5233 elseif (is_array($categories_parent))
5235 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
5243 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
5245 $copyright_url = null;
5246 $copyright_label = null;
5247 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
5249 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5251 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
5253 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5255 $copyrights =& new $this->feed->copyright_class($copyright_url, $copyright_label);
5259 $copyrights = $copyrights_parent;
5263 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5265 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5267 $credit_role = null;
5268 $credit_scheme = null;
5269 $credit_name = null;
5270 if (isset($credit['attribs']['']['role']))
5272 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5274 if (isset($credit['attribs']['']['scheme']))
5276 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5280 $credit_scheme = 'urn:ebu';
5282 if (isset($credit['data']))
5284 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5286 $credits[] =& new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5288 if (is_array($credits))
5290 $credits = array_values(SimplePie_Misc::array_unique($credits));
5295 $credits = $credits_parent;
5299 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5301 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5305 $description = $description_parent;
5309 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5311 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5315 if (isset($hash['data']))
5317 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5319 if (isset($hash['attribs']['']['algo']))
5321 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5327 $hashes[] = $algo.':'.$value;
5329 if (is_array($hashes))
5331 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5336 $hashes = $hashes_parent;
5340 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5342 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5344 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5345 foreach ($temp as $word)
5347 $keywords[] = trim($word);
5351 if (is_array($keywords))
5353 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5358 $keywords = $keywords_parent;
5362 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5364 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5368 $player = $player_parent;
5372 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5374 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5376 $rating_scheme = null;
5377 $rating_value = null;
5378 if (isset($rating['attribs']['']['scheme']))
5380 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5384 $rating_scheme = 'urn:simple';
5386 if (isset($rating['data']))
5388 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5390 $ratings[] =& new $this->feed->rating_class($rating_scheme, $rating_value);
5392 if (is_array($ratings))
5394 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5399 $ratings = $ratings_parent;
5403 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5405 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5407 $restriction_relationship = null;
5408 $restriction_type = null;
5409 $restriction_value = null;
5410 if (isset($restriction['attribs']['']['relationship']))
5412 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5414 if (isset($restriction['attribs']['']['type']))
5416 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5418 if (isset($restriction['data']))
5420 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5422 $restrictions[] =& new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5424 if (is_array($restrictions))
5426 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5431 $restrictions = $restrictions_parent;
5435 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5437 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5439 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5441 if (is_array($thumbnails))
5443 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5448 $thumbnails = $thumbnails_parent;
5452 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5454 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5458 $title = $title_parent;
5461 $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);
5466 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5468 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5481 $samplingrate = null;
5486 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5487 if (isset($link['attribs']['']['type']))
5489 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5491 if (isset($link['attribs']['']['length']))
5493 $length = ceil($link['attribs']['']['length']);
5496 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5497 $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);
5501 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5503 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5516 $samplingrate = null;
5521 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5522 if (isset($link['attribs']['']['type']))
5524 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5526 if (isset($link['attribs']['']['length']))
5528 $length = ceil($link['attribs']['']['length']);
5531 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5532 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5536 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5538 if (isset($enclosure[0]['attribs']['']['url']))
5551 $samplingrate = null;
5556 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5557 if (isset($enclosure[0]['attribs']['']['type']))
5559 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5561 if (isset($enclosure[0]['attribs']['']['length']))
5563 $length = ceil($enclosure[0]['attribs']['']['length']);
5566 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5567 $this->data['enclosures'][] =& new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5571 if (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))
5573 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5574 $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);
5577 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5579 if (!empty($this->data['enclosures']))
5581 return $this->data['enclosures'];
5589 function get_latitude()
5591 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5593 return (float) $return[0]['data'];
5595 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))
5597 return (float) $match[1];
5605 function get_longitude()
5607 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5609 return (float) $return[0]['data'];
5611 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5613 return (float) $return[0]['data'];
5615 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))
5617 return (float) $match[2];
5625 function get_source()
5627 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5629 return new $this->feed->source_class($this, $return[0]);
5638 * Creates the add_to_* methods' return data
5641 * @param string $item_url String to prefix to the item permalink
5642 * @param string $title_url String to prefix to the item title
5643 * (and suffix to the item permalink)
5644 * @return mixed URL if feed exists, false otherwise
5646 function add_to_service($item_url, $title_url = null, $summary_url = null)
5648 if ($this->get_permalink() !== null)
5650 $return = $item_url . rawurlencode($this->get_permalink());
5651 if ($title_url !== null && $this->get_title() !== null)
5653 $return .= $title_url . rawurlencode($this->get_title());
5655 if ($summary_url !== null && $this->get_description() !== null)
5657 $return .= $summary_url . rawurlencode($this->get_description());
5659 return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
5667 function add_to_blinklist()
5669 return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
5672 function add_to_blogmarks()
5674 return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
5677 function add_to_delicious()
5679 return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
5682 function add_to_digg()
5684 return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
5687 function add_to_furl()
5689 return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
5692 function add_to_magnolia()
5694 return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
5697 function add_to_myweb20()
5699 return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
5702 function add_to_newsvine()
5704 return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
5707 function add_to_reddit()
5709 return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
5712 function add_to_segnalo()
5714 return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
5717 function add_to_simpy()
5719 return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
5722 function add_to_spurl()
5724 return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
5727 function add_to_wists()
5729 return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
5732 function search_technorati()
5734 return $this->add_to_service('http://www.technorati.com/search/');
5738 class SimplePie_Source
5741 var $data = array();
5743 function SimplePie_Source($item, $data)
5745 $this->item = $item;
5746 $this->data = $data;
5749 function __toString()
5751 return md5(serialize($this->data));
5754 function get_source_tags($namespace, $tag)
5756 if (isset($this->data['child'][$namespace][$tag]))
5758 return $this->data['child'][$namespace][$tag];
5766 function get_base($element = array())
5768 return $this->item->get_base($element);
5771 function sanitize($data, $type, $base = '')
5773 return $this->item->sanitize($data, $type, $base);
5781 function get_title()
5783 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5785 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5787 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5789 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5791 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5793 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5795 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5797 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5799 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5801 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5803 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5805 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5807 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5809 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5817 function get_category($key = 0)
5819 $categories = $this->get_categories();
5820 if (isset($categories[$key]))
5822 return $categories[$key];
5830 function get_categories()
5832 $categories = array();
5834 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5839 if (isset($category['attribs']['']['term']))
5841 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5843 if (isset($category['attribs']['']['scheme']))
5845 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5847 if (isset($category['attribs']['']['label']))
5849 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5851 $categories[] =& new $this->item->feed->category_class($term, $scheme, $label);
5853 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5855 // This is really the label, but keep this as the term also for BC.
5856 // Label will also work on retrieving because that falls back to term.
5857 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5858 if (isset($category['attribs']['']['domain']))
5860 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5866 $categories[] =& new $this->item->feed->category_class($term, $scheme, null);
5868 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5870 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5872 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5874 $categories[] =& new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5877 if (!empty($categories))
5879 return SimplePie_Misc::array_unique($categories);
5887 function get_author($key = 0)
5889 $authors = $this->get_authors();
5890 if (isset($authors[$key]))
5892 return $authors[$key];
5900 function get_authors()
5903 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5908 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5910 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5912 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5914 $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]));
5916 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5918 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5920 if ($name !== null || $email !== null || $uri !== null)
5922 $authors[] =& new $this->item->feed->author_class($name, $uri, $email);
5925 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5930 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5932 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5934 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5936 $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]));
5938 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5940 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5942 if ($name !== null || $email !== null || $url !== null)
5944 $authors[] =& new $this->item->feed->author_class($name, $url, $email);
5947 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5949 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5951 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5953 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5955 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5957 $authors[] =& new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5960 if (!empty($authors))
5962 return SimplePie_Misc::array_unique($authors);
5970 function get_contributor($key = 0)
5972 $contributors = $this->get_contributors();
5973 if (isset($contributors[$key]))
5975 return $contributors[$key];
5983 function get_contributors()
5985 $contributors = array();
5986 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5991 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5993 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5995 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5997 $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]));
5999 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
6001 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6003 if ($name !== null || $email !== null || $uri !== null)
6005 $contributors[] =& new $this->item->feed->author_class($name, $uri, $email);
6008 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
6013 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
6015 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6017 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
6019 $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]));
6021 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
6023 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6025 if ($name !== null || $email !== null || $url !== null)
6027 $contributors[] =& new $this->item->feed->author_class($name, $url, $email);
6031 if (!empty($contributors))
6033 return SimplePie_Misc::array_unique($contributors);
6041 function get_link($key = 0, $rel = 'alternate')
6043 $links = $this->get_links($rel);
6044 if (isset($links[$key]))
6046 return $links[$key];
6055 * Added for parity between the parent-level and the item/entry-level.
6057 function get_permalink()
6059 return $this->get_link(0);
6062 function get_links($rel = 'alternate')
6064 if (!isset($this->data['links']))
6066 $this->data['links'] = array();
6067 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
6069 foreach ($links as $link)
6071 if (isset($link['attribs']['']['href']))
6073 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6074 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6078 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
6080 foreach ($links as $link)
6082 if (isset($link['attribs']['']['href']))
6084 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
6085 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
6090 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
6092 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6094 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
6096 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6098 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
6100 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
6103 $keys = array_keys($this->data['links']);
6104 foreach ($keys as $key)
6106 if (SimplePie_Misc::is_isegment_nz_nc($key))
6108 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
6110 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
6111 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
6115 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
6118 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
6120 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
6122 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
6126 if (isset($this->data['links'][$rel]))
6128 return $this->data['links'][$rel];
6136 function get_description()
6138 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
6140 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6142 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
6144 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6146 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
6148 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6150 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
6152 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6154 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
6156 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
6158 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
6160 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6162 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
6164 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6166 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
6168 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6170 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
6172 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
6180 function get_copyright()
6182 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
6184 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6186 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
6188 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
6190 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
6192 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6194 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
6196 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6198 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
6200 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6208 function get_language()
6210 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
6212 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6214 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
6216 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6218 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
6220 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
6222 elseif (isset($this->data['xml_lang']))
6224 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
6232 function get_latitude()
6234 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
6236 return (float) $return[0]['data'];
6238 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))
6240 return (float) $match[1];
6248 function get_longitude()
6250 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
6252 return (float) $return[0]['data'];
6254 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
6256 return (float) $return[0]['data'];
6258 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))
6260 return (float) $match[2];
6268 function get_image_url()
6270 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
6272 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
6274 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
6276 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6278 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
6280 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
6289 class SimplePie_Author
6295 // Constructor, used to input the data
6296 function SimplePie_Author($name = null, $link = null, $email = null)
6298 $this->name = $name;
6299 $this->link = $link;
6300 $this->email = $email;
6303 function __toString()
6305 // There is no $this->data here
6306 return md5(serialize($this));
6311 if ($this->name !== null)
6323 if ($this->link !== null)
6333 function get_email()
6335 if ($this->email !== null)
6337 return $this->email;
6346 class SimplePie_Category
6352 // Constructor, used to input the data
6353 function SimplePie_Category($term = null, $scheme = null, $label = null)
6355 $this->term = $term;
6356 $this->scheme = $scheme;
6357 $this->label = $label;
6360 function __toString()
6362 // There is no $this->data here
6363 return md5(serialize($this));
6368 if ($this->term !== null)
6378 function get_scheme()
6380 if ($this->scheme !== null)
6382 return $this->scheme;
6390 function get_label()
6392 if ($this->label !== null)
6394 return $this->label;
6398 return $this->get_term();
6403 class SimplePie_Enclosure
6433 // Constructor, used to input the data
6434 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)
6436 $this->bitrate = $bitrate;
6437 $this->captions = $captions;
6438 $this->categories = $categories;
6439 $this->channels = $channels;
6440 $this->copyright = $copyright;
6441 $this->credits = $credits;
6442 $this->description = $description;
6443 $this->duration = $duration;
6444 $this->expression = $expression;
6445 $this->framerate = $framerate;
6446 $this->hashes = $hashes;
6447 $this->height = $height;
6448 $this->javascript = $javascript;
6449 $this->keywords = $keywords;
6450 $this->lang = $lang;
6451 $this->length = $length;
6452 $this->link = $link;
6453 $this->medium = $medium;
6454 $this->player = $player;
6455 $this->ratings = $ratings;
6456 $this->restrictions = $restrictions;
6457 $this->samplingrate = $samplingrate;
6458 $this->thumbnails = $thumbnails;
6459 $this->title = $title;
6460 $this->type = $type;
6461 $this->width = $width;
6462 if (class_exists('idna_convert'))
6464 $idn =& new idna_convert;
6465 $parsed = SimplePie_Misc::parse_url($link);
6466 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6468 $this->handler = $this->get_handler(); // Needs to load last
6471 function __toString()
6473 // There is no $this->data here
6474 return md5(serialize($this));
6477 function get_bitrate()
6479 if ($this->bitrate !== null)
6481 return $this->bitrate;
6489 function get_caption($key = 0)
6491 $captions = $this->get_captions();
6492 if (isset($captions[$key]))
6494 return $captions[$key];
6502 function get_captions()
6504 if ($this->captions !== null)
6506 return $this->captions;
6514 function get_category($key = 0)
6516 $categories = $this->get_categories();
6517 if (isset($categories[$key]))
6519 return $categories[$key];
6527 function get_categories()
6529 if ($this->categories !== null)
6531 return $this->categories;
6539 function get_channels()
6541 if ($this->channels !== null)
6543 return $this->channels;
6551 function get_copyright()
6553 if ($this->copyright !== null)
6555 return $this->copyright;
6563 function get_credit($key = 0)
6565 $credits = $this->get_credits();
6566 if (isset($credits[$key]))
6568 return $credits[$key];
6576 function get_credits()
6578 if ($this->credits !== null)
6580 return $this->credits;
6588 function get_description()
6590 if ($this->description !== null)
6592 return $this->description;
6600 function get_duration($convert = false)
6602 if ($this->duration !== null)
6606 $time = SimplePie_Misc::time_hms($this->duration);
6611 return $this->duration;
6620 function get_expression()
6622 if ($this->expression !== null)
6624 return $this->expression;
6632 function get_extension()
6634 if ($this->link !== null)
6636 $url = SimplePie_Misc::parse_url($this->link);
6637 if ($url['path'] !== '')
6639 return pathinfo($url['path'], PATHINFO_EXTENSION);
6645 function get_framerate()
6647 if ($this->framerate !== null)
6649 return $this->framerate;
6657 function get_handler()
6659 return $this->get_real_type(true);
6662 function get_hash($key = 0)
6664 $hashes = $this->get_hashes();
6665 if (isset($hashes[$key]))
6667 return $hashes[$key];
6675 function get_hashes()
6677 if ($this->hashes !== null)
6679 return $this->hashes;
6687 function get_height()
6689 if ($this->height !== null)
6691 return $this->height;
6699 function get_language()
6701 if ($this->lang !== null)
6711 function get_keyword($key = 0)
6713 $keywords = $this->get_keywords();
6714 if (isset($keywords[$key]))
6716 return $keywords[$key];
6724 function get_keywords()
6726 if ($this->keywords !== null)
6728 return $this->keywords;
6736 function get_length()
6738 if ($this->length !== null)
6740 return $this->length;
6750 if ($this->link !== null)
6752 return urldecode($this->link);
6760 function get_medium()
6762 if ($this->medium !== null)
6764 return $this->medium;
6772 function get_player()
6774 if ($this->player !== null)
6776 return $this->player;
6784 function get_rating($key = 0)
6786 $ratings = $this->get_ratings();
6787 if (isset($ratings[$key]))
6789 return $ratings[$key];
6797 function get_ratings()
6799 if ($this->ratings !== null)
6801 return $this->ratings;
6809 function get_restriction($key = 0)
6811 $restrictions = $this->get_restrictions();
6812 if (isset($restrictions[$key]))
6814 return $restrictions[$key];
6822 function get_restrictions()
6824 if ($this->restrictions !== null)
6826 return $this->restrictions;
6834 function get_sampling_rate()
6836 if ($this->samplingrate !== null)
6838 return $this->samplingrate;
6848 $length = $this->get_length();
6849 if ($length !== null)
6851 return round($length/1048576, 2);
6859 function get_thumbnail($key = 0)
6861 $thumbnails = $this->get_thumbnails();
6862 if (isset($thumbnails[$key]))
6864 return $thumbnails[$key];
6872 function get_thumbnails()
6874 if ($this->thumbnails !== null)
6876 return $this->thumbnails;
6884 function get_title()
6886 if ($this->title !== null)
6888 return $this->title;
6898 if ($this->type !== null)
6908 function get_width()
6910 if ($this->width !== null)
6912 return $this->width;
6920 function native_embed($options='')
6922 return $this->embed($options, true);
6926 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6928 function embed($options = '', $native = false)
6938 $bgcolor = '#ffffff';
6940 $widescreen = false;
6941 $handler = $this->get_handler();
6942 $type = $this->get_real_type();
6944 // Process options and reassign values as necessary
6945 if (is_array($options))
6951 $options = explode(',', $options);
6952 foreach($options as $option)
6954 $opt = explode(':', $option, 2);
6955 if (isset($opt[0], $opt[1]))
6957 $opt[0] = trim($opt[0]);
6958 $opt[1] = trim($opt[1]);
6974 $altclass = $opt[1];
6994 $mediaplayer = $opt[1];
6998 $widescreen = $opt[1];
7005 $mime = explode('/', $type, 2);
7008 // Process values for 'auto'
7009 if ($width === 'auto')
7011 if ($mime === 'video')
7013 if ($height === 'auto')
7017 elseif ($widescreen)
7019 $width = round((intval($height)/9)*16);
7023 $width = round((intval($height)/3)*4);
7032 if ($height === 'auto')
7034 if ($mime === 'audio')
7038 elseif ($mime === 'video')
7040 if ($width === 'auto')
7051 elseif ($widescreen)
7053 $height = round((intval($width)/16)*9);
7057 $height = round((intval($width)/4)*3);
7065 elseif ($mime === 'audio')
7070 // Set proper placeholder value
7071 if ($mime === 'audio')
7073 $placeholder = $audio;
7075 elseif ($mime === 'video')
7077 $placeholder = $video;
7082 // Make sure the JS library is included
7085 static $javascript_outputted = null;
7086 if (!$javascript_outputted && $this->javascript)
7088 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
7089 $javascript_outputted = true;
7094 if ($handler === 'odeo')
7098 $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>';
7102 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
7107 elseif ($handler === 'flash')
7111 $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>";
7115 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
7119 // Flash Media Player file types.
7120 // Preferred handler for MP3 file types.
7121 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
7126 $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>";
7130 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
7134 // QuickTime 7 file types. Need to test with QuickTime 6.
7135 // Only handle MP3's if the Flash Media Player is not present.
7136 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
7141 if ($placeholder !== '')
7143 $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>";
7147 $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>";
7152 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
7157 elseif ($handler === 'wmedia')
7162 $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>";
7166 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
7171 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
7176 function get_real_type($find_handler = false)
7178 // If it's Odeo, let's get it out of the way.
7179 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
7184 // Mime-types by handler.
7185 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
7186 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
7187 $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
7188 $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
7189 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
7191 if ($this->get_type() !== null)
7193 $type = strtolower($this->type);
7200 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
7201 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
7203 switch (strtolower($this->get_extension()))
7208 $type = 'audio/acc';
7215 $type = 'audio/aiff';
7219 $type = 'audio/wav';
7226 $type = 'audio/midi';
7230 $type = 'audio/x-m4a';
7235 $type = 'audio/mp3';
7239 $type = 'audio/wav';
7243 $type = 'audio/x-ms-wax';
7247 $type = 'audio/x-ms-wma';
7253 $type = 'video/3gpp';
7258 $type = 'video/3gpp2';
7262 $type = 'video/x-ms-asf';
7266 $type = 'video/x-flv';
7280 $type = 'video/mpeg';
7284 $type = 'video/x-m4v';
7289 $type = 'video/quicktime';
7294 $type = 'video/mp4';
7298 $type = 'video/sd-video';
7302 $type = 'video/x-ms-wm';
7306 $type = 'video/x-ms-wmv';
7310 $type = 'video/x-ms-wvx';
7315 $type = 'application/futuresplash';
7319 $type = 'application/x-shockwave-flash';
7326 if (in_array($type, $types_flash))
7330 elseif (in_array($type, $types_fmedia))
7334 elseif (in_array($type, $types_quicktime))
7338 elseif (in_array($type, $types_wmedia))
7342 elseif (in_array($type, $types_mp3))
7358 class SimplePie_Caption
7366 // Constructor, used to input the data
7367 function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7369 $this->type = $type;
7370 $this->lang = $lang;
7371 $this->startTime = $startTime;
7372 $this->endTime = $endTime;
7373 $this->text = $text;
7376 function __toString()
7378 // There is no $this->data here
7379 return md5(serialize($this));
7382 function get_endtime()
7384 if ($this->endTime !== null)
7386 return $this->endTime;
7394 function get_language()
7396 if ($this->lang !== null)
7406 function get_starttime()
7408 if ($this->startTime !== null)
7410 return $this->startTime;
7420 if ($this->text !== null)
7432 if ($this->type !== null)
7443 class SimplePie_Credit
7449 // Constructor, used to input the data
7450 function SimplePie_Credit($role = null, $scheme = null, $name = null)
7452 $this->role = $role;
7453 $this->scheme = $scheme;
7454 $this->name = $name;
7457 function __toString()
7459 // There is no $this->data here
7460 return md5(serialize($this));
7465 if ($this->role !== null)
7475 function get_scheme()
7477 if ($this->scheme !== null)
7479 return $this->scheme;
7489 if ($this->name !== null)
7500 class SimplePie_Copyright
7505 // Constructor, used to input the data
7506 function SimplePie_Copyright($url = null, $label = null)
7509 $this->label = $label;
7512 function __toString()
7514 // There is no $this->data here
7515 return md5(serialize($this));
7520 if ($this->url !== null)
7530 function get_attribution()
7532 if ($this->label !== null)
7534 return $this->label;
7543 class SimplePie_Rating
7548 // Constructor, used to input the data
7549 function SimplePie_Rating($scheme = null, $value = null)
7551 $this->scheme = $scheme;
7552 $this->value = $value;
7555 function __toString()
7557 // There is no $this->data here
7558 return md5(serialize($this));
7561 function get_scheme()
7563 if ($this->scheme !== null)
7565 return $this->scheme;
7573 function get_value()
7575 if ($this->value !== null)
7577 return $this->value;
7586 class SimplePie_Restriction
7592 // Constructor, used to input the data
7593 function SimplePie_Restriction($relationship = null, $type = null, $value = null)
7595 $this->relationship = $relationship;
7596 $this->type = $type;
7597 $this->value = $value;
7600 function __toString()
7602 // There is no $this->data here
7603 return md5(serialize($this));
7606 function get_relationship()
7608 if ($this->relationship !== null)
7610 return $this->relationship;
7620 if ($this->type !== null)
7630 function get_value()
7632 if ($this->value !== null)
7634 return $this->value;
7644 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7646 class SimplePie_File
7650 var $success = true;
7651 var $headers = array();
7656 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7658 function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7660 if (class_exists('idna_convert'))
7662 $idn =& new idna_convert;
7663 $parsed = SimplePie_Misc::parse_url($url);
7664 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7667 $this->useragent = $useragent;
7668 if (preg_match('/^http(s)?:\/\//i', $url))
7670 if ($useragent === null)
7672 $useragent = ini_get('user_agent');
7673 $this->useragent = $useragent;
7675 if (!is_array($headers))
7679 if (!$force_fsockopen && function_exists('curl_exec'))
7681 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7683 $headers2 = array();
7684 foreach ($headers as $key => $value)
7686 $headers2[] = "$key: $value";
7688 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7690 curl_setopt($fp, CURLOPT_ENCODING, '');
7692 curl_setopt($fp, CURLOPT_URL, $url);
7693 curl_setopt($fp, CURLOPT_HEADER, 1);
7694 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7695 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7696 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7697 curl_setopt($fp, CURLOPT_REFERER, $url);
7698 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7699 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7700 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7702 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7703 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7706 $this->headers = curl_exec($fp);
7707 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7709 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7710 $this->headers = curl_exec($fp);
7712 if (curl_errno($fp))
7714 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7715 $this->success = false;
7719 $info = curl_getinfo($fp);
7721 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7722 $this->headers = array_pop($this->headers);
7723 $parser =& new SimplePie_HTTP_Parser($this->headers);
7724 if ($parser->parse())
7726 $this->headers = $parser->headers;
7727 $this->body = $parser->body;
7728 $this->status_code = $parser->status_code;
7729 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)
7732 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7733 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7740 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7741 $url_parts = parse_url($url);
7742 $socket_host = $url_parts['host'];
7743 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7745 $socket_host = "ssl://$url_parts[host]";
7746 $url_parts['port'] = 443;
7748 if (!isset($url_parts['port']))
7750 $url_parts['port'] = 80;
7752 $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
7755 $this->error = 'fsockopen error: ' . $errstr;
7756 $this->success = false;
7760 stream_set_timeout($fp, $timeout);
7761 if (isset($url_parts['path']))
7763 if (isset($url_parts['query']))
7765 $get = "$url_parts[path]?$url_parts[query]";
7769 $get = $url_parts['path'];
7776 $out = "GET $get HTTP/1.0\r\n";
7777 $out .= "Host: $url_parts[host]\r\n";
7778 $out .= "User-Agent: $useragent\r\n";
7779 if (extension_loaded('zlib'))
7781 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7784 if (isset($url_parts['user']) && isset($url_parts['pass']))
7786 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7788 foreach ($headers as $key => $value)
7790 $out .= "$key: $value\r\n";
7792 $out .= "Connection: Close\r\n\r\n";
7795 $info = stream_get_meta_data($fp);
7797 $this->headers = '';
7798 while (!$info['eof'] && !$info['timed_out'])
7800 $this->headers .= fread($fp, 1160);
7801 $info = stream_get_meta_data($fp);
7803 if (!$info['timed_out'])
7805 $parser =& new SimplePie_HTTP_Parser($this->headers);
7806 if ($parser->parse())
7808 $this->headers = $parser->headers;
7809 $this->body = $parser->body;
7810 $this->status_code = $parser->status_code;
7811 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)
7814 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7815 return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7817 if (isset($this->headers['content-encoding']))
7819 // Hey, we act dumb elsewhere, so let's do that here too
7820 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7824 $decoder =& new SimplePie_gzdecode($this->body);
7825 if (!$decoder->parse())
7827 $this->error = 'Unable to decode HTTP "gzip" stream';
7828 $this->success = false;
7832 $this->body = $decoder->data;
7837 if (($body = gzuncompress($this->body)) === false)
7839 if (($body = gzinflate($this->body)) === false)
7841 $this->error = 'Unable to decode HTTP "deflate" stream';
7842 $this->success = false;
7845 $this->body = $body;
7849 $this->error = 'Unknown content coding';
7850 $this->success = false;
7857 $this->error = 'fsocket timed out';
7858 $this->success = false;
7866 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7867 if (!$this->body = file_get_contents($url))
7869 $this->error = 'file_get_contents could not read the file';
7870 $this->success = false;
7877 * HTTP Response Parser
7879 * @package SimplePie
7881 class SimplePie_HTTP_Parser
7889 var $http_version = 0.0;
7897 var $status_code = 0;
7908 * Key/value pairs of the headers
7913 var $headers = array();
7916 * Body of the response
7924 * Current state of the state machine
7929 var $state = 'http_version';
7940 * Input data length (to avoid calling strlen() everytime this is needed)
7945 var $data_length = 0;
7948 * Current position of the pointer
7956 * Name of the hedaer currently being parsed
7964 * Value of the hedaer currently being parsed
7972 * Create an instance of the class with the input data
7975 * @param string $data Input data
7977 function SimplePie_HTTP_Parser($data)
7979 $this->data = $data;
7980 $this->data_length = strlen($this->data);
7984 * Parse the input data
7987 * @return bool true on success, false on failure
7991 while ($this->state && $this->state !== 'emit' && $this->has_data())
7993 $state = $this->state;
7997 if ($this->state === 'emit' || $this->state === 'body')
8003 $this->http_version = '';
8004 $this->status_code = '';
8006 $this->headers = array();
8013 * Check whether there is data beyond the pointer
8016 * @return bool true if there is further data, false if not
8020 return (bool) ($this->position < $this->data_length);
8024 * See if the next character is LWS
8027 * @return bool true if the next character is LWS, false if not
8029 function is_linear_whitespace()
8031 return (bool) ($this->data[$this->position] === "\x09"
8032 || $this->data[$this->position] === "\x20"
8033 || ($this->data[$this->position] === "\x0A"
8034 && isset($this->data[$this->position + 1])
8035 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
8039 * Parse the HTTP version
8043 function http_version()
8045 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
8047 $len = strspn($this->data, '0123456789.', 5);
8048 $this->http_version = substr($this->data, 5, $len);
8049 $this->position += 5 + $len;
8050 if (substr_count($this->http_version, '.') <= 1)
8052 $this->http_version = (float) $this->http_version;
8053 $this->position += strspn($this->data, "\x09\x20", $this->position);
8054 $this->state = 'status';
8058 $this->state = false;
8063 $this->state = false;
8068 * Parse the status code
8074 if ($len = strspn($this->data, '0123456789', $this->position))
8076 $this->status_code = (int) substr($this->data, $this->position, $len);
8077 $this->position += $len;
8078 $this->state = 'reason';
8082 $this->state = false;
8087 * Parse the reason phrase
8093 $len = strcspn($this->data, "\x0A", $this->position);
8094 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
8095 $this->position += $len + 1;
8096 $this->state = 'new_line';
8100 * Deal with a new line, shifting data around as needed
8106 $this->value = trim($this->value, "\x0D\x20");
8107 if ($this->name !== '' && $this->value !== '')
8109 $this->name = strtolower($this->name);
8110 if (isset($this->headers[$this->name]))
8112 $this->headers[$this->name] .= ', ' . $this->value;
8116 $this->headers[$this->name] = $this->value;
8121 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
8123 $this->position += 2;
8124 $this->state = 'body';
8126 elseif ($this->data[$this->position] === "\x0A")
8129 $this->state = 'body';
8133 $this->state = 'name';
8138 * Parse a header name
8144 $len = strcspn($this->data, "\x0A:", $this->position);
8145 if (isset($this->data[$this->position + $len]))
8147 if ($this->data[$this->position + $len] === "\x0A")
8149 $this->position += $len;
8150 $this->state = 'new_line';
8154 $this->name = substr($this->data, $this->position, $len);
8155 $this->position += $len + 1;
8156 $this->state = 'value';
8161 $this->state = false;
8166 * Parse LWS, replacing consecutive LWS characters with a single space
8170 function linear_whitespace()
8174 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
8176 $this->position += 2;
8178 elseif ($this->data[$this->position] === "\x0A")
8182 $this->position += strspn($this->data, "\x09\x20", $this->position);
8183 } while ($this->has_data() && $this->is_linear_whitespace());
8184 $this->value .= "\x20";
8188 * See what state to move to while within non-quoted header values
8194 if ($this->is_linear_whitespace())
8196 $this->linear_whitespace();
8200 switch ($this->data[$this->position])
8204 $this->state = 'quote';
8209 $this->state = 'new_line';
8213 $this->state = 'value_char';
8220 * Parse a header value while outside quotes
8224 function value_char()
8226 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
8227 $this->value .= substr($this->data, $this->position, $len);
8228 $this->position += $len;
8229 $this->state = 'value';
8233 * See what state to move to while within quoted header values
8239 if ($this->is_linear_whitespace())
8241 $this->linear_whitespace();
8245 switch ($this->data[$this->position])
8249 $this->state = 'value';
8254 $this->state = 'new_line';
8259 $this->state = 'quote_escaped';
8263 $this->state = 'quote_char';
8270 * Parse a header value while within quotes
8274 function quote_char()
8276 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
8277 $this->value .= substr($this->data, $this->position, $len);
8278 $this->position += $len;
8279 $this->state = 'value';
8283 * Parse an escaped character within quotes
8287 function quote_escaped()
8289 $this->value .= $this->data[$this->position];
8291 $this->state = 'quote';
8301 $this->body = substr($this->data, $this->position);
8302 $this->state = 'emit';
8309 * @package SimplePie
8311 class SimplePie_gzdecode
8317 * @see gzdecode::$data
8319 var $compressed_data;
8322 * Size of compressed data
8326 var $compressed_size;
8329 * Minimum size of a valid gzip string
8333 var $min_compressed_size = 18;
8336 * Current position of pointer
8353 * @see gzdecode::$compressed_data
8382 * @see gzdecode::$extra_field
8383 * @see gzdecode::$SI2
8391 * @see gzdecode::$extra_field
8392 * @see gzdecode::$SI1
8397 * Extra field content
8400 * @see gzdecode::$SI1
8401 * @see gzdecode::$SI2
8413 * Human readable comment
8420 * Don't allow anything to be set
8424 function __set($name, $value)
8426 trigger_error("Cannot write property $name", E_USER_ERROR);
8430 * Set the compressed string and related properties
8434 function SimplePie_gzdecode($data)
8436 $this->compressed_data = $data;
8437 $this->compressed_size = strlen($data);
8441 * Decode the GZIP stream
8447 if ($this->compressed_size >= $this->min_compressed_size)
8449 // Check ID1, ID2, and CM
8450 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8455 // Get the FLG (FLaGs)
8456 $this->flags = ord($this->compressed_data[3]);
8458 // FLG bits above (1 << 4) are reserved
8459 if ($this->flags > 0x1F)
8464 // Advance the pointer after the above
8465 $this->position += 4;
8468 $mtime = substr($this->compressed_data, $this->position, 4);
8469 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8470 if (current(unpack('S', "\x00\x01")) === 1)
8472 $mtime = strrev($mtime);
8474 $this->MTIME = current(unpack('l', $mtime));
8475 $this->position += 4;
8477 // Get the XFL (eXtra FLags)
8478 $this->XFL = ord($this->compressed_data[$this->position++]);
8480 // Get the OS (Operating System)
8481 $this->OS = ord($this->compressed_data[$this->position++]);
8484 if ($this->flags & 4)
8486 // Read subfield IDs
8487 $this->SI1 = $this->compressed_data[$this->position++];
8488 $this->SI2 = $this->compressed_data[$this->position++];
8490 // SI2 set to zero is reserved for future use
8491 if ($this->SI2 === "\x00")
8496 // Get the length of the extra field
8497 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8498 $this->position += 2;
8500 // Check the length of the string is still valid
8501 $this->min_compressed_size += $len + 4;
8502 if ($this->compressed_size >= $this->min_compressed_size)
8504 // Set the extra field to the given data
8505 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8506 $this->position += $len;
8515 if ($this->flags & 8)
8517 // Get the length of the filename
8518 $len = strcspn($this->compressed_data, "\x00", $this->position);
8520 // Check the length of the string is still valid
8521 $this->min_compressed_size += $len + 1;
8522 if ($this->compressed_size >= $this->min_compressed_size)
8524 // Set the original filename to the given string
8525 $this->filename = substr($this->compressed_data, $this->position, $len);
8526 $this->position += $len + 1;
8534 // Parse the FCOMMENT
8535 if ($this->flags & 16)
8537 // Get the length of the comment
8538 $len = strcspn($this->compressed_data, "\x00", $this->position);
8540 // Check the length of the string is still valid
8541 $this->min_compressed_size += $len + 1;
8542 if ($this->compressed_size >= $this->min_compressed_size)
8544 // Set the original comment to the given string
8545 $this->comment = substr($this->compressed_data, $this->position, $len);
8546 $this->position += $len + 1;
8555 if ($this->flags & 2)
8557 // Check the length of the string is still valid
8558 $this->min_compressed_size += $len + 2;
8559 if ($this->compressed_size >= $this->min_compressed_size)
8562 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8564 // Check the CRC matches
8565 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8567 $this->position += 2;
8580 // Decompress the actual data
8581 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8587 $this->position = $this->compressed_size - 8;
8590 // Check CRC of data
8591 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8592 $this->position += 4;
8593 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8598 // Check ISIZE of data
8599 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8600 $this->position += 4;
8601 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8606 // Wow, against all odds, we've actually got a valid gzip string
8616 class SimplePie_Cache
8619 * Don't call the constructor. Please.
8623 function SimplePie_Cache()
8625 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8629 * Create a new SimplePie_Cache object
8634 function create($location, $filename, $extension)
8636 $location_iri =& new SimplePie_IRI($location);
8637 switch ($location_iri->get_scheme())
8640 if (extension_loaded('mysql'))
8642 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8647 return new SimplePie_Cache_File($location, $filename, $extension);
8652 class SimplePie_Cache_File
8659 function SimplePie_Cache_File($location, $filename, $extension)
8661 $this->location = $location;
8662 $this->filename = $filename;
8663 $this->extension = $extension;
8664 $this->name = "$this->location/$this->filename.$this->extension";
8667 function save($data)
8669 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8671 if (is_a($data, 'SimplePie'))
8673 $data = $data->data;
8676 $data = serialize($data);
8678 if (function_exists('file_put_contents'))
8680 return (bool) file_put_contents($this->name, $data);
8684 $fp = fopen($this->name, 'wb');
8698 if (file_exists($this->name) && is_readable($this->name))
8700 return unserialize(file_get_contents($this->name));
8707 if (file_exists($this->name))
8709 return filemtime($this->name);
8716 if (file_exists($this->name))
8718 return touch($this->name);
8725 if (file_exists($this->name))
8727 return unlink($this->name);
8733 class SimplePie_Cache_DB
8735 function prepare_simplepie_object_for_cache($data)
8737 $items = $data->get_items();
8738 $items_by_id = array();
8742 foreach ($items as $item)
8744 $items_by_id[$item->get_id()] = $item;
8747 if (count($items_by_id) !== count($items))
8749 $items_by_id = array();
8750 foreach ($items as $item)
8752 $items_by_id[$item->get_id(true)] = $item;
8756 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8758 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8760 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8762 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8764 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8766 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8768 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8770 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8777 if ($channel !== null)
8779 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8781 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8783 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8785 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8787 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8789 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8791 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8793 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8795 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8797 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8800 if (isset($data->data['items']))
8802 unset($data->data['items']);
8804 if (isset($data->data['ordered_items']))
8806 unset($data->data['ordered_items']);
8809 return array(serialize($data->data), $items_by_id);
8813 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8819 function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
8821 $host = $mysql_location->get_host();
8822 if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8824 $server = ':' . substr($host, 5, -1);
8829 if ($mysql_location->get_port() !== null)
8831 $server .= ':' . $mysql_location->get_port();
8835 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8837 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8841 $username = $mysql_location->get_userinfo();
8845 if ($this->mysql = mysql_connect($server, $username, $password))
8847 $this->id = $name . $extension;
8848 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8849 if (!isset($this->options['prefix'][0]))
8851 $this->options['prefix'][0] = '';
8854 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8855 && mysql_query('SET NAMES utf8')
8856 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8859 while ($row = mysql_fetch_row($query))
8864 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8866 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)))'))
8868 $this->mysql = null;
8872 if (!in_array($this->options['prefix'][0] . 'items', $db))
8874 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)))'))
8876 $this->mysql = null;
8882 $this->mysql = null;
8887 function save($data)
8891 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8893 if (is_a($data, 'SimplePie'))
8897 // This keyword needs to defy coding standards for PHP4 compatibility
8898 $data = clone($data);
8901 $prepared = $this->prepare_simplepie_object_for_cache($data);
8903 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8905 if (mysql_num_rows($query))
8907 $items = count($prepared[1]);
8910 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8914 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8917 if (!mysql_query($sql, $this->mysql))
8922 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))
8927 $ids = array_keys($prepared[1]);
8930 foreach ($ids as $id)
8932 $database_ids[] = mysql_real_escape_string($id);
8935 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))
8937 $existing_ids = array();
8938 while ($row = mysql_fetch_row($query))
8940 $existing_ids[] = $row[0];
8943 $new_ids = array_diff($ids, $existing_ids);
8945 foreach ($new_ids as $new_id)
8947 if (!($date = $prepared[1][$new_id]->get_date('U')))
8952 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))
8966 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8968 if (mysql_num_rows($query))
8970 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))
8975 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))
8986 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)))
8988 $data = unserialize($row[1]);
8990 if (isset($this->options['items'][0]))
8992 $items = (int) $this->options['items'][0];
8996 $items = (int) $row[0];
9001 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
9003 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
9005 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
9007 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
9009 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
9011 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
9013 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
9015 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
9024 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
9027 $sql .= ' LIMIT ' . $items;
9030 if ($query = mysql_unbuffered_query($sql, $this->mysql))
9032 while ($row = mysql_fetch_row($query))
9034 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
9050 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)))
9062 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))
9074 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)))
9085 class SimplePie_Misc
9087 function time_hms($seconds)
9091 $hours = floor($seconds / 3600);
9092 $remainder = $seconds % 3600;
9095 $time .= $hours.':';
9098 $minutes = floor($remainder / 60);
9099 $seconds = $remainder % 60;
9100 if ($minutes < 10 && $hours > 0)
9102 $minutes = '0' . $minutes;
9106 $seconds = '0' . $seconds;
9109 $time .= $minutes.':';
9115 function absolutize_url($relative, $base)
9117 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
9118 return $iri->get_iri();
9121 function remove_dot_segments($input)
9124 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
9126 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
9127 if (strpos($input, '../') === 0)
9129 $input = substr($input, 3);
9131 elseif (strpos($input, './') === 0)
9133 $input = substr($input, 2);
9135 // 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,
9136 elseif (strpos($input, '/./') === 0)
9138 $input = substr_replace($input, '/', 0, 3);
9140 elseif ($input === '/.')
9144 // 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,
9145 elseif (strpos($input, '/../') === 0)
9147 $input = substr_replace($input, '/', 0, 4);
9148 $output = substr_replace($output, '', strrpos($output, '/'));
9150 elseif ($input === '/..')
9153 $output = substr_replace($output, '', strrpos($output, '/'));
9155 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
9156 elseif ($input === '.' || $input === '..')
9160 // 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
9161 elseif (($pos = strpos($input, '/', 1)) !== false)
9163 $output .= substr($input, 0, $pos);
9164 $input = substr_replace($input, '', 0, $pos);
9172 return $output . $input;
9175 function get_element($realname, $string)
9178 $name = preg_quote($realname, '/');
9179 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
9181 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
9183 $return[$i]['tag'] = $realname;
9184 $return[$i]['full'] = $matches[$i][0][0];
9185 $return[$i]['offset'] = $matches[$i][0][1];
9186 if (strlen($matches[$i][3][0]) <= 2)
9188 $return[$i]['self_closing'] = true;
9192 $return[$i]['self_closing'] = false;
9193 $return[$i]['content'] = $matches[$i][4][0];
9195 $return[$i]['attribs'] = array();
9196 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))
9198 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
9200 if (count($attribs[$j]) === 2)
9202 $attribs[$j][2] = $attribs[$j][1];
9204 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
9212 function element_implode($element)
9214 $full = "<$element[tag]";
9215 foreach ($element['attribs'] as $key => $value)
9217 $key = strtolower($key);
9218 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
9220 if ($element['self_closing'])
9226 $full .= ">$element[content]</$element[tag]>";
9231 function error($message, $level, $file, $line)
9233 if ((ini_get('error_reporting') & $level) > 0)
9238 $note = 'PHP Error';
9240 case E_USER_WARNING:
9241 $note = 'PHP Warning';
9244 $note = 'PHP Notice';
9247 $note = 'Unknown Error';
9252 if (!function_exists('error_log'))
9257 $log_file = @ini_get('error_log');
9258 if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
9265 @error_log("$note: $message in $file on line $line", 0);
9273 * If a file has been cached, retrieve and display it.
9275 * This is most useful for caching images (get_favicon(), etc.),
9276 * however it works for all cached files. This WILL NOT display ANY
9277 * file/image/page/whatever, but rather only display what has already
9278 * been cached by SimplePie.
9281 * @see SimplePie::get_favicon()
9282 * @param str $identifier_url URL that is used to identify the content.
9283 * This may or may not be the actual URL of the live content.
9284 * @param str $cache_location Location of SimplePie's cache. Defaults
9286 * @param str $cache_extension The file extension that the file was
9287 * cached with. Defaults to 'spc'.
9288 * @param str $cache_class Name of the cache-handling class being used
9289 * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
9290 * as-is unless you've overloaded the class.
9291 * @param str $cache_name_function Obsolete. Exists for backwards
9292 * compatibility reasons only.
9294 function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
9296 $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
9298 if ($file = $cache->load())
9300 if (isset($file['headers']['content-type']))
9302 header('Content-type:' . $file['headers']['content-type']);
9306 header('Content-type: application/octet-stream');
9308 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
9313 die('Cached file for ' . $identifier_url . ' cannot be found.');
9316 function fix_protocol($url, $http = 1)
9318 $url = SimplePie_Misc::normalize_url($url);
9319 $parsed = SimplePie_Misc::parse_url($url);
9320 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
9322 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
9325 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
9327 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
9330 if ($http === 2 && $parsed['scheme'] !== '')
9334 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
9336 return substr_replace($url, 'podcast', 0, 4);
9338 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
9340 return substr_replace($url, 'itpc', 0, 4);
9348 function parse_url($url)
9350 $iri =& new SimplePie_IRI($url);
9352 'scheme' => (string) $iri->get_scheme(),
9353 'authority' => (string) $iri->get_authority(),
9354 'path' => (string) $iri->get_path(),
9355 'query' => (string) $iri->get_query(),
9356 'fragment' => (string) $iri->get_fragment()
9360 function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
9362 $iri =& new SimplePie_IRI('');
9363 $iri->set_scheme($scheme);
9364 $iri->set_authority($authority);
9365 $iri->set_path($path);
9366 $iri->set_query($query);
9367 $iri->set_fragment($fragment);
9368 return $iri->get_iri();
9371 function normalize_url($url)
9373 $iri =& new SimplePie_IRI($url);
9374 return $iri->get_iri();
9377 function percent_encoding_normalization($match)
9379 $integer = hexdec($match[1]);
9380 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
9382 return chr($integer);
9386 return strtoupper($match[0]);
9391 * Remove bad UTF-8 bytes
9393 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
9394 * FAQ: Multilingual Forms (modified to include full ASCII range)
9396 * @author Geoffrey Sneddon
9397 * @see http://www.w3.org/International/questions/qa-forms-utf-8
9398 * @param string $str String to remove bad UTF-8 bytes from
9399 * @return string UTF-8 string
9401 function utf8_bad_replace($str)
9403 if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
9407 elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
9411 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))
9413 return implode("\xEF\xBF\xBD", $matches[0]);
9415 elseif ($str !== '')
9417 return "\xEF\xBF\xBD";
9426 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
9430 * @param string $string Windows-1252 encoded string
9431 * @return string UTF-8 encoded string
9433 function windows_1252_to_utf8($string)
9435 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");
9437 return strtr($string, $convert_table);
9440 function change_encoding($data, $input, $output)
9442 $input = SimplePie_Misc::encoding($input);
9443 $output = SimplePie_Misc::encoding($output);
9445 // We fail to fail on non US-ASCII bytes
9446 if ($input === 'US-ASCII')
9448 static $non_ascii_octects = '';
9449 if (!$non_ascii_octects)
9451 for ($i = 0x80; $i <= 0xFF; $i++)
9453 $non_ascii_octects .= chr($i);
9456 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
9459 // This is first, as behaviour of this is completely predictable
9460 if ($input === 'windows-1252' && $output === 'UTF-8')
9462 return SimplePie_Misc::windows_1252_to_utf8($data);
9464 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9465 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)))
9469 // This is last, as behaviour of this varies with OS userland and PHP version
9470 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9474 // If we can't do anything, just fail
9482 * Normalize an encoding name
9484 * This is automatically generated by create.php
9486 * To generate it, run `php create.php` on the command line, and copy the
9487 * output to replace this function.
9489 * @param string $charset Character set to standardise
9490 * @return string Standardised name
9492 function encoding($charset)
9494 // Normalization from UTS #22
9495 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9497 case 'adobestandardencoding':
9498 case 'csadobestandardencoding':
9499 return 'Adobe-Standard-Encoding';
9501 case 'adobesymbolencoding':
9503 return 'Adobe-Symbol-Encoding';
9507 return 'Amiga-1251';
9509 case 'ansix31101983':
9511 case 'csiso99naplps':
9514 return 'ANSI_X3.110-1983';
9518 case 'csiso89asmo449':
9528 return 'Big5-HKSCS';
9539 case 'csiso4unitedkingdom':
9547 case 'csiso47bsviewdata':
9549 return 'BS_viewdata';
9557 case 'csaz243419851':
9558 case 'csiso121canadian1':
9561 return 'CSA_Z243.4-1985-1';
9564 case 'csaz243419852':
9565 case 'csiso122canadian2':
9568 return 'CSA_Z243.4-1985-2';
9570 case 'csaz24341985gr':
9571 case 'csiso123csaz24341985gr':
9573 return 'CSA_Z243.4-1985-gr';
9575 case 'csiso139csn369103':
9578 return 'CSN_369103';
9585 case 'csiso21german':
9596 case 'csiso646danish':
9602 case 'csibmebcdicatde':
9604 return 'EBCDIC-AT-DE';
9606 case 'csebcdicatdea':
9608 return 'EBCDIC-AT-DE-A';
9610 case 'csebcdiccafr':
9612 return 'EBCDIC-CA-FR';
9614 case 'csebcdicdkno':
9616 return 'EBCDIC-DK-NO';
9618 case 'csebcdicdknoa':
9620 return 'EBCDIC-DK-NO-A';
9628 return 'EBCDIC-ES-A';
9632 return 'EBCDIC-ES-S';
9634 case 'csebcdicfise':
9636 return 'EBCDIC-FI-SE';
9638 case 'csebcdicfisea':
9640 return 'EBCDIC-FI-SE-A';
9662 case 'csiso111ecmacyrillic':
9663 case 'ecmacyrillic':
9666 return 'ECMA-cyrillic';
9668 case 'csiso17spanish':
9674 case 'csiso85spanish2':
9680 case 'cseucpkdfmtjapanese':
9682 case 'extendedunixcodepackedformatforjapanese':
9685 case 'cseucfixwidjapanese':
9686 case 'extendedunixcodefixedwidthforjapanese':
9687 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9695 case 'csiso58gb231280':
9705 case 'csiso57gb1988':
9709 return 'GB_1988-80';
9711 case 'csiso153gost1976874':
9715 return 'GOST_19768-74';
9718 case 'csiso150greekccitt':
9721 return 'greek-ccitt';
9723 case 'csiso88greek7':
9728 case 'csiso18greek7old':
9731 return 'greek7-old';
9735 return 'HP-DeskTop';
9747 return 'HP-Pi-font';
9756 return 'HZ-GB-2312';
9758 case 'csibmsymbols':
9760 return 'IBM-Symbols';
9837 case 'ebcdicjpkana':
9867 case 'cspc8codepage437':
9879 case 'cspc775baltic':
9885 case 'cspc850multilingual':
9916 case 'pcmultilingual850euro':
9934 case 'cspc862latinhebrew':
9976 case 'ebcdiccproece':
9989 case 'ebcdiccyrillic':
10017 case 'ebcdiccpar2':
10023 case 'ebcdiclatin9euro':
10037 case 'ebcdicus37euro':
10043 case 'ebcdicde273euro':
10049 case 'ebcdicdk277euro':
10050 case 'ebcdicno277euro':
10056 case 'ebcdicfi278euro':
10057 case 'ebcdicse278euro':
10063 case 'ebcdicit280euro':
10069 case 'ebcdices284euro':
10075 case 'ebcdicgb285euro':
10081 case 'ebcdicfr297euro':
10087 case 'ebcdicinternational500euro':
10093 case 'ebcdicis871euro':
10097 case 'csiso143iecp271':
10100 return 'IEC_P27-1';
10102 case 'csiso49inis':
10107 case 'csiso50inis8':
10112 case 'csiso51iniscyrillic':
10113 case 'iniscyrillic':
10115 return 'INIS-cyrillic';
10117 case 'csinvariant':
10119 return 'INVARIANT';
10122 return 'ISO-2022-CN';
10124 case 'iso2022cnext':
10125 return 'ISO-2022-CN-EXT';
10127 case 'csiso2022jp':
10129 return 'ISO-2022-JP';
10131 case 'csiso2022jp2':
10133 return 'ISO-2022-JP-2';
10135 case 'csiso2022kr':
10137 return 'ISO-2022-KR';
10139 case 'cswindows30latin1':
10140 case 'iso88591windows30latin1':
10141 return 'ISO-8859-1-Windows-3.0-Latin-1';
10143 case 'cswindows31latin1':
10144 case 'iso88591windows31latin1':
10145 return 'ISO-8859-1-Windows-3.1-Latin-1';
10147 case 'csisolatin2':
10149 case 'iso885921987':
10153 return 'ISO-8859-2';
10155 case 'cswindows31latin2':
10156 case 'iso88592windowslatin2':
10157 return 'ISO-8859-2-Windows-Latin-2';
10159 case 'csisolatin3':
10161 case 'iso885931988':
10165 return 'ISO-8859-3';
10167 case 'csisolatin4':
10169 case 'iso885941988':
10173 return 'ISO-8859-4';
10175 case 'csisolatincyrillic':
10178 case 'iso885951988':
10180 return 'ISO-8859-5';
10184 case 'csisolatinarabic':
10187 case 'iso885961987':
10189 return 'ISO-8859-6';
10191 case 'csiso88596e':
10193 return 'ISO-8859-6-E';
10195 case 'csiso88596i':
10197 return 'ISO-8859-6-I';
10199 case 'csisolatingreek':
10205 case 'iso885971987':
10207 return 'ISO-8859-7';
10209 case 'csisolatinhebrew':
10212 case 'iso885981988':
10214 return 'ISO-8859-8';
10216 case 'csiso88598e':
10218 return 'ISO-8859-8-E';
10220 case 'csiso88598i':
10222 return 'ISO-8859-8-I';
10224 case 'cswindows31latin5':
10225 case 'iso88599windowslatin5':
10226 return 'ISO-8859-9-Windows-Latin-5';
10228 case 'csisolatin6':
10230 case 'iso8859101992':
10234 return 'ISO-8859-10';
10237 return 'ISO-8859-13';
10240 case 'iso8859141998':
10245 return 'ISO-8859-14';
10249 return 'ISO-8859-15';
10252 case 'iso8859162001':
10256 return 'ISO-8859-16';
10259 return 'ISO-10646-J-1';
10262 case 'iso10646ucs2':
10263 return 'ISO-10646-UCS-2';
10266 case 'iso10646ucs4':
10267 return 'ISO-10646-UCS-4';
10269 case 'csunicodeascii':
10270 case 'iso10646ucsbasic':
10271 return 'ISO-10646-UCS-Basic';
10273 case 'csunicodelatin1':
10275 case 'iso10646unicodelatin1':
10276 return 'ISO-10646-Unicode-Latin1';
10278 case 'csiso10646utf1':
10279 case 'iso10646utf1':
10280 return 'ISO-10646-UTF-1';
10282 case 'csiso115481':
10284 case 'isotr115481':
10285 return 'ISO-11548-1';
10289 return 'iso-ir-90';
10291 case 'csunicodeibm1261':
10292 case 'isounicodeibm1261':
10293 return 'ISO-Unicode-IBM-1261';
10295 case 'csunicodeibm1264':
10296 case 'isounicodeibm1264':
10297 return 'ISO-Unicode-IBM-1264';
10299 case 'csunicodeibm1265':
10300 case 'isounicodeibm1265':
10301 return 'ISO-Unicode-IBM-1265';
10303 case 'csunicodeibm1268':
10304 case 'isounicodeibm1268':
10305 return 'ISO-Unicode-IBM-1268';
10307 case 'csunicodeibm1276':
10308 case 'isounicodeibm1276':
10309 return 'ISO-Unicode-IBM-1276';
10311 case 'csiso646basic1983':
10312 case 'iso646basic1983':
10314 return 'ISO_646.basic:1983';
10316 case 'csiso2intlrefversion':
10318 case 'iso646irv1983':
10320 return 'ISO_646.irv:1983';
10324 case 'iso20331983':
10326 return 'ISO_2033-1983';
10328 case 'csiso5427cyrillic':
10333 case 'iso5427cyrillic1981':
10334 case 'iso54271981':
10336 return 'ISO_5427:1981';
10338 case 'csiso5428greek':
10339 case 'iso54281980':
10341 return 'ISO_5428:1980';
10343 case 'csiso6937add':
10346 return 'ISO_6937-2-25';
10348 case 'csisotextcomm':
10349 case 'iso69372add':
10351 return 'ISO_6937-2-add';
10353 case 'csiso8859supp':
10354 case 'iso8859supp':
10357 return 'ISO_8859-supp';
10359 case 'csiso10367box':
10360 case 'iso10367box':
10362 return 'ISO_10367-box';
10364 case 'csiso15italian':
10370 case 'csiso13jisc6220jp':
10372 case 'jisc62201969':
10373 case 'jisc62201969jp':
10376 return 'JIS_C6220-1969-jp';
10378 case 'csiso14jisc6220ro':
10381 case 'jisc62201969ro':
10383 return 'JIS_C6220-1969-ro';
10385 case 'csiso42jisc62261978':
10387 case 'jisc62261978':
10388 return 'JIS_C6226-1978';
10390 case 'csiso87jisx208':
10392 case 'jisc62261983':
10393 case 'jisx2081983':
10395 return 'JIS_C6226-1983';
10397 case 'csiso91jisc62291984a':
10399 case 'jisc62291984a':
10401 return 'JIS_C6229-1984-a';
10403 case 'csiso92jisc62991984b':
10404 case 'iso646jpocrb':
10406 case 'jisc62291984b':
10408 return 'JIS_C6229-1984-b';
10410 case 'csiso93jis62291984badd':
10412 case 'jisc62291984badd':
10414 return 'JIS_C6229-1984-b-add';
10416 case 'csiso94jis62291984hand':
10418 case 'jisc62291984hand':
10420 return 'JIS_C6229-1984-hand';
10422 case 'csiso95jis62291984handadd':
10424 case 'jisc62291984handadd':
10425 case 'jpocrhandadd':
10426 return 'JIS_C6229-1984-hand-add';
10428 case 'csiso96jisc62291984kana':
10430 case 'jisc62291984kana':
10431 return 'JIS_C6229-1984-kana';
10433 case 'csjisencoding':
10434 case 'jisencoding':
10435 return 'JIS_Encoding';
10437 case 'cshalfwidthkatakana':
10440 return 'JIS_X0201';
10442 case 'csiso159jisx2121990':
10444 case 'jisx2121990':
10446 return 'JIS_X0212-1990';
10448 case 'csiso141jusib1002':
10454 return 'JUS_I.B1.002';
10456 case 'csiso147macedonian':
10458 case 'jusib1003mac':
10460 return 'JUS_I.B1.003-mac';
10462 case 'csiso146serbian':
10464 case 'jusib1003serb':
10466 return 'JUS_I.B1.003-serb';
10468 case 'koi7switched':
10469 return 'KOI7-switched';
10486 case 'strk10482002':
10489 case 'csiso19latingreek':
10492 return 'latin-greek';
10494 case 'csiso27latingreek1':
10496 case 'latingreek1':
10497 return 'Latin-greek-1';
10499 case 'csiso158lap':
10503 return 'latin-lap';
10505 case 'csmacintosh':
10508 return 'macintosh';
10510 case 'csmicrosoftpublishing':
10511 case 'microsoftpublishing':
10512 return 'Microsoft-Publishing';
10522 case 'csiso86hungarian':
10527 return 'MSZ_7795.3';
10532 return 'NATS-DANO';
10534 case 'csnatsdanoadd':
10536 case 'natsdanoadd':
10537 return 'NATS-DANO-ADD';
10542 return 'NATS-SEFI';
10544 case 'csnatssefiadd':
10546 case 'natssefiadd':
10547 return 'NATS-SEFI-ADD';
10549 case 'csiso151cuba':
10554 return 'NC_NC00-10:81';
10556 case 'csiso69french':
10561 return 'NF_Z_62-010';
10563 case 'csiso25french':
10566 case 'nfz620101973':
10567 return 'NF_Z_62-010_(1973)';
10569 case 'csiso60danishnorwegian':
10570 case 'csiso60norwegian1':
10575 return 'NS_4551-1';
10577 case 'csiso61norwegian2':
10582 return 'NS_4551-2';
10584 case 'osdebcdicdf3irv':
10585 return 'OSD_EBCDIC_DF03_IRV';
10587 case 'osdebcdicdf41':
10588 return 'OSD_EBCDIC_DF04_1';
10590 case 'osdebcdicdf415':
10591 return 'OSD_EBCDIC_DF04_15';
10593 case 'cspc8danishnorwegian':
10594 case 'pc8danishnorwegian':
10595 return 'PC8-Danish-Norwegian';
10597 case 'cspc8turkish':
10599 return 'PC8-Turkish';
10601 case 'csiso16portuguese':
10607 case 'csiso84portuguese2':
10615 case 'cyrillicasian':
10623 case 'csiso10swedish':
10630 return 'SEN_850200_B';
10632 case 'csiso11swedishfornames':
10637 return 'SEN_850200_C';
10639 case 'csiso102t617bit':
10642 return 'T.61-7bit';
10644 case 'csiso103t618bit':
10648 return 'T.61-8bit';
10650 case 'csiso128t101g2':
10659 case 'csunicode11':
10661 return 'UNICODE-1-1';
10663 case 'csunicode11utf7':
10664 case 'unicode11utf7':
10665 return 'UNICODE-1-1-UTF-7';
10667 case 'csunknown8bit':
10668 case 'unknown8bit':
10669 return 'UNKNOWN-8BIT';
10671 case 'ansix341968':
10672 case 'ansix341986':
10677 case 'iso646irv1991':
10712 case 'csventurainternational':
10713 case 'venturainternational':
10714 return 'Ventura-International';
10716 case 'csventuramath':
10717 case 'venturamath':
10718 return 'Ventura-Math';
10720 case 'csventuraus':
10722 return 'Ventura-US';
10724 case 'csiso70videotexsupp1':
10726 case 'videotexsuppl':
10727 return 'videotex-suppl';
10738 case 'cswindows31j':
10742 return 'Windows-31J';
10746 return 'windows-874';
10749 case 'csksc56011987':
10754 case 'ksc56011987':
10755 case 'ksc56011989':
10757 return 'windows-949';
10759 case 'windows1250':
10760 return 'windows-1250';
10762 case 'windows1251':
10763 return 'windows-1251';
10766 case 'csisolatin1':
10769 case 'iso885911987':
10773 case 'windows1252':
10774 return 'windows-1252';
10776 case 'windows1253':
10777 return 'windows-1253';
10779 case 'csisolatin5':
10781 case 'iso885991989':
10785 case 'windows1254':
10786 return 'windows-1254';
10788 case 'windows1255':
10789 return 'windows-1255';
10791 case 'windows1256':
10792 return 'windows-1256';
10794 case 'windows1257':
10795 return 'windows-1257';
10797 case 'windows1258':
10798 return 'windows-1258';
10805 function get_curl_version()
10807 if (is_array($curl = curl_version()))
10809 $curl = $curl['version'];
10811 elseif (substr($curl, 0, 5) === 'curl/')
10813 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10815 elseif (substr($curl, 0, 8) === 'libcurl/')
10817 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10826 function is_subclass_of($class1, $class2)
10828 if (func_num_args() !== 2)
10830 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10832 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10834 return is_subclass_of($class1, $class2);
10836 elseif (is_string($class1) && is_string($class2))
10838 if (class_exists($class1))
10840 if (class_exists($class2))
10842 $class2 = strtolower($class2);
10843 while ($class1 = strtolower(get_parent_class($class1)))
10845 if ($class1 === $class2)
10854 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10861 * Strip HTML comments
10864 * @param string $data Data to strip comments from
10865 * @return string Comment stripped string
10867 function strip_comments($data)
10870 while (($start = strpos($data, '<!--')) !== false)
10872 $output .= substr($data, 0, $start);
10873 if (($end = strpos($data, '-->', $start)) !== false)
10875 $data = substr_replace($data, '', 0, $end + 3);
10882 return $output . $data;
10885 function parse_date($dt)
10887 $parser = SimplePie_Parse_Date::get();
10888 return $parser->parse($dt);
10892 * Decode HTML entities
10896 * @param string $data Input data
10897 * @return string Output data
10899 function entities_decode($data)
10901 $decoder =& new SimplePie_Decode_HTML_Entities($data);
10902 return $decoder->parse();
10906 * Remove RFC822 comments
10909 * @param string $data Data to strip comments from
10910 * @return string Comment stripped string
10912 function uncomment_rfc822($string)
10914 $string = (string) $string;
10916 $length = strlen($string);
10921 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10923 $output .= substr($string, $position, $pos - $position);
10924 $position = $pos + 1;
10925 if ($string[$pos - 1] !== '\\')
10928 while ($depth && $position < $length)
10930 $position += strcspn($string, '()', $position);
10931 if ($string[$position - 1] === '\\')
10936 elseif (isset($string[$position]))
10938 switch ($string[$position])
10961 $output .= substr($string, $position);
10966 function parse_mime($mime)
10968 if (($pos = strpos($mime, ';')) === false)
10970 return trim($mime);
10974 return trim(substr($mime, 0, $pos));
10978 function htmlspecialchars_decode($string, $quote_style)
10980 if (function_exists('htmlspecialchars_decode'))
10982 return htmlspecialchars_decode($string, $quote_style);
10986 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10990 function atom_03_construct_type($attribs)
10992 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10994 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10998 $mode = SIMPLEPIE_CONSTRUCT_NONE;
11000 if (isset($attribs['']['type']))
11002 switch (strtolower(trim($attribs['']['type'])))
11006 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11010 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
11013 case 'application/xhtml+xml':
11014 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
11017 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
11022 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
11026 function atom_10_construct_type($attribs)
11028 if (isset($attribs['']['type']))
11030 switch (strtolower(trim($attribs['']['type'])))
11033 return SIMPLEPIE_CONSTRUCT_TEXT;
11036 return SIMPLEPIE_CONSTRUCT_HTML;
11039 return SIMPLEPIE_CONSTRUCT_XHTML;
11042 return SIMPLEPIE_CONSTRUCT_NONE;
11045 return SIMPLEPIE_CONSTRUCT_TEXT;
11048 function atom_10_content_construct_type($attribs)
11050 if (isset($attribs['']['type']))
11052 $type = strtolower(trim($attribs['']['type']));
11056 return SIMPLEPIE_CONSTRUCT_TEXT;
11059 return SIMPLEPIE_CONSTRUCT_HTML;
11062 return SIMPLEPIE_CONSTRUCT_XHTML;
11064 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
11066 return SIMPLEPIE_CONSTRUCT_NONE;
11070 return SIMPLEPIE_CONSTRUCT_BASE64;
11075 return SIMPLEPIE_CONSTRUCT_TEXT;
11079 function is_isegment_nz_nc($string)
11081 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);
11084 function space_seperated_tokens($string)
11086 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
11087 $string_length = strlen($string);
11089 $position = strspn($string, $space_characters);
11092 while ($position < $string_length)
11094 $len = strcspn($string, $space_characters, $position);
11095 $tokens[] = substr($string, $position, $len);
11097 $position += strspn($string, $space_characters, $position);
11103 function array_unique($array)
11105 if (version_compare(PHP_VERSION, '5.2', '>='))
11107 return array_unique($array);
11111 $array = (array) $array;
11112 $new_array = array();
11113 $new_array_strings = array();
11114 foreach ($array as $key => $value)
11116 if (is_object($value))
11118 if (method_exists($value, '__toString'))
11120 $cmp = $value->__toString();
11124 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
11127 elseif (is_array($value))
11129 $cmp = (string) reset($value);
11133 $cmp = (string) $value;
11135 if (!in_array($cmp, $new_array_strings))
11137 $new_array[$key] = $value;
11138 $new_array_strings[] = $cmp;
11146 * Converts a unicode codepoint to a UTF-8 character
11150 * @param int $codepoint Unicode codepoint
11151 * @return string UTF-8 character
11153 function codepoint_to_utf8($codepoint)
11155 $codepoint = (int) $codepoint;
11156 if ($codepoint < 0)
11160 else if ($codepoint <= 0x7f)
11162 return chr($codepoint);
11164 else if ($codepoint <= 0x7ff)
11166 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
11168 else if ($codepoint <= 0xffff)
11170 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11172 else if ($codepoint <= 0x10ffff)
11174 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
11178 // U+FFFD REPLACEMENT CHARACTER
11179 return "\xEF\xBF\xBD";
11184 * Re-implementation of PHP 5's stripos()
11186 * Returns the numeric position of the first occurrence of needle in the
11191 * @param object $haystack
11192 * @param string $needle Note that the needle may be a string of one or more
11193 * characters. If needle is not a string, it is converted to an integer
11194 * and applied as the ordinal value of a character.
11195 * @param int $offset The optional offset parameter allows you to specify which
11196 * character in haystack to start searching. The position returned is still
11197 * relative to the beginning of haystack.
11198 * @return bool If needle is not found, stripos() will return boolean false.
11200 function stripos($haystack, $needle, $offset = 0)
11202 if (function_exists('stripos'))
11204 return stripos($haystack, $needle, $offset);
11208 if (is_string($needle))
11210 $needle = strtolower($needle);
11212 elseif (is_int($needle) || is_bool($needle) || is_double($needle))
11214 $needle = strtolower(chr($needle));
11218 trigger_error('needle is not a string or an integer', E_USER_WARNING);
11222 return strpos(strtolower($haystack), $needle, $offset);
11227 * Similar to parse_str()
11229 * Returns an associative array of name/value pairs, where the value is an
11230 * array of values that have used the same name
11234 * @param string $str The input string.
11237 function parse_str($str)
11240 $str = explode('&', $str);
11242 foreach ($str as $section)
11244 if (strpos($section, '=') !== false)
11246 list($name, $value) = explode('=', $section, 2);
11247 $return[urldecode($name)][] = urldecode($value);
11251 $return[urldecode($section)][] = null;
11259 * Detect XML encoding, as per XML 1.0 Appendix F.1
11261 * @todo Add support for EBCDIC
11262 * @param string $data XML data
11263 * @return array Possible encodings
11265 function xml_encoding($data)
11267 // UTF-32 Big Endian BOM
11268 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
11270 $encoding[] = 'UTF-32BE';
11272 // UTF-32 Little Endian BOM
11273 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
11275 $encoding[] = 'UTF-32LE';
11277 // UTF-16 Big Endian BOM
11278 elseif (substr($data, 0, 2) === "\xFE\xFF")
11280 $encoding[] = 'UTF-16BE';
11282 // UTF-16 Little Endian BOM
11283 elseif (substr($data, 0, 2) === "\xFF\xFE")
11285 $encoding[] = 'UTF-16LE';
11288 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
11290 $encoding[] = 'UTF-8';
11292 // UTF-32 Big Endian Without BOM
11293 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")
11295 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
11297 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
11298 if ($parser->parse())
11300 $encoding[] = $parser->encoding;
11303 $encoding[] = 'UTF-32BE';
11305 // UTF-32 Little Endian Without BOM
11306 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")
11308 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
11310 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
11311 if ($parser->parse())
11313 $encoding[] = $parser->encoding;
11316 $encoding[] = 'UTF-32LE';
11318 // UTF-16 Big Endian Without BOM
11319 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
11321 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
11323 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
11324 if ($parser->parse())
11326 $encoding[] = $parser->encoding;
11329 $encoding[] = 'UTF-16BE';
11331 // UTF-16 Little Endian Without BOM
11332 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
11334 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
11336 $parser =& new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
11337 if ($parser->parse())
11339 $encoding[] = $parser->encoding;
11342 $encoding[] = 'UTF-16LE';
11344 // US-ASCII (or superset)
11345 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
11347 if ($pos = strpos($data, "\x3F\x3E"))
11349 $parser =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
11350 if ($parser->parse())
11352 $encoding[] = $parser->encoding;
11355 $encoding[] = 'UTF-8';
11357 // Fallback to UTF-8
11360 $encoding[] = 'UTF-8';
11365 function output_javascript()
11367 if (function_exists('ob_gzhandler'))
11369 ob_start('ob_gzhandler');
11371 header('Content-type: text/javascript; charset: UTF-8');
11372 header('Cache-Control: must-revalidate');
11373 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
11375 function embed_odeo(link) {
11376 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>');
11379 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
11380 if (placeholder != '') {
11381 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>');
11384 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>');
11388 function embed_flash(bgcolor, width, height, link, loop, type) {
11389 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>');
11392 function embed_flv(width, height, link, placeholder, loop, player) {
11393 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>');
11396 function embed_wmedia(width, height, link) {
11397 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
11405 * Format debugging information
11407 function debug($sp)
11409 $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
11410 $info .= 'PHP ' . PHP_VERSION . "\n";
11411 if ($sp->error() !== null)
11413 $info .= 'Error occurred: ' . $sp->error() . "\n";
11417 $info .= "No error found.\n";
11419 $info .= "Extensions:\n";
11420 $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
11421 foreach ($extensions as $ext)
11423 if (extension_loaded($ext))
11425 $info .= " $ext loaded\n";
11429 $info .= ' Version ' . PCRE_VERSION . "\n";
11432 $version = curl_version();
11433 $info .= ' Version ' . $version['version'] . "\n";
11436 $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
11439 $info .= ' Version ' . ICONV_VERSION . "\n";
11442 $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n";
11448 $info .= " $ext not loaded\n";
11456 * Decode HTML Entities
11458 * This implements HTML5 as of revision 967 (2007-06-28)
11460 * @package SimplePie
11462 class SimplePie_Decode_HTML_Entities
11465 * Data to be parsed
11473 * Currently consumed bytes
11478 var $consumed = '';
11481 * Position of the current byte being parsed
11489 * Create an instance of the class with the input data
11492 * @param string $data Input data
11494 function SimplePie_Decode_HTML_Entities($data)
11496 $this->data = $data;
11500 * Parse the input data
11503 * @return string Output data
11507 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
11511 $this->consumed = '';
11513 return $this->data;
11517 * Consume the next byte
11520 * @return mixed The next byte, or false, if there is no more data
11524 if (isset($this->data[$this->position]))
11526 $this->consumed .= $this->data[$this->position];
11527 return $this->data[$this->position++];
11536 * Consume a range of characters
11539 * @param string $chars Characters to consume
11540 * @return mixed A series of characters that match the range, or false
11542 function consume_range($chars)
11544 if ($len = strspn($this->data, $chars, $this->position))
11546 $data = substr($this->data, $this->position, $len);
11547 $this->consumed .= $data;
11548 $this->position += $len;
11558 * Unconsume one byte
11562 function unconsume()
11564 $this->consumed = substr($this->consumed, 0, -1);
11575 switch ($this->consume())
11589 switch ($this->consume())
11593 $range = '0123456789ABCDEFabcdef';
11598 $range = '0123456789';
11600 $this->unconsume();
11604 if ($codepoint = $this->consume_range($range))
11606 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");
11610 $codepoint = hexdec($codepoint);
11614 $codepoint = intval($codepoint);
11617 if (isset($windows_1252_specials[$codepoint]))
11619 $replacement = $windows_1252_specials[$codepoint];
11623 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11626 if (!in_array($this->consume(), array(';', false), true))
11628 $this->unconsume();
11631 $consumed_length = strlen($this->consumed);
11632 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11633 $this->position += strlen($replacement) - $consumed_length;
11638 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");
11640 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11642 $consumed = substr($this->consumed, 1);
11643 if (isset($entities[$consumed]))
11645 $match = $consumed;
11649 if ($match !== null)
11651 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11652 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11660 * IRI parser/serialiser
11662 * @package SimplePie
11664 class SimplePie_IRI
11723 * Whether the object represents a valid IRI
11728 var $valid = array();
11731 * Return the entire IRI when you try and read the object as a string
11736 function __toString()
11738 return $this->get_iri();
11742 * Create a new IRI object, from a specified string
11745 * @param string $iri
11746 * @return SimplePie_IRI
11748 function SimplePie_IRI($iri)
11750 $iri = (string) $iri;
11753 $parsed = $this->parse_iri($iri);
11754 $this->set_scheme($parsed['scheme']);
11755 $this->set_authority($parsed['authority']);
11756 $this->set_path($parsed['path']);
11757 $this->set_query($parsed['query']);
11758 $this->set_fragment($parsed['fragment']);
11763 * Create a new IRI object by resolving a relative IRI
11767 * @param SimplePie_IRI $base Base IRI
11768 * @param string $relative Relative IRI
11769 * @return SimplePie_IRI
11771 function absolutize($base, $relative)
11773 $relative = (string) $relative;
11774 if ($relative !== '')
11776 $relative =& new SimplePie_IRI($relative);
11777 if ($relative->get_scheme() !== null)
11779 $target = $relative;
11781 elseif ($base->get_iri() !== null)
11783 if ($relative->get_authority() !== null)
11785 $target = $relative;
11786 $target->set_scheme($base->get_scheme());
11790 $target =& new SimplePie_IRI('');
11791 $target->set_scheme($base->get_scheme());
11792 $target->set_userinfo($base->get_userinfo());
11793 $target->set_host($base->get_host());
11794 $target->set_port($base->get_port());
11795 if ($relative->get_path() !== null)
11797 if (strpos($relative->get_path(), '/') === 0)
11799 $target->set_path($relative->get_path());
11801 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11803 $target->set_path('/' . $relative->get_path());
11805 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11807 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11811 $target->set_path($relative->get_path());
11813 $target->set_query($relative->get_query());
11817 $target->set_path($base->get_path());
11818 if ($relative->get_query() !== null)
11820 $target->set_query($relative->get_query());
11822 elseif ($base->get_query() !== null)
11824 $target->set_query($base->get_query());
11828 $target->set_fragment($relative->get_fragment());
11832 // No base URL, just return the relative URL
11833 $target = $relative;
11844 * Parse an IRI into scheme/authority/path/query/fragment segments
11847 * @param string $iri
11850 function parse_iri($iri)
11852 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11853 for ($i = count($match); $i <= 9; $i++)
11857 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11861 * Remove dot segments from a path
11864 * @param string $input
11867 function remove_dot_segments($input)
11870 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11872 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11873 if (strpos($input, '../') === 0)
11875 $input = substr($input, 3);
11877 elseif (strpos($input, './') === 0)
11879 $input = substr($input, 2);
11881 // 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,
11882 elseif (strpos($input, '/./') === 0)
11884 $input = substr_replace($input, '/', 0, 3);
11886 elseif ($input === '/.')
11890 // 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,
11891 elseif (strpos($input, '/../') === 0)
11893 $input = substr_replace($input, '/', 0, 4);
11894 $output = substr_replace($output, '', strrpos($output, '/'));
11896 elseif ($input === '/..')
11899 $output = substr_replace($output, '', strrpos($output, '/'));
11901 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11902 elseif ($input === '.' || $input === '..')
11906 // 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
11907 elseif (($pos = strpos($input, '/', 1)) !== false)
11909 $output .= substr($input, 0, $pos);
11910 $input = substr_replace($input, '', 0, $pos);
11918 return $output . $input;
11922 * Replace invalid character with percent encoding
11924 * @param string $string Input string
11925 * @param string $valid_chars Valid characters
11926 * @param int $case Normalise case
11929 function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false)
11931 // Normalize as many pct-encoded sections as possible
11932 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
11934 // Replace invalid percent characters
11935 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
11937 // Add unreserved and % to $valid_chars (the latter is safe because all
11938 // pct-encoded sections are now valid).
11939 $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
11941 // Now replace any bytes that aren't allowed with their pct-encoded versions
11943 $strlen = strlen($string);
11944 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11946 $value = ord($string[$position]);
11949 $start = $position;
11951 // By default we are valid
11954 // No one byte sequences are valid due to the while.
11955 // Two byte sequence:
11956 if (($value & 0xE0) === 0xC0)
11958 $character = ($value & 0x1F) << 6;
11962 // Three byte sequence:
11963 elseif (($value & 0xF0) === 0xE0)
11965 $character = ($value & 0x0F) << 12;
11969 // Four byte sequence:
11970 elseif (($value & 0xF8) === 0xF0)
11972 $character = ($value & 0x07) << 18;
11986 if ($position + $length <= $strlen)
11988 for ($position++; $remaining; $position++)
11990 $value = ord($string[$position]);
11992 // Check that the byte is valid, then add it to the character:
11993 if (($value & 0xC0) === 0x80)
11995 $character |= ($value & 0x3F) << (--$remaining * 6);
11997 // If it is invalid, count the sequence as invalid and reprocess the current byte:
12008 $position = $strlen - 1;
12013 // Percent encode anything invalid or not in ucschar
12015 // Invalid sequences
12017 // Non-shortest form sequences are invalid
12018 || $length > 1 && $character <= 0x7F
12019 || $length > 2 && $character <= 0x7FF
12020 || $length > 3 && $character <= 0xFFFF
12021 // Outside of range of ucschar codepoints
12023 || ($character & 0xFFFE) === 0xFFFE
12024 || $character >= 0xFDD0 && $character <= 0xFDEF
12026 // Everything else not in ucschar
12027 $character > 0xD7FF && $character < 0xF900
12028 || $character < 0xA0
12029 || $character > 0xEFFFD
12032 // Everything not in iprivate, if it applies
12034 || $character < 0xE000
12035 || $character > 0x10FFFD
12039 // If we were a character, pretend we weren't, but rather an error.
12043 for ($j = $start; $j <= $position; $j++)
12045 $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
12054 if ($case & SIMPLEPIE_LOWERCASE)
12056 $string = strtolower($string);
12058 elseif ($case & SIMPLEPIE_UPPERCASE)
12060 $string = strtoupper($string);
12067 * Callback function for preg_replace_callback.
12069 * Removes sequences of percent encoded bytes that represent UTF-8
12070 * encoded characters in iunreserved
12073 * @param array $match PCRE match
12074 * @return string Replacement
12076 function remove_iunreserved_percent_encoded($match)
12078 // As we just have valid percent encoded sequences we can just explode
12079 // and ignore the first member of the returned array (an empty string).
12080 $bytes = explode('%', $match[0]);
12082 // Initialize the new string (this is what will be returned) and that
12083 // there are no bytes remaining in the current sequence (unsurprising
12084 // at the first byte!).
12088 // Loop over each and every byte, and set $value to its value
12089 for ($i = 1, $len = count($bytes); $i < $len; $i++)
12091 $value = hexdec($bytes[$i]);
12093 // If we're the first byte of sequence:
12099 // By default we are valid
12102 // One byte sequence:
12103 if ($value <= 0x7F)
12105 $character = $value;
12108 // Two byte sequence:
12109 elseif (($value & 0xE0) === 0xC0)
12111 $character = ($value & 0x1F) << 6;
12115 // Three byte sequence:
12116 elseif (($value & 0xF0) === 0xE0)
12118 $character = ($value & 0x0F) << 12;
12122 // Four byte sequence:
12123 elseif (($value & 0xF8) === 0xF0)
12125 $character = ($value & 0x07) << 18;
12136 // Continuation byte:
12139 // Check that the byte is valid, then add it to the character:
12140 if (($value & 0xC0) === 0x80)
12143 $character |= ($value & 0x3F) << ($remaining * 6);
12145 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
12154 // If we've reached the end of the current byte sequence, append it to Unicode::$data
12157 // Percent encode anything invalid or not in iunreserved
12159 // Invalid sequences
12161 // Non-shortest form sequences are invalid
12162 || $length > 1 && $character <= 0x7F
12163 || $length > 2 && $character <= 0x7FF
12164 || $length > 3 && $character <= 0xFFFF
12165 // Outside of range of iunreserved codepoints
12166 || $character < 0x2D
12167 || $character > 0xEFFFD
12169 || ($character & 0xFFFE) === 0xFFFE
12170 || $character >= 0xFDD0 && $character <= 0xFDEF
12171 // Everything else not in iunreserved (this is all BMP)
12172 || $character === 0x2F
12173 || $character > 0x39 && $character < 0x41
12174 || $character > 0x5A && $character < 0x61
12175 || $character > 0x7A && $character < 0x7E
12176 || $character > 0x7E && $character < 0xA0
12177 || $character > 0xD7FF && $character < 0xF900
12180 for ($j = $start; $j <= $i; $j++)
12182 $string .= '%' . strtoupper($bytes[$j]);
12187 for ($j = $start; $j <= $i; $j++)
12189 $string .= chr(hexdec($bytes[$j]));
12195 // If we have any bytes left over they are invalid (i.e., we are
12196 // mid-way through a multi-byte sequence)
12199 for ($j = $start; $j < $len; $j++)
12201 $string .= '%' . strtoupper($bytes[$j]);
12209 * Check if the object represents a valid IRI
12214 function is_valid()
12216 return array_sum($this->valid) === count($this->valid);
12220 * Set the scheme. Returns true on success, false on failure (if there are
12221 * any invalid characters).
12224 * @param string $scheme
12227 function set_scheme($scheme)
12229 if ($scheme === null || $scheme === '')
12231 $this->scheme = null;
12235 $len = strlen($scheme);
12239 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
12241 $this->scheme = null;
12242 $this->valid[__FUNCTION__] = false;
12247 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
12249 $this->scheme = null;
12250 $this->valid[__FUNCTION__] = false;
12254 $this->scheme = strtolower($scheme);
12256 $this->valid[__FUNCTION__] = true;
12261 * Set the authority. Returns true on success, false on failure (if there are
12262 * any invalid characters).
12265 * @param string $authority
12268 function set_authority($authority)
12270 if (($userinfo_end = strrpos($authority, '@')) !== false)
12272 $userinfo = substr($authority, 0, $userinfo_end);
12273 $authority = substr($authority, $userinfo_end + 1);
12280 if (($port_start = strpos($authority, ':')) !== false)
12282 $port = substr($authority, $port_start + 1);
12283 $authority = substr($authority, 0, $port_start);
12290 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
12294 * Set the userinfo.
12297 * @param string $userinfo
12300 function set_userinfo($userinfo)
12302 if ($userinfo === null || $userinfo === '')
12304 $this->userinfo = null;
12308 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
12310 $this->valid[__FUNCTION__] = true;
12315 * Set the host. Returns true on success, false on failure (if there are
12316 * any invalid characters).
12319 * @param string $host
12322 function set_host($host)
12324 if ($host === null || $host === '')
12326 $this->host = null;
12327 $this->valid[__FUNCTION__] = true;
12330 elseif ($host[0] === '[' && substr($host, -1) === ']')
12332 if (SimplePie_Net_IPv6::checkIPv6(substr($host, 1, -1)))
12334 $this->host = $host;
12335 $this->valid[__FUNCTION__] = true;
12340 $this->host = null;
12341 $this->valid[__FUNCTION__] = false;
12347 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
12348 $this->valid[__FUNCTION__] = true;
12354 * Set the port. Returns true on success, false on failure (if there are
12355 * any invalid characters).
12358 * @param string $port
12361 function set_port($port)
12363 if ($port === null || $port === '')
12365 $this->port = null;
12366 $this->valid[__FUNCTION__] = true;
12369 elseif (strspn($port, '0123456789') === strlen($port))
12371 $this->port = (int) $port;
12372 $this->valid[__FUNCTION__] = true;
12377 $this->port = null;
12378 $this->valid[__FUNCTION__] = false;
12387 * @param string $path
12390 function set_path($path)
12392 if ($path === null || $path === '')
12394 $this->path = null;
12395 $this->valid[__FUNCTION__] = true;
12398 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
12400 $this->path = null;
12401 $this->valid[__FUNCTION__] = false;
12406 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
12407 if ($this->scheme !== null)
12409 $this->path = $this->remove_dot_segments($this->path);
12411 $this->valid[__FUNCTION__] = true;
12420 * @param string $query
12423 function set_query($query)
12425 if ($query === null || $query === '')
12427 $this->query = null;
12431 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
12433 $this->valid[__FUNCTION__] = true;
12438 * Set the fragment.
12441 * @param string $fragment
12444 function set_fragment($fragment)
12446 if ($fragment === null || $fragment === '')
12448 $this->fragment = null;
12452 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
12454 $this->valid[__FUNCTION__] = true;
12459 * Get the complete IRI
12467 if ($this->scheme !== null)
12469 $iri .= $this->scheme . ':';
12471 if (($authority = $this->get_authority()) !== null)
12473 $iri .= '//' . $authority;
12475 if ($this->path !== null)
12477 $iri .= $this->path;
12479 if ($this->query !== null)
12481 $iri .= '?' . $this->query;
12483 if ($this->fragment !== null)
12485 $iri .= '#' . $this->fragment;
12504 function get_scheme()
12506 return $this->scheme;
12510 * Get the complete authority
12515 function get_authority()
12518 if ($this->userinfo !== null)
12520 $authority .= $this->userinfo . '@';
12522 if ($this->host !== null)
12524 $authority .= $this->host;
12526 if ($this->port !== null)
12528 $authority .= ':' . $this->port;
12531 if ($authority !== '')
12542 * Get the user information
12547 function get_userinfo()
12549 return $this->userinfo;
12558 function get_host()
12560 return $this->host;
12569 function get_port()
12571 return $this->port;
12580 function get_path()
12582 return $this->path;
12591 function get_query()
12593 return $this->query;
12602 function get_fragment()
12604 return $this->fragment;
12609 * Class to validate and to work with IPv6 addresses.
12611 * @package SimplePie
12612 * @copyright 2003-2005 The PHP Group
12613 * @license http://www.opensource.org/licenses/bsd-license.php
12614 * @link http://pear.php.net/package/Net_IPv6
12615 * @author Alexander Merz <alexander.merz@web.de>
12616 * @author elfrink at introweb dot nl
12617 * @author Josh Peck <jmp at joshpeck dot org>
12618 * @author Geoffrey Sneddon <geoffers@gmail.com>
12620 class SimplePie_Net_IPv6
12623 * Removes a possible existing netmask specification of an IP address.
12625 * @param string $ip the (compressed) IP as Hex representation
12626 * @return string the IP the without netmask
12631 function removeNetmaskSpec($ip)
12633 if (strpos($ip, '/') !== false)
12635 list($addr, $nm) = explode('/', $ip);
12645 * Uncompresses an IPv6 address
12647 * RFC 2373 allows you to compress zeros in an address to '::'. This
12648 * function expects an valid IPv6 address and expands the '::' to
12649 * the required zeros.
12651 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
12652 * ::1 -> 0:0:0:0:0:0:0:1
12656 * @param string $ip a valid IPv6-address (hex format)
12657 * @return string the uncompressed IPv6-address (hex format)
12659 function Uncompress($ip)
12661 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
12664 if (strpos($ip, '::') !== false)
12666 list($ip1, $ip2) = explode('::', $ip);
12674 if (($pos = substr_count($ip1, ':')) > 0)
12690 if (($pos = substr_count($ip2, ':')) > 0)
12699 if (strstr($ip2, '.'))
12704 if ($c1 === -1 && $c2 === -1)
12706 $uip = '0:0:0:0:0:0:0:0';
12709 else if ($c1 === -1)
12711 $fill = str_repeat('0:', 7 - $c2);
12712 $uip = str_replace('::', $fill, $uip);
12715 else if ($c2 === -1)
12717 $fill = str_repeat(':0', 7 - $c1);
12718 $uip = str_replace('::', $fill, $uip);
12723 $fill = str_repeat(':0:', 6 - $c2 - $c1);
12724 $uip = str_replace('::', $fill, $uip);
12725 $uip = str_replace('::', ':', $uip);
12732 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
12734 * RFC 2373 allows you to note the last two parts of an IPv6 address as
12735 * an IPv4 compatible address
12737 * Example: 0:0:0:0:0:0:13.1.68.3
12738 * 0:0:0:0:0:FFFF:129.144.52.38
12742 * @param string $ip a valid IPv6-address (hex format)
12743 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
12745 function SplitV64($ip)
12747 $ip = SimplePie_Net_IPv6::Uncompress($ip);
12748 if (strstr($ip, '.'))
12750 $pos = strrpos($ip, ':');
12752 $ipPart = explode('_', $ip);
12757 return array($ip, '');
12762 * Checks an IPv6 address
12764 * Checks if the given IP is IPv6-compatible
12768 * @param string $ip a valid IPv6-address
12769 * @return bool true if $ip is an IPv6 address
12771 function checkIPv6($ip)
12773 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12775 if (!empty($ipPart[0]))
12777 $ipv6 = explode(':', $ipPart[0]);
12778 for ($i = 0; $i < count($ipv6); $i++)
12780 $dec = hexdec($ipv6[$i]);
12781 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12782 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12791 elseif ($count === 6 && !empty($ipPart[1]))
12793 $ipv4 = explode('.', $ipPart[1]);
12795 foreach ($ipv4 as $ipv4_part)
12797 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12823 * @package SimplePie
12825 class SimplePie_Parse_Date
12830 * @access protected
12836 * List of days, calendar day name => ordinal day number in the week
12838 * @access protected
12901 'keskiviikko' => 3,
12925 * List of months, calendar month name => calendar month number
12927 * @access protected
12930 var $month = array(
12941 // No long form of May
13070 * List of timezones, abbreviation => offset from UTC
13072 * @access protected
13075 var $timezone = array(
13278 * Cached PCRE for SimplePie_Parse_Date::$day
13280 * @access protected
13286 * Cached PCRE for SimplePie_Parse_Date::$month
13288 * @access protected
13294 * Array of user-added callback methods
13299 var $built_in = array();
13302 * Array of user-added callback methods
13307 var $user = array();
13310 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
13311 * self::month_pcre, and self::built_in
13315 function SimplePie_Parse_Date()
13317 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
13318 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
13321 if (!isset($cache[get_class($this)]))
13323 $all_methods = get_class_methods($this);
13325 foreach ($all_methods as $method)
13327 if (strtolower(substr($method, 0, 5)) === 'date_')
13329 $cache[get_class($this)][] = $method;
13334 foreach ($cache[get_class($this)] as $method)
13336 $this->built_in[] = $method;
13350 $object =& new SimplePie_Parse_Date;
13360 * @param string $date Date to parse
13361 * @return int Timestamp corresponding to date string, or false on failure
13363 function parse($date)
13365 foreach ($this->user as $method)
13367 if (($returned = call_user_func($method, $date)) !== false)
13373 foreach ($this->built_in as $method)
13375 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
13385 * Add a callback method to parse a date
13389 * @param callback $callback
13391 function add_callback($callback)
13393 if (is_callable($callback))
13395 $this->user[] = $callback;
13399 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
13404 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
13405 * well as allowing any of upper or lower case "T", horizontal tabs, or
13406 * spaces to be used as the time seperator (including more than one))
13408 * @access protected
13409 * @return int Timestamp
13411 function date_w3cdtf($date)
13416 $year = '([0-9]{4})';
13417 $month = $day = $hour = $minute = $second = '([0-9]{2})';
13418 $decimal = '([0-9]*)';
13419 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
13420 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
13422 if (preg_match($pcre, $date, $match))
13425 Capturing subpatterns:
13432 7: Decimal fraction of a second
13436 11: Timezone minutes
13439 // Fill in empty matches
13440 for ($i = count($match); $i <= 3; $i++)
13445 for ($i = count($match); $i <= 7; $i++)
13450 // Numeric timezone
13451 if (isset($match[9]) && $match[9] !== '')
13453 $timezone = $match[10] * 3600;
13454 $timezone += $match[11] * 60;
13455 if ($match[9] === '-')
13457 $timezone = 0 - $timezone;
13465 // Convert the number of seconds to an integer, taking decimals into account
13466 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
13468 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
13477 * Remove RFC822 comments
13479 * @access protected
13480 * @param string $data Data to strip comments from
13481 * @return string Comment stripped string
13483 function remove_rfc2822_comments($string)
13485 $string = (string) $string;
13487 $length = strlen($string);
13492 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13494 $output .= substr($string, $position, $pos - $position);
13495 $position = $pos + 1;
13496 if ($string[$pos - 1] !== '\\')
13499 while ($depth && $position < $length)
13501 $position += strcspn($string, '()', $position);
13502 if ($string[$position - 1] === '\\')
13507 elseif (isset($string[$position]))
13509 switch ($string[$position])
13532 $output .= substr($string, $position);
13538 * Parse RFC2822's date format
13540 * @access protected
13541 * @return int Timestamp
13543 function date_rfc2822($date)
13548 $wsp = '[\x09\x20]';
13549 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
13550 $optional_fws = $fws . '?';
13551 $day_name = $this->day_pcre;
13552 $month = $this->month_pcre;
13553 $day = '([0-9]{1,2})';
13554 $hour = $minute = $second = '([0-9]{2})';
13555 $year = '([0-9]{2,4})';
13556 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
13557 $character_zone = '([A-Z]{1,5})';
13558 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
13559 $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';
13561 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
13564 Capturing subpatterns:
13574 10: Timezone minutes
13575 11: Alphabetic timezone
13578 // Find the month number
13579 $month = $this->month[strtolower($match[3])];
13581 // Numeric timezone
13582 if ($match[8] !== '')
13584 $timezone = $match[9] * 3600;
13585 $timezone += $match[10] * 60;
13586 if ($match[8] === '-')
13588 $timezone = 0 - $timezone;
13591 // Character timezone
13592 elseif (isset($this->timezone[strtoupper($match[11])]))
13594 $timezone = $this->timezone[strtoupper($match[11])];
13596 // Assume everything else to be -0000
13602 // Deal with 2/3 digit years
13603 if ($match[4] < 50)
13607 elseif ($match[4] < 1000)
13612 // Second is optional, if it is empty set it to zero
13613 if ($match[7] !== '')
13615 $second = $match[7];
13622 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
13631 * Parse RFC850's date format
13633 * @access protected
13634 * @return int Timestamp
13636 function date_rfc850($date)
13641 $space = '[\x09\x20]+';
13642 $day_name = $this->day_pcre;
13643 $month = $this->month_pcre;
13644 $day = '([0-9]{1,2})';
13645 $year = $hour = $minute = $second = '([0-9]{2})';
13646 $zone = '([A-Z]{1,5})';
13647 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
13649 if (preg_match($pcre, $date, $match))
13652 Capturing subpatterns:
13664 $month = $this->month[strtolower($match[3])];
13666 // Character timezone
13667 if (isset($this->timezone[strtoupper($match[8])]))
13669 $timezone = $this->timezone[strtoupper($match[8])];
13671 // Assume everything else to be -0000
13677 // Deal with 2 digit year
13678 if ($match[4] < 50)
13687 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
13696 * Parse C99's asctime()'s date format
13698 * @access protected
13699 * @return int Timestamp
13701 function date_asctime($date)
13706 $space = '[\x09\x20]+';
13707 $wday_name = $this->day_pcre;
13708 $mon_name = $this->month_pcre;
13709 $day = '([0-9]{1,2})';
13710 $hour = $sec = $min = '([0-9]{2})';
13711 $year = '([0-9]{4})';
13712 $terminator = '\x0A?\x00?';
13713 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
13715 if (preg_match($pcre, $date, $match))
13718 Capturing subpatterns:
13728 $month = $this->month[strtolower($match[2])];
13729 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
13738 * Parse dates using strtotime()
13740 * @access protected
13741 * @return int Timestamp
13743 function date_strtotime($date)
13745 $strtotime = strtotime($date);
13746 if ($strtotime === -1 || $strtotime === false)
13758 * Content-type sniffing
13760 * @package SimplePie
13762 class SimplePie_Content_Type_Sniffer
13767 * @var SimplePie_File
13773 * Create an instance of the class with the input file
13776 * @param SimplePie_Content_Type_Sniffer $file Input file
13778 function SimplePie_Content_Type_Sniffer($file)
13780 $this->file = $file;
13784 * Get the Content-Type of the specified file
13787 * @return string Actual Content-Type
13789 function get_type()
13791 if (isset($this->file->headers['content-type']))
13793 if (!isset($this->file->headers['content-encoding'])
13794 && ($this->file->headers['content-type'] === 'text/plain'
13795 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13796 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13798 return $this->text_or_binary();
13801 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13803 $official = substr($this->file->headers['content-type'], 0, $pos);
13807 $official = $this->file->headers['content-type'];
13809 $official = strtolower($official);
13811 if ($official === 'unknown/unknown'
13812 || $official === 'application/unknown')
13814 return $this->unknown();
13816 elseif (substr($official, -4) === '+xml'
13817 || $official === 'text/xml'
13818 || $official === 'application/xml')
13822 elseif (substr($official, 0, 6) === 'image/')
13824 if ($return = $this->image())
13833 elseif ($official === 'text/html')
13835 return $this->feed_or_html();
13844 return $this->unknown();
13849 * Sniff text or binary
13852 * @return string Actual Content-Type
13854 function text_or_binary()
13856 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13857 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13858 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13859 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13861 return 'text/plain';
13863 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13865 return 'application/octect-stream';
13869 return 'text/plain';
13877 * @return string Actual Content-Type
13881 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13882 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13883 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13884 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13886 return 'text/html';
13888 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13890 return 'application/pdf';
13892 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13894 return 'application/postscript';
13896 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13897 || substr($this->file->body, 0, 6) === 'GIF89a')
13899 return 'image/gif';
13901 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13903 return 'image/png';
13905 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13907 return 'image/jpeg';
13909 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13911 return 'image/bmp';
13915 return $this->text_or_binary();
13923 * @return string Actual Content-Type
13927 if (substr($this->file->body, 0, 6) === 'GIF87a'
13928 || substr($this->file->body, 0, 6) === 'GIF89a')
13930 return 'image/gif';
13932 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13934 return 'image/png';
13936 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13938 return 'image/jpeg';
13940 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13942 return 'image/bmp';
13954 * @return string Actual Content-Type
13956 function feed_or_html()
13958 $len = strlen($this->file->body);
13959 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13961 while ($pos < $len)
13963 switch ($this->file->body[$pos])
13969 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13977 return 'text/html';
13980 if (substr($this->file->body, $pos, 3) === '!--')
13983 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13989 return 'text/html';
13992 elseif (substr($this->file->body, $pos, 1) === '!')
13994 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
14000 return 'text/html';
14003 elseif (substr($this->file->body, $pos, 1) === '?')
14005 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
14011 return 'text/html';
14014 elseif (substr($this->file->body, $pos, 3) === 'rss'
14015 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
14017 return 'application/rss+xml';
14019 elseif (substr($this->file->body, $pos, 4) === 'feed')
14021 return 'application/atom+xml';
14025 return 'text/html';
14029 return 'text/html';
14034 * Parses the XML Declaration
14036 * @package SimplePie
14038 class SimplePie_XML_Declaration_Parser
14046 var $version = '1.0';
14054 var $encoding = 'UTF-8';
14062 var $standalone = false;
14065 * Current state of the state machine
14070 var $state = 'before_version_name';
14081 * Input data length (to avoid calling strlen() everytime this is needed)
14086 var $data_length = 0;
14089 * Current position of the pointer
14097 * Create an instance of the class with the input data
14100 * @param string $data Input data
14102 function SimplePie_XML_Declaration_Parser($data)
14104 $this->data = $data;
14105 $this->data_length = strlen($this->data);
14109 * Parse the input data
14112 * @return bool true on success, false on failure
14116 while ($this->state && $this->state !== 'emit' && $this->has_data())
14118 $state = $this->state;
14122 if ($this->state === 'emit')
14128 $this->version = '';
14129 $this->encoding = '';
14130 $this->standalone = '';
14136 * Check whether there is data beyond the pointer
14139 * @return bool true if there is further data, false if not
14141 function has_data()
14143 return (bool) ($this->position < $this->data_length);
14147 * Advance past any whitespace
14149 * @return int Number of whitespace characters passed
14151 function skip_whitespace()
14153 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
14154 $this->position += $whitespace;
14155 return $whitespace;
14161 function get_value()
14163 $quote = substr($this->data, $this->position, 1);
14164 if ($quote === '"' || $quote === "'")
14167 $len = strcspn($this->data, $quote, $this->position);
14168 if ($this->has_data())
14170 $value = substr($this->data, $this->position, $len);
14171 $this->position += $len + 1;
14178 function before_version_name()
14180 if ($this->skip_whitespace())
14182 $this->state = 'version_name';
14186 $this->state = false;
14190 function version_name()
14192 if (substr($this->data, $this->position, 7) === 'version')
14194 $this->position += 7;
14195 $this->skip_whitespace();
14196 $this->state = 'version_equals';
14200 $this->state = false;
14204 function version_equals()
14206 if (substr($this->data, $this->position, 1) === '=')
14209 $this->skip_whitespace();
14210 $this->state = 'version_value';
14214 $this->state = false;
14218 function version_value()
14220 if ($this->version = $this->get_value())
14222 $this->skip_whitespace();
14223 if ($this->has_data())
14225 $this->state = 'encoding_name';
14229 $this->state = 'emit';
14234 $this->state = false;
14238 function encoding_name()
14240 if (substr($this->data, $this->position, 8) === 'encoding')
14242 $this->position += 8;
14243 $this->skip_whitespace();
14244 $this->state = 'encoding_equals';
14248 $this->state = 'standalone_name';
14252 function encoding_equals()
14254 if (substr($this->data, $this->position, 1) === '=')
14257 $this->skip_whitespace();
14258 $this->state = 'encoding_value';
14262 $this->state = false;
14266 function encoding_value()
14268 if ($this->encoding = $this->get_value())
14270 $this->skip_whitespace();
14271 if ($this->has_data())
14273 $this->state = 'standalone_name';
14277 $this->state = 'emit';
14282 $this->state = false;
14286 function standalone_name()
14288 if (substr($this->data, $this->position, 10) === 'standalone')
14290 $this->position += 10;
14291 $this->skip_whitespace();
14292 $this->state = 'standalone_equals';
14296 $this->state = false;
14300 function standalone_equals()
14302 if (substr($this->data, $this->position, 1) === '=')
14305 $this->skip_whitespace();
14306 $this->state = 'standalone_value';
14310 $this->state = false;
14314 function standalone_value()
14316 if ($standalone = $this->get_value())
14318 switch ($standalone)
14321 $this->standalone = true;
14325 $this->standalone = false;
14329 $this->state = false;
14333 $this->skip_whitespace();
14334 if ($this->has_data())
14336 $this->state = false;
14340 $this->state = 'emit';
14345 $this->state = false;
14350 class SimplePie_Locator
14355 var $local = array();
14356 var $elsewhere = array();
14357 var $file_class = 'SimplePie_File';
14358 var $cached_entities = array();
14361 var $base_location = 0;
14362 var $checked_feeds = 0;
14363 var $max_checked_feeds = 10;
14364 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
14366 function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
14368 $this->file =& $file;
14369 $this->file_class = $file_class;
14370 $this->useragent = $useragent;
14371 $this->timeout = $timeout;
14372 $this->max_checked_feeds = $max_checked_feeds;
14373 $this->content_type_sniffer_class = $content_type_sniffer_class;
14376 function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
14378 if ($this->is_feed($this->file))
14380 return $this->file;
14383 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14385 $sniffer =& new $this->content_type_sniffer_class($this->file);
14386 if ($sniffer->get_type() !== 'text/html')
14392 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
14397 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
14399 return $working[0];
14402 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
14404 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
14409 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
14414 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
14419 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
14427 function is_feed(&$file)
14429 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
14431 $sniffer =& new $this->content_type_sniffer_class($file);
14432 $sniffed = $sniffer->get_type();
14433 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
14442 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
14452 function get_base()
14454 $this->http_base = $this->file->url;
14455 $this->base = $this->http_base;
14456 $elements = SimplePie_Misc::get_element('base', $this->file->body);
14457 foreach ($elements as $element)
14459 if ($element['attribs']['href']['data'] !== '')
14461 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
14462 $this->base_location = $element['offset'];
14468 function autodiscovery()
14470 $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));
14473 foreach ($links as $link)
14475 if ($this->checked_feeds === $this->max_checked_feeds)
14479 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
14481 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
14483 if ($this->base_location < $link['offset'])
14485 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14489 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14492 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]))
14494 $this->checked_feeds++;
14495 $feed =& new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
14496 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))
14498 $feeds[$href] = $feed;
14505 if (!empty($feeds))
14507 return array_values($feeds);
14514 function get_links()
14516 $links = SimplePie_Misc::get_element('a', $this->file->body);
14517 foreach ($links as $link)
14519 if (isset($link['attribs']['href']['data']))
14521 $href = trim($link['attribs']['href']['data']);
14522 $parsed = SimplePie_Misc::parse_url($href);
14523 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
14525 if ($this->base_location < $link['offset'])
14527 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
14531 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
14534 $current = SimplePie_Misc::parse_url($this->file->url);
14536 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
14538 $this->local[] = $href;
14542 $this->elsewhere[] = $href;
14547 $this->local = array_unique($this->local);
14548 $this->elsewhere = array_unique($this->elsewhere);
14549 if (!empty($this->local) || !empty($this->elsewhere))
14556 function extension(&$array)
14558 foreach ($array as $key => $value)
14560 if ($this->checked_feeds === $this->max_checked_feeds)
14564 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
14566 $this->checked_feeds++;
14567 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14568 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))
14574 unset($array[$key]);
14581 function body(&$array)
14583 foreach ($array as $key => $value)
14585 if ($this->checked_feeds === $this->max_checked_feeds)
14589 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
14591 $this->checked_feeds++;
14592 $feed =& new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
14593 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))
14599 unset($array[$key]);
14607 class SimplePie_Parser
14612 var $current_column;
14614 var $separator = ' ';
14615 var $namespace = array('');
14616 var $element = array('');
14617 var $xml_base = array('');
14618 var $xml_base_explicit = array(false);
14619 var $xml_lang = array('');
14620 var $data = array();
14621 var $datas = array(array());
14622 var $current_xhtml_construct = -1;
14625 function parse(&$data, $encoding)
14627 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
14628 if (strtoupper($encoding) === 'US-ASCII')
14630 $this->encoding = 'UTF-8';
14634 $this->encoding = $encoding;
14638 // UTF-32 Big Endian BOM
14639 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14641 $data = substr($data, 4);
14643 // UTF-32 Little Endian BOM
14644 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14646 $data = substr($data, 4);
14648 // UTF-16 Big Endian BOM
14649 elseif (substr($data, 0, 2) === "\xFE\xFF")
14651 $data = substr($data, 2);
14653 // UTF-16 Little Endian BOM
14654 elseif (substr($data, 0, 2) === "\xFF\xFE")
14656 $data = substr($data, 2);
14659 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14661 $data = substr($data, 3);
14664 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
14666 $declaration =& new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
14667 if ($declaration->parse())
14669 $data = substr($data, $pos + 2);
14670 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
14674 $this->error_string = 'SimplePie bug! Please report this!';
14681 static $xml_is_sane = null;
14682 if ($xml_is_sane === null)
14684 $parser_check = xml_parser_create();
14685 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
14686 xml_parser_free($parser_check);
14687 $xml_is_sane = isset($values[0]['value']);
14690 // Create the parser
14693 $xml = xml_parser_create_ns($this->encoding, $this->separator);
14694 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
14695 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
14696 xml_set_object($xml, $this);
14697 xml_set_character_data_handler($xml, 'cdata');
14698 xml_set_element_handler($xml, 'tag_open', 'tag_close');
14701 if (!xml_parse($xml, $data, true))
14703 $this->error_code = xml_get_error_code($xml);
14704 $this->error_string = xml_error_string($this->error_code);
14707 $this->current_line = xml_get_current_line_number($xml);
14708 $this->current_column = xml_get_current_column_number($xml);
14709 $this->current_byte = xml_get_current_byte_index($xml);
14710 xml_parser_free($xml);
14715 libxml_clear_errors();
14716 $xml =& new XMLReader();
14718 while (@$xml->read())
14720 switch ($xml->nodeType)
14723 case constant('XMLReader::END_ELEMENT'):
14724 if ($xml->namespaceURI !== '')
14726 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14730 $tagName = $xml->localName;
14732 $this->tag_close(null, $tagName);
14734 case constant('XMLReader::ELEMENT'):
14735 $empty = $xml->isEmptyElement;
14736 if ($xml->namespaceURI !== '')
14738 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
14742 $tagName = $xml->localName;
14744 $attributes = array();
14745 while ($xml->moveToNextAttribute())
14747 if ($xml->namespaceURI !== '')
14749 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
14753 $attrName = $xml->localName;
14755 $attributes[$attrName] = $xml->value;
14757 $this->tag_open(null, $tagName, $attributes);
14760 $this->tag_close(null, $tagName);
14763 case constant('XMLReader::TEXT'):
14765 case constant('XMLReader::CDATA'):
14766 $this->cdata(null, $xml->value);
14770 if ($error = libxml_get_last_error())
14772 $this->error_code = $error->code;
14773 $this->error_string = $error->message;
14774 $this->current_line = $error->line;
14775 $this->current_column = $error->column;
14785 function get_error_code()
14787 return $this->error_code;
14790 function get_error_string()
14792 return $this->error_string;
14795 function get_current_line()
14797 return $this->current_line;
14800 function get_current_column()
14802 return $this->current_column;
14805 function get_current_byte()
14807 return $this->current_byte;
14810 function get_data()
14812 return $this->data;
14815 function tag_open($parser, $tag, $attributes)
14817 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14819 $attribs = array();
14820 foreach ($attributes as $name => $value)
14822 list($attrib_namespace, $attribute) = $this->split_ns($name);
14823 $attribs[$attrib_namespace][$attribute] = $value;
14826 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14828 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14829 $this->xml_base_explicit[] = true;
14833 $this->xml_base[] = end($this->xml_base);
14834 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14837 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14839 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14843 $this->xml_lang[] = end($this->xml_lang);
14846 if ($this->current_xhtml_construct >= 0)
14848 $this->current_xhtml_construct++;
14849 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14851 $this->data['data'] .= '<' . end($this->element);
14852 if (isset($attribs['']))
14854 foreach ($attribs[''] as $name => $value)
14856 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14859 $this->data['data'] .= '>';
14864 $this->datas[] =& $this->data;
14865 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14866 $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));
14867 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')
14868 || (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'))
14870 $this->current_xhtml_construct = 0;
14875 function cdata($parser, $cdata)
14877 if ($this->current_xhtml_construct >= 0)
14879 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14883 $this->data['data'] .= $cdata;
14887 function tag_close($parser, $tag)
14889 if ($this->current_xhtml_construct >= 0)
14891 $this->current_xhtml_construct--;
14892 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')))
14894 $this->data['data'] .= '</' . end($this->element) . '>';
14897 if ($this->current_xhtml_construct === -1)
14899 $this->data =& $this->datas[count($this->datas) - 1];
14900 array_pop($this->datas);
14903 array_pop($this->element);
14904 array_pop($this->namespace);
14905 array_pop($this->xml_base);
14906 array_pop($this->xml_base_explicit);
14907 array_pop($this->xml_lang);
14910 function split_ns($string)
14912 static $cache = array();
14913 if (!isset($cache[$string]))
14915 if ($pos = strpos($string, $this->separator))
14917 static $separator_length;
14918 if (!$separator_length)
14920 $separator_length = strlen($this->separator);
14922 $namespace = substr($string, 0, $pos);
14923 $local_name = substr($string, $pos + $separator_length);
14924 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14926 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14929 // Normalize the Media RSS namespaces
14930 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
14932 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14934 $cache[$string] = array($namespace, $local_name);
14938 $cache[$string] = array('', $string);
14941 return $cache[$string];
14946 * @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
14948 class SimplePie_Sanitize
14954 var $remove_div = true;
14955 var $image_handler = '';
14956 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14957 var $encode_instead_of_strip = false;
14958 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14959 var $strip_comments = false;
14960 var $output_encoding = 'UTF-8';
14961 var $enable_cache = true;
14962 var $cache_location = './cache';
14963 var $cache_name_function = 'md5';
14964 var $cache_class = 'SimplePie_Cache';
14965 var $file_class = 'SimplePie_File';
14967 var $useragent = '';
14968 var $force_fsockopen = false;
14970 var $replace_url_attributes = array(
14973 'blockquote' => 'cite',
14975 'form' => 'action',
14976 'img' => array('longdesc', 'src'),
14982 function remove_div($enable = true)
14984 $this->remove_div = (bool) $enable;
14987 function set_image_handler($page = false)
14991 $this->image_handler = (string) $page;
14995 $this->image_handler = false;
14999 function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
15001 if (isset($enable_cache))
15003 $this->enable_cache = (bool) $enable_cache;
15006 if ($cache_location)
15008 $this->cache_location = (string) $cache_location;
15011 if ($cache_name_function)
15013 $this->cache_name_function = (string) $cache_name_function;
15018 $this->cache_class = (string) $cache_class;
15022 function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
15026 $this->file_class = (string) $file_class;
15031 $this->timeout = (string) $timeout;
15036 $this->useragent = (string) $useragent;
15039 if ($force_fsockopen)
15041 $this->force_fsockopen = (string) $force_fsockopen;
15045 function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
15049 if (is_array($tags))
15051 $this->strip_htmltags = $tags;
15055 $this->strip_htmltags = explode(',', $tags);
15060 $this->strip_htmltags = false;
15064 function encode_instead_of_strip($encode = false)
15066 $this->encode_instead_of_strip = (bool) $encode;
15069 function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
15073 if (is_array($attribs))
15075 $this->strip_attributes = $attribs;
15079 $this->strip_attributes = explode(',', $attribs);
15084 $this->strip_attributes = false;
15088 function strip_comments($strip = false)
15090 $this->strip_comments = (bool) $strip;
15093 function set_output_encoding($encoding = 'UTF-8')
15095 $this->output_encoding = (string) $encoding;
15099 * Set element/attribute key/value pairs of HTML attributes
15100 * containing URLs that need to be resolved relative to the feed
15104 * @param array $element_attribute Element/attribute key/value pairs
15106 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'))
15108 $this->replace_url_attributes = (array) $element_attribute;
15111 function sanitize($data, $type, $base = '')
15113 $data = trim($data);
15114 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
15116 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
15118 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))
15120 $type |= SIMPLEPIE_CONSTRUCT_HTML;
15124 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
15128 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
15130 $data = base64_decode($data);
15133 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
15135 if ($this->remove_div)
15137 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
15138 $data = preg_replace('/<\/div>$/', '', $data);
15142 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
15146 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
15149 if ($this->strip_comments)
15151 $data = SimplePie_Misc::strip_comments($data);
15154 // Strip out HTML tags and attributes that might cause various security problems.
15155 // Based on recommendations by Mark Pilgrim at:
15156 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
15157 if ($this->strip_htmltags)
15159 foreach ($this->strip_htmltags as $tag)
15161 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
15162 while (preg_match($pcre, $data))
15164 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
15169 if ($this->strip_attributes)
15171 foreach ($this->strip_attributes as $attrib)
15173 $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);
15177 // Replace relative URLs
15178 $this->base = $base;
15179 foreach ($this->replace_url_attributes as $element => $attributes)
15181 $data = $this->replace_urls($data, $element, $attributes);
15184 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
15185 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
15187 $images = SimplePie_Misc::get_element('img', $data);
15188 foreach ($images as $img)
15190 if (isset($img['attribs']['src']['data']))
15192 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
15193 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
15195 if ($cache->load())
15197 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15198 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15202 $file =& new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
15203 $headers = $file->headers;
15205 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
15207 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
15209 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
15210 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
15214 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);
15222 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
15223 $data = trim($data);
15226 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
15228 $data = SimplePie_Misc::absolutize_url($data, $base);
15231 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
15233 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
15236 if ($this->output_encoding !== 'UTF-8')
15238 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
15244 function replace_urls($data, $tag, $attributes)
15246 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
15248 $elements = SimplePie_Misc::get_element($tag, $data);
15249 foreach ($elements as $element)
15251 if (is_array($attributes))
15253 foreach ($attributes as $attribute)
15255 if (isset($element['attribs'][$attribute]['data']))
15257 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
15258 $new_element = SimplePie_Misc::element_implode($element);
15259 $data = str_replace($element['full'], $new_element, $data);
15260 $element['full'] = $new_element;
15264 elseif (isset($element['attribs'][$attributes]['data']))
15266 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
15267 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
15274 function do_strip_htmltags($match)
15276 if ($this->encode_instead_of_strip)
15278 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
15280 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
15281 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
15282 return "<$match[1]$match[2]>$match[3]</$match[1]>";
15286 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
15289 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))