5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
8 * Please note: This file is automatically generated by a build script. The
9 * full original source is always available from http://simplepie.org/
11 * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
12 * All rights reserved.
14 * Redistribution and use in source and binary forms, with or without modification, are
15 * permitted provided that the following conditions are met:
17 * * Redistributions of source code must retain the above copyright notice, this list of
18 * conditions and the following disclaimer.
20 * * Redistributions in binary form must reproduce the above copyright notice, this list
21 * of conditions and the following disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
25 * to endorse or promote products derived from this software without specific prior
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
29 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
30 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
31 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
40 * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
42 * @author Geoffrey Sneddon
44 * @link http://simplepie.org/ SimplePie
45 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
51 define('SIMPLEPIE_NAME', 'SimplePie');
56 define('SIMPLEPIE_VERSION', '1.3.1');
60 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
62 define('SIMPLEPIE_BUILD', '20121030175911');
65 * SimplePie Website URL
67 define('SIMPLEPIE_URL', 'http://simplepie.org');
71 * @see SimplePie::set_useragent()
73 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME
. '/' . SIMPLEPIE_VERSION
. ' (Feed Parser; ' . SIMPLEPIE_URL
. '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD
);
78 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL
. '" title="' . SIMPLEPIE_NAME
. ' ' . SIMPLEPIE_VERSION
. '">' . SIMPLEPIE_NAME
. '</a>');
82 * @see SimplePie::set_autodiscovery_level()
84 define('SIMPLEPIE_LOCATOR_NONE', 0);
87 * Feed Link Element Autodiscovery
88 * @see SimplePie::set_autodiscovery_level()
90 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
93 * Local Feed Extension Autodiscovery
94 * @see SimplePie::set_autodiscovery_level()
96 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
99 * Local Feed Body Autodiscovery
100 * @see SimplePie::set_autodiscovery_level()
102 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
105 * Remote Feed Extension Autodiscovery
106 * @see SimplePie::set_autodiscovery_level()
108 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
111 * Remote Feed Body Autodiscovery
112 * @see SimplePie::set_autodiscovery_level()
114 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
117 * All Feed Autodiscovery
118 * @see SimplePie::set_autodiscovery_level()
120 define('SIMPLEPIE_LOCATOR_ALL', 31);
125 define('SIMPLEPIE_TYPE_NONE', 0);
130 define('SIMPLEPIE_TYPE_RSS_090', 1);
133 * RSS 0.91 (Netscape)
135 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
138 * RSS 0.91 (Userland)
140 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
143 * RSS 0.91 (both Netscape and Userland)
145 define('SIMPLEPIE_TYPE_RSS_091', 6);
150 define('SIMPLEPIE_TYPE_RSS_092', 8);
155 define('SIMPLEPIE_TYPE_RSS_093', 16);
160 define('SIMPLEPIE_TYPE_RSS_094', 32);
165 define('SIMPLEPIE_TYPE_RSS_10', 64);
170 define('SIMPLEPIE_TYPE_RSS_20', 128);
175 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
178 * Non-RDF-based RSS (truly intended as syndication format)
180 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
185 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
190 define('SIMPLEPIE_TYPE_ATOM_03', 256);
195 define('SIMPLEPIE_TYPE_ATOM_10', 512);
200 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
205 define('SIMPLEPIE_TYPE_ALL', 1023);
210 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
215 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
220 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
225 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
228 * base64-encoded construct
230 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
235 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
238 * A construct that might be HTML
240 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
245 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
250 define('SIMPLEPIE_SAME_CASE', 1);
253 * Change to lowercase
255 define('SIMPLEPIE_LOWERCASE', 2);
258 * Change to uppercase
260 define('SIMPLEPIE_UPPERCASE', 4);
263 * PCRE for HTML attributes
265 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]*');
268 * PCRE for XML attributes
270 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
275 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
280 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
285 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
290 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
295 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
300 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
303 * RSS 1.0 Content Module Namespace
305 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
309 * (Stupid, I know, but I'm certain it will confuse people less with support.)
311 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
316 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
321 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
324 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
326 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
331 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
334 * Media RSS Namespace
336 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
339 * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
341 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
344 * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
346 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
349 * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
351 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
354 * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
356 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
359 * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
361 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
364 * iTunes RSS Namespace
366 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
371 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
374 * IANA Link Relations Registry
376 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
381 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
386 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
391 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
394 * fsockopen() file source
396 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
401 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
404 * file_get_contents() file source
406 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
417 * @var array Raw data
420 public $data = array();
423 * @var mixed Error string
429 * @var object Instance of SimplePie_Sanitize (or other class)
430 * @see SimplePie::set_sanitize_class()
436 * @var string SimplePie Useragent
437 * @see SimplePie::set_useragent()
440 public $useragent = SIMPLEPIE_USERAGENT
;
443 * @var string Feed URL
444 * @see SimplePie::set_feed_url()
450 * @var object Instance of SimplePie_File to use as a feed
451 * @see SimplePie::set_file()
457 * @var string Raw feed data
458 * @see SimplePie::set_raw_data()
464 * @var int Timeout for fetching remote files
465 * @see SimplePie::set_timeout()
468 public $timeout = 10;
471 * @var bool Forces fsockopen() to be used for remote files instead
472 * of cURL, even if a new enough version is installed
473 * @see SimplePie::force_fsockopen()
476 public $force_fsockopen = false;
479 * @var bool Force the given data/URL to be treated as a feed no matter what
481 * @see SimplePie::force_feed()
484 public $force_feed = false;
487 * @var bool Enable/Disable Caching
488 * @see SimplePie::enable_cache()
491 public $cache = true;
494 * @var int Cache duration (in seconds)
495 * @see SimplePie::set_cache_duration()
498 public $cache_duration = 3600;
501 * @var int Auto-discovery cache duration (in seconds)
502 * @see SimplePie::set_autodiscovery_cache_duration()
505 public $autodiscovery_cache_duration = 604800; // 7 Days.
508 * @var string Cache location (relative to executing script)
509 * @see SimplePie::set_cache_location()
512 public $cache_location = './cache';
515 * @var string Function that creates the cache filename
516 * @see SimplePie::set_cache_name_function()
519 public $cache_name_function = 'md5';
522 * @var bool Reorder feed by date descending
523 * @see SimplePie::enable_order_by_date()
526 public $order_by_date = true;
529 * @var mixed Force input encoding to be set to the follow value
530 * (false, or anything type-cast to false, disables this feature)
531 * @see SimplePie::set_input_encoding()
534 public $input_encoding = false;
537 * @var int Feed Autodiscovery Level
538 * @see SimplePie::set_autodiscovery_level()
541 public $autodiscovery = SIMPLEPIE_LOCATOR_ALL
;
544 * Class registry object
546 * @var SimplePie_Registry
551 * @var int Maximum number of feeds to check with autodiscovery
552 * @see SimplePie::set_max_checked_feeds()
555 public $max_checked_feeds = 10;
558 * @var array All the feeds found during the autodiscovery process
559 * @see SimplePie::get_all_discovered_feeds()
562 public $all_discovered_feeds = array();
565 * @var string Web-accessible path to the handler_image.php file.
566 * @see SimplePie::set_image_handler()
569 public $image_handler = '';
572 * @var array Stores the URLs when multiple feeds are being initialized.
573 * @see SimplePie::set_feed_url()
576 public $multifeed_url = array();
579 * @var array Stores SimplePie objects when multiple feeds initialized.
582 public $multifeed_objects = array();
585 * @var array Stores the get_object_vars() array for use with multifeeds.
586 * @see SimplePie::set_feed_url()
589 public $config_settings = null;
592 * @var integer Stores the number of items to return per-feed with multifeeds.
593 * @see SimplePie::set_item_limit()
596 public $item_limit = 0;
599 * @var array Stores the default attributes to be stripped by strip_attributes().
600 * @see SimplePie::strip_attributes()
603 public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
606 * @var array Stores the default tags to be stripped by strip_htmltags().
607 * @see SimplePie::strip_htmltags()
610 public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
613 * The SimplePie class contains feed level data and options
615 * To use SimplePie, create the SimplePie object with no parameters. You can
616 * then set configuration options using the provided methods. After setting
617 * them, you must initialise the feed using $feed->init(). At that point the
618 * object's methods and properties will be available to you.
620 * Previously, it was possible to pass in the feed URL along with cache
621 * options directly into the constructor. This has been removed as of 1.3 as
622 * it caused a lot of confusion.
624 * @since 1.0 Preview Release
626 public function __construct()
628 if (version_compare(PHP_VERSION
, '5.2', '<'))
630 trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
634 // Other objects, instances created here so we can set options on them
635 $this->sanitize
= new SimplePie_Sanitize();
636 $this->registry
= new SimplePie_Registry();
638 if (func_num_args() > 0)
640 $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED
: E_USER_WARNING
;
641 trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
643 $args = func_get_args();
644 switch (count($args)) {
646 $this->set_cache_duration($args[2]);
648 $this->set_cache_location($args[1]);
650 $this->set_feed_url($args[0]);
657 * Used for converting object to a string
659 public function __toString()
661 return md5(serialize($this->data
));
665 * Remove items that link back to this before destroying this object
667 public function __destruct()
669 if ((version_compare(PHP_VERSION
, '5.3', '<') ||
!gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
671 if (!empty($this->data
['items']))
673 foreach ($this->data
['items'] as $item)
677 unset($item, $this->data
['items']);
679 if (!empty($this->data
['ordered_items']))
681 foreach ($this->data
['ordered_items'] as $item)
685 unset($item, $this->data
['ordered_items']);
691 * Force the given data/URL to be treated as a feed
693 * This tells SimplePie to ignore the content-type provided by the server.
694 * Be careful when using this option, as it will also disable autodiscovery.
697 * @param bool $enable Force the given data/URL to be treated as a feed
699 public function force_feed($enable = false)
701 $this->force_feed
= (bool) $enable;
705 * Set the URL of the feed you want to parse
707 * This allows you to enter the URL of the feed you want to parse, or the
708 * website you want to try to use auto-discovery on. This takes priority
709 * over any set raw data.
711 * You can set multiple feeds to mash together by passing an array instead
712 * of a string for the $url. Remember that with each additional feed comes
713 * additional processing and resources.
715 * @since 1.0 Preview Release
716 * @see set_raw_data()
717 * @param string|array $url This is the URL (or array of URLs) that you want to parse.
719 public function set_feed_url($url)
721 $this->multifeed_url
= array();
724 foreach ($url as $value)
726 $this->multifeed_url
[] = $this->registry
->call('Misc', 'fix_protocol', array($value, 1));
731 $this->feed_url
= $this->registry
->call('Misc', 'fix_protocol', array($url, 1));
736 * Set an instance of {@see SimplePie_File} to use as a feed
738 * @param SimplePie_File &$file
739 * @return bool True on success, false on failure
741 public function set_file(&$file)
743 if ($file instanceof SimplePie_File
)
745 $this->feed_url
= $file->url
;
746 $this->file
=& $file;
753 * Set the raw XML data to parse
755 * Allows you to use a string of RSS/Atom data instead of a remote feed.
757 * If you have a feed available as a string in PHP, you can tell SimplePie
758 * to parse that data string instead of a remote feed. Any set feed URL
762 * @param string $data RSS or Atom data as a string.
763 * @see set_feed_url()
765 public function set_raw_data($data)
767 $this->raw_data
= $data;
771 * Set the the default timeout for fetching remote feeds
773 * This allows you to change the maximum time the feed's server to respond
774 * and send the feed back.
777 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
779 public function set_timeout($timeout = 10)
781 $this->timeout
= (int) $timeout;
785 * Force SimplePie to use fsockopen() instead of cURL
788 * @param bool $enable Force fsockopen() to be used
790 public function force_fsockopen($enable = false)
792 $this->force_fsockopen
= (bool) $enable;
796 * Enable/disable caching in SimplePie.
798 * This option allows you to disable caching all-together in SimplePie.
799 * However, disabling the cache can lead to longer load times.
801 * @since 1.0 Preview Release
802 * @param bool $enable Enable caching
804 public function enable_cache($enable = true)
806 $this->cache
= (bool) $enable;
810 * Set the length of time (in seconds) that the contents of a feed will be
813 * @param int $seconds The feed content cache duration
815 public function set_cache_duration($seconds = 3600)
817 $this->cache_duration
= (int) $seconds;
821 * Set the length of time (in seconds) that the autodiscovered feed URL will
824 * @param int $seconds The autodiscovered feed URL cache duration.
826 public function set_autodiscovery_cache_duration($seconds = 604800)
828 $this->autodiscovery_cache_duration
= (int) $seconds;
832 * Set the file system location where the cached files should be stored
834 * @param string $location The file system location.
836 public function set_cache_location($location = './cache')
838 $this->cache_location
= (string) $location;
842 * Set whether feed items should be sorted into reverse chronological order
844 * @param bool $enable Sort as reverse chronological order.
846 public function enable_order_by_date($enable = true)
848 $this->order_by_date
= (bool) $enable;
852 * Set the character encoding used to parse the feed
854 * This overrides the encoding reported by the feed, however it will fall
855 * back to the normal encoding detection if the override fails
857 * @param string $encoding Character encoding
859 public function set_input_encoding($encoding = false)
863 $this->input_encoding
= (string) $encoding;
867 $this->input_encoding
= false;
872 * Set how much feed autodiscovery to do
874 * @see SIMPLEPIE_LOCATOR_NONE
875 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
876 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
877 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
878 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
879 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
880 * @see SIMPLEPIE_LOCATOR_ALL
881 * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
883 public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL
)
885 $this->autodiscovery
= (int) $level;
889 * Get the class registry
891 * Use this to override SimplePie's default classes
892 * @see SimplePie_Registry
893 * @return SimplePie_Registry
895 public function &get_registry()
897 return $this->registry
;
901 * Useful when you are overloading or extending SimplePie's default classes.
903 * @deprecated Use {@see get_registry()} instead
904 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
905 * @param string $class Name of custom class
906 * @return boolean True on success, false otherwise
909 * Set which class SimplePie uses for caching
911 public function set_cache_class($class = 'SimplePie_Cache')
913 return $this->registry
->register('Cache', $class, true);
917 * Set which class SimplePie uses for auto-discovery
919 public function set_locator_class($class = 'SimplePie_Locator')
921 return $this->registry
->register('Locator', $class, true);
925 * Set which class SimplePie uses for XML parsing
927 public function set_parser_class($class = 'SimplePie_Parser')
929 return $this->registry
->register('Parser', $class, true);
933 * Set which class SimplePie uses for remote file fetching
935 public function set_file_class($class = 'SimplePie_File')
937 return $this->registry
->register('File', $class, true);
941 * Set which class SimplePie uses for data sanitization
943 public function set_sanitize_class($class = 'SimplePie_Sanitize')
945 return $this->registry
->register('Sanitize', $class, true);
949 * Set which class SimplePie uses for handling feed items
951 public function set_item_class($class = 'SimplePie_Item')
953 return $this->registry
->register('Item', $class, true);
957 * Set which class SimplePie uses for handling author data
959 public function set_author_class($class = 'SimplePie_Author')
961 return $this->registry
->register('Author', $class, true);
965 * Set which class SimplePie uses for handling category data
967 public function set_category_class($class = 'SimplePie_Category')
969 return $this->registry
->register('Category', $class, true);
973 * Set which class SimplePie uses for feed enclosures
975 public function set_enclosure_class($class = 'SimplePie_Enclosure')
977 return $this->registry
->register('Enclosure', $class, true);
981 * Set which class SimplePie uses for `<media:text>` captions
983 public function set_caption_class($class = 'SimplePie_Caption')
985 return $this->registry
->register('Caption', $class, true);
989 * Set which class SimplePie uses for `<media:copyright>`
991 public function set_copyright_class($class = 'SimplePie_Copyright')
993 return $this->registry
->register('Copyright', $class, true);
997 * Set which class SimplePie uses for `<media:credit>`
999 public function set_credit_class($class = 'SimplePie_Credit')
1001 return $this->registry
->register('Credit', $class, true);
1005 * Set which class SimplePie uses for `<media:rating>`
1007 public function set_rating_class($class = 'SimplePie_Rating')
1009 return $this->registry
->register('Rating', $class, true);
1013 * Set which class SimplePie uses for `<media:restriction>`
1015 public function set_restriction_class($class = 'SimplePie_Restriction')
1017 return $this->registry
->register('Restriction', $class, true);
1021 * Set which class SimplePie uses for content-type sniffing
1023 public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1025 return $this->registry
->register('Content_Type_Sniffer', $class, true);
1029 * Set which class SimplePie uses item sources
1031 public function set_source_class($class = 'SimplePie_Source')
1033 return $this->registry
->register('Source', $class, true);
1038 * Set the user agent string
1040 * @param string $ua New user agent string.
1042 public function set_useragent($ua = SIMPLEPIE_USERAGENT
)
1044 $this->useragent
= (string) $ua;
1048 * Set callback function to create cache filename with
1050 * @param mixed $function Callback function
1052 public function set_cache_name_function($function = 'md5')
1054 if (is_callable($function))
1056 $this->cache_name_function
= $function;
1061 * Set options to make SP as fast as possible
1063 * Forgoes a substantial amount of data sanitization in favor of speed. This
1064 * turns SimplePie into a dumb parser of feeds.
1066 * @param bool $set Whether to set them or not
1068 public function set_stupidly_fast($set = false)
1072 $this->enable_order_by_date(false);
1073 $this->remove_div(false);
1074 $this->strip_comments(false);
1075 $this->strip_htmltags(false);
1076 $this->strip_attributes(false);
1077 $this->set_image_handler(false);
1082 * Set maximum number of feeds to check with autodiscovery
1084 * @param int $max Maximum number of feeds to check
1086 public function set_max_checked_feeds($max = 10)
1088 $this->max_checked_feeds
= (int) $max;
1091 public function remove_div($enable = true)
1093 $this->sanitize
->remove_div($enable);
1096 public function strip_htmltags($tags = '', $encode = null)
1100 $tags = $this->strip_htmltags
;
1102 $this->sanitize
->strip_htmltags($tags);
1103 if ($encode !== null)
1105 $this->sanitize
->encode_instead_of_strip($tags);
1109 public function encode_instead_of_strip($enable = true)
1111 $this->sanitize
->encode_instead_of_strip($enable);
1114 public function strip_attributes($attribs = '')
1116 if ($attribs === '')
1118 $attribs = $this->strip_attributes
;
1120 $this->sanitize
->strip_attributes($attribs);
1124 * Set the output encoding
1126 * Allows you to override SimplePie's output to match that of your webpage.
1127 * This is useful for times when your webpages are not being served as
1128 * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and
1129 * is similar to {@see set_input_encoding()}.
1131 * It should be noted, however, that not all character encodings can support
1132 * all characters. If your page is being served as ISO-8859-1 and you try
1133 * to display a Japanese feed, you'll likely see garbled characters.
1134 * Because of this, it is highly recommended to ensure that your webpages
1135 * are served as UTF-8.
1137 * The number of supported character encodings depends on whether your web
1138 * host supports {@link http://php.net/mbstring mbstring},
1139 * {@link http://php.net/iconv iconv}, or both. See
1140 * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
1143 * @param string $encoding
1145 public function set_output_encoding($encoding = 'UTF-8')
1147 $this->sanitize
->set_output_encoding($encoding);
1150 public function strip_comments($strip = false)
1152 $this->sanitize
->strip_comments($strip);
1156 * Set element/attribute key/value pairs of HTML attributes
1157 * containing URLs that need to be resolved relative to the feed
1159 * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
1160 * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
1164 * @param array|null $element_attribute Element/attribute key/value pairs, null for default
1166 public function set_url_replacements($element_attribute = null)
1168 $this->sanitize
->set_url_replacements($element_attribute);
1172 * Set the handler to enable the display of cached images.
1174 * @param str $page Web-accessible path to the handler_image.php file.
1175 * @param str $qs The query string that the value should be passed to.
1177 public function set_image_handler($page = false, $qs = 'i')
1179 if ($page !== false)
1181 $this->sanitize
->set_image_handler($page . '?' . $qs . '=');
1185 $this->image_handler
= '';
1190 * Set the limit for items returned per-feed with multifeeds
1192 * @param integer $limit The maximum number of items to return.
1194 public function set_item_limit($limit = 0)
1196 $this->item_limit
= (int) $limit;
1200 * Initialize the feed object
1202 * This is what makes everything happen. Period. This is where all of the
1203 * configuration options get processed, feeds are fetched, cached, and
1204 * parsed, and all of that other good stuff.
1206 * @return boolean True if successful, false otherwise
1208 public function init()
1210 // Check absolute bare minimum requirements.
1211 if (!extension_loaded('xml') ||
!extension_loaded('pcre'))
1215 // 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.
1216 elseif (!extension_loaded('xmlreader'))
1218 static $xml_is_sane = null;
1219 if ($xml_is_sane === null)
1221 $parser_check = xml_parser_create();
1222 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
1223 xml_parser_free($parser_check);
1224 $xml_is_sane = isset($values[0]['value']);
1232 if (method_exists($this->sanitize
, 'set_registry'))
1234 $this->sanitize
->set_registry($this->registry
);
1237 // Pass whatever was set with config options over to the sanitizer.
1238 // Pass the classes in for legacy support; new classes should use the registry instead
1239 $this->sanitize
->pass_cache_data($this->cache
, $this->cache_location
, $this->cache_name_function
, $this->registry
->get_class('Cache'));
1240 $this->sanitize
->pass_file_data($this->registry
->get_class('File'), $this->timeout
, $this->useragent
, $this->force_fsockopen
);
1242 if (!empty($this->multifeed_url
))
1246 $this->multifeed_objects
= array();
1247 $this->error
= array();
1248 foreach ($this->multifeed_url
as $url)
1250 $this->multifeed_objects
[$i] = clone $this;
1251 $this->multifeed_objects
[$i]->set_feed_url($url);
1252 $single_success = $this->multifeed_objects
[$i]->init();
1253 $success |
= $single_success;
1254 if (!$single_success)
1256 $this->error
[$i] = $this->multifeed_objects
[$i]->error();
1260 return (bool) $success;
1262 elseif ($this->feed_url
=== null && $this->raw_data
=== null)
1267 $this->error
= null;
1268 $this->data
= array();
1269 $this->multifeed_objects
= array();
1272 if ($this->feed_url
!== null)
1274 $parsed_feed_url = $this->registry
->call('Misc', 'parse_url', array($this->feed_url
));
1276 // Decide whether to enable caching
1277 if ($this->cache
&& $parsed_feed_url['scheme'] !== '')
1279 $cache = $this->registry
->call('Cache', 'get_handler', array($this->cache_location
, call_user_func($this->cache_name_function
, $this->feed_url
), 'spc'));
1282 // Fetch the data via SimplePie_File into $this->raw_data
1283 if (($fetched = $this->fetch_data($cache)) === true)
1287 elseif ($fetched === false) {
1291 list($headers, $sniffed) = $fetched;
1294 // Set up array of possible encodings
1295 $encodings = array();
1297 // First check to see if input has been overridden.
1298 if ($this->input_encoding
!== false)
1300 $encodings[] = $this->input_encoding
;
1303 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1304 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1306 // RFC 3023 (only applies to sniffed content)
1307 if (isset($sniffed))
1309 if (in_array($sniffed, $application_types) ||
substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1311 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1313 $encodings[] = strtoupper($charset[1]);
1315 $encodings = array_merge($encodings, $this->registry
->call('Misc', 'xml_encoding', array($this->raw_data
, &$this->registry
)));
1316 $encodings[] = 'UTF-8';
1318 elseif (in_array($sniffed, $text_types) ||
substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1320 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1322 $encodings[] = $charset[1];
1324 $encodings[] = 'US-ASCII';
1326 // Text MIME-type default
1327 elseif (substr($sniffed, 0, 5) === 'text/')
1329 $encodings[] = 'US-ASCII';
1333 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1334 $encodings = array_merge($encodings, $this->registry
->call('Misc', 'xml_encoding', array($this->raw_data
, &$this->registry
)));
1335 $encodings[] = 'UTF-8';
1336 $encodings[] = 'ISO-8859-1';
1338 // There's no point in trying an encoding twice
1339 $encodings = array_unique($encodings);
1341 // Loop through each possible encoding, till we return something, or run out of possibilities
1342 foreach ($encodings as $encoding)
1344 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1345 if ($utf8_data = $this->registry
->call('Misc', 'change_encoding', array($this->raw_data
, $encoding, 'UTF-8')))
1347 // Create new parser
1348 $parser = $this->registry
->create('Parser');
1350 // If it's parsed fine
1351 if ($parser->parse($utf8_data, 'UTF-8'))
1353 $this->data
= $parser->get_data();
1354 if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE
))
1356 $this->error
= "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1357 $this->registry
->call('Misc', 'error', array($this->error
, E_USER_NOTICE
, __FILE__
, __LINE__
));
1361 if (isset($headers))
1363 $this->data
['headers'] = $headers;
1365 $this->data
['build'] = SIMPLEPIE_BUILD
;
1367 // Cache the file if caching is enabled
1368 if ($cache && !$cache->save($this))
1370 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
);
1379 // We have an error, just set SimplePie_Misc::error to it and quit
1380 $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());
1384 $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.';
1387 $this->registry
->call('Misc', 'error', array($this->error
, E_USER_NOTICE
, __FILE__
, __LINE__
));
1393 * Fetch the data via SimplePie_File
1395 * If the data is already cached, attempt to fetch it from there instead
1396 * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
1397 * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
1399 protected function fetch_data(&$cache)
1401 // If it's enabled, use the cache
1405 $this->data
= $cache->load();
1406 if (!empty($this->data
))
1408 // If the cache is for an outdated build of SimplePie
1409 if (!isset($this->data
['build']) ||
$this->data
['build'] !== SIMPLEPIE_BUILD
)
1412 $this->data
= array();
1414 // If we've hit a collision just rerun it with caching disabled
1415 elseif (isset($this->data
['url']) && $this->data
['url'] !== $this->feed_url
)
1418 $this->data
= array();
1420 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1421 elseif (isset($this->data
['feed_url']))
1423 // If the autodiscovery cache is still valid use it.
1424 if ($cache->mtime() +
$this->autodiscovery_cache_duration
> time())
1426 // Do not need to do feed autodiscovery yet.
1427 if ($this->data
['feed_url'] !== $this->data
['url'])
1429 $this->set_feed_url($this->data
['feed_url']);
1430 return $this->init();
1434 $this->data
= array();
1437 // Check if the cache has been updated
1438 elseif ($cache->mtime() +
$this->cache_duration
< time())
1440 // If we have last-modified and/or etag set
1441 if (isset($this->data
['headers']['last-modified']) ||
isset($this->data
['headers']['etag']))
1444 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
1446 if (isset($this->data
['headers']['last-modified']))
1448 $headers['if-modified-since'] = $this->data
['headers']['last-modified'];
1450 if (isset($this->data
['headers']['etag']))
1452 $headers['if-none-match'] = $this->data
['headers']['etag'];
1455 $file = $this->registry
->create('File', array($this->feed_url
, $this->timeout
/10, 5, $headers, $this->useragent
, $this->force_fsockopen
));
1459 if ($file->status_code
=== 304)
1471 // If the cache is still valid, just return true
1474 $this->raw_data
= false;
1478 // If the cache is empty, delete it
1482 $this->data
= array();
1485 // 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.
1488 if ($this->file
instanceof SimplePie_File
&& $this->file
->url
=== $this->feed_url
)
1490 $file =& $this->file
;
1495 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
1497 $file = $this->registry
->create('File', array($this->feed_url
, $this->timeout
, 5, $headers, $this->useragent
, $this->force_fsockopen
));
1500 // If the file connection has an error, set SimplePie::error to that and quit
1501 if (!$file->success
&& !($file->method
& SIMPLEPIE_FILE_SOURCE_REMOTE
=== 0 ||
($file->status_code
=== 200 ||
$file->status_code
> 206 && $file->status_code
< 300)))
1503 $this->error
= $file->error
;
1504 return !empty($this->data
);
1507 if (!$this->force_feed
)
1509 // Check if the supplied URL is a feed, if it isn't, look for it.
1510 $locate = $this->registry
->create('Locator', array(&$file, $this->timeout
, $this->useragent
, $this->max_checked_feeds
));
1512 if (!$locate->is_feed($file))
1514 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1518 if (!($file = $locate->find($this->autodiscovery
, $this->all_discovered_feeds
)))
1520 $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.";
1521 $this->registry
->call('Misc', 'error', array($this->error
, E_USER_NOTICE
, __FILE__
, __LINE__
));
1525 catch (SimplePie_Exception
$e)
1527 // This is usually because DOMDocument doesn't exist
1528 $this->error
= $e->getMessage();
1529 $this->registry
->call('Misc', 'error', array($this->error
, E_USER_NOTICE
, $e->getFile(), $e->getLine()));
1534 $this->data
= array('url' => $this->feed_url
, 'feed_url' => $file->url
, 'build' => SIMPLEPIE_BUILD
);
1535 if (!$cache->save($this))
1537 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
);
1539 $cache = $this->registry
->call('Cache', 'get_handler', array($this->cache_location
, call_user_func($this->cache_name_function
, $file->url
), 'spc'));
1541 $this->feed_url
= $file->url
;
1546 $this->raw_data
= $file->body
;
1548 $headers = $file->headers
;
1549 $sniffer = $this->registry
->create('Content_Type_Sniffer', array(&$file));
1550 $sniffed = $sniffer->get_type();
1552 return array($headers, $sniffed);
1556 * Get the error message for the occured error
1558 * @return string|array Error message, or array of messages for multifeeds
1560 public function error()
1562 return $this->error
;
1568 * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
1569 * the data instead of printing it.
1571 * @return string|boolean Raw XML data, false if the cache is used
1573 public function get_raw_data()
1575 return $this->raw_data
;
1579 * Get the character encoding used for output
1581 * @since Preview Release
1584 public function get_encoding()
1586 return $this->sanitize
->output_encoding
;
1590 * Send the content-type header with correct encoding
1592 * This method ensures that the SimplePie-enabled page is being served with
1593 * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
1594 * and character encoding HTTP headers (character encoding determined by the
1595 * {@see set_output_encoding} config option).
1597 * This won't work properly if any content or whitespace has already been
1598 * sent to the browser, because it relies on PHP's
1599 * {@link http://php.net/header header()} function, and these are the
1600 * circumstances under which the function works.
1602 * Because it's setting these settings for the entire page (as is the nature
1603 * of HTTP headers), this should only be used once per page (again, at the
1606 * @param string $mime MIME type to serve the page as
1608 public function handle_content_type($mime = 'text/html')
1610 if (!headers_sent())
1612 $header = "Content-type: $mime;";
1613 if ($this->get_encoding())
1615 $header .= ' charset=' . $this->get_encoding();
1619 $header .= ' charset=UTF-8';
1626 * Get the type of the feed
1628 * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
1629 * using {@link http://php.net/language.operators.bitwise bitwise operators}
1631 * @since 0.8 (usage changed to using constants in 1.0)
1632 * @see SIMPLEPIE_TYPE_NONE Unknown.
1633 * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
1634 * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
1635 * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
1636 * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
1637 * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
1638 * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
1639 * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
1640 * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
1641 * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
1642 * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
1643 * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
1644 * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
1645 * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
1646 * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
1647 * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
1648 * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
1649 * @return int SIMPLEPIE_TYPE_* constant
1651 public function get_type()
1653 if (!isset($this->data
['type']))
1655 $this->data
['type'] = SIMPLEPIE_TYPE_ALL
;
1656 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed']))
1658 $this->data
['type'] &= SIMPLEPIE_TYPE_ATOM_10
;
1660 elseif (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed']))
1662 $this->data
['type'] &= SIMPLEPIE_TYPE_ATOM_03
;
1664 elseif (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF']))
1666 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10
]['channel'])
1667 ||
isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10
]['image'])
1668 ||
isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10
]['item'])
1669 ||
isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10
]['textinput']))
1671 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_10
;
1673 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090
]['channel'])
1674 ||
isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090
]['image'])
1675 ||
isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090
]['item'])
1676 ||
isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090
]['textinput']))
1678 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_090
;
1681 elseif (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss']))
1683 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_ALL
;
1684 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['attribs']['']['version']))
1686 switch (trim($this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['attribs']['']['version']))
1689 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_091
;
1690 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['skiphours']['hour'][0]['data']))
1692 switch (trim($this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['skiphours']['hour'][0]['data']))
1695 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE
;
1699 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND
;
1706 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_092
;
1710 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_093
;
1714 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_094
;
1718 $this->data
['type'] &= SIMPLEPIE_TYPE_RSS_20
;
1725 $this->data
['type'] = SIMPLEPIE_TYPE_NONE
;
1728 return $this->data
['type'];
1732 * Get the URL for the feed
1734 * May or may not be different from the URL passed to {@see set_feed_url()},
1735 * depending on whether auto-discovery was used.
1737 * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
1738 * @todo If we have a perm redirect we should return the new URL
1739 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1740 * @todo Also, |atom:link|@rel=self
1741 * @return string|null
1743 public function subscribe_url()
1745 if ($this->feed_url
!== null)
1747 return $this->sanitize($this->feed_url
, SIMPLEPIE_CONSTRUCT_IRI
);
1756 * Get data for an feed-level element
1758 * This method allows you to get access to ANY element/attribute that is a
1759 * sub-element of the opening feed tag.
1761 * The return value is an indexed array of elements matching the given
1762 * namespace and tag name. Each element has `attribs`, `data` and `child`
1763 * subkeys. For `attribs` and `child`, these contain namespace subkeys.
1764 * `attribs` then has one level of associative name => value data (where
1765 * `value` is a string) after the namespace. `child` has tag-indexed keys
1766 * after the namespace, each member of which is an indexed array matching
1771 * // This is probably a bad example because we already support
1772 * // <media:content> natively, but it shows you how to parse through
1774 * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
1775 * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
1776 * $file = $content[0]['attribs']['']['url'];
1781 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1782 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1783 * @param string $tag Tag name
1786 public function get_feed_tags($namespace, $tag)
1788 $type = $this->get_type();
1789 if ($type & SIMPLEPIE_TYPE_ATOM_10
)
1791 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0]['child'][$namespace][$tag]))
1793 return $this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0]['child'][$namespace][$tag];
1796 if ($type & SIMPLEPIE_TYPE_ATOM_03
)
1798 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0]['child'][$namespace][$tag]))
1800 return $this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0]['child'][$namespace][$tag];
1803 if ($type & SIMPLEPIE_TYPE_RSS_RDF
)
1805 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][$namespace][$tag]))
1807 return $this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['child'][$namespace][$tag];
1810 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION
)
1812 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['child'][$namespace][$tag]))
1814 return $this->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['child'][$namespace][$tag];
1821 * Get data for an channel-level element
1823 * This method allows you to get access to ANY element/attribute in the
1824 * channel/header section of the feed.
1826 * See {@see SimplePie::get_feed_tags()} for a description of the return value
1829 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1830 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1831 * @param string $tag Tag name
1834 public function get_channel_tags($namespace, $tag)
1836 $type = $this->get_type();
1837 if ($type & SIMPLEPIE_TYPE_ATOM_ALL
)
1839 if ($return = $this->get_feed_tags($namespace, $tag))
1844 if ($type & SIMPLEPIE_TYPE_RSS_10
)
1846 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'channel'))
1848 if (isset($channel[0]['child'][$namespace][$tag]))
1850 return $channel[0]['child'][$namespace][$tag];
1854 if ($type & SIMPLEPIE_TYPE_RSS_090
)
1856 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'channel'))
1858 if (isset($channel[0]['child'][$namespace][$tag]))
1860 return $channel[0]['child'][$namespace][$tag];
1864 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION
)
1866 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'channel'))
1868 if (isset($channel[0]['child'][$namespace][$tag]))
1870 return $channel[0]['child'][$namespace][$tag];
1878 * Get data for an channel-level element
1880 * This method allows you to get access to ANY element/attribute in the
1881 * image/logo section of the feed.
1883 * See {@see SimplePie::get_feed_tags()} for a description of the return value
1886 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1887 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1888 * @param string $tag Tag name
1891 public function get_image_tags($namespace, $tag)
1893 $type = $this->get_type();
1894 if ($type & SIMPLEPIE_TYPE_RSS_10
)
1896 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'image'))
1898 if (isset($image[0]['child'][$namespace][$tag]))
1900 return $image[0]['child'][$namespace][$tag];
1904 if ($type & SIMPLEPIE_TYPE_RSS_090
)
1906 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'image'))
1908 if (isset($image[0]['child'][$namespace][$tag]))
1910 return $image[0]['child'][$namespace][$tag];
1914 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION
)
1916 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'image'))
1918 if (isset($image[0]['child'][$namespace][$tag]))
1920 return $image[0]['child'][$namespace][$tag];
1928 * Get the base URL value from the feed
1930 * Uses `<xml:base>` if available, otherwise uses the first link in the
1931 * feed, or failing that, the URL of the feed itself.
1934 * @see subscribe_url
1936 * @param array $element
1939 public function get_base($element = array())
1941 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION
) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
1943 return $element['xml_base'];
1945 elseif ($this->get_link() !== null)
1947 return $this->get_link();
1951 return $this->subscribe_url();
1956 * Sanitize feed data
1959 * @see SimplePie_Sanitize::sanitize()
1960 * @param string $data Data to sanitize
1961 * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
1962 * @param string $base Base URL to resolve URLs against
1963 * @return string Sanitized data
1965 public function sanitize($data, $type, $base = '')
1967 return $this->sanitize
->sanitize($data, $type, $base);
1971 * Get the title of the feed
1973 * Uses `<atom:title>`, `<title>` or `<dc:title>`
1975 * @since 1.0 (previously called `get_feed_title` since 0.8)
1976 * @return string|null
1978 public function get_title()
1980 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'title'))
1982 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
1984 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'title'))
1986 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
1988 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'title'))
1990 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
1992 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'title'))
1994 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
1996 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'title'))
1998 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
2000 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'title'))
2002 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2004 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'title'))
2006 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2015 * Get a category for the feed
2018 * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
2019 * @return SimplePie_Category|null
2021 public function get_category($key = 0)
2023 $categories = $this->get_categories();
2024 if (isset($categories[$key]))
2026 return $categories[$key];
2035 * Get all categories for the feed
2037 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
2040 * @return array|null List of {@see SimplePie_Category} objects
2042 public function get_categories()
2044 $categories = array();
2046 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'category') as $category)
2051 if (isset($category['attribs']['']['term']))
2053 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT
);
2055 if (isset($category['attribs']['']['scheme']))
2057 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
2059 if (isset($category['attribs']['']['label']))
2061 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
2063 $categories[] = $this->registry
->create('Category', array($term, $scheme, $label));
2065 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'category') as $category)
2067 // This is really the label, but keep this as the term also for BC.
2068 // Label will also work on retrieving because that falls back to term.
2069 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2070 if (isset($category['attribs']['']['domain']))
2072 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT
);
2078 $categories[] = $this->registry
->create('Category', array($term, $scheme, null));
2080 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'subject') as $category)
2082 $categories[] = $this->registry
->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
2084 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'subject') as $category)
2086 $categories[] = $this->registry
->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
2089 if (!empty($categories))
2091 return array_unique($categories);
2100 * Get an author for the feed
2103 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
2104 * @return SimplePie_Author|null
2106 public function get_author($key = 0)
2108 $authors = $this->get_authors();
2109 if (isset($authors[$key]))
2111 return $authors[$key];
2120 * Get all authors for the feed
2122 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
2125 * @return array|null List of {@see SimplePie_Author} objects
2127 public function get_authors()
2130 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'author') as $author)
2135 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data']))
2137 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2139 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['uri'][0]['data']))
2141 $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]));
2143 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data']))
2145 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2147 if ($name !== null ||
$email !== null ||
$uri !== null)
2149 $authors[] = $this->registry
->create('Author', array($name, $uri, $email));
2152 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'author'))
2157 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data']))
2159 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2161 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['url'][0]['data']))
2163 $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]));
2165 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data']))
2167 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2169 if ($name !== null ||
$email !== null ||
$url !== null)
2171 $authors[] = $this->registry
->create('Author', array($name, $url, $email));
2174 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'creator') as $author)
2176 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
2178 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'creator') as $author)
2180 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
2182 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'author') as $author)
2184 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
2187 if (!empty($authors))
2189 return array_unique($authors);
2198 * Get a contributor for the feed
2201 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
2202 * @return SimplePie_Author|null
2204 public function get_contributor($key = 0)
2206 $contributors = $this->get_contributors();
2207 if (isset($contributors[$key]))
2209 return $contributors[$key];
2218 * Get all contributors for the feed
2220 * Uses `<atom:contributor>`
2223 * @return array|null List of {@see SimplePie_Author} objects
2225 public function get_contributors()
2227 $contributors = array();
2228 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'contributor') as $contributor)
2233 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data']))
2235 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2237 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['uri'][0]['data']))
2239 $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]));
2241 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data']))
2243 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2245 if ($name !== null ||
$email !== null ||
$uri !== null)
2247 $contributors[] = $this->registry
->create('Author', array($name, $uri, $email));
2250 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'contributor') as $contributor)
2255 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data']))
2257 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2259 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['url'][0]['data']))
2261 $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]));
2263 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data']))
2265 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2267 if ($name !== null ||
$email !== null ||
$url !== null)
2269 $contributors[] = $this->registry
->create('Author', array($name, $url, $email));
2273 if (!empty($contributors))
2275 return array_unique($contributors);
2284 * Get a single link for the feed
2286 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2287 * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
2288 * @param string $rel The relationship of the link to return
2289 * @return string|null Link URL
2291 public function get_link($key = 0, $rel = 'alternate')
2293 $links = $this->get_links($rel);
2294 if (isset($links[$key]))
2296 return $links[$key];
2305 * Get the permalink for the item
2307 * Returns the first link available with a relationship of "alternate".
2308 * Identical to {@see get_link()} with key 0
2311 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2312 * @internal Added for parity between the parent-level and the item/entry-level.
2313 * @return string|null Link URL
2315 public function get_permalink()
2317 return $this->get_link(0);
2321 * Get all links for the feed
2323 * Uses `<atom:link>` or `<link>`
2326 * @param string $rel The relationship of links to return
2327 * @return array|null Links found for the feed (strings)
2329 public function get_links($rel = 'alternate')
2331 if (!isset($this->data
['links']))
2333 $this->data
['links'] = array();
2334 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'link'))
2336 foreach ($links as $link)
2338 if (isset($link['attribs']['']['href']))
2340 $link_rel = (isset($link['attribs']['']['rel'])) ?
$link['attribs']['']['rel'] : 'alternate';
2341 $this->data
['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
2345 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'link'))
2347 foreach ($links as $link)
2349 if (isset($link['attribs']['']['href']))
2351 $link_rel = (isset($link['attribs']['']['rel'])) ?
$link['attribs']['']['rel'] : 'alternate';
2352 $this->data
['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
2357 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'link'))
2359 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
2361 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'link'))
2363 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
2365 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'link'))
2367 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
2370 $keys = array_keys($this->data
['links']);
2371 foreach ($keys as $key)
2373 if ($this->registry
->call('Misc', 'is_isegment_nz_nc', array($key)))
2375 if (isset($this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key]))
2377 $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key] = array_merge($this->data
['links'][$key], $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key]);
2378 $this->data
['links'][$key] =& $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key];
2382 $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key] =& $this->data
['links'][$key];
2385 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
)
2387 $this->data
['links'][substr($key, 41)] =& $this->data
['links'][$key];
2389 $this->data
['links'][$key] = array_unique($this->data
['links'][$key]);
2393 if (isset($this->data
['links'][$rel]))
2395 return $this->data
['links'][$rel];
2403 public function get_all_discovered_feeds()
2405 return $this->all_discovered_feeds
;
2409 * Get the content for the item
2411 * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
2412 * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
2414 * @since 1.0 (previously called `get_feed_description()` since 0.8)
2415 * @return string|null
2417 public function get_description()
2419 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'subtitle'))
2421 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2423 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'tagline'))
2425 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2427 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'description'))
2429 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
2431 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'description'))
2433 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
2435 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'description'))
2437 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
2439 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'description'))
2441 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2443 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'description'))
2445 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2447 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'summary'))
2449 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
2451 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'subtitle'))
2453 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
2462 * Get the copyright info for the feed
2464 * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
2466 * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
2467 * @return string|null
2469 public function get_copyright()
2471 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'rights'))
2473 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2475 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'copyright'))
2477 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2479 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'copyright'))
2481 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2483 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'rights'))
2485 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2487 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'rights'))
2489 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2498 * Get the language for the feed
2500 * Uses `<language>`, `<dc:language>`, or @xml_lang
2502 * @since 1.0 (previously called `get_feed_language()` since 0.8)
2503 * @return string|null
2505 public function get_language()
2507 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'language'))
2509 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2511 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'language'))
2513 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2515 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'language'))
2517 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2519 elseif (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0]['xml_lang']))
2521 return $this->sanitize($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
2523 elseif (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0]['xml_lang']))
2525 return $this->sanitize($this->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
2527 elseif (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['xml_lang']))
2529 return $this->sanitize($this->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
2531 elseif (isset($this->data
['headers']['content-language']))
2533 return $this->sanitize($this->data
['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT
);
2542 * Get the latitude coordinates for the item
2544 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2546 * Uses `<geo:lat>` or `<georss:point>`
2549 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2550 * @link http://www.georss.org/ GeoRSS
2551 * @return string|null
2553 public function get_latitude()
2556 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'lat'))
2558 return (float) $return[0]['data'];
2560 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))
2562 return (float) $match[1];
2571 * Get the longitude coordinates for the feed
2573 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2575 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2578 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2579 * @link http://www.georss.org/ GeoRSS
2580 * @return string|null
2582 public function get_longitude()
2584 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'long'))
2586 return (float) $return[0]['data'];
2588 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'lon'))
2590 return (float) $return[0]['data'];
2592 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))
2594 return (float) $match[2];
2603 * Get the feed logo's title
2605 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
2607 * Uses `<image><title>` or `<image><dc:title>`
2609 * @return string|null
2611 public function get_image_title()
2613 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'title'))
2615 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2617 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'title'))
2619 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2621 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'title'))
2623 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2625 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'title'))
2627 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2629 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'title'))
2631 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
2640 * Get the feed logo's URL
2642 * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
2643 * have a "feed logo" URL. This points directly to the image itself.
2645 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2646 * `<image><title>` or `<image><dc:title>`
2648 * @return string|null
2650 public function get_image_url()
2652 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'image'))
2654 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
);
2656 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'logo'))
2658 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2660 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'icon'))
2662 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2664 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'url'))
2666 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2668 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'url'))
2670 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2672 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'url'))
2674 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2683 * Get the feed logo's link
2685 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
2686 * points to a human-readable page that the image should link to.
2688 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2689 * `<image><title>` or `<image><dc:title>`
2691 * @return string|null
2693 public function get_image_link()
2695 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'link'))
2697 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2699 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'link'))
2701 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2703 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'link'))
2705 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
2714 * Get the feed logo's link
2716 * RSS 2.0 feeds are allowed to have a "feed logo" width.
2718 * Uses `<image><width>` or defaults to 88.0 if no width is specified and
2719 * the feed is an RSS 2.0 feed.
2721 * @return int|float|null
2723 public function get_image_width()
2725 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'width'))
2727 return round($return[0]['data']);
2729 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION
&& $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'url'))
2740 * Get the feed logo's height
2742 * RSS 2.0 feeds are allowed to have a "feed logo" height.
2744 * Uses `<image><height>` or defaults to 31.0 if no height is specified and
2745 * the feed is an RSS 2.0 feed.
2747 * @return int|float|null
2749 public function get_image_height()
2751 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'height'))
2753 return round($return[0]['data']);
2755 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION
&& $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'url'))
2766 * Get the number of items in the feed
2768 * This is well-suited for {@link http://php.net/for for()} loops with
2771 * @param int $max Maximum value to return. 0 for no limit
2772 * @return int Number of items in the feed
2774 public function get_item_quantity($max = 0)
2777 $qty = count($this->get_items());
2784 return ($qty > $max) ?
$max : $qty;
2789 * Get a single item from the feed
2791 * This is better suited for {@link http://php.net/for for()} loops, whereas
2792 * {@see get_items()} is better suited for
2793 * {@link http://php.net/foreach foreach()} loops.
2795 * @see get_item_quantity()
2797 * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1
2798 * @return SimplePie_Item|null
2800 public function get_item($key = 0)
2802 $items = $this->get_items();
2803 if (isset($items[$key]))
2805 return $items[$key];
2814 * Get all items from the feed
2816 * This is better suited for {@link http://php.net/for for()} loops, whereas
2817 * {@see get_items()} is better suited for
2818 * {@link http://php.net/foreach foreach()} loops.
2820 * @see get_item_quantity
2822 * @param int $start Index to start at
2823 * @param int $end Number of items to return. 0 for all items after `$start`
2824 * @return array|null List of {@see SimplePie_Item} objects
2826 public function get_items($start = 0, $end = 0)
2828 if (!isset($this->data
['items']))
2830 if (!empty($this->multifeed_objects
))
2832 $this->data
['items'] = SimplePie
::merge_items($this->multifeed_objects
, $start, $end, $this->item_limit
);
2836 $this->data
['items'] = array();
2837 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'entry'))
2839 $keys = array_keys($items);
2840 foreach ($keys as $key)
2842 $this->data
['items'][] = $this->registry
->create('Item', array($this, $items[$key]));
2845 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'entry'))
2847 $keys = array_keys($items);
2848 foreach ($keys as $key)
2850 $this->data
['items'][] = $this->registry
->create('Item', array($this, $items[$key]));
2853 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'item'))
2855 $keys = array_keys($items);
2856 foreach ($keys as $key)
2858 $this->data
['items'][] = $this->registry
->create('Item', array($this, $items[$key]));
2861 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'item'))
2863 $keys = array_keys($items);
2864 foreach ($keys as $key)
2866 $this->data
['items'][] = $this->registry
->create('Item', array($this, $items[$key]));
2869 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'item'))
2871 $keys = array_keys($items);
2872 foreach ($keys as $key)
2874 $this->data
['items'][] = $this->registry
->create('Item', array($this, $items[$key]));
2880 if (!empty($this->data
['items']))
2882 // If we want to order it by date, check if all items have a date, and then sort it
2883 if ($this->order_by_date
&& empty($this->multifeed_objects
))
2885 if (!isset($this->data
['ordered_items']))
2888 foreach ($this->data
['items'] as $item)
2890 if (!$item->get_date('U'))
2897 $this->data
['ordered_items'] = $this->data
['items'];
2900 usort($this->data
['ordered_items'], array(get_class($this), 'sort_items'));
2903 $items = $this->data
['ordered_items'];
2907 $items = $this->data
['items'];
2910 // Slice the data as desired
2913 return array_slice($items, $start);
2917 return array_slice($items, $start, $end);
2927 * Set the favicon handler
2929 * @deprecated Use your own favicon handling instead
2931 public function set_favicon_handler($page = false, $qs = 'i')
2933 $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED
: E_USER_WARNING
;
2934 trigger_error('Favicon handling has been removed, please use your own handling', $level);
2939 * Get the favicon for the current feed
2941 * @deprecated Use your own favicon handling instead
2943 public function get_favicon()
2945 $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED
: E_USER_WARNING
;
2946 trigger_error('Favicon handling has been removed, please use your own handling', $level);
2948 if (($url = $this->get_link()) !== null)
2950 return 'http://g.etfv.co/' . urlencode($url);
2957 * Magic method handler
2959 * @param string $method Method name
2960 * @param array $args Arguments to the method
2963 public function __call($method, $args)
2965 if (strpos($method, 'subscribe_') === 0)
2967 $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED
: E_USER_WARNING
;
2968 trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
2971 if ($method === 'enable_xml_dump')
2973 $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED
: E_USER_WARNING
;
2974 trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
2978 $class = get_class($this);
2979 $trace = debug_backtrace();
2980 $file = $trace[0]['file'];
2981 $line = $trace[0]['line'];
2982 trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR
);
2986 * Sorting callback for items
2989 * @param SimplePie $a
2990 * @param SimplePie $b
2993 public static function sort_items($a, $b)
2995 return $a->get_date('U') <= $b->get_date('U');
2999 * Merge items from several feeds into one
3001 * If you're merging multiple feeds together, they need to all have dates
3002 * for the items or else SimplePie will refuse to sort them.
3004 * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
3005 * @param array $urls List of SimplePie feed objects to merge
3006 * @param int $start Starting item
3007 * @param int $end Number of items to return
3008 * @param int $limit Maximum number of items per feed
3011 public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3013 if (is_array($urls) && sizeof($urls) > 0)
3016 foreach ($urls as $arg)
3018 if ($arg instanceof SimplePie
)
3020 $items = array_merge($items, $arg->get_items(0, $limit));
3024 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING
);
3029 foreach ($items as $item)
3031 if (!$item->get_date('U'))
3040 usort($items, array(get_class($urls[0]), 'sort_items'));
3045 return array_slice($items, $start);
3049 return array_slice($items, $start, $end);
3054 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING
);
3061 * Manages all author-related data
3063 * Used by {@see SimplePie_Item::get_author()} and {@see SimplePie::get_authors()}
3065 * This class can be overloaded with {@see SimplePie::set_author_class()}
3067 * @package SimplePie
3070 class SimplePie_Author
3089 * Author's email address
3097 * Constructor, used to input the data
3099 * @param string $name
3100 * @param string $link
3101 * @param string $email
3103 public function __construct($name = null, $link = null, $email = null)
3105 $this->name
= $name;
3106 $this->link
= $link;
3107 $this->email
= $email;
3111 * String-ified version
3115 public function __toString()
3117 // There is no $this->data here
3118 return md5(serialize($this));
3124 * @return string|null
3126 public function get_name()
3128 if ($this->name
!== null)
3141 * @return string|null
3143 public function get_link()
3145 if ($this->link
!== null)
3156 * Author's email address
3158 * @return string|null
3160 public function get_email()
3162 if ($this->email
!== null)
3164 return $this->email
;
3174 * Base for cache objects
3176 * Classes to be used with {@see SimplePie_Cache::register()} are expected
3177 * to implement this interface.
3179 * @package SimplePie
3180 * @subpackage Caching
3182 interface SimplePie_Cache_Base
3189 const TYPE_FEED
= 'spc';
3196 const TYPE_IMAGE
= 'spi';
3199 * Create a new cache object
3201 * @param string $location Location string (from SimplePie::$cache_location)
3202 * @param string $name Unique ID for the cache
3203 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3205 public function __construct($location, $name, $type);
3208 * Save data to the cache
3210 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3211 * @return bool Successfulness
3213 public function save($data);
3216 * Retrieve the data saved to the cache
3218 * @return array Data for SimplePie::$data
3220 public function load();
3223 * Retrieve the last modified time for the cache
3225 * @return int Timestamp
3227 public function mtime();
3230 * Set the last modified time to the current time
3232 * @return bool Success status
3234 public function touch();
3239 * @return bool Success status
3241 public function unlink();
3245 * Base class for database-based caches
3247 * @package SimplePie
3248 * @subpackage Caching
3250 abstract class SimplePie_Cache_DB
implements SimplePie_Cache_Base
3253 * Helper for database conversion
3255 * Converts a given {@see SimplePie} object into data to be stored
3257 * @param SimplePie $data
3258 * @return array First item is the serialized data for storage, second item is the unique ID for this item
3260 protected static function prepare_simplepie_object_for_cache($data)
3262 $items = $data->get_items();
3263 $items_by_id = array();
3267 foreach ($items as $item)
3269 $items_by_id[$item->get_id()] = $item;
3272 if (count($items_by_id) !== count($items))
3274 $items_by_id = array();
3275 foreach ($items as $item)
3277 $items_by_id[$item->get_id(true)] = $item;
3281 if (isset($data->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0]))
3283 $channel =& $data->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0];
3285 elseif (isset($data->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0]))
3287 $channel =& $data->data
['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0];
3289 elseif (isset($data->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]))
3291 $channel =& $data->data
['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0];
3293 elseif (isset($data->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['channel'][0]))
3295 $channel =& $data->data
['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['channel'][0];
3302 if ($channel !== null)
3304 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['entry']))
3306 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['entry']);
3308 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['entry']))
3310 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['entry']);
3312 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10
]['item']))
3314 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10
]['item']);
3316 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090
]['item']))
3318 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090
]['item']);
3320 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['item']))
3322 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['item']);
3325 if (isset($data->data
['items']))
3327 unset($data->data
['items']);
3329 if (isset($data->data
['ordered_items']))
3331 unset($data->data
['ordered_items']);
3334 return array(serialize($data->data
), $items_by_id);
3339 * Caches data to the filesystem
3341 * @package SimplePie
3342 * @subpackage Caching
3344 class SimplePie_Cache_File
implements SimplePie_Cache_Base
3349 * @see SimplePie::$cache_location
3352 protected $location;
3359 protected $filename;
3366 protected $extension;
3376 * Create a new cache object
3378 * @param string $location Location string (from SimplePie::$cache_location)
3379 * @param string $name Unique ID for the cache
3380 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3382 public function __construct($location, $name, $type)
3384 $this->location
= $location;
3385 $this->filename
= $name;
3386 $this->extension
= $type;
3387 $this->name
= "$this->location/$this->filename.$this->extension";
3391 * Save data to the cache
3393 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3394 * @return bool Successfulness
3396 public function save($data)
3398 if (file_exists($this->name
) && is_writeable($this->name
) ||
file_exists($this->location
) && is_writeable($this->location
))
3400 if ($data instanceof SimplePie
)
3402 $data = $data->data
;
3405 $data = serialize($data);
3406 return (bool) file_put_contents($this->name
, $data);
3412 * Retrieve the data saved to the cache
3414 * @return array Data for SimplePie::$data
3416 public function load()
3418 if (file_exists($this->name
) && is_readable($this->name
))
3420 return unserialize(file_get_contents($this->name
));
3426 * Retrieve the last modified time for the cache
3428 * @return int Timestamp
3430 public function mtime()
3432 if (file_exists($this->name
))
3434 return filemtime($this->name
);
3440 * Set the last modified time to the current time
3442 * @return bool Success status
3444 public function touch()
3446 if (file_exists($this->name
))
3448 return touch($this->name
);
3456 * @return bool Success status
3458 public function unlink()
3460 if (file_exists($this->name
))
3462 return unlink($this->name
);
3469 * Caches data to memcache
3471 * Registered for URLs with the "memcache" protocol
3473 * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will
3474 * connect to memcache on `localhost` on port 11211. All tables will be
3475 * prefixed with `sp_` and data will expire after 3600 seconds
3477 * @package SimplePie
3478 * @subpackage Caching
3481 class SimplePie_Cache_Memcache
implements SimplePie_Cache_Base
3505 * Create a new cache object
3507 * @param string $location Location string (from SimplePie::$cache_location)
3508 * @param string $name Unique ID for the cache
3509 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3511 public function __construct($location, $name, $type)
3513 $this->options
= array(
3514 'host' => '127.0.0.1',
3517 'timeout' => 3600, // one hour
3518 'prefix' => 'simplepie_',
3521 $parsed = SimplePie_Cache
::parse_URL($location);
3522 $this->options
['host'] = empty($parsed['host']) ?
$this->options
['host'] : $parsed['host'];
3523 $this->options
['port'] = empty($parsed['port']) ?
$this->options
['port'] : $parsed['port'];
3524 $this->options
['extras'] = array_merge($this->options
['extras'], $parsed['extras']);
3525 $this->name
= $this->options
['extras']['prefix'] . md5("$name:$type");
3527 $this->cache
= new Memcache();
3528 $this->cache
->addServer($this->options
['host'], (int) $this->options
['port']);
3532 * Save data to the cache
3534 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3535 * @return bool Successfulness
3537 public function save($data)
3539 if ($data instanceof SimplePie
)
3541 $data = $data->data
;
3543 return $this->cache
->set($this->name
, serialize($data), MEMCACHE_COMPRESSED
, (int) $this->options
['extras']['timeout']);
3547 * Retrieve the data saved to the cache
3549 * @return array Data for SimplePie::$data
3551 public function load()
3553 $data = $this->cache
->get($this->name
);
3555 if ($data !== false)
3557 return unserialize($data);
3563 * Retrieve the last modified time for the cache
3565 * @return int Timestamp
3567 public function mtime()
3569 $data = $this->cache
->get($this->name
);
3571 if ($data !== false)
3573 // essentially ignore the mtime because Memcache expires on it's own
3581 * Set the last modified time to the current time
3583 * @return bool Success status
3585 public function touch()
3587 $data = $this->cache
->get($this->name
);
3589 if ($data !== false)
3591 return $this->cache
->set($this->name
, $data, MEMCACHE_COMPRESSED
, (int) $this->duration
);
3600 * @return bool Success status
3602 public function unlink()
3604 return $this->cache
->delete($this->name
, 0);
3609 * Caches data to a MySQL database
3611 * Registered for URLs with the "mysql" protocol
3613 * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will
3614 * connect to the `mydb` database on `localhost` on port 3306, with the user
3615 * `root` and the password `password`. All tables will be prefixed with `sp_`
3617 * @package SimplePie
3618 * @subpackage Caching
3620 class SimplePie_Cache_MySQL
extends SimplePie_Cache_DB
3644 * Create a new cache object
3646 * @param string $location Location string (from SimplePie::$cache_location)
3647 * @param string $name Unique ID for the cache
3648 * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
3650 public function __construct($location, $name, $type)
3652 $this->options
= array(
3655 'host' => '127.0.0.1',
3662 $this->options
= array_merge_recursive($this->options
, SimplePie_Cache
::parse_URL($location));
3664 // Path is prefixed with a "/"
3665 $this->options
['dbname'] = substr($this->options
['path'], 1);
3669 $this->mysql
= new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options
['user'], $this->options
['pass'], array(PDO
::MYSQL_ATTR_INIT_COMMAND
=> 'SET NAMES utf8'));
3671 catch (PDOException
$e)
3673 $this->mysql
= null;
3677 $this->id
= $name . $type;
3679 if (!$query = $this->mysql
->query('SHOW TABLES'))
3681 $this->mysql
= null;
3686 while ($row = $query->fetchColumn())
3691 if (!in_array($this->options
['extras']['prefix'] . 'cache_data', $db))
3693 $query = $this->mysql
->exec('CREATE TABLE `' . $this->options
['extras']['prefix'] . '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)))');
3694 if ($query === false)
3696 $this->mysql
= null;
3700 if (!in_array($this->options
['extras']['prefix'] . 'items', $db))
3702 $query = $this->mysql
->exec('CREATE TABLE `' . $this->options
['extras']['prefix'] . '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)))');
3703 if ($query === false)
3705 $this->mysql
= null;
3711 * Save data to the cache
3713 * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
3714 * @return bool Successfulness
3716 public function save($data)
3718 if ($this->mysql
=== null)
3723 if ($data instanceof SimplePie
)
3725 $data = clone $data;
3727 $prepared = self
::prepare_simplepie_object_for_cache($data);
3729 $query = $this->mysql
->prepare('SELECT COUNT(*) FROM `' . $this->options
['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
3730 $query->bindValue(':feed', $this->id
);
3731 if ($query->execute())
3733 if ($query->fetchColumn() > 0)
3735 $items = count($prepared[1]);
3738 $sql = 'UPDATE `' . $this->options
['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';
3739 $query = $this->mysql
->prepare($sql);
3740 $query->bindValue(':items', $items);
3744 $sql = 'UPDATE `' . $this->options
['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';
3745 $query = $this->mysql
->prepare($sql);
3748 $query->bindValue(':data', $prepared[0]);
3749 $query->bindValue(':time', time());
3750 $query->bindValue(':feed', $this->id
);
3751 if (!$query->execute())
3758 $query = $this->mysql
->prepare('INSERT INTO `' . $this->options
['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');
3759 $query->bindValue(':feed', $this->id
);
3760 $query->bindValue(':count', count($prepared[1]));
3761 $query->bindValue(':data', $prepared[0]);
3762 $query->bindValue(':time', time());
3763 if (!$query->execute())
3769 $ids = array_keys($prepared[1]);
3772 foreach ($ids as $id)
3774 $database_ids[] = $this->mysql
->quote($id);
3777 $query = $this->mysql
->prepare('SELECT `id` FROM `' . $this->options
['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');
3778 $query->bindValue(':feed', $this->id
);
3780 if ($query->execute())
3782 $existing_ids = array();
3783 while ($row = $query->fetchColumn())
3785 $existing_ids[] = $row;
3788 $new_ids = array_diff($ids, $existing_ids);
3790 foreach ($new_ids as $new_id)
3792 if (!($date = $prepared[1][$new_id]->get_date('U')))
3797 $query = $this->mysql
->prepare('INSERT INTO `' . $this->options
['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');
3798 $query->bindValue(':feed', $this->id
);
3799 $query->bindValue(':id', $new_id);
3800 $query->bindValue(':data', serialize($prepared[1][$new_id]->data
));
3801 $query->bindValue(':date', $date);
3802 if (!$query->execute())
3818 $query = $this->mysql
->prepare('SELECT `id` FROM `' . $this->options
['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
3819 $query->bindValue(':feed', $this->id
);
3820 if ($query->execute())
3822 if ($query->rowCount() > 0)
3824 $query = $this->mysql
->prepare('UPDATE `' . $this->options
['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');
3825 $query->bindValue(':data', serialize($data));
3826 $query->bindValue(':time', time());
3827 $query->bindValue(':feed', $this->id
);
3828 if ($this->execute())
3835 $query = $this->mysql
->prepare('INSERT INTO `' . $this->options
['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');
3836 $query->bindValue(':id', $this->id
);
3837 $query->bindValue(':data', serialize($data));
3838 $query->bindValue(':time', time());
3839 if ($query->execute())
3850 * Retrieve the data saved to the cache
3852 * @return array Data for SimplePie::$data
3854 public function load()
3856 if ($this->mysql
=== null)
3861 $query = $this->mysql
->prepare('SELECT `items`, `data` FROM `' . $this->options
['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
3862 $query->bindValue(':id', $this->id
);
3863 if ($query->execute() && ($row = $query->fetch()))
3865 $data = unserialize($row[1]);
3867 if (isset($this->options
['items'][0]))
3869 $items = (int) $this->options
['items'][0];
3873 $items = (int) $row[0];
3878 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0]))
3880 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['feed'][0];
3882 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0]))
3884 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['feed'][0];
3886 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0]))
3888 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF
]['RDF'][0];
3890 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0]))
3892 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20
]['rss'][0];
3901 $sql = 'SELECT `data` FROM `' . $this->options
['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';
3904 $sql .= ' LIMIT ' . $items;
3907 $query = $this->mysql
->prepare($sql);
3908 $query->bindValue(':feed', $this->id
);
3909 if ($query->execute())
3911 while ($row = $query->fetchColumn())
3913 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['entry'][] = unserialize($row);
3928 * Retrieve the last modified time for the cache
3930 * @return int Timestamp
3932 public function mtime()
3934 if ($this->mysql
=== null)
3939 $query = $this->mysql
->prepare('SELECT `mtime` FROM `' . $this->options
['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
3940 $query->bindValue(':id', $this->id
);
3941 if ($query->execute() && ($time = $query->fetchColumn()))
3952 * Set the last modified time to the current time
3954 * @return bool Success status
3956 public function touch()
3958 if ($this->mysql
=== null)
3963 $query = $this->mysql
->prepare('UPDATE `' . $this->options
['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');
3964 $query->bindValue(':time', time());
3965 $query->bindValue(':id', $this->id
);
3966 if ($query->execute() && $query->rowCount() > 0)
3979 * @return bool Success status
3981 public function unlink()
3983 if ($this->mysql
=== null)
3988 $query = $this->mysql
->prepare('DELETE FROM `' . $this->options
['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
3989 $query->bindValue(':id', $this->id
);
3990 $query2 = $this->mysql
->prepare('DELETE FROM `' . $this->options
['extras']['prefix'] . 'items` WHERE `feed_id` = :id');
3991 $query2->bindValue(':id', $this->id
);
3992 if ($query->execute() && $query2->execute())
4004 * Used to create cache objects
4006 * This class can be overloaded with {@see SimplePie::set_cache_class()},
4007 * although the preferred way is to create your own handler
4008 * via {@see register()}
4010 * @package SimplePie
4011 * @subpackage Caching
4013 class SimplePie_Cache
4016 * Cache handler classes
4018 * These receive 3 parameters to their constructor, as documented in
4022 protected static $handlers = array(
4023 'mysql' => 'SimplePie_Cache_MySQL',
4024 'memcache' => 'SimplePie_Cache_Memcache',
4028 * Don't call the constructor. Please.
4030 private function __construct() { }
4033 * Create a new SimplePie_Cache object
4035 * @param string $location URL location (scheme is used to determine handler)
4036 * @param string $filename Unique identifier for cache object
4037 * @param string $extension 'spi' or 'spc'
4038 * @return SimplePie_Cache_Base Type of object depends on scheme of `$location`
4040 public static function get_handler($location, $filename, $extension)
4042 $type = explode(':', $location, 2);
4044 if (!empty(self
::$handlers[$type]))
4046 $class = self
::$handlers[$type];
4047 return new $class($location, $filename, $extension);
4050 return new SimplePie_Cache_File($location, $filename, $extension);
4054 * Create a new SimplePie_Cache object
4056 * @deprecated Use {@see get_handler} instead
4058 public function create($location, $filename, $extension)
4060 trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED
);
4061 return self
::get_handler($location, $filename, $extension);
4065 * Register a handler
4067 * @param string $type DSN type to register for
4068 * @param string $class Name of handler class. Must implement SimplePie_Cache_Base
4070 public static function register($type, $class)
4072 self
::$handlers[$type] = $class;
4076 * Parse a URL into an array
4078 * @param string $url
4081 public static function parse_URL($url)
4083 $params = parse_url($url);
4084 $params['extras'] = array();
4085 if (isset($params['query']))
4087 parse_str($params['query'], $params['extras']);
4094 * Handles `<media:text>` captions as defined in Media RSS.
4096 * Used by {@see SimplePie_Enclosure::get_caption()} and {@see SimplePie_Enclosure::get_captions()}
4098 * This class can be overloaded with {@see SimplePie::set_caption_class()}
4100 * @package SimplePie
4103 class SimplePie_Caption
4117 * @see get_language()
4125 * @see get_starttime()
4133 * @see get_endtime()
4146 * Constructor, used to input the data
4148 * For documentation on all the parameters, see the corresponding
4149 * properties and their accessors
4151 public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
4153 $this->type
= $type;
4154 $this->lang
= $lang;
4155 $this->startTime
= $startTime;
4156 $this->endTime
= $endTime;
4157 $this->text
= $text;
4161 * String-ified version
4165 public function __toString()
4167 // There is no $this->data here
4168 return md5(serialize($this));
4174 * @return string|null Time in the format 'hh:mm:ss.SSS'
4176 public function get_endtime()
4178 if ($this->endTime
!== null)
4180 return $this->endTime
;
4191 * @link http://tools.ietf.org/html/rfc3066
4192 * @return string|null Language code as per RFC 3066
4194 public function get_language()
4196 if ($this->lang
!== null)
4207 * Get the start time
4209 * @return string|null Time in the format 'hh:mm:ss.SSS'
4211 public function get_starttime()
4213 if ($this->startTime
!== null)
4215 return $this->startTime
;
4224 * Get the text of the caption
4226 * @return string|null
4228 public function get_text()
4230 if ($this->text
!== null)
4241 * Get the content type (not MIME type)
4243 * @return string|null Either 'text' or 'html'
4245 public function get_type()
4247 if ($this->type
!== null)
4259 * Manages all category-related data
4261 * Used by {@see SimplePie_Item::get_category()} and {@see SimplePie_Item::get_categories()}
4263 * This class can be overloaded with {@see SimplePie::set_category_class()}
4265 * @package SimplePie
4268 class SimplePie_Category
4271 * Category identifier
4279 * Categorization scheme identifier
4287 * Human readable label
4295 * Constructor, used to input the data
4297 * @param string $term
4298 * @param string $scheme
4299 * @param string $label
4301 public function __construct($term = null, $scheme = null, $label = null)
4303 $this->term
= $term;
4304 $this->scheme
= $scheme;
4305 $this->label
= $label;
4309 * String-ified version
4313 public function __toString()
4315 // There is no $this->data here
4316 return md5(serialize($this));
4320 * Get the category identifier
4322 * @return string|null
4324 public function get_term()
4326 if ($this->term
!== null)
4337 * Get the categorization scheme identifier
4339 * @return string|null
4341 public function get_scheme()
4343 if ($this->scheme
!== null)
4345 return $this->scheme
;
4354 * Get the human readable label
4356 * @return string|null
4358 public function get_label()
4360 if ($this->label
!== null)
4362 return $this->label
;
4366 return $this->get_term();
4372 * Content-type sniffing
4374 * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06
4376 * This is used since we can't always trust Content-Type headers, and is based
4377 * upon the HTML5 parsing rules.
4380 * This class can be overloaded with {@see SimplePie::set_content_type_sniffer_class()}
4382 * @package SimplePie
4385 class SimplePie_Content_Type_Sniffer
4390 * @var SimplePie_File
4395 * Create an instance of the class with the input file
4397 * @param SimplePie_Content_Type_Sniffer $file Input file
4399 public function __construct($file)
4401 $this->file
= $file;
4405 * Get the Content-Type of the specified file
4407 * @return string Actual Content-Type
4409 public function get_type()
4411 if (isset($this->file
->headers
['content-type']))
4413 if (!isset($this->file
->headers
['content-encoding'])
4414 && ($this->file
->headers
['content-type'] === 'text/plain'
4415 ||
$this->file
->headers
['content-type'] === 'text/plain; charset=ISO-8859-1'
4416 ||
$this->file
->headers
['content-type'] === 'text/plain; charset=iso-8859-1'
4417 ||
$this->file
->headers
['content-type'] === 'text/plain; charset=UTF-8'))
4419 return $this->text_or_binary();
4422 if (($pos = strpos($this->file
->headers
['content-type'], ';')) !== false)
4424 $official = substr($this->file
->headers
['content-type'], 0, $pos);
4428 $official = $this->file
->headers
['content-type'];
4430 $official = trim(strtolower($official));
4432 if ($official === 'unknown/unknown'
4433 ||
$official === 'application/unknown')
4435 return $this->unknown();
4437 elseif (substr($official, -4) === '+xml'
4438 ||
$official === 'text/xml'
4439 ||
$official === 'application/xml')
4443 elseif (substr($official, 0, 6) === 'image/')
4445 if ($return = $this->image())
4454 elseif ($official === 'text/html')
4456 return $this->feed_or_html();
4465 return $this->unknown();
4470 * Sniff text or binary
4472 * @return string Actual Content-Type
4474 public function text_or_binary()
4476 if (substr($this->file
->body
, 0, 2) === "\xFE\xFF"
4477 ||
substr($this->file
->body
, 0, 2) === "\xFF\xFE"
4478 ||
substr($this->file
->body
, 0, 4) === "\x00\x00\xFE\xFF"
4479 ||
substr($this->file
->body
, 0, 3) === "\xEF\xBB\xBF")
4481 return 'text/plain';
4483 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file
->body
))
4485 return 'application/octect-stream';
4489 return 'text/plain';
4496 * @return string Actual Content-Type
4498 public function unknown()
4500 $ws = strspn($this->file
->body
, "\x09\x0A\x0B\x0C\x0D\x20");
4501 if (strtolower(substr($this->file
->body
, $ws, 14)) === '<!doctype html'
4502 ||
strtolower(substr($this->file
->body
, $ws, 5)) === '<html'
4503 ||
strtolower(substr($this->file
->body
, $ws, 7)) === '<script')
4507 elseif (substr($this->file
->body
, 0, 5) === '%PDF-')
4509 return 'application/pdf';
4511 elseif (substr($this->file
->body
, 0, 11) === '%!PS-Adobe-')
4513 return 'application/postscript';
4515 elseif (substr($this->file
->body
, 0, 6) === 'GIF87a'
4516 ||
substr($this->file
->body
, 0, 6) === 'GIF89a')
4520 elseif (substr($this->file
->body
, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
4524 elseif (substr($this->file
->body
, 0, 3) === "\xFF\xD8\xFF")
4526 return 'image/jpeg';
4528 elseif (substr($this->file
->body
, 0, 2) === "\x42\x4D")
4532 elseif (substr($this->file
->body
, 0, 4) === "\x00\x00\x01\x00")
4534 return 'image/vnd.microsoft.icon';
4538 return $this->text_or_binary();
4545 * @return string Actual Content-Type
4547 public function image()
4549 if (substr($this->file
->body
, 0, 6) === 'GIF87a'
4550 ||
substr($this->file
->body
, 0, 6) === 'GIF89a')
4554 elseif (substr($this->file
->body
, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
4558 elseif (substr($this->file
->body
, 0, 3) === "\xFF\xD8\xFF")
4560 return 'image/jpeg';
4562 elseif (substr($this->file
->body
, 0, 2) === "\x42\x4D")
4566 elseif (substr($this->file
->body
, 0, 4) === "\x00\x00\x01\x00")
4568 return 'image/vnd.microsoft.icon';
4579 * @return string Actual Content-Type
4581 public function feed_or_html()
4583 $len = strlen($this->file
->body
);
4584 $pos = strspn($this->file
->body
, "\x09\x0A\x0D\x20");
4588 switch ($this->file
->body
[$pos])
4594 $pos +
= strspn($this->file
->body
, "\x09\x0A\x0D\x20", $pos);
4605 if (substr($this->file
->body
, $pos, 3) === '!--')
4608 if ($pos < $len && ($pos = strpos($this->file
->body
, '-->', $pos)) !== false)
4617 elseif (substr($this->file
->body
, $pos, 1) === '!')
4619 if ($pos < $len && ($pos = strpos($this->file
->body
, '>', $pos)) !== false)
4628 elseif (substr($this->file
->body
, $pos, 1) === '?')
4630 if ($pos < $len && ($pos = strpos($this->file
->body
, '?>', $pos)) !== false)
4639 elseif (substr($this->file
->body
, $pos, 3) === 'rss'
4640 ||
substr($this->file
->body
, $pos, 7) === 'rdf:RDF')
4642 return 'application/rss+xml';
4644 elseif (substr($this->file
->body
, $pos, 4) === 'feed')
4646 return 'application/atom+xml';
4659 * Manages `<media:copyright>` copyright tags as defined in Media RSS
4661 * Used by {@see SimplePie_Enclosure::get_copyright()}
4663 * This class can be overloaded with {@see SimplePie::set_copyright_class()}
4665 * @package SimplePie
4668 class SimplePie_Copyright
4682 * @see get_attribution()
4687 * Constructor, used to input the data
4689 * For documentation on all the parameters, see the corresponding
4690 * properties and their accessors
4692 public function __construct($url = null, $label = null)
4695 $this->label
= $label;
4699 * String-ified version
4703 public function __toString()
4705 // There is no $this->data here
4706 return md5(serialize($this));
4710 * Get the copyright URL
4712 * @return string|null URL to copyright information
4714 public function get_url()
4716 if ($this->url
!== null)
4727 * Get the attribution text
4729 * @return string|null
4731 public function get_attribution()
4733 if ($this->label
!== null)
4735 return $this->label
;
4747 * Class for backward compatibility.
4749 * @deprecated Use {@see SimplePie} directly
4750 * @package SimplePie
4753 class SimplePie_Core
extends SimplePie
4759 * Handles `<media:credit>` as defined in Media RSS
4761 * Used by {@see SimplePie_Enclosure::get_credit()} and {@see SimplePie_Enclosure::get_credits()}
4763 * This class can be overloaded with {@see SimplePie::set_credit_class()}
4765 * @package SimplePie
4768 class SimplePie_Credit
4779 * Organizational scheme
4795 * Constructor, used to input the data
4797 * For documentation on all the parameters, see the corresponding
4798 * properties and their accessors
4800 public function __construct($role = null, $scheme = null, $name = null)
4802 $this->role
= $role;
4803 $this->scheme
= $scheme;
4804 $this->name
= $name;
4808 * String-ified version
4812 public function __toString()
4814 // There is no $this->data here
4815 return md5(serialize($this));
4819 * Get the role of the person receiving credit
4821 * @return string|null
4823 public function get_role()
4825 if ($this->role
!== null)
4836 * Get the organizational scheme
4838 * @return string|null
4840 public function get_scheme()
4842 if ($this->scheme
!== null)
4844 return $this->scheme
;
4853 * Get the credited person/entity's name
4855 * @return string|null
4857 public function get_name()
4859 if ($this->name
!== null)
4871 * Decode HTML Entities
4873 * This implements HTML5 as of revision 967 (2007-06-28)
4875 * @deprecated Use DOMDocument instead!
4876 * @package SimplePie
4878 class SimplePie_Decode_HTML_Entities
4889 * Currently consumed bytes
4897 * Position of the current byte being parsed
4905 * Create an instance of the class with the input data
4908 * @param string $data Input data
4910 public function __construct($data)
4912 $this->data
= $data;
4916 * Parse the input data
4919 * @return string Output data
4921 public function parse()
4923 while (($this->position
= strpos($this->data
, '&', $this->position
)) !== false)
4927 $this->consumed
= '';
4933 * Consume the next byte
4936 * @return mixed The next byte, or false, if there is no more data
4938 public function consume()
4940 if (isset($this->data
[$this->position
]))
4942 $this->consumed
.= $this->data
[$this->position
];
4943 return $this->data
[$this->position++
];
4952 * Consume a range of characters
4955 * @param string $chars Characters to consume
4956 * @return mixed A series of characters that match the range, or false
4958 public function consume_range($chars)
4960 if ($len = strspn($this->data
, $chars, $this->position
))
4962 $data = substr($this->data
, $this->position
, $len);
4963 $this->consumed
.= $data;
4964 $this->position +
= $len;
4974 * Unconsume one byte
4978 public function unconsume()
4980 $this->consumed
= substr($this->consumed
, 0, -1);
4989 public function entity()
4991 switch ($this->consume())
5005 switch ($this->consume())
5009 $range = '0123456789ABCDEFabcdef';
5014 $range = '0123456789';
5020 if ($codepoint = $this->consume_range($range))
5022 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");
5026 $codepoint = hexdec($codepoint);
5030 $codepoint = intval($codepoint);
5033 if (isset($windows_1252_specials[$codepoint]))
5035 $replacement = $windows_1252_specials[$codepoint];
5039 $replacement = SimplePie_Misc
::codepoint_to_utf8($codepoint);
5042 if (!in_array($this->consume(), array(';', false), true))
5047 $consumed_length = strlen($this->consumed
);
5048 $this->data
= substr_replace($this->data
, $replacement, $this->position
- $consumed_length, $consumed_length);
5049 $this->position +
= strlen($replacement) - $consumed_length;
5054 static $entities = array(
5055 'Aacute' => "\xC3\x81",
5056 'aacute' => "\xC3\xA1",
5057 'Aacute;' => "\xC3\x81",
5058 'aacute;' => "\xC3\xA1",
5059 'Acirc' => "\xC3\x82",
5060 'acirc' => "\xC3\xA2",
5061 'Acirc;' => "\xC3\x82",
5062 'acirc;' => "\xC3\xA2",
5063 'acute' => "\xC2\xB4",
5064 'acute;' => "\xC2\xB4",
5065 'AElig' => "\xC3\x86",
5066 'aelig' => "\xC3\xA6",
5067 'AElig;' => "\xC3\x86",
5068 'aelig;' => "\xC3\xA6",
5069 'Agrave' => "\xC3\x80",
5070 'agrave' => "\xC3\xA0",
5071 'Agrave;' => "\xC3\x80",
5072 'agrave;' => "\xC3\xA0",
5073 'alefsym;' => "\xE2\x84\xB5",
5074 'Alpha;' => "\xCE\x91",
5075 'alpha;' => "\xCE\xB1",
5080 'and;' => "\xE2\x88\xA7",
5081 'ang;' => "\xE2\x88\xA0",
5083 'Aring' => "\xC3\x85",
5084 'aring' => "\xC3\xA5",
5085 'Aring;' => "\xC3\x85",
5086 'aring;' => "\xC3\xA5",
5087 'asymp;' => "\xE2\x89\x88",
5088 'Atilde' => "\xC3\x83",
5089 'atilde' => "\xC3\xA3",
5090 'Atilde;' => "\xC3\x83",
5091 'atilde;' => "\xC3\xA3",
5092 'Auml' => "\xC3\x84",
5093 'auml' => "\xC3\xA4",
5094 'Auml;' => "\xC3\x84",
5095 'auml;' => "\xC3\xA4",
5096 'bdquo;' => "\xE2\x80\x9E",
5097 'Beta;' => "\xCE\x92",
5098 'beta;' => "\xCE\xB2",
5099 'brvbar' => "\xC2\xA6",
5100 'brvbar;' => "\xC2\xA6",
5101 'bull;' => "\xE2\x80\xA2",
5102 'cap;' => "\xE2\x88\xA9",
5103 'Ccedil' => "\xC3\x87",
5104 'ccedil' => "\xC3\xA7",
5105 'Ccedil;' => "\xC3\x87",
5106 'ccedil;' => "\xC3\xA7",
5107 'cedil' => "\xC2\xB8",
5108 'cedil;' => "\xC2\xB8",
5109 'cent' => "\xC2\xA2",
5110 'cent;' => "\xC2\xA2",
5111 'Chi;' => "\xCE\xA7",
5112 'chi;' => "\xCF\x87",
5113 'circ;' => "\xCB\x86",
5114 'clubs;' => "\xE2\x99\xA3",
5115 'cong;' => "\xE2\x89\x85",
5116 'COPY' => "\xC2\xA9",
5117 'copy' => "\xC2\xA9",
5118 'COPY;' => "\xC2\xA9",
5119 'copy;' => "\xC2\xA9",
5120 'crarr;' => "\xE2\x86\xB5",
5121 'cup;' => "\xE2\x88\xAA",
5122 'curren' => "\xC2\xA4",
5123 'curren;' => "\xC2\xA4",
5124 'Dagger;' => "\xE2\x80\xA1",
5125 'dagger;' => "\xE2\x80\xA0",
5126 'dArr;' => "\xE2\x87\x93",
5127 'darr;' => "\xE2\x86\x93",
5128 'deg' => "\xC2\xB0",
5129 'deg;' => "\xC2\xB0",
5130 'Delta;' => "\xCE\x94",
5131 'delta;' => "\xCE\xB4",
5132 'diams;' => "\xE2\x99\xA6",
5133 'divide' => "\xC3\xB7",
5134 'divide;' => "\xC3\xB7",
5135 'Eacute' => "\xC3\x89",
5136 'eacute' => "\xC3\xA9",
5137 'Eacute;' => "\xC3\x89",
5138 'eacute;' => "\xC3\xA9",
5139 'Ecirc' => "\xC3\x8A",
5140 'ecirc' => "\xC3\xAA",
5141 'Ecirc;' => "\xC3\x8A",
5142 'ecirc;' => "\xC3\xAA",
5143 'Egrave' => "\xC3\x88",
5144 'egrave' => "\xC3\xA8",
5145 'Egrave;' => "\xC3\x88",
5146 'egrave;' => "\xC3\xA8",
5147 'empty;' => "\xE2\x88\x85",
5148 'emsp;' => "\xE2\x80\x83",
5149 'ensp;' => "\xE2\x80\x82",
5150 'Epsilon;' => "\xCE\x95",
5151 'epsilon;' => "\xCE\xB5",
5152 'equiv;' => "\xE2\x89\xA1",
5153 'Eta;' => "\xCE\x97",
5154 'eta;' => "\xCE\xB7",
5155 'ETH' => "\xC3\x90",
5156 'eth' => "\xC3\xB0",
5157 'ETH;' => "\xC3\x90",
5158 'eth;' => "\xC3\xB0",
5159 'Euml' => "\xC3\x8B",
5160 'euml' => "\xC3\xAB",
5161 'Euml;' => "\xC3\x8B",
5162 'euml;' => "\xC3\xAB",
5163 'euro;' => "\xE2\x82\xAC",
5164 'exist;' => "\xE2\x88\x83",
5165 'fnof;' => "\xC6\x92",
5166 'forall;' => "\xE2\x88\x80",
5167 'frac12' => "\xC2\xBD",
5168 'frac12;' => "\xC2\xBD",
5169 'frac14' => "\xC2\xBC",
5170 'frac14;' => "\xC2\xBC",
5171 'frac34' => "\xC2\xBE",
5172 'frac34;' => "\xC2\xBE",
5173 'frasl;' => "\xE2\x81\x84",
5174 'Gamma;' => "\xCE\x93",
5175 'gamma;' => "\xCE\xB3",
5176 'ge;' => "\xE2\x89\xA5",
5181 'hArr;' => "\xE2\x87\x94",
5182 'harr;' => "\xE2\x86\x94",
5183 'hearts;' => "\xE2\x99\xA5",
5184 'hellip;' => "\xE2\x80\xA6",
5185 'Iacute' => "\xC3\x8D",
5186 'iacute' => "\xC3\xAD",
5187 'Iacute;' => "\xC3\x8D",
5188 'iacute;' => "\xC3\xAD",
5189 'Icirc' => "\xC3\x8E",
5190 'icirc' => "\xC3\xAE",
5191 'Icirc;' => "\xC3\x8E",
5192 'icirc;' => "\xC3\xAE",
5193 'iexcl' => "\xC2\xA1",
5194 'iexcl;' => "\xC2\xA1",
5195 'Igrave' => "\xC3\x8C",
5196 'igrave' => "\xC3\xAC",
5197 'Igrave;' => "\xC3\x8C",
5198 'igrave;' => "\xC3\xAC",
5199 'image;' => "\xE2\x84\x91",
5200 'infin;' => "\xE2\x88\x9E",
5201 'int;' => "\xE2\x88\xAB",
5202 'Iota;' => "\xCE\x99",
5203 'iota;' => "\xCE\xB9",
5204 'iquest' => "\xC2\xBF",
5205 'iquest;' => "\xC2\xBF",
5206 'isin;' => "\xE2\x88\x88",
5207 'Iuml' => "\xC3\x8F",
5208 'iuml' => "\xC3\xAF",
5209 'Iuml;' => "\xC3\x8F",
5210 'iuml;' => "\xC3\xAF",
5211 'Kappa;' => "\xCE\x9A",
5212 'kappa;' => "\xCE\xBA",
5213 'Lambda;' => "\xCE\x9B",
5214 'lambda;' => "\xCE\xBB",
5215 'lang;' => "\xE3\x80\x88",
5216 'laquo' => "\xC2\xAB",
5217 'laquo;' => "\xC2\xAB",
5218 'lArr;' => "\xE2\x87\x90",
5219 'larr;' => "\xE2\x86\x90",
5220 'lceil;' => "\xE2\x8C\x88",
5221 'ldquo;' => "\xE2\x80\x9C",
5222 'le;' => "\xE2\x89\xA4",
5223 'lfloor;' => "\xE2\x8C\x8A",
5224 'lowast;' => "\xE2\x88\x97",
5225 'loz;' => "\xE2\x97\x8A",
5226 'lrm;' => "\xE2\x80\x8E",
5227 'lsaquo;' => "\xE2\x80\xB9",
5228 'lsquo;' => "\xE2\x80\x98",
5233 'macr' => "\xC2\xAF",
5234 'macr;' => "\xC2\xAF",
5235 'mdash;' => "\xE2\x80\x94",
5236 'micro' => "\xC2\xB5",
5237 'micro;' => "\xC2\xB5",
5238 'middot' => "\xC2\xB7",
5239 'middot;' => "\xC2\xB7",
5240 'minus;' => "\xE2\x88\x92",
5241 'Mu;' => "\xCE\x9C",
5242 'mu;' => "\xCE\xBC",
5243 'nabla;' => "\xE2\x88\x87",
5244 'nbsp' => "\xC2\xA0",
5245 'nbsp;' => "\xC2\xA0",
5246 'ndash;' => "\xE2\x80\x93",
5247 'ne;' => "\xE2\x89\xA0",
5248 'ni;' => "\xE2\x88\x8B",
5249 'not' => "\xC2\xAC",
5250 'not;' => "\xC2\xAC",
5251 'notin;' => "\xE2\x88\x89",
5252 'nsub;' => "\xE2\x8A\x84",
5253 'Ntilde' => "\xC3\x91",
5254 'ntilde' => "\xC3\xB1",
5255 'Ntilde;' => "\xC3\x91",
5256 'ntilde;' => "\xC3\xB1",
5257 'Nu;' => "\xCE\x9D",
5258 'nu;' => "\xCE\xBD",
5259 'Oacute' => "\xC3\x93",
5260 'oacute' => "\xC3\xB3",
5261 'Oacute;' => "\xC3\x93",
5262 'oacute;' => "\xC3\xB3",
5263 'Ocirc' => "\xC3\x94",
5264 'ocirc' => "\xC3\xB4",
5265 'Ocirc;' => "\xC3\x94",
5266 'ocirc;' => "\xC3\xB4",
5267 'OElig;' => "\xC5\x92",
5268 'oelig;' => "\xC5\x93",
5269 'Ograve' => "\xC3\x92",
5270 'ograve' => "\xC3\xB2",
5271 'Ograve;' => "\xC3\x92",
5272 'ograve;' => "\xC3\xB2",
5273 'oline;' => "\xE2\x80\xBE",
5274 'Omega;' => "\xCE\xA9",
5275 'omega;' => "\xCF\x89",
5276 'Omicron;' => "\xCE\x9F",
5277 'omicron;' => "\xCE\xBF",
5278 'oplus;' => "\xE2\x8A\x95",
5279 'or;' => "\xE2\x88\xA8",
5280 'ordf' => "\xC2\xAA",
5281 'ordf;' => "\xC2\xAA",
5282 'ordm' => "\xC2\xBA",
5283 'ordm;' => "\xC2\xBA",
5284 'Oslash' => "\xC3\x98",
5285 'oslash' => "\xC3\xB8",
5286 'Oslash;' => "\xC3\x98",
5287 'oslash;' => "\xC3\xB8",
5288 'Otilde' => "\xC3\x95",
5289 'otilde' => "\xC3\xB5",
5290 'Otilde;' => "\xC3\x95",
5291 'otilde;' => "\xC3\xB5",
5292 'otimes;' => "\xE2\x8A\x97",
5293 'Ouml' => "\xC3\x96",
5294 'ouml' => "\xC3\xB6",
5295 'Ouml;' => "\xC3\x96",
5296 'ouml;' => "\xC3\xB6",
5297 'para' => "\xC2\xB6",
5298 'para;' => "\xC2\xB6",
5299 'part;' => "\xE2\x88\x82",
5300 'permil;' => "\xE2\x80\xB0",
5301 'perp;' => "\xE2\x8A\xA5",
5302 'Phi;' => "\xCE\xA6",
5303 'phi;' => "\xCF\x86",
5304 'Pi;' => "\xCE\xA0",
5305 'pi;' => "\xCF\x80",
5306 'piv;' => "\xCF\x96",
5307 'plusmn' => "\xC2\xB1",
5308 'plusmn;' => "\xC2\xB1",
5309 'pound' => "\xC2\xA3",
5310 'pound;' => "\xC2\xA3",
5311 'Prime;' => "\xE2\x80\xB3",
5312 'prime;' => "\xE2\x80\xB2",
5313 'prod;' => "\xE2\x88\x8F",
5314 'prop;' => "\xE2\x88\x9D",
5315 'Psi;' => "\xCE\xA8",
5316 'psi;' => "\xCF\x88",
5321 'radic;' => "\xE2\x88\x9A",
5322 'rang;' => "\xE3\x80\x89",
5323 'raquo' => "\xC2\xBB",
5324 'raquo;' => "\xC2\xBB",
5325 'rArr;' => "\xE2\x87\x92",
5326 'rarr;' => "\xE2\x86\x92",
5327 'rceil;' => "\xE2\x8C\x89",
5328 'rdquo;' => "\xE2\x80\x9D",
5329 'real;' => "\xE2\x84\x9C",
5330 'REG' => "\xC2\xAE",
5331 'reg' => "\xC2\xAE",
5332 'REG;' => "\xC2\xAE",
5333 'reg;' => "\xC2\xAE",
5334 'rfloor;' => "\xE2\x8C\x8B",
5335 'Rho;' => "\xCE\xA1",
5336 'rho;' => "\xCF\x81",
5337 'rlm;' => "\xE2\x80\x8F",
5338 'rsaquo;' => "\xE2\x80\xBA",
5339 'rsquo;' => "\xE2\x80\x99",
5340 'sbquo;' => "\xE2\x80\x9A",
5341 'Scaron;' => "\xC5\xA0",
5342 'scaron;' => "\xC5\xA1",
5343 'sdot;' => "\xE2\x8B\x85",
5344 'sect' => "\xC2\xA7",
5345 'sect;' => "\xC2\xA7",
5346 'shy' => "\xC2\xAD",
5347 'shy;' => "\xC2\xAD",
5348 'Sigma;' => "\xCE\xA3",
5349 'sigma;' => "\xCF\x83",
5350 'sigmaf;' => "\xCF\x82",
5351 'sim;' => "\xE2\x88\xBC",
5352 'spades;' => "\xE2\x99\xA0",
5353 'sub;' => "\xE2\x8A\x82",
5354 'sube;' => "\xE2\x8A\x86",
5355 'sum;' => "\xE2\x88\x91",
5356 'sup;' => "\xE2\x8A\x83",
5357 'sup1' => "\xC2\xB9",
5358 'sup1;' => "\xC2\xB9",
5359 'sup2' => "\xC2\xB2",
5360 'sup2;' => "\xC2\xB2",
5361 'sup3' => "\xC2\xB3",
5362 'sup3;' => "\xC2\xB3",
5363 'supe;' => "\xE2\x8A\x87",
5364 'szlig' => "\xC3\x9F",
5365 'szlig;' => "\xC3\x9F",
5366 'Tau;' => "\xCE\xA4",
5367 'tau;' => "\xCF\x84",
5368 'there4;' => "\xE2\x88\xB4",
5369 'Theta;' => "\xCE\x98",
5370 'theta;' => "\xCE\xB8",
5371 'thetasym;' => "\xCF\x91",
5372 'thinsp;' => "\xE2\x80\x89",
5373 'THORN' => "\xC3\x9E",
5374 'thorn' => "\xC3\xBE",
5375 'THORN;' => "\xC3\x9E",
5376 'thorn;' => "\xC3\xBE",
5377 'tilde;' => "\xCB\x9C",
5378 'times' => "\xC3\x97",
5379 'times;' => "\xC3\x97",
5380 'TRADE;' => "\xE2\x84\xA2",
5381 'trade;' => "\xE2\x84\xA2",
5382 'Uacute' => "\xC3\x9A",
5383 'uacute' => "\xC3\xBA",
5384 'Uacute;' => "\xC3\x9A",
5385 'uacute;' => "\xC3\xBA",
5386 'uArr;' => "\xE2\x87\x91",
5387 'uarr;' => "\xE2\x86\x91",
5388 'Ucirc' => "\xC3\x9B",
5389 'ucirc' => "\xC3\xBB",
5390 'Ucirc;' => "\xC3\x9B",
5391 'ucirc;' => "\xC3\xBB",
5392 'Ugrave' => "\xC3\x99",
5393 'ugrave' => "\xC3\xB9",
5394 'Ugrave;' => "\xC3\x99",
5395 'ugrave;' => "\xC3\xB9",
5396 'uml' => "\xC2\xA8",
5397 'uml;' => "\xC2\xA8",
5398 'upsih;' => "\xCF\x92",
5399 'Upsilon;' => "\xCE\xA5",
5400 'upsilon;' => "\xCF\x85",
5401 'Uuml' => "\xC3\x9C",
5402 'uuml' => "\xC3\xBC",
5403 'Uuml;' => "\xC3\x9C",
5404 'uuml;' => "\xC3\xBC",
5405 'weierp;' => "\xE2\x84\x98",
5406 'Xi;' => "\xCE\x9E",
5407 'xi;' => "\xCE\xBE",
5408 'Yacute' => "\xC3\x9D",
5409 'yacute' => "\xC3\xBD",
5410 'Yacute;' => "\xC3\x9D",
5411 'yacute;' => "\xC3\xBD",
5412 'yen' => "\xC2\xA5",
5413 'yen;' => "\xC2\xA5",
5414 'yuml' => "\xC3\xBF",
5415 'Yuml;' => "\xC5\xB8",
5416 'yuml;' => "\xC3\xBF",
5417 'Zeta;' => "\xCE\x96",
5418 'zeta;' => "\xCE\xB6",
5419 'zwj;' => "\xE2\x80\x8D",
5420 'zwnj;' => "\xE2\x80\x8C"
5423 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++
)
5425 $consumed = substr($this->consumed
, 1);
5426 if (isset($entities[$consumed]))
5432 if ($match !== null)
5434 $this->data
= substr_replace($this->data
, $entities[$match], $this->position
- strlen($consumed) - 1, strlen($match) +
1);
5435 $this->position +
= strlen($entities[$match]) - strlen($consumed) - 1;
5443 * Handles everything related to enclosures (including Media RSS and iTunes RSS)
5445 * Used by {@see SimplePie_Item::get_enclosure()} and {@see SimplePie_Item::get_enclosures()}
5447 * This class can be overloaded with {@see SimplePie::set_enclosure_class()}
5449 * @package SimplePie
5452 class SimplePie_Enclosure
5456 * @see get_bitrate()
5462 * @see get_captions()
5468 * @see get_categories()
5474 * @see get_channels()
5479 * @var SimplePie_Copyright
5480 * @see get_copyright()
5486 * @see get_credits()
5492 * @see get_description()
5498 * @see get_duration()
5504 * @see get_expression()
5510 * @see get_framerate()
5516 * @see get_handler()
5540 * @see get_keywords()
5546 * @see get_language()
5576 * @see get_ratings()
5582 * @see get_restrictions()
5588 * @see get_sampling_rate()
5594 * @see get_thumbnails()
5617 * Constructor, used to input the data
5619 * For documentation on all the parameters, see the corresponding
5620 * properties and their accessors
5622 * @uses idna_convert If available, this will convert an IDN
5624 public function __construct($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)
5626 $this->bitrate
= $bitrate;
5627 $this->captions
= $captions;
5628 $this->categories
= $categories;
5629 $this->channels
= $channels;
5630 $this->copyright
= $copyright;
5631 $this->credits
= $credits;
5632 $this->description
= $description;
5633 $this->duration
= $duration;
5634 $this->expression
= $expression;
5635 $this->framerate
= $framerate;
5636 $this->hashes
= $hashes;
5637 $this->height
= $height;
5638 $this->keywords
= $keywords;
5639 $this->lang
= $lang;
5640 $this->length
= $length;
5641 $this->link
= $link;
5642 $this->medium
= $medium;
5643 $this->player
= $player;
5644 $this->ratings
= $ratings;
5645 $this->restrictions
= $restrictions;
5646 $this->samplingrate
= $samplingrate;
5647 $this->thumbnails
= $thumbnails;
5648 $this->title
= $title;
5649 $this->type
= $type;
5650 $this->width
= $width;
5652 if (class_exists('idna_convert'))
5654 $idn = new idna_convert();
5655 $parsed = SimplePie_Misc
::parse_url($link);
5656 $this->link
= SimplePie_Misc
::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
5658 $this->handler
= $this->get_handler(); // Needs to load last
5662 * String-ified version
5666 public function __toString()
5668 // There is no $this->data here
5669 return md5(serialize($this));
5675 * @return string|null
5677 public function get_bitrate()
5679 if ($this->bitrate
!== null)
5681 return $this->bitrate
;
5690 * Get a single caption
5693 * @return SimplePie_Caption|null
5695 public function get_caption($key = 0)
5697 $captions = $this->get_captions();
5698 if (isset($captions[$key]))
5700 return $captions[$key];
5711 * @return array|null Array of {@see SimplePie_Caption} objects
5713 public function get_captions()
5715 if ($this->captions
!== null)
5717 return $this->captions
;
5726 * Get a single category
5729 * @return SimplePie_Category|null
5731 public function get_category($key = 0)
5733 $categories = $this->get_categories();
5734 if (isset($categories[$key]))
5736 return $categories[$key];
5745 * Get all categories
5747 * @return array|null Array of {@see SimplePie_Category} objects
5749 public function get_categories()
5751 if ($this->categories
!== null)
5753 return $this->categories
;
5762 * Get the number of audio channels
5766 public function get_channels()
5768 if ($this->channels
!== null)
5770 return $this->channels
;
5779 * Get the copyright information
5781 * @return SimplePie_Copyright|null
5783 public function get_copyright()
5785 if ($this->copyright
!== null)
5787 return $this->copyright
;
5796 * Get a single credit
5799 * @return SimplePie_Credit|null
5801 public function get_credit($key = 0)
5803 $credits = $this->get_credits();
5804 if (isset($credits[$key]))
5806 return $credits[$key];
5817 * @return array|null Array of {@see SimplePie_Credit} objects
5819 public function get_credits()
5821 if ($this->credits
!== null)
5823 return $this->credits
;
5832 * Get the description of the enclosure
5834 * @return string|null
5836 public function get_description()
5838 if ($this->description
!== null)
5840 return $this->description
;
5849 * Get the duration of the enclosure
5851 * @param string $convert Convert seconds into hh:mm:ss
5852 * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found)
5854 public function get_duration($convert = false)
5856 if ($this->duration
!== null)
5860 $time = SimplePie_Misc
::time_hms($this->duration
);
5865 return $this->duration
;
5875 * Get the expression
5877 * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full'
5879 public function get_expression()
5881 if ($this->expression
!== null)
5883 return $this->expression
;
5892 * Get the file extension
5894 * @return string|null
5896 public function get_extension()
5898 if ($this->link
!== null)
5900 $url = SimplePie_Misc
::parse_url($this->link
);
5901 if ($url['path'] !== '')
5903 return pathinfo($url['path'], PATHINFO_EXTENSION
);
5910 * Get the framerate (in frames-per-second)
5912 * @return string|null
5914 public function get_framerate()
5916 if ($this->framerate
!== null)
5918 return $this->framerate
;
5927 * Get the preferred handler
5929 * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3'
5931 public function get_handler()
5933 return $this->get_real_type(true);
5939 * @link http://www.rssboard.org/media-rss#media-hash
5941 * @return string|null Hash as per `media:hash`, prefixed with "$algo:"
5943 public function get_hash($key = 0)
5945 $hashes = $this->get_hashes();
5946 if (isset($hashes[$key]))
5948 return $hashes[$key];
5959 * @return array|null Array of strings, see {@see get_hash()}
5961 public function get_hashes()
5963 if ($this->hashes
!== null)
5965 return $this->hashes
;
5976 * @return string|null
5978 public function get_height()
5980 if ($this->height
!== null)
5982 return $this->height
;
5993 * @link http://tools.ietf.org/html/rfc3066
5994 * @return string|null Language code as per RFC 3066
5996 public function get_language()
5998 if ($this->lang
!== null)
6009 * Get a single keyword
6012 * @return string|null
6014 public function get_keyword($key = 0)
6016 $keywords = $this->get_keywords();
6017 if (isset($keywords[$key]))
6019 return $keywords[$key];
6030 * @return array|null Array of strings
6032 public function get_keywords()
6034 if ($this->keywords
!== null)
6036 return $this->keywords
;
6047 * @return float Length in bytes
6049 public function get_length()
6051 if ($this->length
!== null)
6053 return $this->length
;
6064 * @return string|null
6066 public function get_link()
6068 if ($this->link
!== null)
6070 return urldecode($this->link
);
6081 * @link http://www.rssboard.org/media-rss#media-content
6082 * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable'
6084 public function get_medium()
6086 if ($this->medium
!== null)
6088 return $this->medium
;
6097 * Get the player URL
6099 * Typically the same as {@see get_permalink()}
6100 * @return string|null Player URL
6102 public function get_player()
6104 if ($this->player
!== null)
6106 return $this->player
;
6115 * Get a single rating
6118 * @return SimplePie_Rating|null
6120 public function get_rating($key = 0)
6122 $ratings = $this->get_ratings();
6123 if (isset($ratings[$key]))
6125 return $ratings[$key];
6136 * @return array|null Array of {@see SimplePie_Rating} objects
6138 public function get_ratings()
6140 if ($this->ratings
!== null)
6142 return $this->ratings
;
6151 * Get a single restriction
6154 * @return SimplePie_Restriction|null
6156 public function get_restriction($key = 0)
6158 $restrictions = $this->get_restrictions();
6159 if (isset($restrictions[$key]))
6161 return $restrictions[$key];
6170 * Get all restrictions
6172 * @return array|null Array of {@see SimplePie_Restriction} objects
6174 public function get_restrictions()
6176 if ($this->restrictions
!== null)
6178 return $this->restrictions
;
6187 * Get the sampling rate (in kHz)
6189 * @return string|null
6191 public function get_sampling_rate()
6193 if ($this->samplingrate
!== null)
6195 return $this->samplingrate
;
6204 * Get the file size (in MiB)
6206 * @return float|null File size in mebibytes (1048 bytes)
6208 public function get_size()
6210 $length = $this->get_length();
6211 if ($length !== null)
6213 return round($length/1048576, 2);
6222 * Get a single thumbnail
6225 * @return string|null Thumbnail URL
6227 public function get_thumbnail($key = 0)
6229 $thumbnails = $this->get_thumbnails();
6230 if (isset($thumbnails[$key]))
6232 return $thumbnails[$key];
6241 * Get all thumbnails
6243 * @return array|null Array of thumbnail URLs
6245 public function get_thumbnails()
6247 if ($this->thumbnails
!== null)
6249 return $this->thumbnails
;
6260 * @return string|null
6262 public function get_title()
6264 if ($this->title
!== null)
6266 return $this->title
;
6275 * Get mimetype of the enclosure
6277 * @see get_real_type()
6278 * @return string|null MIME type
6280 public function get_type()
6282 if ($this->type
!== null)
6295 * @return string|null
6297 public function get_width()
6299 if ($this->width
!== null)
6301 return $this->width
;
6310 * Embed the enclosure using `<embed>`
6312 * @deprecated Use the second parameter to {@see embed} instead
6314 * @param array|string $options See first paramter to {@see embed}
6315 * @return string HTML string to output
6317 public function native_embed($options='')
6319 return $this->embed($options, true);
6323 * Embed the enclosure using Javascript
6325 * `$options` is an array or comma-separated key:value string, with the
6326 * following properties:
6328 * - `alt` (string): Alternate content for when an end-user does not have
6329 * the appropriate handler installed or when a file type is
6330 * unsupported. Can be any text or HTML. Defaults to blank.
6331 * - `altclass` (string): If a file type is unsupported, the end-user will
6332 * see the alt text (above) linked directly to the content. That link
6333 * will have this value as its class name. Defaults to blank.
6334 * - `audio` (string): This is an image that should be used as a
6335 * placeholder for audio files before they're loaded (QuickTime-only).
6336 * Can be any relative or absolute URL. Defaults to blank.
6337 * - `bgcolor` (string): The background color for the media, if not
6338 * already transparent. Defaults to `#ffffff`.
6339 * - `height` (integer): The height of the embedded media. Accepts any
6340 * numeric pixel value (such as `360`) or `auto`. Defaults to `auto`,
6341 * and it is recommended that you use this default.
6342 * - `loop` (boolean): Do you want the media to loop when its done?
6343 * Defaults to `false`.
6344 * - `mediaplayer` (string): The location of the included
6345 * `mediaplayer.swf` file. This allows for the playback of Flash Video
6346 * (`.flv`) files, and is the default handler for non-Odeo MP3's.
6347 * Defaults to blank.
6348 * - `video` (string): This is an image that should be used as a
6349 * placeholder for video files before they're loaded (QuickTime-only).
6350 * Can be any relative or absolute URL. Defaults to blank.
6351 * - `width` (integer): The width of the embedded media. Accepts any
6352 * numeric pixel value (such as `480`) or `auto`. Defaults to `auto`,
6353 * and it is recommended that you use this default.
6354 * - `widescreen` (boolean): Is the enclosure widescreen or standard?
6355 * This applies only to video enclosures, and will automatically resize
6356 * the content appropriately. Defaults to `false`, implying 4:3 mode.
6358 * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto`
6359 * will default to 480x360 video resolution. Widescreen (16:9) mode with
6360 * `width` and `height` set to `auto` will default to 480x270 video resolution.
6362 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6363 * @param array|string $options Comma-separated key:value list, or array
6364 * @param bool $native Use `<embed>`
6365 * @return string HTML string to output
6367 public function embed($options = '', $native = false)
6377 $bgcolor = '#ffffff';
6379 $widescreen = false;
6380 $handler = $this->get_handler();
6381 $type = $this->get_real_type();
6383 // Process options and reassign values as necessary
6384 if (is_array($options))
6390 $options = explode(',', $options);
6391 foreach($options as $option)
6393 $opt = explode(':', $option, 2);
6394 if (isset($opt[0], $opt[1]))
6396 $opt[0] = trim($opt[0]);
6397 $opt[1] = trim($opt[1]);
6413 $altclass = $opt[1];
6433 $mediaplayer = $opt[1];
6437 $widescreen = $opt[1];
6444 $mime = explode('/', $type, 2);
6447 // Process values for 'auto'
6448 if ($width === 'auto')
6450 if ($mime === 'video')
6452 if ($height === 'auto')
6456 elseif ($widescreen)
6458 $width = round((intval($height)/9)*16);
6462 $width = round((intval($height)/3)*4);
6471 if ($height === 'auto')
6473 if ($mime === 'audio')
6477 elseif ($mime === 'video')
6479 if ($width === 'auto')
6490 elseif ($widescreen)
6492 $height = round((intval($width)/16)*9);
6496 $height = round((intval($width)/4)*3);
6504 elseif ($mime === 'audio')
6509 // Set proper placeholder value
6510 if ($mime === 'audio')
6512 $placeholder = $audio;
6514 elseif ($mime === 'video')
6516 $placeholder = $video;
6522 if ($handler === 'flash')
6526 $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>";
6530 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
6534 // Flash Media Player file types.
6535 // Preferred handler for MP3 file types.
6536 elseif ($handler === 'fmedia' ||
($handler === 'mp3' && $mediaplayer !== ''))
6541 $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>";
6545 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
6549 // QuickTime 7 file types. Need to test with QuickTime 6.
6550 // Only handle MP3's if the Flash Media Player is not present.
6551 elseif ($handler === 'quicktime' ||
($handler === 'mp3' && $mediaplayer === ''))
6556 if ($placeholder !== '')
6558 $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>";
6562 $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>";
6567 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
6572 elseif ($handler === 'wmedia')
6577 $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>";
6581 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
6586 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
6592 * Get the real media type
6594 * Often, feeds lie to us, necessitating a bit of deeper inspection. This
6595 * converts types to their canonical representations based on the file
6599 * @param bool $find_handler Internal use only, use {@see get_handler()} instead
6600 * @return string MIME type
6602 public function get_real_type($find_handler = false)
6604 // Mime-types by handler.
6605 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
6606 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
6607 $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
6608 $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
6609 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
6611 if ($this->get_type() !== null)
6613 $type = strtolower($this->type
);
6620 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
6621 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
6623 switch (strtolower($this->get_extension()))
6628 $type = 'audio/acc';
6635 $type = 'audio/aiff';
6639 $type = 'audio/wav';
6646 $type = 'audio/midi';
6650 $type = 'audio/x-m4a';
6655 $type = 'audio/mp3';
6659 $type = 'audio/wav';
6663 $type = 'audio/x-ms-wax';
6667 $type = 'audio/x-ms-wma';
6673 $type = 'video/3gpp';
6678 $type = 'video/3gpp2';
6682 $type = 'video/x-ms-asf';
6686 $type = 'video/x-flv';
6700 $type = 'video/mpeg';
6704 $type = 'video/x-m4v';
6709 $type = 'video/quicktime';
6714 $type = 'video/mp4';
6718 $type = 'video/sd-video';
6722 $type = 'video/x-ms-wm';
6726 $type = 'video/x-ms-wmv';
6730 $type = 'video/x-ms-wvx';
6735 $type = 'application/futuresplash';
6739 $type = 'application/x-shockwave-flash';
6746 if (in_array($type, $types_flash))
6750 elseif (in_array($type, $types_fmedia))
6754 elseif (in_array($type, $types_quicktime))
6758 elseif (in_array($type, $types_wmedia))
6762 elseif (in_array($type, $types_mp3))
6779 * General SimplePie exception class
6781 * @package SimplePie
6783 class SimplePie_Exception
extends Exception
6788 * Used for fetching remote files and reading local files
6790 * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support
6792 * This class can be overloaded with {@see SimplePie::set_file_class()}
6794 * @package SimplePie
6796 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
6798 class SimplePie_File
6802 var $success = true;
6803 var $headers = array();
6808 var $method = SIMPLEPIE_FILE_SOURCE_NONE
;
6810 public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
6812 if (class_exists('idna_convert'))
6814 $idn = new idna_convert();
6815 $parsed = SimplePie_Misc
::parse_url($url);
6816 $url = SimplePie_Misc
::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6819 $this->useragent
= $useragent;
6820 if (preg_match('/^http(s)?:\/\//i', $url))
6822 if ($useragent === null)
6824 $useragent = ini_get('user_agent');
6825 $this->useragent
= $useragent;
6827 if (!is_array($headers))
6831 if (!$force_fsockopen && function_exists('curl_exec'))
6833 $this->method
= SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL
;
6835 $headers2 = array();
6836 foreach ($headers as $key => $value)
6838 $headers2[] = "$key: $value";
6840 if (version_compare(SimplePie_Misc
::get_curl_version(), '7.10.5', '>='))
6842 curl_setopt($fp, CURLOPT_ENCODING
, '');
6844 curl_setopt($fp, CURLOPT_URL
, $url);
6845 curl_setopt($fp, CURLOPT_HEADER
, 1);
6846 curl_setopt($fp, CURLOPT_RETURNTRANSFER
, 1);
6847 curl_setopt($fp, CURLOPT_TIMEOUT
, $timeout);
6848 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT
, $timeout);
6849 curl_setopt($fp, CURLOPT_REFERER
, $url);
6850 curl_setopt($fp, CURLOPT_USERAGENT
, $useragent);
6851 curl_setopt($fp, CURLOPT_HTTPHEADER
, $headers2);
6852 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc
::get_curl_version(), '7.15.2', '>='))
6854 curl_setopt($fp, CURLOPT_FOLLOWLOCATION
, 1);
6855 curl_setopt($fp, CURLOPT_MAXREDIRS
, $redirects);
6858 $this->headers
= curl_exec($fp);
6859 if (curl_errno($fp) === 23 ||
curl_errno($fp) === 61)
6861 curl_setopt($fp, CURLOPT_ENCODING
, 'none');
6862 $this->headers
= curl_exec($fp);
6864 if (curl_errno($fp))
6866 $this->error
= 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
6867 $this->success
= false;
6871 $info = curl_getinfo($fp);
6873 $this->headers
= explode("\r\n\r\n", $this->headers
, $info['redirect_count'] +
1);
6874 $this->headers
= array_pop($this->headers
);
6875 $parser = new SimplePie_HTTP_Parser($this->headers
);
6876 if ($parser->parse())
6878 $this->headers
= $parser->headers
;
6879 $this->body
= $parser->body
;
6880 $this->status_code
= $parser->status_code
;
6881 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)
6884 $location = SimplePie_Misc
::absolutize_url($this->headers
['location'], $url);
6885 return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
6892 $this->method
= SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN
;
6893 $url_parts = parse_url($url);
6894 $socket_host = $url_parts['host'];
6895 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
6897 $socket_host = "ssl://$url_parts[host]";
6898 $url_parts['port'] = 443;
6900 if (!isset($url_parts['port']))
6902 $url_parts['port'] = 80;
6904 $fp = @fsockopen
($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
6907 $this->error
= 'fsockopen error: ' . $errstr;
6908 $this->success
= false;
6912 stream_set_timeout($fp, $timeout);
6913 if (isset($url_parts['path']))
6915 if (isset($url_parts['query']))
6917 $get = "$url_parts[path]?$url_parts[query]";
6921 $get = $url_parts['path'];
6928 $out = "GET $get HTTP/1.1\r\n";
6929 $out .= "Host: $url_parts[host]\r\n";
6930 $out .= "User-Agent: $useragent\r\n";
6931 if (extension_loaded('zlib'))
6933 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
6936 if (isset($url_parts['user']) && isset($url_parts['pass']))
6938 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
6940 foreach ($headers as $key => $value)
6942 $out .= "$key: $value\r\n";
6944 $out .= "Connection: Close\r\n\r\n";
6947 $info = stream_get_meta_data($fp);
6949 $this->headers
= '';
6950 while (!$info['eof'] && !$info['timed_out'])
6952 $this->headers
.= fread($fp, 1160);
6953 $info = stream_get_meta_data($fp);
6955 if (!$info['timed_out'])
6957 $parser = new SimplePie_HTTP_Parser($this->headers
);
6958 if ($parser->parse())
6960 $this->headers
= $parser->headers
;
6961 $this->body
= $parser->body
;
6962 $this->status_code
= $parser->status_code
;
6963 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)
6966 $location = SimplePie_Misc
::absolutize_url($this->headers
['location'], $url);
6967 return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
6969 if (isset($this->headers
['content-encoding']))
6971 // Hey, we act dumb elsewhere, so let's do that here too
6972 switch (strtolower(trim($this->headers
['content-encoding'], "\x09\x0A\x0D\x20")))
6976 $decoder = new SimplePie_gzdecode($this->body
);
6977 if (!$decoder->parse())
6979 $this->error
= 'Unable to decode HTTP "gzip" stream';
6980 $this->success
= false;
6984 $this->body
= $decoder->data
;
6989 if (($decompressed = gzinflate($this->body
)) !== false)
6991 $this->body
= $decompressed;
6993 else if (($decompressed = gzuncompress($this->body
)) !== false)
6995 $this->body
= $decompressed;
6997 else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body
)) !== false)
6999 $this->body
= $decompressed;
7003 $this->error
= 'Unable to decode HTTP "deflate" stream';
7004 $this->success
= false;
7009 $this->error
= 'Unknown content coding';
7010 $this->success
= false;
7017 $this->error
= 'fsocket timed out';
7018 $this->success
= false;
7026 $this->method
= SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS
;
7027 if (!$this->body
= file_get_contents($url))
7029 $this->error
= 'file_get_contents could not read the file';
7030 $this->success
= false;
7037 * Decode 'gzip' encoded HTTP data
7039 * @package SimplePie
7041 * @link http://www.gzip.org/format.txt
7043 class SimplePie_gzdecode
7050 * @see gzdecode::$data
7052 var $compressed_data;
7055 * Size of compressed data
7060 var $compressed_size;
7063 * Minimum size of a valid gzip string
7068 var $min_compressed_size = 18;
7071 * Current position of pointer
7090 * @see gzdecode::$compressed_data
7123 * @see gzdecode::$extra_field
7124 * @see gzdecode::$SI2
7133 * @see gzdecode::$extra_field
7134 * @see gzdecode::$SI1
7140 * Extra field content
7143 * @see gzdecode::$SI1
7144 * @see gzdecode::$SI2
7158 * Human readable comment
7166 * Don't allow anything to be set
7168 * @param string $name
7169 * @param mixed $value
7171 public function __set($name, $value)
7173 trigger_error("Cannot write property $name", E_USER_ERROR
);
7177 * Set the compressed string and related properties
7179 * @param string $data
7181 public function __construct($data)
7183 $this->compressed_data
= $data;
7184 $this->compressed_size
= strlen($data);
7188 * Decode the GZIP stream
7190 * @return bool Successfulness
7192 public function parse()
7194 if ($this->compressed_size
>= $this->min_compressed_size
)
7196 // Check ID1, ID2, and CM
7197 if (substr($this->compressed_data
, 0, 3) !== "\x1F\x8B\x08")
7202 // Get the FLG (FLaGs)
7203 $this->flags
= ord($this->compressed_data
[3]);
7205 // FLG bits above (1 << 4) are reserved
7206 if ($this->flags
> 0x1F)
7211 // Advance the pointer after the above
7212 $this->position +
= 4;
7215 $mtime = substr($this->compressed_data
, $this->position
, 4);
7216 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
7217 if (current(unpack('S', "\x00\x01")) === 1)
7219 $mtime = strrev($mtime);
7221 $this->MTIME
= current(unpack('l', $mtime));
7222 $this->position +
= 4;
7224 // Get the XFL (eXtra FLags)
7225 $this->XFL
= ord($this->compressed_data
[$this->position++
]);
7227 // Get the OS (Operating System)
7228 $this->OS
= ord($this->compressed_data
[$this->position++
]);
7231 if ($this->flags
& 4)
7233 // Read subfield IDs
7234 $this->SI1
= $this->compressed_data
[$this->position++
];
7235 $this->SI2
= $this->compressed_data
[$this->position++
];
7237 // SI2 set to zero is reserved for future use
7238 if ($this->SI2
=== "\x00")
7243 // Get the length of the extra field
7244 $len = current(unpack('v', substr($this->compressed_data
, $this->position
, 2)));
7245 $this->position +
= 2;
7247 // Check the length of the string is still valid
7248 $this->min_compressed_size +
= $len +
4;
7249 if ($this->compressed_size
>= $this->min_compressed_size
)
7251 // Set the extra field to the given data
7252 $this->extra_field
= substr($this->compressed_data
, $this->position
, $len);
7253 $this->position +
= $len;
7262 if ($this->flags
& 8)
7264 // Get the length of the filename
7265 $len = strcspn($this->compressed_data
, "\x00", $this->position
);
7267 // Check the length of the string is still valid
7268 $this->min_compressed_size +
= $len +
1;
7269 if ($this->compressed_size
>= $this->min_compressed_size
)
7271 // Set the original filename to the given string
7272 $this->filename
= substr($this->compressed_data
, $this->position
, $len);
7273 $this->position +
= $len +
1;
7281 // Parse the FCOMMENT
7282 if ($this->flags
& 16)
7284 // Get the length of the comment
7285 $len = strcspn($this->compressed_data
, "\x00", $this->position
);
7287 // Check the length of the string is still valid
7288 $this->min_compressed_size +
= $len +
1;
7289 if ($this->compressed_size
>= $this->min_compressed_size
)
7291 // Set the original comment to the given string
7292 $this->comment
= substr($this->compressed_data
, $this->position
, $len);
7293 $this->position +
= $len +
1;
7302 if ($this->flags
& 2)
7304 // Check the length of the string is still valid
7305 $this->min_compressed_size +
= $len +
2;
7306 if ($this->compressed_size
>= $this->min_compressed_size
)
7309 $crc = current(unpack('v', substr($this->compressed_data
, $this->position
, 2)));
7311 // Check the CRC matches
7312 if ((crc32(substr($this->compressed_data
, 0, $this->position
)) & 0xFFFF) === $crc)
7314 $this->position +
= 2;
7327 // Decompress the actual data
7328 if (($this->data
= gzinflate(substr($this->compressed_data
, $this->position
, -8))) === false)
7334 $this->position
= $this->compressed_size
- 8;
7337 // Check CRC of data
7338 $crc = current(unpack('V', substr($this->compressed_data
, $this->position
, 4)));
7339 $this->position +
= 4;
7340 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
7345 // Check ISIZE of data
7346 $isize = current(unpack('V', substr($this->compressed_data
, $this->position
, 4)));
7347 $this->position +
= 4;
7348 if (sprintf('%u', strlen($this->data
) & 0xFFFFFFFF) !== sprintf('%u', $isize))
7353 // Wow, against all odds, we've actually got a valid gzip string
7364 * HTTP Response Parser
7366 * @package SimplePie
7369 class SimplePie_HTTP_Parser
7376 public $http_version = 0.0;
7383 public $status_code = 0;
7390 public $reason = '';
7393 * Key/value pairs of the headers
7397 public $headers = array();
7400 * Body of the response
7407 * Current state of the state machine
7411 protected $state = 'http_version';
7418 protected $data = '';
7421 * Input data length (to avoid calling strlen() everytime this is needed)
7425 protected $data_length = 0;
7428 * Current position of the pointer
7432 protected $position = 0;
7435 * Name of the hedaer currently being parsed
7439 protected $name = '';
7442 * Value of the hedaer currently being parsed
7446 protected $value = '';
7449 * Create an instance of the class with the input data
7451 * @param string $data Input data
7453 public function __construct($data)
7455 $this->data
= $data;
7456 $this->data_length
= strlen($this->data
);
7460 * Parse the input data
7462 * @return bool true on success, false on failure
7464 public function parse()
7466 while ($this->state
&& $this->state
!== 'emit' && $this->has_data())
7468 $state = $this->state
;
7472 if ($this->state
=== 'emit' ||
$this->state
=== 'body')
7478 $this->http_version
= '';
7479 $this->status_code
= '';
7481 $this->headers
= array();
7488 * Check whether there is data beyond the pointer
7490 * @return bool true if there is further data, false if not
7492 protected function has_data()
7494 return (bool) ($this->position
< $this->data_length
);
7498 * See if the next character is LWS
7500 * @return bool true if the next character is LWS, false if not
7502 protected function is_linear_whitespace()
7504 return (bool) ($this->data
[$this->position
] === "\x09"
7505 ||
$this->data
[$this->position
] === "\x20"
7506 ||
($this->data
[$this->position
] === "\x0A"
7507 && isset($this->data
[$this->position +
1])
7508 && ($this->data
[$this->position +
1] === "\x09" ||
$this->data
[$this->position +
1] === "\x20")));
7512 * Parse the HTTP version
7514 protected function http_version()
7516 if (strpos($this->data
, "\x0A") !== false && strtoupper(substr($this->data
, 0, 5)) === 'HTTP/')
7518 $len = strspn($this->data
, '0123456789.', 5);
7519 $this->http_version
= substr($this->data
, 5, $len);
7520 $this->position +
= 5 +
$len;
7521 if (substr_count($this->http_version
, '.') <= 1)
7523 $this->http_version
= (float) $this->http_version
;
7524 $this->position +
= strspn($this->data
, "\x09\x20", $this->position
);
7525 $this->state
= 'status';
7529 $this->state
= false;
7534 $this->state
= false;
7539 * Parse the status code
7541 protected function status()
7543 if ($len = strspn($this->data
, '0123456789', $this->position
))
7545 $this->status_code
= (int) substr($this->data
, $this->position
, $len);
7546 $this->position +
= $len;
7547 $this->state
= 'reason';
7551 $this->state
= false;
7556 * Parse the reason phrase
7558 protected function reason()
7560 $len = strcspn($this->data
, "\x0A", $this->position
);
7561 $this->reason
= trim(substr($this->data
, $this->position
, $len), "\x09\x0D\x20");
7562 $this->position +
= $len +
1;
7563 $this->state
= 'new_line';
7567 * Deal with a new line, shifting data around as needed
7569 protected function new_line()
7571 $this->value
= trim($this->value
, "\x0D\x20");
7572 if ($this->name
!== '' && $this->value
!== '')
7574 $this->name
= strtolower($this->name
);
7575 // We should only use the last Content-Type header. c.f. issue #1
7576 if (isset($this->headers
[$this->name
]) && $this->name
!== 'content-type')
7578 $this->headers
[$this->name
] .= ', ' . $this->value
;
7582 $this->headers
[$this->name
] = $this->value
;
7587 if (substr($this->data
[$this->position
], 0, 2) === "\x0D\x0A")
7589 $this->position +
= 2;
7590 $this->state
= 'body';
7592 elseif ($this->data
[$this->position
] === "\x0A")
7595 $this->state
= 'body';
7599 $this->state
= 'name';
7604 * Parse a header name
7606 protected function name()
7608 $len = strcspn($this->data
, "\x0A:", $this->position
);
7609 if (isset($this->data
[$this->position +
$len]))
7611 if ($this->data
[$this->position +
$len] === "\x0A")
7613 $this->position +
= $len;
7614 $this->state
= 'new_line';
7618 $this->name
= substr($this->data
, $this->position
, $len);
7619 $this->position +
= $len +
1;
7620 $this->state
= 'value';
7625 $this->state
= false;
7630 * Parse LWS, replacing consecutive LWS characters with a single space
7632 protected function linear_whitespace()
7636 if (substr($this->data
, $this->position
, 2) === "\x0D\x0A")
7638 $this->position +
= 2;
7640 elseif ($this->data
[$this->position
] === "\x0A")
7644 $this->position +
= strspn($this->data
, "\x09\x20", $this->position
);
7645 } while ($this->has_data() && $this->is_linear_whitespace());
7646 $this->value
.= "\x20";
7650 * See what state to move to while within non-quoted header values
7652 protected function value()
7654 if ($this->is_linear_whitespace())
7656 $this->linear_whitespace();
7660 switch ($this->data
[$this->position
])
7663 // Workaround for ETags: we have to include the quotes as
7665 if (strtolower($this->name
) === 'etag')
7667 $this->value
.= '"';
7669 $this->state
= 'value_char';
7673 $this->state
= 'quote';
7678 $this->state
= 'new_line';
7682 $this->state
= 'value_char';
7689 * Parse a header value while outside quotes
7691 protected function value_char()
7693 $len = strcspn($this->data
, "\x09\x20\x0A\"", $this->position
);
7694 $this->value
.= substr($this->data
, $this->position
, $len);
7695 $this->position +
= $len;
7696 $this->state
= 'value';
7700 * See what state to move to while within quoted header values
7702 protected function quote()
7704 if ($this->is_linear_whitespace())
7706 $this->linear_whitespace();
7710 switch ($this->data
[$this->position
])
7714 $this->state
= 'value';
7719 $this->state
= 'new_line';
7724 $this->state
= 'quote_escaped';
7728 $this->state
= 'quote_char';
7735 * Parse a header value while within quotes
7737 protected function quote_char()
7739 $len = strcspn($this->data
, "\x09\x20\x0A\"\\", $this->position
);
7740 $this->value
.= substr($this->data
, $this->position
, $len);
7741 $this->position +
= $len;
7742 $this->state
= 'value';
7746 * Parse an escaped character within quotes
7748 protected function quote_escaped()
7750 $this->value
.= $this->data
[$this->position
];
7752 $this->state
= 'quote';
7758 protected function body()
7760 $this->body
= substr($this->data
, $this->position
);
7761 if (!empty($this->headers
['transfer-encoding']))
7763 unset($this->headers
['transfer-encoding']);
7764 $this->state
= 'chunked';
7768 $this->state
= 'emit';
7773 * Parsed a "Transfer-Encoding: chunked" body
7775 protected function chunked()
7777 if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body
)))
7779 $this->state
= 'emit';
7784 $encoded = $this->body
;
7788 $is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );
7791 // Looks like it's not chunked after all
7792 $this->state
= 'emit';
7796 $length = hexdec(trim($matches[1]));
7799 // Ignore trailer headers
7800 $this->state
= 'emit';
7801 $this->body
= $decoded;
7805 $chunk_length = strlen($matches[0]);
7806 $decoded .= $part = substr($encoded, $chunk_length, $length);
7807 $encoded = substr($encoded, $chunk_length +
$length +
2);
7809 if (trim($encoded) === '0' ||
empty($encoded))
7811 $this->state
= 'emit';
7812 $this->body
= $decoded;
7820 * IRI parser/serialiser/normaliser
7822 * @package SimplePie
7824 * @author Geoffrey Sneddon
7825 * @author Steve Minutillo
7826 * @author Ryan McCue
7827 * @copyright 2007-2012 Geoffrey Sneddon, Steve Minutillo, Ryan McCue
7828 * @license http://www.opensource.org/licenses/bsd-license.php
7837 protected $scheme = null;
7844 protected $iuserinfo = null;
7851 protected $ihost = null;
7858 protected $port = null;
7865 protected $ipath = '';
7872 protected $iquery = null;
7879 protected $ifragment = null;
7882 * Normalization database
7884 * Each key is the scheme, each value is an array with each key as the IRI
7885 * part and value as the default value for that part.
7887 protected $normalization = array(
7895 'ihost' => 'localhost'
7908 * Return the entire IRI when you try and read the object as a string
7912 public function __toString()
7914 return $this->get_iri();
7918 * Overload __set() to provide access via properties
7920 * @param string $name Property name
7921 * @param mixed $value Property value
7923 public function __set($name, $value)
7925 if (method_exists($this, 'set_' . $name))
7927 call_user_func(array($this, 'set_' . $name), $value);
7930 $name === 'iauthority'
7931 ||
$name === 'iuserinfo'
7932 ||
$name === 'ihost'
7933 ||
$name === 'ipath'
7934 ||
$name === 'iquery'
7935 ||
$name === 'ifragment'
7938 call_user_func(array($this, 'set_' . substr($name, 1)), $value);
7943 * Overload __get() to provide access via properties
7945 * @param string $name Property name
7948 public function __get($name)
7950 // isset() returns false for null, we don't want to do that
7951 // Also why we use array_key_exists below instead of isset()
7952 $props = get_object_vars($this);
7957 $name === 'iauthority' ||
7958 $name === 'authority'
7961 $return = $this->{"get_$name"}();
7963 elseif (array_key_exists($name, $props))
7965 $return = $this->$name;
7968 elseif (($prop = 'i' . $name) && array_key_exists($prop, $props))
7971 $return = $this->$prop;
7973 // ischeme -> scheme
7974 elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))
7977 $return = $this->$prop;
7981 trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE
);
7985 if ($return === null && isset($this->normalization
[$this->scheme
][$name]))
7987 return $this->normalization
[$this->scheme
][$name];
7996 * Overload __isset() to provide access via properties
7998 * @param string $name Property name
8001 public function __isset($name)
8003 if (method_exists($this, 'get_' . $name) ||
isset($this->$name))
8014 * Overload __unset() to provide access via properties
8016 * @param string $name Property name
8018 public function __unset($name)
8020 if (method_exists($this, 'set_' . $name))
8022 call_user_func(array($this, 'set_' . $name), '');
8027 * Create a new IRI object, from a specified string
8029 * @param string $iri
8031 public function __construct($iri = null)
8033 $this->set_iri($iri);
8037 * Create a new IRI object by resolving a relative IRI
8039 * Returns false if $base is not absolute, otherwise an IRI.
8041 * @param IRI|string $base (Absolute) Base IRI
8042 * @param IRI|string $relative Relative IRI
8045 public static function absolutize($base, $relative)
8047 if (!($relative instanceof SimplePie_IRI
))
8049 $relative = new SimplePie_IRI($relative);
8051 if (!$relative->is_valid())
8055 elseif ($relative->scheme
!== null)
8057 return clone $relative;
8061 if (!($base instanceof SimplePie_IRI
))
8063 $base = new SimplePie_IRI($base);
8065 if ($base->scheme
!== null && $base->is_valid())
8067 if ($relative->get_iri() !== '')
8069 if ($relative->iuserinfo
!== null ||
$relative->ihost
!== null ||
$relative->port
!== null)
8071 $target = clone $relative;
8072 $target->scheme
= $base->scheme
;
8076 $target = new SimplePie_IRI
;
8077 $target->scheme
= $base->scheme
;
8078 $target->iuserinfo
= $base->iuserinfo
;
8079 $target->ihost
= $base->ihost
;
8080 $target->port
= $base->port
;
8081 if ($relative->ipath
!== '')
8083 if ($relative->ipath
[0] === '/')
8085 $target->ipath
= $relative->ipath
;
8087 elseif (($base->iuserinfo
!== null ||
$base->ihost
!== null ||
$base->port
!== null) && $base->ipath
=== '')
8089 $target->ipath
= '/' . $relative->ipath
;
8091 elseif (($last_segment = strrpos($base->ipath
, '/')) !== false)
8093 $target->ipath
= substr($base->ipath
, 0, $last_segment +
1) . $relative->ipath
;
8097 $target->ipath
= $relative->ipath
;
8099 $target->ipath
= $target->remove_dot_segments($target->ipath
);
8100 $target->iquery
= $relative->iquery
;
8104 $target->ipath
= $base->ipath
;
8105 if ($relative->iquery
!== null)
8107 $target->iquery
= $relative->iquery
;
8109 elseif ($base->iquery
!== null)
8111 $target->iquery
= $base->iquery
;
8114 $target->ifragment
= $relative->ifragment
;
8119 $target = clone $base;
8120 $target->ifragment
= null;
8122 $target->scheme_normalization();
8133 * Parse an IRI into scheme/authority/path/query/fragment segments
8135 * @param string $iri
8138 protected function parse_iri($iri)
8140 $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
8141 if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
8143 if ($match[1] === '')
8145 $match['scheme'] = null;
8147 if (!isset($match[3]) ||
$match[3] === '')
8149 $match['authority'] = null;
8151 if (!isset($match[5]))
8153 $match['path'] = '';
8155 if (!isset($match[6]) ||
$match[6] === '')
8157 $match['query'] = null;
8159 if (!isset($match[8]) ||
$match[8] === '')
8161 $match['fragment'] = null;
8167 // This can occur when a paragraph is accidentally parsed as a URI
8173 * Remove dot segments from a path
8175 * @param string $input
8178 protected function remove_dot_segments($input)
8181 while (strpos($input, './') !== false ||
strpos($input, '/.') !== false ||
$input === '.' ||
$input === '..')
8183 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
8184 if (strpos($input, '../') === 0)
8186 $input = substr($input, 3);
8188 elseif (strpos($input, './') === 0)
8190 $input = substr($input, 2);
8192 // 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,
8193 elseif (strpos($input, '/./') === 0)
8195 $input = substr($input, 2);
8197 elseif ($input === '/.')
8201 // 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,
8202 elseif (strpos($input, '/../') === 0)
8204 $input = substr($input, 3);
8205 $output = substr_replace($output, '', strrpos($output, '/'));
8207 elseif ($input === '/..')
8210 $output = substr_replace($output, '', strrpos($output, '/'));
8212 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
8213 elseif ($input === '.' ||
$input === '..')
8217 // 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
8218 elseif (($pos = strpos($input, '/', 1)) !== false)
8220 $output .= substr($input, 0, $pos);
8221 $input = substr_replace($input, '', 0, $pos);
8229 return $output . $input;
8233 * Replace invalid character with percent encoding
8235 * @param string $string Input string
8236 * @param string $extra_chars Valid characters not in iunreserved or
8237 * iprivate (this is ASCII-only)
8238 * @param bool $iprivate Allow iprivate
8241 protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)
8243 // Normalize as many pct-encoded sections as possible
8244 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);
8246 // Replace invalid percent characters
8247 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
8249 // Add unreserved and % to $extra_chars (the latter is safe because all
8250 // pct-encoded sections are now valid).
8251 $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
8253 // Now replace any bytes that aren't allowed with their pct-encoded versions
8255 $strlen = strlen($string);
8256 while (($position +
= strspn($string, $extra_chars, $position)) < $strlen)
8258 $value = ord($string[$position]);
8263 // By default we are valid
8266 // No one byte sequences are valid due to the while.
8267 // Two byte sequence:
8268 if (($value & 0xE0) === 0xC0)
8270 $character = ($value & 0x1F) << 6;
8274 // Three byte sequence:
8275 elseif (($value & 0xF0) === 0xE0)
8277 $character = ($value & 0x0F) << 12;
8281 // Four byte sequence:
8282 elseif (($value & 0xF8) === 0xF0)
8284 $character = ($value & 0x07) << 18;
8298 if ($position +
$length <= $strlen)
8300 for ($position++
; $remaining; $position++
)
8302 $value = ord($string[$position]);
8304 // Check that the byte is valid, then add it to the character:
8305 if (($value & 0xC0) === 0x80)
8307 $character |
= ($value & 0x3F) << (--$remaining * 6);
8309 // If it is invalid, count the sequence as invalid and reprocess the current byte:
8320 $position = $strlen - 1;
8325 // Percent encode anything invalid or not in ucschar
8327 // Invalid sequences
8329 // Non-shortest form sequences are invalid
8330 ||
$length > 1 && $character <= 0x7F
8331 ||
$length > 2 && $character <= 0x7FF
8332 ||
$length > 3 && $character <= 0xFFFF
8333 // Outside of range of ucschar codepoints
8335 ||
($character & 0xFFFE) === 0xFFFE
8336 ||
$character >= 0xFDD0 && $character <= 0xFDEF
8338 // Everything else not in ucschar
8339 $character > 0xD7FF && $character < 0xF900
8340 ||
$character < 0xA0
8341 ||
$character > 0xEFFFD
8344 // Everything not in iprivate, if it applies
8346 ||
$character < 0xE000
8347 ||
$character > 0x10FFFD
8351 // If we were a character, pretend we weren't, but rather an error.
8355 for ($j = $start; $j <= $position; $j++
)
8357 $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
8369 * Callback function for preg_replace_callback.
8371 * Removes sequences of percent encoded bytes that represent UTF-8
8372 * encoded characters in iunreserved
8374 * @param array $match PCRE match
8375 * @return string Replacement
8377 protected function remove_iunreserved_percent_encoded($match)
8379 // As we just have valid percent encoded sequences we can just explode
8380 // and ignore the first member of the returned array (an empty string).
8381 $bytes = explode('%', $match[0]);
8383 // Initialize the new string (this is what will be returned) and that
8384 // there are no bytes remaining in the current sequence (unsurprising
8385 // at the first byte!).
8389 // Loop over each and every byte, and set $value to its value
8390 for ($i = 1, $len = count($bytes); $i < $len; $i++
)
8392 $value = hexdec($bytes[$i]);
8394 // If we're the first byte of sequence:
8400 // By default we are valid
8403 // One byte sequence:
8406 $character = $value;
8409 // Two byte sequence:
8410 elseif (($value & 0xE0) === 0xC0)
8412 $character = ($value & 0x1F) << 6;
8416 // Three byte sequence:
8417 elseif (($value & 0xF0) === 0xE0)
8419 $character = ($value & 0x0F) << 12;
8423 // Four byte sequence:
8424 elseif (($value & 0xF8) === 0xF0)
8426 $character = ($value & 0x07) << 18;
8437 // Continuation byte:
8440 // Check that the byte is valid, then add it to the character:
8441 if (($value & 0xC0) === 0x80)
8444 $character |
= ($value & 0x3F) << ($remaining * 6);
8446 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
8455 // If we've reached the end of the current byte sequence, append it to Unicode::$data
8458 // Percent encode anything invalid or not in iunreserved
8460 // Invalid sequences
8462 // Non-shortest form sequences are invalid
8463 ||
$length > 1 && $character <= 0x7F
8464 ||
$length > 2 && $character <= 0x7FF
8465 ||
$length > 3 && $character <= 0xFFFF
8466 // Outside of range of iunreserved codepoints
8467 ||
$character < 0x2D
8468 ||
$character > 0xEFFFD
8470 ||
($character & 0xFFFE) === 0xFFFE
8471 ||
$character >= 0xFDD0 && $character <= 0xFDEF
8472 // Everything else not in iunreserved (this is all BMP)
8473 ||
$character === 0x2F
8474 ||
$character > 0x39 && $character < 0x41
8475 ||
$character > 0x5A && $character < 0x61
8476 ||
$character > 0x7A && $character < 0x7E
8477 ||
$character > 0x7E && $character < 0xA0
8478 ||
$character > 0xD7FF && $character < 0xF900
8481 for ($j = $start; $j <= $i; $j++
)
8483 $string .= '%' . strtoupper($bytes[$j]);
8488 for ($j = $start; $j <= $i; $j++
)
8490 $string .= chr(hexdec($bytes[$j]));
8496 // If we have any bytes left over they are invalid (i.e., we are
8497 // mid-way through a multi-byte sequence)
8500 for ($j = $start; $j < $len; $j++
)
8502 $string .= '%' . strtoupper($bytes[$j]);
8509 protected function scheme_normalization()
8511 if (isset($this->normalization
[$this->scheme
]['iuserinfo']) && $this->iuserinfo
=== $this->normalization
[$this->scheme
]['iuserinfo'])
8513 $this->iuserinfo
= null;
8515 if (isset($this->normalization
[$this->scheme
]['ihost']) && $this->ihost
=== $this->normalization
[$this->scheme
]['ihost'])
8517 $this->ihost
= null;
8519 if (isset($this->normalization
[$this->scheme
]['port']) && $this->port
=== $this->normalization
[$this->scheme
]['port'])
8523 if (isset($this->normalization
[$this->scheme
]['ipath']) && $this->ipath
=== $this->normalization
[$this->scheme
]['ipath'])
8527 if (isset($this->normalization
[$this->scheme
]['iquery']) && $this->iquery
=== $this->normalization
[$this->scheme
]['iquery'])
8529 $this->iquery
= null;
8531 if (isset($this->normalization
[$this->scheme
]['ifragment']) && $this->ifragment
=== $this->normalization
[$this->scheme
]['ifragment'])
8533 $this->ifragment
= null;
8538 * Check if the object represents a valid IRI. This needs to be done on each
8539 * call as some things change depending on another part of the IRI.
8543 public function is_valid()
8545 $isauthority = $this->iuserinfo
!== null ||
$this->ihost
!== null ||
$this->port
!== null;
8546 if ($this->ipath
!== '' &&
8549 $this->ipath
[0] !== '/' ||
8550 substr($this->ipath
, 0, 2) === '//'
8553 $this->scheme
=== null &&
8555 strpos($this->ipath
, ':') !== false &&
8556 (strpos($this->ipath
, '/') === false ?
true : strpos($this->ipath
, ':') < strpos($this->ipath
, '/'))
8568 * Set the entire IRI. Returns true on success, false on failure (if there
8569 * are any invalid characters).
8571 * @param string $iri
8574 public function set_iri($iri)
8586 elseif (isset($cache[$iri]))
8595 $return) = $cache[$iri];
8600 $parsed = $this->parse_iri((string) $iri);
8606 $return = $this->set_scheme($parsed['scheme'])
8607 && $this->set_authority($parsed['authority'])
8608 && $this->set_path($parsed['path'])
8609 && $this->set_query($parsed['query'])
8610 && $this->set_fragment($parsed['fragment']);
8612 $cache[$iri] = array($this->scheme
,
8625 * Set the scheme. Returns true on success, false on failure (if there are
8626 * any invalid characters).
8628 * @param string $scheme
8631 public function set_scheme($scheme)
8633 if ($scheme === null)
8635 $this->scheme
= null;
8637 elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))
8639 $this->scheme
= null;
8644 $this->scheme
= strtolower($scheme);
8650 * Set the authority. Returns true on success, false on failure (if there are
8651 * any invalid characters).
8653 * @param string $authority
8656 public function set_authority($authority)
8662 if ($authority === null)
8664 $this->iuserinfo
= null;
8665 $this->ihost
= null;
8669 elseif (isset($cache[$authority]))
8671 list($this->iuserinfo
,
8674 $return) = $cache[$authority];
8680 $remaining = $authority;
8681 if (($iuserinfo_end = strrpos($remaining, '@')) !== false)
8683 $iuserinfo = substr($remaining, 0, $iuserinfo_end);
8684 $remaining = substr($remaining, $iuserinfo_end +
1);
8690 if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)
8692 if (($port = substr($remaining, $port_start +
1)) === false)
8696 $remaining = substr($remaining, 0, $port_start);
8703 $return = $this->set_userinfo($iuserinfo) &&
8704 $this->set_host($remaining) &&
8705 $this->set_port($port);
8707 $cache[$authority] = array($this->iuserinfo
,
8717 * Set the iuserinfo.
8719 * @param string $iuserinfo
8722 public function set_userinfo($iuserinfo)
8724 if ($iuserinfo === null)
8726 $this->iuserinfo
= null;
8730 $this->iuserinfo
= $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
8731 $this->scheme_normalization();
8738 * Set the ihost. Returns true on success, false on failure (if there are
8739 * any invalid characters).
8741 * @param string $ihost
8744 public function set_host($ihost)
8746 if ($ihost === null)
8748 $this->ihost
= null;
8751 elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')
8753 if (SimplePie_Net_IPv6
::check_ipv6(substr($ihost, 1, -1)))
8755 $this->ihost
= '[' . SimplePie_Net_IPv6
::compress(substr($ihost, 1, -1)) . ']';
8759 $this->ihost
= null;
8765 $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
8767 // Lowercase, but ignore pct-encoded sections (as they should
8768 // remain uppercase). This must be done after the previous step
8769 // as that can add unescaped characters.
8771 $strlen = strlen($ihost);
8772 while (($position +
= strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)
8774 if ($ihost[$position] === '%')
8780 $ihost[$position] = strtolower($ihost[$position]);
8785 $this->ihost
= $ihost;
8788 $this->scheme_normalization();
8794 * Set the port. Returns true on success, false on failure (if there are
8795 * any invalid characters).
8797 * @param string $port
8800 public function set_port($port)
8807 elseif (strspn($port, '0123456789') === strlen($port))
8809 $this->port
= (int) $port;
8810 $this->scheme_normalization();
8823 * @param string $ipath
8826 public function set_path($ipath)
8834 $ipath = (string) $ipath;
8836 if (isset($cache[$ipath]))
8838 $this->ipath
= $cache[$ipath][(int) ($this->scheme
!== null)];
8842 $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
8843 $removed = $this->remove_dot_segments($valid);
8845 $cache[$ipath] = array($valid, $removed);
8846 $this->ipath
= ($this->scheme
!== null) ?
$removed : $valid;
8849 $this->scheme_normalization();
8856 * @param string $iquery
8859 public function set_query($iquery)
8861 if ($iquery === null)
8863 $this->iquery
= null;
8867 $this->iquery
= $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
8868 $this->scheme_normalization();
8874 * Set the ifragment.
8876 * @param string $ifragment
8879 public function set_fragment($ifragment)
8881 if ($ifragment === null)
8883 $this->ifragment
= null;
8887 $this->ifragment
= $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
8888 $this->scheme_normalization();
8894 * Convert an IRI to a URI (or parts thereof)
8898 public function to_uri($string)
8903 $non_ascii = implode('', range("\x80", "\xFF"));
8907 $strlen = strlen($string);
8908 while (($position +
= strcspn($string, $non_ascii, $position)) < $strlen)
8910 $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
8919 * Get the complete IRI
8923 public function get_iri()
8925 if (!$this->is_valid())
8931 if ($this->scheme
!== null)
8933 $iri .= $this->scheme
. ':';
8935 if (($iauthority = $this->get_iauthority()) !== null)
8937 $iri .= '//' . $iauthority;
8939 if ($this->ipath
!== '')
8941 $iri .= $this->ipath
;
8943 elseif (!empty($this->normalization
[$this->scheme
]['ipath']) && $iauthority !== null && $iauthority !== '')
8945 $iri .= $this->normalization
[$this->scheme
]['ipath'];
8947 if ($this->iquery
!== null)
8949 $iri .= '?' . $this->iquery
;
8951 if ($this->ifragment
!== null)
8953 $iri .= '#' . $this->ifragment
;
8960 * Get the complete URI
8964 public function get_uri()
8966 return $this->to_uri($this->get_iri());
8970 * Get the complete iauthority
8974 protected function get_iauthority()
8976 if ($this->iuserinfo
!== null ||
$this->ihost
!== null ||
$this->port
!== null)
8979 if ($this->iuserinfo
!== null)
8981 $iauthority .= $this->iuserinfo
. '@';
8983 if ($this->ihost
!== null)
8985 $iauthority .= $this->ihost
;
8987 if ($this->port
!== null)
8989 $iauthority .= ':' . $this->port
;
9000 * Get the complete authority
9004 protected function get_authority()
9006 $iauthority = $this->get_iauthority();
9007 if (is_string($iauthority))
9008 return $this->to_uri($iauthority);
9015 * Manages all item-related data
9017 * Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()}
9019 * This class can be overloaded with {@see SimplePie::set_item_class()}
9021 * @package SimplePie
9024 class SimplePie_Item
9040 var $data = array();
9046 * @var SimplePie_Registry
9048 protected $registry;
9051 * Create a new item object
9053 * This is usually used by {@see SimplePie::get_items} and
9054 * {@see SimplePie::get_item}. Avoid creating this manually.
9056 * @param SimplePie $feed Parent feed
9057 * @param array $data Raw data
9059 public function __construct($feed, $data)
9061 $this->feed
= $feed;
9062 $this->data
= $data;
9066 * Set the registry handler
9068 * This is usually used by {@see SimplePie_Registry::create}
9071 * @param SimplePie_Registry $registry
9073 public function set_registry(SimplePie_Registry
$registry)
9075 $this->registry
= $registry;
9079 * Get a string representation of the item
9083 public function __toString()
9085 return md5(serialize($this->data
));
9089 * Remove items that link back to this before destroying this object
9091 public function __destruct()
9093 if ((version_compare(PHP_VERSION
, '5.3', '<') ||
!gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
9100 * Get data for an item-level element
9102 * This method allows you to get access to ANY element/attribute that is a
9103 * sub-element of the item/entry tag.
9105 * See {@see SimplePie::get_feed_tags()} for a description of the return value
9108 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
9109 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
9110 * @param string $tag Tag name
9113 public function get_item_tags($namespace, $tag)
9115 if (isset($this->data
['child'][$namespace][$tag]))
9117 return $this->data
['child'][$namespace][$tag];
9126 * Get the base URL value from the parent feed
9130 * @param array $element
9133 public function get_base($element = array())
9135 return $this->feed
->get_base($element);
9139 * Sanitize feed data
9142 * @see SimplePie::sanitize()
9143 * @param string $data Data to sanitize
9144 * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
9145 * @param string $base Base URL to resolve URLs against
9146 * @return string Sanitized data
9148 public function sanitize($data, $type, $base = '')
9150 return $this->feed
->sanitize($data, $type, $base);
9154 * Get the parent feed
9156 * Note: this may not work as you think for multifeeds!
9158 * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed
9162 public function get_feed()
9168 * Get the unique identifier for the item
9170 * This is usually used when writing code to check for new items in a feed.
9172 * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute
9173 * for RDF. If none of these are supplied (or `$hash` is true), creates an
9174 * MD5 hash based on the permalink and title. If either of those are not
9175 * supplied, creates a hash based on the full feed data.
9178 * @param boolean $hash Should we force using a hash instead of the supplied ID?
9181 public function get_id($hash = false)
9185 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'id'))
9187 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9189 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'id'))
9191 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9193 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'guid'))
9195 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9197 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'identifier'))
9199 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9201 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'identifier'))
9203 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9205 elseif (isset($this->data
['attribs'][SIMPLEPIE_NAMESPACE_RDF
]['about']))
9207 return $this->sanitize($this->data
['attribs'][SIMPLEPIE_NAMESPACE_RDF
]['about'], SIMPLEPIE_CONSTRUCT_TEXT
);
9209 elseif (($return = $this->get_permalink()) !== null)
9213 elseif (($return = $this->get_title()) !== null)
9218 if ($this->get_permalink() !== null ||
$this->get_title() !== null)
9220 return md5($this->get_permalink() . $this->get_title());
9224 return md5(serialize($this->data
));
9229 * Get the title of the item
9231 * Uses `<atom:title>`, `<title>` or `<dc:title>`
9233 * @since Beta 2 (previously called `get_item_title` since 0.8)
9234 * @return string|null
9236 public function get_title()
9238 if (!isset($this->data
['title']))
9240 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'title'))
9242 $this->data
['title'] = $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9244 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'title'))
9246 $this->data
['title'] = $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9248 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'title'))
9250 $this->data
['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
9252 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'title'))
9254 $this->data
['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
9256 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'title'))
9258 $this->data
['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
9260 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'title'))
9262 $this->data
['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9264 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'title'))
9266 $this->data
['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9270 $this->data
['title'] = null;
9273 return $this->data
['title'];
9277 * Get the content for the item
9279 * Prefers summaries over full content , but will return full content if a
9280 * summary does not exist.
9282 * To prefer full content instead, use {@see get_content}
9284 * Uses `<atom:summary>`, `<description>`, `<dc:description>` or
9285 * `<itunes:subtitle>`
9288 * @param boolean $description_only Should we avoid falling back to the content?
9289 * @return string|null
9291 public function get_description($description_only = false)
9293 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'summary'))
9295 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9297 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'summary'))
9299 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9301 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'description'))
9303 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
9305 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'description'))
9307 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
9309 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'description'))
9311 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9313 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'description'))
9315 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9317 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'summary'))
9319 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
9321 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'subtitle'))
9323 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9325 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'description'))
9327 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
);
9330 elseif (!$description_only)
9332 return $this->get_content(true);
9341 * Get the content for the item
9343 * Prefers full content over summaries, but will return a summary if full
9344 * content does not exist.
9346 * To prefer summaries instead, use {@see get_description}
9348 * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)
9351 * @param boolean $content_only Should we avoid falling back to the description?
9352 * @return string|null
9354 public function get_content($content_only = false)
9356 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'content'))
9358 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9360 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'content'))
9362 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9364 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT
, 'encoded'))
9366 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
9368 elseif (!$content_only)
9370 return $this->get_description(true);
9379 * Get a category for the item
9381 * @since Beta 3 (previously called `get_categories()` since Beta 2)
9382 * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
9383 * @return SimplePie_Category|null
9385 public function get_category($key = 0)
9387 $categories = $this->get_categories();
9388 if (isset($categories[$key]))
9390 return $categories[$key];
9399 * Get all categories for the item
9401 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
9404 * @return array|null List of {@see SimplePie_Category} objects
9406 public function get_categories()
9408 $categories = array();
9410 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'category') as $category)
9415 if (isset($category['attribs']['']['term']))
9417 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT
);
9419 if (isset($category['attribs']['']['scheme']))
9421 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
9423 if (isset($category['attribs']['']['label']))
9425 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
9427 $categories[] = $this->registry
->create('Category', array($term, $scheme, $label));
9429 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'category') as $category)
9431 // This is really the label, but keep this as the term also for BC.
9432 // Label will also work on retrieving because that falls back to term.
9433 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9434 if (isset($category['attribs']['']['domain']))
9436 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT
);
9442 $categories[] = $this->registry
->create('Category', array($term, $scheme, null));
9444 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'subject') as $category)
9446 $categories[] = $this->registry
->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
9448 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'subject') as $category)
9450 $categories[] = $this->registry
->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
9453 if (!empty($categories))
9455 return array_unique($categories);
9464 * Get an author for the item
9467 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
9468 * @return SimplePie_Author|null
9470 public function get_author($key = 0)
9472 $authors = $this->get_authors();
9473 if (isset($authors[$key]))
9475 return $authors[$key];
9484 * Get a contributor for the item
9487 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
9488 * @return SimplePie_Author|null
9490 public function get_contributor($key = 0)
9492 $contributors = $this->get_contributors();
9493 if (isset($contributors[$key]))
9495 return $contributors[$key];
9504 * Get all contributors for the item
9506 * Uses `<atom:contributor>`
9509 * @return array|null List of {@see SimplePie_Author} objects
9511 public function get_contributors()
9513 $contributors = array();
9514 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'contributor') as $contributor)
9519 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data']))
9521 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9523 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['uri'][0]['data']))
9525 $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]));
9527 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data']))
9529 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9531 if ($name !== null ||
$email !== null ||
$uri !== null)
9533 $contributors[] = $this->registry
->create('Author', array($name, $uri, $email));
9536 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'contributor') as $contributor)
9541 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data']))
9543 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9545 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['url'][0]['data']))
9547 $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]));
9549 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data']))
9551 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9553 if ($name !== null ||
$email !== null ||
$url !== null)
9555 $contributors[] = $this->registry
->create('Author', array($name, $url, $email));
9559 if (!empty($contributors))
9561 return array_unique($contributors);
9570 * Get all authors for the item
9572 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
9575 * @return array|null List of {@see SimplePie_Author} objects
9577 public function get_authors()
9580 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'author') as $author)
9585 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data']))
9587 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9589 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['uri'][0]['data']))
9591 $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]));
9593 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data']))
9595 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9597 if ($name !== null ||
$email !== null ||
$uri !== null)
9599 $authors[] = $this->registry
->create('Author', array($name, $uri, $email));
9602 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'author'))
9607 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data']))
9609 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9611 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['url'][0]['data']))
9613 $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]));
9615 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data']))
9617 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9619 if ($name !== null ||
$email !== null ||
$url !== null)
9621 $authors[] = $this->registry
->create('Author', array($name, $url, $email));
9624 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'author'))
9626 $authors[] = $this->registry
->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
)));
9628 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'creator') as $author)
9630 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
9632 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'creator') as $author)
9634 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
9636 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'author') as $author)
9638 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
9641 if (!empty($authors))
9643 return array_unique($authors);
9645 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
9649 elseif ($authors = $this->feed
->get_authors())
9660 * Get the copyright info for the item
9662 * Uses `<atom:rights>` or `<dc:rights>`
9667 public function get_copyright()
9669 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'rights'))
9671 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
9673 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'rights'))
9675 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9677 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'rights'))
9679 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
9688 * Get the posting date/time for the item
9690 * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`,
9691 * `<atom:modified>`, `<pubDate>` or `<dc:date>`
9693 * Note: obeys PHP's timezone setting. To get a UTC date/time, use
9696 * @since Beta 2 (previously called `get_item_date` since 0.8)
9698 * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
9699 * @return int|string|null
9701 public function get_date($date_format = 'j F Y, g:i a')
9703 if (!isset($this->data
['date']))
9705 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'published'))
9707 $this->data
['date']['raw'] = $return[0]['data'];
9709 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'updated'))
9711 $this->data
['date']['raw'] = $return[0]['data'];
9713 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'issued'))
9715 $this->data
['date']['raw'] = $return[0]['data'];
9717 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'created'))
9719 $this->data
['date']['raw'] = $return[0]['data'];
9721 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'modified'))
9723 $this->data
['date']['raw'] = $return[0]['data'];
9725 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'pubDate'))
9727 $this->data
['date']['raw'] = $return[0]['data'];
9729 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'date'))
9731 $this->data
['date']['raw'] = $return[0]['data'];
9733 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'date'))
9735 $this->data
['date']['raw'] = $return[0]['data'];
9738 if (!empty($this->data
['date']['raw']))
9740 $parser = $this->registry
->call('Parse_Date', 'get');
9741 $this->data
['date']['parsed'] = $parser->parse($this->data
['date']['raw']);
9745 $this->data
['date'] = null;
9748 if ($this->data
['date'])
9750 $date_format = (string) $date_format;
9751 switch ($date_format)
9754 return $this->sanitize($this->data
['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT
);
9757 return $this->data
['date']['parsed'];
9760 return date($date_format, $this->data
['date']['parsed']);
9770 * Get the update date/time for the item
9772 * Uses `<atom:updated>`
9774 * Note: obeys PHP's timezone setting. To get a UTC date/time, use
9777 * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
9778 * @return int|string|null
9780 public function get_updated_date($date_format = 'j F Y, g:i a')
9782 if (!isset($this->data
['updated']))
9784 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'updated'))
9786 $this->data
['updated']['raw'] = $return[0]['data'];
9789 if (!empty($this->data
['updated']['raw']))
9791 $parser = $this->registry
->call('Parse_Date', 'get');
9792 $this->data
['updated']['parsed'] = $parser->parse($this->data
['date']['raw']);
9796 $this->data
['updated'] = null;
9799 if ($this->data
['updated'])
9801 $date_format = (string) $date_format;
9802 switch ($date_format)
9805 return $this->sanitize($this->data
['updated']['raw'], SIMPLEPIE_CONSTRUCT_TEXT
);
9808 return $this->data
['updated']['parsed'];
9811 return date($date_format, $this->data
['updated']['parsed']);
9821 * Get the localized posting date/time for the item
9823 * Returns the date formatted in the localized language. To display in
9824 * languages other than the server's default, you need to change the locale
9825 * with {@link http://php.net/setlocale setlocale()}. The available
9826 * localizations depend on which ones are installed on your web server.
9830 * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data)
9831 * @return int|string|null
9833 public function get_local_date($date_format = '%c')
9837 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT
);
9839 elseif (($date = $this->get_date('U')) !== null && $date !== false)
9841 return strftime($date_format, $date);
9850 * Get the posting date/time for the item (UTC time)
9853 * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
9854 * @return int|string|null
9856 public function get_gmdate($date_format = 'j F Y, g:i a')
9858 $date = $this->get_date('U');
9864 return gmdate($date_format, $date);
9868 * Get the update date/time for the item (UTC time)
9870 * @see get_updated_date
9871 * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
9872 * @return int|string|null
9874 public function get_updated_gmdate($date_format = 'j F Y, g:i a')
9876 $date = $this->get_updated_date('U');
9882 return gmdate($date_format, $date);
9886 * Get the permalink for the item
9888 * Returns the first link available with a relationship of "alternate".
9889 * Identical to {@see get_link()} with key 0
9893 * @return string|null Permalink URL
9895 public function get_permalink()
9897 $link = $this->get_link();
9898 $enclosure = $this->get_enclosure(0);
9903 elseif ($enclosure !== null)
9905 return $enclosure->get_link();
9914 * Get a single link for the item
9917 * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
9918 * @param string $rel The relationship of the link to return
9919 * @return string|null Link URL
9921 public function get_link($key = 0, $rel = 'alternate')
9923 $links = $this->get_links($rel);
9924 if ($links[$key] !== null)
9926 return $links[$key];
9935 * Get all links for the item
9937 * Uses `<atom:link>`, `<link>` or `<guid>`
9940 * @param string $rel The relationship of links to return
9941 * @return array|null Links found for the item (strings)
9943 public function get_links($rel = 'alternate')
9945 if (!isset($this->data
['links']))
9947 $this->data
['links'] = array();
9948 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'link') as $link)
9950 if (isset($link['attribs']['']['href']))
9952 $link_rel = (isset($link['attribs']['']['rel'])) ?
$link['attribs']['']['rel'] : 'alternate';
9953 $this->data
['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
9957 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'link') as $link)
9959 if (isset($link['attribs']['']['href']))
9961 $link_rel = (isset($link['attribs']['']['rel'])) ?
$link['attribs']['']['rel'] : 'alternate';
9962 $this->data
['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
9965 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'link'))
9967 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
9969 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'link'))
9971 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
9973 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'link'))
9975 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
9977 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'guid'))
9979 if (!isset($links[0]['attribs']['']['isPermaLink']) ||
strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
9981 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
9985 $keys = array_keys($this->data
['links']);
9986 foreach ($keys as $key)
9988 if ($this->registry
->call('Misc', 'is_isegment_nz_nc', array($key)))
9990 if (isset($this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key]))
9992 $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key] = array_merge($this->data
['links'][$key], $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key]);
9993 $this->data
['links'][$key] =& $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key];
9997 $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key] =& $this->data
['links'][$key];
10000 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
)
10002 $this->data
['links'][substr($key, 41)] =& $this->data
['links'][$key];
10004 $this->data
['links'][$key] = array_unique($this->data
['links'][$key]);
10007 if (isset($this->data
['links'][$rel]))
10009 return $this->data
['links'][$rel];
10018 * Get an enclosure from the item
10020 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
10023 * @todo Add ability to prefer one type of content over another (in a media group).
10024 * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1
10025 * @return SimplePie_Enclosure|null
10027 public function get_enclosure($key = 0, $prefer = null)
10029 $enclosures = $this->get_enclosures();
10030 if (isset($enclosures[$key]))
10032 return $enclosures[$key];
10041 * Get all available enclosures (podcasts, etc.)
10043 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
10045 * At this point, we're pretty much assuming that all enclosures for an item
10046 * are the same content. Anything else is too complicated to
10047 * properly support.
10050 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
10051 * @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).
10052 * @return array|null List of SimplePie_Enclosure items
10054 public function get_enclosures()
10056 if (!isset($this->data
['enclosures']))
10058 $this->data
['enclosures'] = array();
10061 $captions_parent = null;
10062 $categories_parent = null;
10063 $copyrights_parent = null;
10064 $credits_parent = null;
10065 $description_parent = null;
10066 $duration_parent = null;
10067 $hashes_parent = null;
10068 $keywords_parent = null;
10069 $player_parent = null;
10070 $ratings_parent = null;
10071 $restrictions_parent = null;
10072 $thumbnails_parent = null;
10073 $title_parent = null;
10075 // Let's do the channel and item-level ones first, and just re-use them if we need to.
10076 $parent = $this->get_feed();
10079 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'text'))
10081 foreach ($captions as $caption)
10083 $caption_type = null;
10084 $caption_lang = null;
10085 $caption_startTime = null;
10086 $caption_endTime = null;
10087 $caption_text = null;
10088 if (isset($caption['attribs']['']['type']))
10090 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10092 if (isset($caption['attribs']['']['lang']))
10094 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
10096 if (isset($caption['attribs']['']['start']))
10098 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT
);
10100 if (isset($caption['attribs']['']['end']))
10102 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT
);
10104 if (isset($caption['data']))
10106 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10108 $captions_parent[] = $this->registry
->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
10111 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'text'))
10113 foreach ($captions as $caption)
10115 $caption_type = null;
10116 $caption_lang = null;
10117 $caption_startTime = null;
10118 $caption_endTime = null;
10119 $caption_text = null;
10120 if (isset($caption['attribs']['']['type']))
10122 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10124 if (isset($caption['attribs']['']['lang']))
10126 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
10128 if (isset($caption['attribs']['']['start']))
10130 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT
);
10132 if (isset($caption['attribs']['']['end']))
10134 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT
);
10136 if (isset($caption['data']))
10138 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10140 $captions_parent[] = $this->registry
->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
10143 if (is_array($captions_parent))
10145 $captions_parent = array_values(array_unique($captions_parent));
10149 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'category') as $category)
10154 if (isset($category['data']))
10156 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10158 if (isset($category['attribs']['']['scheme']))
10160 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10164 $scheme = 'http://search.yahoo.com/mrss/category_schema';
10166 if (isset($category['attribs']['']['label']))
10168 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
10170 $categories_parent[] = $this->registry
->create('Category', array($term, $scheme, $label));
10172 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'category') as $category)
10177 if (isset($category['data']))
10179 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10181 if (isset($category['attribs']['']['scheme']))
10183 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10187 $scheme = 'http://search.yahoo.com/mrss/category_schema';
10189 if (isset($category['attribs']['']['label']))
10191 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
10193 $categories_parent[] = $this->registry
->create('Category', array($term, $scheme, $label));
10195 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'category') as $category)
10198 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
10200 if (isset($category['attribs']['']['text']))
10202 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT
);
10204 $categories_parent[] = $this->registry
->create('Category', array($term, $scheme, $label));
10206 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES
]['category']))
10208 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES
]['category'] as $subcategory)
10210 if (isset($subcategory['attribs']['']['text']))
10212 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT
);
10214 $categories_parent[] = $this->registry
->create('Category', array($term, $scheme, $label));
10218 if (is_array($categories_parent))
10220 $categories_parent = array_values(array_unique($categories_parent));
10224 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'copyright'))
10226 $copyright_url = null;
10227 $copyright_label = null;
10228 if (isset($copyright[0]['attribs']['']['url']))
10230 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT
);
10232 if (isset($copyright[0]['data']))
10234 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10236 $copyrights_parent = $this->registry
->create('Copyright', array($copyright_url, $copyright_label));
10238 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'copyright'))
10240 $copyright_url = null;
10241 $copyright_label = null;
10242 if (isset($copyright[0]['attribs']['']['url']))
10244 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT
);
10246 if (isset($copyright[0]['data']))
10248 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10250 $copyrights_parent = $this->registry
->create('Copyright', array($copyright_url, $copyright_label));
10254 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'credit'))
10256 foreach ($credits as $credit)
10258 $credit_role = null;
10259 $credit_scheme = null;
10260 $credit_name = null;
10261 if (isset($credit['attribs']['']['role']))
10263 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT
);
10265 if (isset($credit['attribs']['']['scheme']))
10267 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10271 $credit_scheme = 'urn:ebu';
10273 if (isset($credit['data']))
10275 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10277 $credits_parent[] = $this->registry
->create('Credit', array($credit_role, $credit_scheme, $credit_name));
10280 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'credit'))
10282 foreach ($credits as $credit)
10284 $credit_role = null;
10285 $credit_scheme = null;
10286 $credit_name = null;
10287 if (isset($credit['attribs']['']['role']))
10289 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT
);
10291 if (isset($credit['attribs']['']['scheme']))
10293 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10297 $credit_scheme = 'urn:ebu';
10299 if (isset($credit['data']))
10301 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10303 $credits_parent[] = $this->registry
->create('Credit', array($credit_role, $credit_scheme, $credit_name));
10306 if (is_array($credits_parent))
10308 $credits_parent = array_values(array_unique($credits_parent));
10312 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'description'))
10314 if (isset($description_parent[0]['data']))
10316 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10319 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'description'))
10321 if (isset($description_parent[0]['data']))
10323 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10328 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'duration'))
10333 if (isset($duration_parent[0]['data']))
10335 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
10336 if (sizeof($temp) > 0)
10338 $seconds = (int) array_pop($temp);
10340 if (sizeof($temp) > 0)
10342 $minutes = (int) array_pop($temp);
10343 $seconds +
= $minutes * 60;
10345 if (sizeof($temp) > 0)
10347 $hours = (int) array_pop($temp);
10348 $seconds +
= $hours * 3600;
10351 $duration_parent = $seconds;
10356 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'hash'))
10358 foreach ($hashes_iterator as $hash)
10362 if (isset($hash['data']))
10364 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10366 if (isset($hash['attribs']['']['algo']))
10368 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT
);
10374 $hashes_parent[] = $algo.':'.$value;
10377 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'hash'))
10379 foreach ($hashes_iterator as $hash)
10383 if (isset($hash['data']))
10385 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10387 if (isset($hash['attribs']['']['algo']))
10389 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT
);
10395 $hashes_parent[] = $algo.':'.$value;
10398 if (is_array($hashes_parent))
10400 $hashes_parent = array_values(array_unique($hashes_parent));
10404 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'keywords'))
10406 if (isset($keywords[0]['data']))
10408 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
10409 foreach ($temp as $word)
10411 $keywords_parent[] = trim($word);
10416 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'keywords'))
10418 if (isset($keywords[0]['data']))
10420 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
10421 foreach ($temp as $word)
10423 $keywords_parent[] = trim($word);
10428 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'keywords'))
10430 if (isset($keywords[0]['data']))
10432 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
10433 foreach ($temp as $word)
10435 $keywords_parent[] = trim($word);
10440 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'keywords'))
10442 if (isset($keywords[0]['data']))
10444 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
10445 foreach ($temp as $word)
10447 $keywords_parent[] = trim($word);
10452 if (is_array($keywords_parent))
10454 $keywords_parent = array_values(array_unique($keywords_parent));
10458 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'player'))
10460 if (isset($player_parent[0]['attribs']['']['url']))
10462 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
10465 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'player'))
10467 if (isset($player_parent[0]['attribs']['']['url']))
10469 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
10474 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'rating'))
10476 foreach ($ratings as $rating)
10478 $rating_scheme = null;
10479 $rating_value = null;
10480 if (isset($rating['attribs']['']['scheme']))
10482 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10486 $rating_scheme = 'urn:simple';
10488 if (isset($rating['data']))
10490 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10492 $ratings_parent[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
10495 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'explicit'))
10497 foreach ($ratings as $rating)
10499 $rating_scheme = 'urn:itunes';
10500 $rating_value = null;
10501 if (isset($rating['data']))
10503 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10505 $ratings_parent[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
10508 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'rating'))
10510 foreach ($ratings as $rating)
10512 $rating_scheme = null;
10513 $rating_value = null;
10514 if (isset($rating['attribs']['']['scheme']))
10516 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10520 $rating_scheme = 'urn:simple';
10522 if (isset($rating['data']))
10524 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10526 $ratings_parent[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
10529 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'explicit'))
10531 foreach ($ratings as $rating)
10533 $rating_scheme = 'urn:itunes';
10534 $rating_value = null;
10535 if (isset($rating['data']))
10537 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10539 $ratings_parent[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
10542 if (is_array($ratings_parent))
10544 $ratings_parent = array_values(array_unique($ratings_parent));
10548 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'restriction'))
10550 foreach ($restrictions as $restriction)
10552 $restriction_relationship = null;
10553 $restriction_type = null;
10554 $restriction_value = null;
10555 if (isset($restriction['attribs']['']['relationship']))
10557 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT
);
10559 if (isset($restriction['attribs']['']['type']))
10561 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10563 if (isset($restriction['data']))
10565 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10567 $restrictions_parent[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10570 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'block'))
10572 foreach ($restrictions as $restriction)
10574 $restriction_relationship = 'allow';
10575 $restriction_type = null;
10576 $restriction_value = 'itunes';
10577 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
10579 $restriction_relationship = 'deny';
10581 $restrictions_parent[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10584 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'restriction'))
10586 foreach ($restrictions as $restriction)
10588 $restriction_relationship = null;
10589 $restriction_type = null;
10590 $restriction_value = null;
10591 if (isset($restriction['attribs']['']['relationship']))
10593 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT
);
10595 if (isset($restriction['attribs']['']['type']))
10597 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10599 if (isset($restriction['data']))
10601 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10603 $restrictions_parent[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10606 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'block'))
10608 foreach ($restrictions as $restriction)
10610 $restriction_relationship = 'allow';
10611 $restriction_type = null;
10612 $restriction_value = 'itunes';
10613 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
10615 $restriction_relationship = 'deny';
10617 $restrictions_parent[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
10620 if (is_array($restrictions_parent))
10622 $restrictions_parent = array_values(array_unique($restrictions_parent));
10626 $restrictions_parent = array(new SimplePie_Restriction('allow', null, 'default'));
10630 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'thumbnail'))
10632 foreach ($thumbnails as $thumbnail)
10634 if (isset($thumbnail['attribs']['']['url']))
10636 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
10640 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'thumbnail'))
10642 foreach ($thumbnails as $thumbnail)
10644 if (isset($thumbnail['attribs']['']['url']))
10646 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
10652 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'title'))
10654 if (isset($title_parent[0]['data']))
10656 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10659 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'title'))
10661 if (isset($title_parent[0]['data']))
10663 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10667 // Clear the memory
10674 $expression = null;
10677 $javascript = null;
10681 $samplingrate = null;
10688 $categories = null;
10689 $copyrights = null;
10691 $description = null;
10696 $restrictions = null;
10697 $thumbnails = null;
10700 // If we have media:group tags, loop through them.
10701 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS
, 'group') as $group)
10703 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['content']))
10705 // If we have media:content tags, loop through them.
10706 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['content'] as $content)
10708 if (isset($content['attribs']['']['url']))
10714 $expression = null;
10717 $javascript = null;
10721 $samplingrate = null;
10728 $categories = null;
10729 $copyrights = null;
10731 $description = null;
10736 $restrictions = null;
10737 $thumbnails = null;
10740 // Start checking the attributes of media:content
10741 if (isset($content['attribs']['']['bitrate']))
10743 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT
);
10745 if (isset($content['attribs']['']['channels']))
10747 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT
);
10749 if (isset($content['attribs']['']['duration']))
10751 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT
);
10755 $duration = $duration_parent;
10757 if (isset($content['attribs']['']['expression']))
10759 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT
);
10761 if (isset($content['attribs']['']['framerate']))
10763 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT
);
10765 if (isset($content['attribs']['']['height']))
10767 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT
);
10769 if (isset($content['attribs']['']['lang']))
10771 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
10773 if (isset($content['attribs']['']['fileSize']))
10775 $length = ceil($content['attribs']['']['fileSize']);
10777 if (isset($content['attribs']['']['medium']))
10779 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT
);
10781 if (isset($content['attribs']['']['samplingrate']))
10783 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT
);
10785 if (isset($content['attribs']['']['type']))
10787 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10789 if (isset($content['attribs']['']['width']))
10791 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT
);
10793 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
10795 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
10798 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['text']))
10800 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['text'] as $caption)
10802 $caption_type = null;
10803 $caption_lang = null;
10804 $caption_startTime = null;
10805 $caption_endTime = null;
10806 $caption_text = null;
10807 if (isset($caption['attribs']['']['type']))
10809 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10811 if (isset($caption['attribs']['']['lang']))
10813 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
10815 if (isset($caption['attribs']['']['start']))
10817 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT
);
10819 if (isset($caption['attribs']['']['end']))
10821 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT
);
10823 if (isset($caption['data']))
10825 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10827 $captions[] = $this->registry
->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
10829 if (is_array($captions))
10831 $captions = array_values(array_unique($captions));
10834 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['text']))
10836 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['text'] as $caption)
10838 $caption_type = null;
10839 $caption_lang = null;
10840 $caption_startTime = null;
10841 $caption_endTime = null;
10842 $caption_text = null;
10843 if (isset($caption['attribs']['']['type']))
10845 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
10847 if (isset($caption['attribs']['']['lang']))
10849 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
10851 if (isset($caption['attribs']['']['start']))
10853 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT
);
10855 if (isset($caption['attribs']['']['end']))
10857 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT
);
10859 if (isset($caption['data']))
10861 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10863 $captions[] = $this->registry
->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
10865 if (is_array($captions))
10867 $captions = array_values(array_unique($captions));
10872 $captions = $captions_parent;
10876 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['category']))
10878 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['category'] as $category)
10883 if (isset($category['data']))
10885 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10887 if (isset($category['attribs']['']['scheme']))
10889 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10893 $scheme = 'http://search.yahoo.com/mrss/category_schema';
10895 if (isset($category['attribs']['']['label']))
10897 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
10899 $categories[] = $this->registry
->create('Category', array($term, $scheme, $label));
10902 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['category']))
10904 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['category'] as $category)
10909 if (isset($category['data']))
10911 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10913 if (isset($category['attribs']['']['scheme']))
10915 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10919 $scheme = 'http://search.yahoo.com/mrss/category_schema';
10921 if (isset($category['attribs']['']['label']))
10923 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
10925 $categories[] = $this->registry
->create('Category', array($term, $scheme, $label));
10928 if (is_array($categories) && is_array($categories_parent))
10930 $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
10932 elseif (is_array($categories))
10934 $categories = array_values(array_unique($categories));
10936 elseif (is_array($categories_parent))
10938 $categories = array_values(array_unique($categories_parent));
10942 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright']))
10944 $copyright_url = null;
10945 $copyright_label = null;
10946 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['attribs']['']['url']))
10948 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT
);
10950 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['data']))
10952 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10954 $copyrights = $this->registry
->create('Copyright', array($copyright_url, $copyright_label));
10956 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright']))
10958 $copyright_url = null;
10959 $copyright_label = null;
10960 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['attribs']['']['url']))
10962 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT
);
10964 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['data']))
10966 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10968 $copyrights = $this->registry
->create('Copyright', array($copyright_url, $copyright_label));
10972 $copyrights = $copyrights_parent;
10976 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['credit']))
10978 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['credit'] as $credit)
10980 $credit_role = null;
10981 $credit_scheme = null;
10982 $credit_name = null;
10983 if (isset($credit['attribs']['']['role']))
10985 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT
);
10987 if (isset($credit['attribs']['']['scheme']))
10989 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
10993 $credit_scheme = 'urn:ebu';
10995 if (isset($credit['data']))
10997 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
10999 $credits[] = $this->registry
->create('Credit', array($credit_role, $credit_scheme, $credit_name));
11001 if (is_array($credits))
11003 $credits = array_values(array_unique($credits));
11006 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['credit']))
11008 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['credit'] as $credit)
11010 $credit_role = null;
11011 $credit_scheme = null;
11012 $credit_name = null;
11013 if (isset($credit['attribs']['']['role']))
11015 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT
);
11017 if (isset($credit['attribs']['']['scheme']))
11019 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
11023 $credit_scheme = 'urn:ebu';
11025 if (isset($credit['data']))
11027 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11029 $credits[] = $this->registry
->create('Credit', array($credit_role, $credit_scheme, $credit_name));
11031 if (is_array($credits))
11033 $credits = array_values(array_unique($credits));
11038 $credits = $credits_parent;
11042 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['description']))
11044 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11046 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['description']))
11048 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11052 $description = $description_parent;
11056 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['hash']))
11058 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['hash'] as $hash)
11062 if (isset($hash['data']))
11064 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11066 if (isset($hash['attribs']['']['algo']))
11068 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT
);
11074 $hashes[] = $algo.':'.$value;
11076 if (is_array($hashes))
11078 $hashes = array_values(array_unique($hashes));
11081 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['hash']))
11083 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['hash'] as $hash)
11087 if (isset($hash['data']))
11089 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11091 if (isset($hash['attribs']['']['algo']))
11093 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT
);
11099 $hashes[] = $algo.':'.$value;
11101 if (is_array($hashes))
11103 $hashes = array_values(array_unique($hashes));
11108 $hashes = $hashes_parent;
11112 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords']))
11114 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords'][0]['data']))
11116 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
11117 foreach ($temp as $word)
11119 $keywords[] = trim($word);
11123 if (is_array($keywords))
11125 $keywords = array_values(array_unique($keywords));
11128 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords']))
11130 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords'][0]['data']))
11132 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
11133 foreach ($temp as $word)
11135 $keywords[] = trim($word);
11139 if (is_array($keywords))
11141 $keywords = array_values(array_unique($keywords));
11146 $keywords = $keywords_parent;
11150 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player']))
11152 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11154 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player']))
11156 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11160 $player = $player_parent;
11164 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['rating']))
11166 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['rating'] as $rating)
11168 $rating_scheme = null;
11169 $rating_value = null;
11170 if (isset($rating['attribs']['']['scheme']))
11172 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
11176 $rating_scheme = 'urn:simple';
11178 if (isset($rating['data']))
11180 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11182 $ratings[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
11184 if (is_array($ratings))
11186 $ratings = array_values(array_unique($ratings));
11189 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['rating']))
11191 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['rating'] as $rating)
11193 $rating_scheme = null;
11194 $rating_value = null;
11195 if (isset($rating['attribs']['']['scheme']))
11197 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
11201 $rating_scheme = 'urn:simple';
11203 if (isset($rating['data']))
11205 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11207 $ratings[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
11209 if (is_array($ratings))
11211 $ratings = array_values(array_unique($ratings));
11216 $ratings = $ratings_parent;
11220 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['restriction']))
11222 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['restriction'] as $restriction)
11224 $restriction_relationship = null;
11225 $restriction_type = null;
11226 $restriction_value = null;
11227 if (isset($restriction['attribs']['']['relationship']))
11229 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT
);
11231 if (isset($restriction['attribs']['']['type']))
11233 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11235 if (isset($restriction['data']))
11237 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11239 $restrictions[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
11241 if (is_array($restrictions))
11243 $restrictions = array_values(array_unique($restrictions));
11246 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['restriction']))
11248 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['restriction'] as $restriction)
11250 $restriction_relationship = null;
11251 $restriction_type = null;
11252 $restriction_value = null;
11253 if (isset($restriction['attribs']['']['relationship']))
11255 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT
);
11257 if (isset($restriction['attribs']['']['type']))
11259 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11261 if (isset($restriction['data']))
11263 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11265 $restrictions[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
11267 if (is_array($restrictions))
11269 $restrictions = array_values(array_unique($restrictions));
11274 $restrictions = $restrictions_parent;
11278 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['thumbnail']))
11280 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['thumbnail'] as $thumbnail)
11282 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11284 if (is_array($thumbnails))
11286 $thumbnails = array_values(array_unique($thumbnails));
11289 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['thumbnail']))
11291 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['thumbnail'] as $thumbnail)
11293 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11295 if (is_array($thumbnails))
11297 $thumbnails = array_values(array_unique($thumbnails));
11302 $thumbnails = $thumbnails_parent;
11306 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['title']))
11308 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11310 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['title']))
11312 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11316 $title = $title_parent;
11319 $this->data
['enclosures'][] = $this->registry
->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
11325 // If we have standalone media:content tags, loop through them.
11326 if (isset($this->data
['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['content']))
11328 foreach ((array) $this->data
['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['content'] as $content)
11330 if (isset($content['attribs']['']['url']) ||
isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player']))
11336 $expression = null;
11339 $javascript = null;
11343 $samplingrate = null;
11350 $categories = null;
11351 $copyrights = null;
11353 $description = null;
11358 $restrictions = null;
11359 $thumbnails = null;
11362 // Start checking the attributes of media:content
11363 if (isset($content['attribs']['']['bitrate']))
11365 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT
);
11367 if (isset($content['attribs']['']['channels']))
11369 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT
);
11371 if (isset($content['attribs']['']['duration']))
11373 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT
);
11377 $duration = $duration_parent;
11379 if (isset($content['attribs']['']['expression']))
11381 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT
);
11383 if (isset($content['attribs']['']['framerate']))
11385 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT
);
11387 if (isset($content['attribs']['']['height']))
11389 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT
);
11391 if (isset($content['attribs']['']['lang']))
11393 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
11395 if (isset($content['attribs']['']['fileSize']))
11397 $length = ceil($content['attribs']['']['fileSize']);
11399 if (isset($content['attribs']['']['medium']))
11401 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT
);
11403 if (isset($content['attribs']['']['samplingrate']))
11405 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT
);
11407 if (isset($content['attribs']['']['type']))
11409 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11411 if (isset($content['attribs']['']['width']))
11413 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT
);
11415 if (isset($content['attribs']['']['url']))
11417 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11419 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
11422 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['text']))
11424 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['text'] as $caption)
11426 $caption_type = null;
11427 $caption_lang = null;
11428 $caption_startTime = null;
11429 $caption_endTime = null;
11430 $caption_text = null;
11431 if (isset($caption['attribs']['']['type']))
11433 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11435 if (isset($caption['attribs']['']['lang']))
11437 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
11439 if (isset($caption['attribs']['']['start']))
11441 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT
);
11443 if (isset($caption['attribs']['']['end']))
11445 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT
);
11447 if (isset($caption['data']))
11449 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11451 $captions[] = $this->registry
->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
11453 if (is_array($captions))
11455 $captions = array_values(array_unique($captions));
11460 $captions = $captions_parent;
11464 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['category']))
11466 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['category'] as $category)
11471 if (isset($category['data']))
11473 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11475 if (isset($category['attribs']['']['scheme']))
11477 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
11481 $scheme = 'http://search.yahoo.com/mrss/category_schema';
11483 if (isset($category['attribs']['']['label']))
11485 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
11487 $categories[] = $this->registry
->create('Category', array($term, $scheme, $label));
11490 if (is_array($categories) && is_array($categories_parent))
11492 $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
11494 elseif (is_array($categories))
11496 $categories = array_values(array_unique($categories));
11498 elseif (is_array($categories_parent))
11500 $categories = array_values(array_unique($categories_parent));
11504 $categories = null;
11508 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright']))
11510 $copyright_url = null;
11511 $copyright_label = null;
11512 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['attribs']['']['url']))
11514 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT
);
11516 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['data']))
11518 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11520 $copyrights = $this->registry
->create('Copyright', array($copyright_url, $copyright_label));
11524 $copyrights = $copyrights_parent;
11528 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['credit']))
11530 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['credit'] as $credit)
11532 $credit_role = null;
11533 $credit_scheme = null;
11534 $credit_name = null;
11535 if (isset($credit['attribs']['']['role']))
11537 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT
);
11539 if (isset($credit['attribs']['']['scheme']))
11541 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
11545 $credit_scheme = 'urn:ebu';
11547 if (isset($credit['data']))
11549 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11551 $credits[] = $this->registry
->create('Credit', array($credit_role, $credit_scheme, $credit_name));
11553 if (is_array($credits))
11555 $credits = array_values(array_unique($credits));
11560 $credits = $credits_parent;
11564 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['description']))
11566 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11570 $description = $description_parent;
11574 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['hash']))
11576 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['hash'] as $hash)
11580 if (isset($hash['data']))
11582 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11584 if (isset($hash['attribs']['']['algo']))
11586 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT
);
11592 $hashes[] = $algo.':'.$value;
11594 if (is_array($hashes))
11596 $hashes = array_values(array_unique($hashes));
11601 $hashes = $hashes_parent;
11605 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords']))
11607 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords'][0]['data']))
11609 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
));
11610 foreach ($temp as $word)
11612 $keywords[] = trim($word);
11616 if (is_array($keywords))
11618 $keywords = array_values(array_unique($keywords));
11623 $keywords = $keywords_parent;
11627 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player']))
11629 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11633 $player = $player_parent;
11637 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['rating']))
11639 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['rating'] as $rating)
11641 $rating_scheme = null;
11642 $rating_value = null;
11643 if (isset($rating['attribs']['']['scheme']))
11645 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
11649 $rating_scheme = 'urn:simple';
11651 if (isset($rating['data']))
11653 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11655 $ratings[] = $this->registry
->create('Rating', array($rating_scheme, $rating_value));
11657 if (is_array($ratings))
11659 $ratings = array_values(array_unique($ratings));
11664 $ratings = $ratings_parent;
11668 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['restriction']))
11670 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['restriction'] as $restriction)
11672 $restriction_relationship = null;
11673 $restriction_type = null;
11674 $restriction_value = null;
11675 if (isset($restriction['attribs']['']['relationship']))
11677 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT
);
11679 if (isset($restriction['attribs']['']['type']))
11681 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11683 if (isset($restriction['data']))
11685 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11687 $restrictions[] = $this->registry
->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
11689 if (is_array($restrictions))
11691 $restrictions = array_values(array_unique($restrictions));
11696 $restrictions = $restrictions_parent;
11700 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['thumbnail']))
11702 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['thumbnail'] as $thumbnail)
11704 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
);
11706 if (is_array($thumbnails))
11708 $thumbnails = array_values(array_unique($thumbnails));
11713 $thumbnails = $thumbnails_parent;
11717 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['title']))
11719 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS
]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
11723 $title = $title_parent;
11726 $this->data
['enclosures'][] = $this->registry
->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
11731 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'link') as $link)
11733 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
11739 $expression = null;
11742 $javascript = null;
11746 $samplingrate = null;
11751 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
11752 if (isset($link['attribs']['']['type']))
11754 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11756 if (isset($link['attribs']['']['length']))
11758 $length = ceil($link['attribs']['']['length']);
11761 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
11762 $this->data
['enclosures'][] = $this->registry
->create('Enclosure', array($url, $type, $length, null, $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));
11766 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'link') as $link)
11768 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
11774 $expression = null;
11777 $javascript = null;
11781 $samplingrate = null;
11786 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
11787 if (isset($link['attribs']['']['type']))
11789 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11791 if (isset($link['attribs']['']['length']))
11793 $length = ceil($link['attribs']['']['length']);
11796 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
11797 $this->data
['enclosures'][] = $this->registry
->create('Enclosure', array($url, $type, $length, null, $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));
11801 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'enclosure'))
11803 if (isset($enclosure[0]['attribs']['']['url']))
11809 $expression = null;
11812 $javascript = null;
11816 $samplingrate = null;
11821 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($enclosure[0]));
11822 if (isset($enclosure[0]['attribs']['']['type']))
11824 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT
);
11826 if (isset($enclosure[0]['attribs']['']['length']))
11828 $length = ceil($enclosure[0]['attribs']['']['length']);
11831 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
11832 $this->data
['enclosures'][] = $this->registry
->create('Enclosure', array($url, $type, $length, null, $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));
11836 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))
11838 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
11839 $this->data
['enclosures'][] = $this->registry
->create('Enclosure', array($url, $type, $length, null, $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));
11842 $this->data
['enclosures'] = array_values(array_unique($this->data
['enclosures']));
11844 if (!empty($this->data
['enclosures']))
11846 return $this->data
['enclosures'];
11855 * Get the latitude coordinates for the item
11857 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
11859 * Uses `<geo:lat>` or `<georss:point>`
11862 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
11863 * @link http://www.georss.org/ GeoRSS
11864 * @return string|null
11866 public function get_latitude()
11868 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'lat'))
11870 return (float) $return[0]['data'];
11872 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))
11874 return (float) $match[1];
11883 * Get the longitude coordinates for the item
11885 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
11887 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
11890 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
11891 * @link http://www.georss.org/ GeoRSS
11892 * @return string|null
11894 public function get_longitude()
11896 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'long'))
11898 return (float) $return[0]['data'];
11900 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'lon'))
11902 return (float) $return[0]['data'];
11904 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))
11906 return (float) $match[2];
11915 * Get the `<atom:source>` for the item
11918 * @return SimplePie_Source|null
11920 public function get_source()
11922 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'source'))
11924 return $this->registry
->create('Source', array($this, $return[0]));
11934 * Used for feed auto-discovery
11937 * This class can be overloaded with {@see SimplePie::set_locator_class()}
11939 * @package SimplePie
11941 class SimplePie_Locator
11946 var $local = array();
11947 var $elsewhere = array();
11948 var $cached_entities = array();
11951 var $base_location = 0;
11952 var $checked_feeds = 0;
11953 var $max_checked_feeds = 10;
11954 protected $registry;
11956 public function __construct(SimplePie_File
$file, $timeout = 10, $useragent = null, $max_checked_feeds = 10)
11958 $this->file
= $file;
11959 $this->useragent
= $useragent;
11960 $this->timeout
= $timeout;
11961 $this->max_checked_feeds
= $max_checked_feeds;
11963 if (class_exists('DOMDocument'))
11965 $this->dom
= new DOMDocument();
11967 set_error_handler(array('SimplePie_Misc', 'silence_errors'));
11968 $this->dom
->loadHTML($this->file
->body
);
11969 restore_error_handler();
11977 public function set_registry(SimplePie_Registry
$registry)
11979 $this->registry
= $registry;
11982 public function find($type = SIMPLEPIE_LOCATOR_ALL
, &$working)
11984 if ($this->is_feed($this->file
))
11986 return $this->file
;
11989 if ($this->file
->method
& SIMPLEPIE_FILE_SOURCE_REMOTE
)
11991 $sniffer = $this->registry
->create('Content_Type_Sniffer', array($this->file
));
11992 if ($sniffer->get_type() !== 'text/html')
11998 if ($type & ~SIMPLEPIE_LOCATOR_NONE
)
12003 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY
&& $working = $this->autodiscovery())
12005 return $working[0];
12008 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY
) && $this->get_links())
12010 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
&& $working = $this->extension($this->local
))
12015 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY
&& $working = $this->body($this->local
))
12020 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
&& $working = $this->extension($this->elsewhere
))
12025 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY
&& $working = $this->body($this->elsewhere
))
12033 public function is_feed($file)
12035 if ($file->method
& SIMPLEPIE_FILE_SOURCE_REMOTE
)
12037 $sniffer = $this->registry
->create('Content_Type_Sniffer', array($file));
12038 $sniffed = $sniffer->get_type();
12039 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
12048 elseif ($file->method
& SIMPLEPIE_FILE_SOURCE_LOCAL
)
12058 public function get_base()
12060 if ($this->dom
=== null)
12062 throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
12064 $this->http_base
= $this->file
->url
;
12065 $this->base
= $this->http_base
;
12066 $elements = $this->dom
->getElementsByTagName('base');
12067 foreach ($elements as $element)
12069 if ($element->hasAttribute('href'))
12071 $base = $this->registry
->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base
));
12072 if ($base === false)
12076 $this->base
= $base;
12077 $this->base_location
= method_exists($element, 'getLineNo') ?
$element->getLineNo() : 0;
12083 public function autodiscovery()
12087 $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));
12088 $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));
12089 $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));
12091 if (!empty($feeds))
12093 return array_values($feeds);
12101 protected function search_elements_by_tag($name, &$done, $feeds)
12103 if ($this->dom
=== null)
12105 throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
12108 $links = $this->dom
->getElementsByTagName($name);
12109 foreach ($links as $link)
12111 if ($this->checked_feeds
=== $this->max_checked_feeds
)
12115 if ($link->hasAttribute('href') && $link->hasAttribute('rel'))
12117 $rel = array_unique($this->registry
->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel')))));
12118 $line = method_exists($link, 'getLineNo') ?
$link->getLineNo() : 1;
12120 if ($this->base_location
< $line)
12122 $href = $this->registry
->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base
));
12126 $href = $this->registry
->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base
));
12128 if ($href === false)
12133 if (!in_array($href, $done) && in_array('feed', $rel) ||
(in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry
->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
12135 $this->checked_feeds++
;
12137 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
12139 $feed = $this->registry
->create('File', array($href, $this->timeout
, 5, $headers, $this->useragent
));
12140 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))
12142 $feeds[$href] = $feed;
12152 public function get_links()
12154 if ($this->dom
=== null)
12156 throw new SimplePie_Exception('DOMDocument not found, unable to use locator');
12159 $links = $this->dom
->getElementsByTagName('a');
12160 foreach ($links as $link)
12162 if ($link->hasAttribute('href'))
12164 $href = trim($link->getAttribute('href'));
12165 $parsed = $this->registry
->call('Misc', 'parse_url', array($href));
12166 if ($parsed['scheme'] === '' ||
preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
12168 if ($this->base_location
< $link->getLineNo())
12170 $href = $this->registry
->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base
));
12174 $href = $this->registry
->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base
));
12176 if ($href === false)
12181 $current = $this->registry
->call('Misc', 'parse_url', array($this->file
->url
));
12183 if ($parsed['authority'] === '' ||
$parsed['authority'] === $current['authority'])
12185 $this->local
[] = $href;
12189 $this->elsewhere
[] = $href;
12194 $this->local
= array_unique($this->local
);
12195 $this->elsewhere
= array_unique($this->elsewhere
);
12196 if (!empty($this->local
) ||
!empty($this->elsewhere
))
12203 public function extension(&$array)
12205 foreach ($array as $key => $value)
12207 if ($this->checked_feeds
=== $this->max_checked_feeds
)
12211 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
12213 $this->checked_feeds++
;
12216 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
12218 $feed = $this->registry
->create('File', array($value, $this->timeout
, 5, $headers, $this->useragent
));
12219 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))
12225 unset($array[$key]);
12232 public function body(&$array)
12234 foreach ($array as $key => $value)
12236 if ($this->checked_feeds
=== $this->max_checked_feeds
)
12240 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
12242 $this->checked_feeds++
;
12244 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
12246 $feed = $this->registry
->create('File', array($value, $this->timeout
, 5, null, $this->useragent
));
12247 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))
12253 unset($array[$key]);
12262 * Miscellanous utilities
12264 * @package SimplePie
12266 class SimplePie_Misc
12268 public static function time_hms($seconds)
12272 $hours = floor($seconds / 3600);
12273 $remainder = $seconds %
3600;
12276 $time .= $hours.':';
12279 $minutes = floor($remainder / 60);
12280 $seconds = $remainder %
60;
12281 if ($minutes < 10 && $hours > 0)
12283 $minutes = '0' . $minutes;
12287 $seconds = '0' . $seconds;
12290 $time .= $minutes.':';
12296 public static function absolutize_url($relative, $base)
12298 $iri = SimplePie_IRI
::absolutize(new SimplePie_IRI($base), $relative);
12299 if ($iri === false)
12303 return $iri->get_uri();
12307 * Get a HTML/XML element from a HTML string
12309 * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!)
12310 * @param string $realname Element name (including namespace prefix if applicable)
12311 * @param string $string HTML document
12314 public static function get_element($realname, $string)
12317 $name = preg_quote($realname, '/');
12318 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE
. "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE
))
12320 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++
)
12322 $return[$i]['tag'] = $realname;
12323 $return[$i]['full'] = $matches[$i][0][0];
12324 $return[$i]['offset'] = $matches[$i][0][1];
12325 if (strlen($matches[$i][3][0]) <= 2)
12327 $return[$i]['self_closing'] = true;
12331 $return[$i]['self_closing'] = false;
12332 $return[$i]['content'] = $matches[$i][4][0];
12334 $return[$i]['attribs'] = array();
12335 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
))
12337 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++
)
12339 if (count($attribs[$j]) === 2)
12341 $attribs[$j][2] = $attribs[$j][1];
12343 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc
::entities_decode(end($attribs[$j]), 'UTF-8');
12351 public static function element_implode($element)
12353 $full = "<$element[tag]";
12354 foreach ($element['attribs'] as $key => $value)
12356 $key = strtolower($key);
12357 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
12359 if ($element['self_closing'])
12365 $full .= ">$element[content]</$element[tag]>";
12370 public static function error($message, $level, $file, $line)
12372 if ((ini_get('error_reporting') & $level) > 0)
12377 $note = 'PHP Error';
12379 case E_USER_WARNING
:
12380 $note = 'PHP Warning';
12382 case E_USER_NOTICE
:
12383 $note = 'PHP Notice';
12386 $note = 'Unknown Error';
12391 if (!function_exists('error_log'))
12393 $log_error = false;
12396 $log_file = @ini_get
('error_log');
12397 if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable
($log_file))
12399 $log_error = false;
12404 @error_log
("$note: $message in $file on line $line", 0);
12411 public static function fix_protocol($url, $http = 1)
12413 $url = SimplePie_Misc
::normalize_url($url);
12414 $parsed = SimplePie_Misc
::parse_url($url);
12415 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
12417 return SimplePie_Misc
::fix_protocol(SimplePie_Misc
::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
12420 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
12422 return SimplePie_Misc
::fix_protocol(SimplePie_Misc
::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
12425 if ($http === 2 && $parsed['scheme'] !== '')
12427 return "feed:$url";
12429 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
12431 return substr_replace($url, 'podcast', 0, 4);
12433 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
12435 return substr_replace($url, 'itpc', 0, 4);
12443 public static function parse_url($url)
12445 $iri = new SimplePie_IRI($url);
12447 'scheme' => (string) $iri->scheme
,
12448 'authority' => (string) $iri->authority
,
12449 'path' => (string) $iri->path
,
12450 'query' => (string) $iri->query
,
12451 'fragment' => (string) $iri->fragment
12455 public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
12457 $iri = new SimplePie_IRI('');
12458 $iri->scheme
= $scheme;
12459 $iri->authority
= $authority;
12460 $iri->path
= $path;
12461 $iri->query
= $query;
12462 $iri->fragment
= $fragment;
12463 return $iri->get_uri();
12466 public static function normalize_url($url)
12468 $iri = new SimplePie_IRI($url);
12469 return $iri->get_uri();
12472 public static function percent_encoding_normalization($match)
12474 $integer = hexdec($match[1]);
12475 if ($integer >= 0x41 && $integer <= 0x5A ||
$integer >= 0x61 && $integer <= 0x7A ||
$integer >= 0x30 && $integer <= 0x39 ||
$integer === 0x2D ||
$integer === 0x2E ||
$integer === 0x5F ||
$integer === 0x7E)
12477 return chr($integer);
12481 return strtoupper($match[0]);
12486 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
12489 * @param string $string Windows-1252 encoded string
12490 * @return string UTF-8 encoded string
12492 public static function windows_1252_to_utf8($string)
12494 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");
12496 return strtr($string, $convert_table);
12500 * Change a string from one encoding to another
12502 * @param string $data Raw data in $input encoding
12503 * @param string $input Encoding of $data
12504 * @param string $output Encoding you want
12505 * @return string|boolean False if we can't convert it
12507 public static function change_encoding($data, $input, $output)
12509 $input = SimplePie_Misc
::encoding($input);
12510 $output = SimplePie_Misc
::encoding($output);
12512 // We fail to fail on non US-ASCII bytes
12513 if ($input === 'US-ASCII')
12515 static $non_ascii_octects = '';
12516 if (!$non_ascii_octects)
12518 for ($i = 0x80; $i <= 0xFF; $i++
)
12520 $non_ascii_octects .= chr($i);
12523 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
12526 // This is first, as behaviour of this is completely predictable
12527 if ($input === 'windows-1252' && $output === 'UTF-8')
12529 return SimplePie_Misc
::windows_1252_to_utf8($data);
12531 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
12532 elseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc
::change_encoding_mbstring($data, $input, $output)))
12536 // This is last, as behaviour of this varies with OS userland and PHP version
12537 elseif (function_exists('iconv') && ($return = SimplePie_Misc
::change_encoding_iconv($data, $input, $output)))
12541 // If we can't do anything, just fail
12548 protected static function change_encoding_mbstring($data, $input, $output)
12550 if ($input === 'windows-949')
12554 if ($output === 'windows-949')
12556 $output = 'EUC-KR';
12558 if ($input === 'Windows-31J')
12562 if ($output === 'Windows-31J')
12567 // Check that the encoding is supported
12568 if (@mb_convert_encoding
("\x80", 'UTF-16BE', $input) === "\x00\x80")
12572 if (!in_array($input, mb_list_encodings()))
12577 // Let's do some conversion
12578 if ($return = @mb_convert_encoding
($data, $output, $input))
12586 protected static function change_encoding_iconv($data, $input, $output)
12588 return @iconv
($input, $output, $data);
12592 * Normalize an encoding name
12594 * This is automatically generated by create.php
12596 * To generate it, run `php create.php` on the command line, and copy the
12597 * output to replace this function.
12599 * @param string $charset Character set to standardise
12600 * @return string Standardised name
12602 public static function encoding($charset)
12604 // Normalization from UTS #22
12605 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
12607 case 'adobestandardencoding':
12608 case 'csadobestandardencoding':
12609 return 'Adobe-Standard-Encoding';
12611 case 'adobesymbolencoding':
12613 return 'Adobe-Symbol-Encoding';
12617 return 'Amiga-1251';
12619 case 'ansix31101983':
12620 case 'csat5001983':
12621 case 'csiso99naplps':
12624 return 'ANSI_X3.110-1983';
12628 case 'csiso89asmo449':
12638 return 'Big5-HKSCS';
12649 case 'csiso4unitedkingdom':
12657 case 'csiso47bsviewdata':
12659 return 'BS_viewdata';
12667 case 'csaz243419851':
12668 case 'csiso121canadian1':
12671 return 'CSA_Z243.4-1985-1';
12674 case 'csaz243419852':
12675 case 'csiso122canadian2':
12678 return 'CSA_Z243.4-1985-2';
12680 case 'csaz24341985gr':
12681 case 'csiso123csaz24341985gr':
12683 return 'CSA_Z243.4-1985-gr';
12685 case 'csiso139csn369103':
12688 return 'CSN_369103';
12695 case 'csiso21german':
12700 return 'DIN_66003';
12706 case 'csiso646danish':
12712 case 'csibmebcdicatde':
12714 return 'EBCDIC-AT-DE';
12716 case 'csebcdicatdea':
12717 case 'ebcdicatdea':
12718 return 'EBCDIC-AT-DE-A';
12720 case 'csebcdiccafr':
12722 return 'EBCDIC-CA-FR';
12724 case 'csebcdicdkno':
12726 return 'EBCDIC-DK-NO';
12728 case 'csebcdicdknoa':
12729 case 'ebcdicdknoa':
12730 return 'EBCDIC-DK-NO-A';
12734 return 'EBCDIC-ES';
12736 case 'csebcdicesa':
12738 return 'EBCDIC-ES-A';
12740 case 'csebcdicess':
12742 return 'EBCDIC-ES-S';
12744 case 'csebcdicfise':
12746 return 'EBCDIC-FI-SE';
12748 case 'csebcdicfisea':
12749 case 'ebcdicfisea':
12750 return 'EBCDIC-FI-SE-A';
12754 return 'EBCDIC-FR';
12758 return 'EBCDIC-IT';
12762 return 'EBCDIC-PT';
12766 return 'EBCDIC-UK';
12770 return 'EBCDIC-US';
12772 case 'csiso111ecmacyrillic':
12773 case 'ecmacyrillic':
12776 return 'ECMA-cyrillic';
12778 case 'csiso17spanish':
12784 case 'csiso85spanish2':
12790 case 'cseucpkdfmtjapanese':
12792 case 'extendedunixcodepackedformatforjapanese':
12795 case 'cseucfixwidjapanese':
12796 case 'extendedunixcodefixedwidthforjapanese':
12797 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
12805 case 'csiso58gb231280':
12815 case 'csiso57gb1988':
12819 return 'GB_1988-80';
12821 case 'csiso153gost1976874':
12822 case 'gost1976874':
12825 return 'GOST_19768-74';
12828 case 'csiso150greekccitt':
12831 return 'greek-ccitt';
12833 case 'csiso88greek7':
12838 case 'csiso18greek7old':
12841 return 'greek7-old';
12843 case 'cshpdesktop':
12845 return 'HP-DeskTop';
12857 return 'HP-Pi-font';
12863 return 'hp-roman8';
12866 return 'HZ-GB-2312';
12868 case 'csibmsymbols':
12870 return 'IBM-Symbols';
12947 case 'ebcdicjpkana':
12959 case 'ebcdiccpar1':
12977 case 'cspc8codepage437':
12989 case 'cspc775baltic':
12995 case 'cspc850multilingual':
13026 case 'pcmultilingual850euro':
13044 case 'cspc862latinhebrew':
13086 case 'ebcdiccproece':
13099 case 'ebcdiccyrillic':
13127 case 'ebcdiccpar2':
13133 case 'ebcdiclatin9euro':
13147 case 'ebcdicus37euro':
13153 case 'ebcdicde273euro':
13159 case 'ebcdicdk277euro':
13160 case 'ebcdicno277euro':
13166 case 'ebcdicfi278euro':
13167 case 'ebcdicse278euro':
13173 case 'ebcdicit280euro':
13179 case 'ebcdices284euro':
13185 case 'ebcdicgb285euro':
13191 case 'ebcdicfr297euro':
13197 case 'ebcdicinternational500euro':
13203 case 'ebcdicis871euro':
13207 case 'csiso143iecp271':
13210 return 'IEC_P27-1';
13212 case 'csiso49inis':
13217 case 'csiso50inis8':
13222 case 'csiso51iniscyrillic':
13223 case 'iniscyrillic':
13225 return 'INIS-cyrillic';
13227 case 'csinvariant':
13229 return 'INVARIANT';
13232 return 'ISO-2022-CN';
13234 case 'iso2022cnext':
13235 return 'ISO-2022-CN-EXT';
13237 case 'csiso2022jp':
13239 return 'ISO-2022-JP';
13241 case 'csiso2022jp2':
13243 return 'ISO-2022-JP-2';
13245 case 'csiso2022kr':
13247 return 'ISO-2022-KR';
13249 case 'cswindows30latin1':
13250 case 'iso88591windows30latin1':
13251 return 'ISO-8859-1-Windows-3.0-Latin-1';
13253 case 'cswindows31latin1':
13254 case 'iso88591windows31latin1':
13255 return 'ISO-8859-1-Windows-3.1-Latin-1';
13257 case 'csisolatin2':
13259 case 'iso885921987':
13263 return 'ISO-8859-2';
13265 case 'cswindows31latin2':
13266 case 'iso88592windowslatin2':
13267 return 'ISO-8859-2-Windows-Latin-2';
13269 case 'csisolatin3':
13271 case 'iso885931988':
13275 return 'ISO-8859-3';
13277 case 'csisolatin4':
13279 case 'iso885941988':
13283 return 'ISO-8859-4';
13285 case 'csisolatincyrillic':
13288 case 'iso885951988':
13290 return 'ISO-8859-5';
13294 case 'csisolatinarabic':
13297 case 'iso885961987':
13299 return 'ISO-8859-6';
13301 case 'csiso88596e':
13303 return 'ISO-8859-6-E';
13305 case 'csiso88596i':
13307 return 'ISO-8859-6-I';
13309 case 'csisolatingreek':
13315 case 'iso885971987':
13317 return 'ISO-8859-7';
13319 case 'csisolatinhebrew':
13322 case 'iso885981988':
13324 return 'ISO-8859-8';
13326 case 'csiso88598e':
13328 return 'ISO-8859-8-E';
13330 case 'csiso88598i':
13332 return 'ISO-8859-8-I';
13334 case 'cswindows31latin5':
13335 case 'iso88599windowslatin5':
13336 return 'ISO-8859-9-Windows-Latin-5';
13338 case 'csisolatin6':
13340 case 'iso8859101992':
13344 return 'ISO-8859-10';
13347 return 'ISO-8859-13';
13350 case 'iso8859141998':
13355 return 'ISO-8859-14';
13359 return 'ISO-8859-15';
13362 case 'iso8859162001':
13366 return 'ISO-8859-16';
13369 return 'ISO-10646-J-1';
13372 case 'iso10646ucs2':
13373 return 'ISO-10646-UCS-2';
13376 case 'iso10646ucs4':
13377 return 'ISO-10646-UCS-4';
13379 case 'csunicodeascii':
13380 case 'iso10646ucsbasic':
13381 return 'ISO-10646-UCS-Basic';
13383 case 'csunicodelatin1':
13385 case 'iso10646unicodelatin1':
13386 return 'ISO-10646-Unicode-Latin1';
13388 case 'csiso10646utf1':
13389 case 'iso10646utf1':
13390 return 'ISO-10646-UTF-1';
13392 case 'csiso115481':
13394 case 'isotr115481':
13395 return 'ISO-11548-1';
13399 return 'iso-ir-90';
13401 case 'csunicodeibm1261':
13402 case 'isounicodeibm1261':
13403 return 'ISO-Unicode-IBM-1261';
13405 case 'csunicodeibm1264':
13406 case 'isounicodeibm1264':
13407 return 'ISO-Unicode-IBM-1264';
13409 case 'csunicodeibm1265':
13410 case 'isounicodeibm1265':
13411 return 'ISO-Unicode-IBM-1265';
13413 case 'csunicodeibm1268':
13414 case 'isounicodeibm1268':
13415 return 'ISO-Unicode-IBM-1268';
13417 case 'csunicodeibm1276':
13418 case 'isounicodeibm1276':
13419 return 'ISO-Unicode-IBM-1276';
13421 case 'csiso646basic1983':
13422 case 'iso646basic1983':
13424 return 'ISO_646.basic:1983';
13426 case 'csiso2intlrefversion':
13428 case 'iso646irv1983':
13430 return 'ISO_646.irv:1983';
13434 case 'iso20331983':
13436 return 'ISO_2033-1983';
13438 case 'csiso5427cyrillic':
13443 case 'iso5427cyrillic1981':
13444 case 'iso54271981':
13446 return 'ISO_5427:1981';
13448 case 'csiso5428greek':
13449 case 'iso54281980':
13451 return 'ISO_5428:1980';
13453 case 'csiso6937add':
13456 return 'ISO_6937-2-25';
13458 case 'csisotextcomm':
13459 case 'iso69372add':
13461 return 'ISO_6937-2-add';
13463 case 'csiso8859supp':
13464 case 'iso8859supp':
13467 return 'ISO_8859-supp';
13469 case 'csiso10367box':
13470 case 'iso10367box':
13472 return 'ISO_10367-box';
13474 case 'csiso15italian':
13480 case 'csiso13jisc6220jp':
13482 case 'jisc62201969':
13483 case 'jisc62201969jp':
13486 return 'JIS_C6220-1969-jp';
13488 case 'csiso14jisc6220ro':
13491 case 'jisc62201969ro':
13493 return 'JIS_C6220-1969-ro';
13495 case 'csiso42jisc62261978':
13497 case 'jisc62261978':
13498 return 'JIS_C6226-1978';
13500 case 'csiso87jisx208':
13502 case 'jisc62261983':
13503 case 'jisx2081983':
13505 return 'JIS_C6226-1983';
13507 case 'csiso91jisc62291984a':
13509 case 'jisc62291984a':
13511 return 'JIS_C6229-1984-a';
13513 case 'csiso92jisc62991984b':
13514 case 'iso646jpocrb':
13516 case 'jisc62291984b':
13518 return 'JIS_C6229-1984-b';
13520 case 'csiso93jis62291984badd':
13522 case 'jisc62291984badd':
13524 return 'JIS_C6229-1984-b-add';
13526 case 'csiso94jis62291984hand':
13528 case 'jisc62291984hand':
13530 return 'JIS_C6229-1984-hand';
13532 case 'csiso95jis62291984handadd':
13534 case 'jisc62291984handadd':
13535 case 'jpocrhandadd':
13536 return 'JIS_C6229-1984-hand-add';
13538 case 'csiso96jisc62291984kana':
13540 case 'jisc62291984kana':
13541 return 'JIS_C6229-1984-kana';
13543 case 'csjisencoding':
13544 case 'jisencoding':
13545 return 'JIS_Encoding';
13547 case 'cshalfwidthkatakana':
13550 return 'JIS_X0201';
13552 case 'csiso159jisx2121990':
13554 case 'jisx2121990':
13556 return 'JIS_X0212-1990';
13558 case 'csiso141jusib1002':
13564 return 'JUS_I.B1.002';
13566 case 'csiso147macedonian':
13568 case 'jusib1003mac':
13570 return 'JUS_I.B1.003-mac';
13572 case 'csiso146serbian':
13574 case 'jusib1003serb':
13576 return 'JUS_I.B1.003-serb';
13578 case 'koi7switched':
13579 return 'KOI7-switched';
13596 case 'strk10482002':
13599 case 'csiso19latingreek':
13602 return 'latin-greek';
13604 case 'csiso27latingreek1':
13606 case 'latingreek1':
13607 return 'Latin-greek-1';
13609 case 'csiso158lap':
13613 return 'latin-lap';
13615 case 'csmacintosh':
13618 return 'macintosh';
13620 case 'csmicrosoftpublishing':
13621 case 'microsoftpublishing':
13622 return 'Microsoft-Publishing';
13632 case 'csiso86hungarian':
13637 return 'MSZ_7795.3';
13642 return 'NATS-DANO';
13644 case 'csnatsdanoadd':
13646 case 'natsdanoadd':
13647 return 'NATS-DANO-ADD';
13652 return 'NATS-SEFI';
13654 case 'csnatssefiadd':
13656 case 'natssefiadd':
13657 return 'NATS-SEFI-ADD';
13659 case 'csiso151cuba':
13664 return 'NC_NC00-10:81';
13666 case 'csiso69french':
13671 return 'NF_Z_62-010';
13673 case 'csiso25french':
13676 case 'nfz620101973':
13677 return 'NF_Z_62-010_(1973)';
13679 case 'csiso60danishnorwegian':
13680 case 'csiso60norwegian1':
13685 return 'NS_4551-1';
13687 case 'csiso61norwegian2':
13692 return 'NS_4551-2';
13694 case 'osdebcdicdf3irv':
13695 return 'OSD_EBCDIC_DF03_IRV';
13697 case 'osdebcdicdf41':
13698 return 'OSD_EBCDIC_DF04_1';
13700 case 'osdebcdicdf415':
13701 return 'OSD_EBCDIC_DF04_15';
13703 case 'cspc8danishnorwegian':
13704 case 'pc8danishnorwegian':
13705 return 'PC8-Danish-Norwegian';
13707 case 'cspc8turkish':
13709 return 'PC8-Turkish';
13711 case 'csiso16portuguese':
13717 case 'csiso84portuguese2':
13725 case 'cyrillicasian':
13733 case 'csiso10swedish':
13740 return 'SEN_850200_B';
13742 case 'csiso11swedishfornames':
13747 return 'SEN_850200_C';
13749 case 'csiso102t617bit':
13752 return 'T.61-7bit';
13754 case 'csiso103t618bit':
13758 return 'T.61-8bit';
13760 case 'csiso128t101g2':
13769 case 'csunicode11':
13771 return 'UNICODE-1-1';
13773 case 'csunicode11utf7':
13774 case 'unicode11utf7':
13775 return 'UNICODE-1-1-UTF-7';
13777 case 'csunknown8bit':
13778 case 'unknown8bit':
13779 return 'UNKNOWN-8BIT';
13781 case 'ansix341968':
13782 case 'ansix341986':
13787 case 'iso646irv1991':
13822 case 'csventurainternational':
13823 case 'venturainternational':
13824 return 'Ventura-International';
13826 case 'csventuramath':
13827 case 'venturamath':
13828 return 'Ventura-Math';
13830 case 'csventuraus':
13832 return 'Ventura-US';
13834 case 'csiso70videotexsupp1':
13836 case 'videotexsuppl':
13837 return 'videotex-suppl';
13848 case 'cswindows31j':
13852 return 'Windows-31J';
13856 return 'windows-874';
13859 case 'csksc56011987':
13864 case 'ksc56011987':
13865 case 'ksc56011989':
13867 return 'windows-949';
13869 case 'windows1250':
13870 return 'windows-1250';
13872 case 'windows1251':
13873 return 'windows-1251';
13876 case 'csisolatin1':
13879 case 'iso885911987':
13883 case 'windows1252':
13884 return 'windows-1252';
13886 case 'windows1253':
13887 return 'windows-1253';
13889 case 'csisolatin5':
13891 case 'iso885991989':
13895 case 'windows1254':
13896 return 'windows-1254';
13898 case 'windows1255':
13899 return 'windows-1255';
13901 case 'windows1256':
13902 return 'windows-1256';
13904 case 'windows1257':
13905 return 'windows-1257';
13907 case 'windows1258':
13908 return 'windows-1258';
13915 public static function get_curl_version()
13917 if (is_array($curl = curl_version()))
13919 $curl = $curl['version'];
13921 elseif (substr($curl, 0, 5) === 'curl/')
13923 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
13925 elseif (substr($curl, 0, 8) === 'libcurl/')
13927 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
13937 * Strip HTML comments
13939 * @param string $data Data to strip comments from
13940 * @return string Comment stripped string
13942 public static function strip_comments($data)
13945 while (($start = strpos($data, '<!--')) !== false)
13947 $output .= substr($data, 0, $start);
13948 if (($end = strpos($data, '-->', $start)) !== false)
13950 $data = substr_replace($data, '', 0, $end +
3);
13957 return $output . $data;
13960 public static function parse_date($dt)
13962 $parser = SimplePie_Parse_Date
::get();
13963 return $parser->parse($dt);
13967 * Decode HTML entities
13969 * @deprecated Use DOMDocument instead
13970 * @param string $data Input data
13971 * @return string Output data
13973 public static function entities_decode($data)
13975 $decoder = new SimplePie_Decode_HTML_Entities($data);
13976 return $decoder->parse();
13980 * Remove RFC822 comments
13982 * @param string $data Data to strip comments from
13983 * @return string Comment stripped string
13985 public static function uncomment_rfc822($string)
13987 $string = (string) $string;
13989 $length = strlen($string);
13994 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
13996 $output .= substr($string, $position, $pos - $position);
13997 $position = $pos +
1;
13998 if ($string[$pos - 1] !== '\\')
14001 while ($depth && $position < $length)
14003 $position +
= strcspn($string, '()', $position);
14004 if ($string[$position - 1] === '\\')
14009 elseif (isset($string[$position]))
14011 switch ($string[$position])
14034 $output .= substr($string, $position);
14039 public static function parse_mime($mime)
14041 if (($pos = strpos($mime, ';')) === false)
14043 return trim($mime);
14047 return trim(substr($mime, 0, $pos));
14051 public static function atom_03_construct_type($attribs)
14053 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
14055 $mode = SIMPLEPIE_CONSTRUCT_BASE64
;
14059 $mode = SIMPLEPIE_CONSTRUCT_NONE
;
14061 if (isset($attribs['']['type']))
14063 switch (strtolower(trim($attribs['']['type'])))
14067 return SIMPLEPIE_CONSTRUCT_TEXT |
$mode;
14071 return SIMPLEPIE_CONSTRUCT_HTML |
$mode;
14074 case 'application/xhtml+xml':
14075 return SIMPLEPIE_CONSTRUCT_XHTML |
$mode;
14078 return SIMPLEPIE_CONSTRUCT_NONE |
$mode;
14083 return SIMPLEPIE_CONSTRUCT_TEXT |
$mode;
14087 public static function atom_10_construct_type($attribs)
14089 if (isset($attribs['']['type']))
14091 switch (strtolower(trim($attribs['']['type'])))
14094 return SIMPLEPIE_CONSTRUCT_TEXT
;
14097 return SIMPLEPIE_CONSTRUCT_HTML
;
14100 return SIMPLEPIE_CONSTRUCT_XHTML
;
14103 return SIMPLEPIE_CONSTRUCT_NONE
;
14106 return SIMPLEPIE_CONSTRUCT_TEXT
;
14109 public static function atom_10_content_construct_type($attribs)
14111 if (isset($attribs['']['type']))
14113 $type = strtolower(trim($attribs['']['type']));
14117 return SIMPLEPIE_CONSTRUCT_TEXT
;
14120 return SIMPLEPIE_CONSTRUCT_HTML
;
14123 return SIMPLEPIE_CONSTRUCT_XHTML
;
14125 if (in_array(substr($type, -4), array('+xml', '/xml')) ||
substr($type, 0, 5) === 'text/')
14127 return SIMPLEPIE_CONSTRUCT_NONE
;
14131 return SIMPLEPIE_CONSTRUCT_BASE64
;
14136 return SIMPLEPIE_CONSTRUCT_TEXT
;
14140 public static function is_isegment_nz_nc($string)
14142 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);
14145 public static function space_seperated_tokens($string)
14147 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
14148 $string_length = strlen($string);
14150 $position = strspn($string, $space_characters);
14153 while ($position < $string_length)
14155 $len = strcspn($string, $space_characters, $position);
14156 $tokens[] = substr($string, $position, $len);
14158 $position +
= strspn($string, $space_characters, $position);
14165 * Converts a unicode codepoint to a UTF-8 character
14168 * @param int $codepoint Unicode codepoint
14169 * @return string UTF-8 character
14171 public static function codepoint_to_utf8($codepoint)
14173 $codepoint = (int) $codepoint;
14174 if ($codepoint < 0)
14178 else if ($codepoint <= 0x7f)
14180 return chr($codepoint);
14182 else if ($codepoint <= 0x7ff)
14184 return chr(0xc0 |
($codepoint >> 6)) . chr(0x80 |
($codepoint & 0x3f));
14186 else if ($codepoint <= 0xffff)
14188 return chr(0xe0 |
($codepoint >> 12)) . chr(0x80 |
(($codepoint >> 6) & 0x3f)) . chr(0x80 |
($codepoint & 0x3f));
14190 else if ($codepoint <= 0x10ffff)
14192 return chr(0xf0 |
($codepoint >> 18)) . chr(0x80 |
(($codepoint >> 12) & 0x3f)) . chr(0x80 |
(($codepoint >> 6) & 0x3f)) . chr(0x80 |
($codepoint & 0x3f));
14196 // U+FFFD REPLACEMENT CHARACTER
14197 return "\xEF\xBF\xBD";
14202 * Similar to parse_str()
14204 * Returns an associative array of name/value pairs, where the value is an
14205 * array of values that have used the same name
14208 * @param string $str The input string.
14211 public static function parse_str($str)
14214 $str = explode('&', $str);
14216 foreach ($str as $section)
14218 if (strpos($section, '=') !== false)
14220 list($name, $value) = explode('=', $section, 2);
14221 $return[urldecode($name)][] = urldecode($value);
14225 $return[urldecode($section)][] = null;
14233 * Detect XML encoding, as per XML 1.0 Appendix F.1
14235 * @todo Add support for EBCDIC
14236 * @param string $data XML data
14237 * @param SimplePie_Registry $registry Class registry
14238 * @return array Possible encodings
14240 public static function xml_encoding($data, $registry)
14242 // UTF-32 Big Endian BOM
14243 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
14245 $encoding[] = 'UTF-32BE';
14247 // UTF-32 Little Endian BOM
14248 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
14250 $encoding[] = 'UTF-32LE';
14252 // UTF-16 Big Endian BOM
14253 elseif (substr($data, 0, 2) === "\xFE\xFF")
14255 $encoding[] = 'UTF-16BE';
14257 // UTF-16 Little Endian BOM
14258 elseif (substr($data, 0, 2) === "\xFF\xFE")
14260 $encoding[] = 'UTF-16LE';
14263 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
14265 $encoding[] = 'UTF-8';
14267 // UTF-32 Big Endian Without BOM
14268 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")
14270 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
14272 $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc
::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')));
14273 if ($parser->parse())
14275 $encoding[] = $parser->encoding
;
14278 $encoding[] = 'UTF-32BE';
14280 // UTF-32 Little Endian Without BOM
14281 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")
14283 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
14285 $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc
::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')));
14286 if ($parser->parse())
14288 $encoding[] = $parser->encoding
;
14291 $encoding[] = 'UTF-32LE';
14293 // UTF-16 Big Endian Without BOM
14294 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
14296 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
14298 $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc
::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')));
14299 if ($parser->parse())
14301 $encoding[] = $parser->encoding
;
14304 $encoding[] = 'UTF-16BE';
14306 // UTF-16 Little Endian Without BOM
14307 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
14309 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
14311 $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc
::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')));
14312 if ($parser->parse())
14314 $encoding[] = $parser->encoding
;
14317 $encoding[] = 'UTF-16LE';
14319 // US-ASCII (or superset)
14320 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
14322 if ($pos = strpos($data, "\x3F\x3E"))
14324 $parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
14325 if ($parser->parse())
14327 $encoding[] = $parser->encoding
;
14330 $encoding[] = 'UTF-8';
14332 // Fallback to UTF-8
14335 $encoding[] = 'UTF-8';
14340 public static function output_javascript()
14342 if (function_exists('ob_gzhandler'))
14344 ob_start('ob_gzhandler');
14346 header('Content-type: text/javascript; charset: UTF-8');
14347 header('Cache-Control: must-revalidate');
14348 header('Expires: ' . gmdate('D, d M Y H:i:s', time() +
604800) . ' GMT'); // 7 days
14350 function embed_quicktime(type
, bgcolor
, width
, height
, link
, placeholder
, loop
) {
14351 if (placeholder
!= '') {
14352 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>');
14355 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>');
14359 function embed_flash(bgcolor
, width
, height
, link
, loop
, type
) {
14360 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>');
14363 function embed_flv(width
, height
, link
, placeholder
, loop
, player
) {
14364 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>');
14367 function embed_wmedia(width
, height
, link
) {
14368 document
.writeln('<embed type="application/x-mplayer2" src="'+link+
'" autosize="1" width="'+width+
'" height="'+height+
'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
14374 * Get the SimplePie build timestamp
14376 * Uses the git index if it exists, otherwise uses the modification time
14377 * of the newest file.
14379 public static function get_build()
14381 $root = dirname(dirname(__FILE__
));
14382 if (file_exists($root . '/.git/index'))
14384 return filemtime($root . '/.git/index');
14386 elseif (file_exists($root . '/SimplePie'))
14389 foreach (glob($root . '/SimplePie/*.php') as $file)
14391 if (($mtime = filemtime($file)) > $time)
14398 elseif (file_exists(dirname(__FILE__
) . '/Core.php'))
14400 return filemtime(dirname(__FILE__
) . '/Core.php');
14404 return filemtime(__FILE__
);
14409 * Format debugging information
14411 public static function debug(&$sp)
14413 $info = 'SimplePie ' . SIMPLEPIE_VERSION
. ' Build ' . SIMPLEPIE_BUILD
. "\n";
14414 $info .= 'PHP ' . PHP_VERSION
. "\n";
14415 if ($sp->error() !== null)
14417 $info .= 'Error occurred: ' . $sp->error() . "\n";
14421 $info .= "No error found.\n";
14423 $info .= "Extensions:\n";
14424 $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
14425 foreach ($extensions as $ext)
14427 if (extension_loaded($ext))
14429 $info .= " $ext loaded\n";
14433 $info .= ' Version ' . PCRE_VERSION
. "\n";
14436 $version = curl_version();
14437 $info .= ' Version ' . $version['version'] . "\n";
14440 $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
14443 $info .= ' Version ' . ICONV_VERSION
. "\n";
14446 $info .= ' Version ' . LIBXML_DOTTED_VERSION
. "\n";
14452 $info .= " $ext not loaded\n";
14458 public static function silence_errors($num, $str)
14465 * Class to validate and to work with IPv6 addresses.
14467 * @package SimplePie
14469 * @copyright 2003-2005 The PHP Group
14470 * @license http://www.opensource.org/licenses/bsd-license.php
14471 * @link http://pear.php.net/package/Net_IPv6
14472 * @author Alexander Merz <alexander.merz@web.de>
14473 * @author elfrink at introweb dot nl
14474 * @author Josh Peck <jmp at joshpeck dot org>
14475 * @author Geoffrey Sneddon <geoffers@gmail.com>
14477 class SimplePie_Net_IPv6
14480 * Uncompresses an IPv6 address
14482 * RFC 4291 allows you to compress concecutive zero pieces in an address to
14483 * '::'. This method expects a valid IPv6 address and expands the '::' to
14484 * the required number of zero pieces.
14486 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
14487 * ::1 -> 0:0:0:0:0:0:0:1
14489 * @author Alexander Merz <alexander.merz@web.de>
14490 * @author elfrink at introweb dot nl
14491 * @author Josh Peck <jmp at joshpeck dot org>
14492 * @copyright 2003-2005 The PHP Group
14493 * @license http://www.opensource.org/licenses/bsd-license.php
14494 * @param string $ip An IPv6 address
14495 * @return string The uncompressed IPv6 address
14497 public static function uncompress($ip)
14501 if (substr_count($ip, '::') === 1)
14503 list($ip1, $ip2) = explode('::', $ip);
14510 $c1 = substr_count($ip1, ':');
14518 $c2 = substr_count($ip2, ':');
14520 if (strpos($ip2, '.') !== false)
14525 if ($c1 === -1 && $c2 === -1)
14527 $ip = '0:0:0:0:0:0:0:0';
14530 else if ($c1 === -1)
14532 $fill = str_repeat('0:', 7 - $c2);
14533 $ip = str_replace('::', $fill, $ip);
14536 else if ($c2 === -1)
14538 $fill = str_repeat(':0', 7 - $c1);
14539 $ip = str_replace('::', $fill, $ip);
14544 $fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
14545 $ip = str_replace('::', $fill, $ip);
14552 * Compresses an IPv6 address
14554 * RFC 4291 allows you to compress concecutive zero pieces in an address to
14555 * '::'. This method expects a valid IPv6 address and compresses consecutive
14556 * zero pieces to '::'.
14558 * Example: FF01:0:0:0:0:0:0:101 -> FF01::101
14559 * 0:0:0:0:0:0:0:1 -> ::1
14561 * @see uncompress()
14562 * @param string $ip An IPv6 address
14563 * @return string The compressed IPv6 address
14565 public static function compress($ip)
14567 // Prepare the IP to be compressed
14568 $ip = self
::uncompress($ip);
14569 $ip_parts = self
::split_v6_v4($ip);
14571 // Replace all leading zeros
14572 $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
14574 // Find bunches of zeros
14575 if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE
))
14579 foreach ($matches[0] as $match)
14581 if (strlen($match[0]) > $max)
14583 $max = strlen($match[0]);
14588 $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
14591 if ($ip_parts[1] !== '')
14593 return implode(':', $ip_parts);
14597 return $ip_parts[0];
14602 * Splits an IPv6 address into the IPv6 and IPv4 representation parts
14604 * RFC 4291 allows you to represent the last two parts of an IPv6 address
14605 * using the standard IPv4 representation
14607 * Example: 0:0:0:0:0:0:13.1.68.3
14608 * 0:0:0:0:0:FFFF:129.144.52.38
14610 * @param string $ip An IPv6 address
14611 * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part
14613 private static function split_v6_v4($ip)
14615 if (strpos($ip, '.') !== false)
14617 $pos = strrpos($ip, ':');
14618 $ipv6_part = substr($ip, 0, $pos);
14619 $ipv4_part = substr($ip, $pos +
1);
14620 return array($ipv6_part, $ipv4_part);
14624 return array($ip, '');
14629 * Checks an IPv6 address
14631 * Checks if the given IP is a valid IPv6 address
14633 * @param string $ip An IPv6 address
14634 * @return bool true if $ip is a valid IPv6 address
14636 public static function check_ipv6($ip)
14638 $ip = self
::uncompress($ip);
14639 list($ipv6, $ipv4) = self
::split_v6_v4($ip);
14640 $ipv6 = explode(':', $ipv6);
14641 $ipv4 = explode('.', $ipv4);
14642 if (count($ipv6) === 8 && count($ipv4) === 1 ||
count($ipv6) === 6 && count($ipv4) === 4)
14644 foreach ($ipv6 as $ipv6_part)
14646 // The section can't be empty
14647 if ($ipv6_part === '')
14650 // Nor can it be over four characters
14651 if (strlen($ipv6_part) > 4)
14654 // Remove leading zeros (this is safe because of the above)
14655 $ipv6_part = ltrim($ipv6_part, '0');
14656 if ($ipv6_part === '')
14659 // Check the value is valid
14660 $value = hexdec($ipv6_part);
14661 if (dechex($value) !== strtolower($ipv6_part) ||
$value < 0 ||
$value > 0xFFFF)
14664 if (count($ipv4) === 4)
14666 foreach ($ipv4 as $ipv4_part)
14668 $value = (int) $ipv4_part;
14669 if ((string) $value !== $ipv4_part ||
$value < 0 ||
$value > 0xFF)
14682 * Checks if the given IP is a valid IPv6 address
14684 * @codeCoverageIgnore
14685 * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead
14687 * @param string $ip An IPv6 address
14688 * @return bool true if $ip is a valid IPv6 address
14690 public static function checkIPv6($ip)
14692 return self
::check_ipv6($ip);
14699 * @package SimplePie
14700 * @subpackage Parsing
14702 class SimplePie_Parse_Date
14707 * @access protected
14713 * List of days, calendar day name => ordinal day number in the week
14715 * @access protected
14778 'keskiviikko' => 3,
14802 * List of months, calendar month name => calendar month number
14804 * @access protected
14807 var $month = array(
14818 // No long form of May
14947 * List of timezones, abbreviation => offset from UTC
14949 * @access protected
14952 var $timezone = array(
15155 * Cached PCRE for SimplePie_Parse_Date::$day
15157 * @access protected
15163 * Cached PCRE for SimplePie_Parse_Date::$month
15165 * @access protected
15171 * Array of user-added callback methods
15176 var $built_in = array();
15179 * Array of user-added callback methods
15184 var $user = array();
15187 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
15188 * self::month_pcre, and self::built_in
15192 public function __construct()
15194 $this->day_pcre
= '(' . implode(array_keys($this->day
), '|') . ')';
15195 $this->month_pcre
= '(' . implode(array_keys($this->month
), '|') . ')';
15198 if (!isset($cache[get_class($this)]))
15200 $all_methods = get_class_methods($this);
15202 foreach ($all_methods as $method)
15204 if (strtolower(substr($method, 0, 5)) === 'date_')
15206 $cache[get_class($this)][] = $method;
15211 foreach ($cache[get_class($this)] as $method)
15213 $this->built_in
[] = $method;
15222 public static function get()
15227 $object = new SimplePie_Parse_Date
;
15237 * @param string $date Date to parse
15238 * @return int Timestamp corresponding to date string, or false on failure
15240 public function parse($date)
15242 foreach ($this->user
as $method)
15244 if (($returned = call_user_func($method, $date)) !== false)
15250 foreach ($this->built_in
as $method)
15252 if (($returned = call_user_func(array($this, $method), $date)) !== false)
15262 * Add a callback method to parse a date
15266 * @param callback $callback
15268 public function add_callback($callback)
15270 if (is_callable($callback))
15272 $this->user
[] = $callback;
15276 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING
);
15281 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
15282 * well as allowing any of upper or lower case "T", horizontal tabs, or
15283 * spaces to be used as the time seperator (including more than one))
15285 * @access protected
15286 * @return int Timestamp
15288 public function date_w3cdtf($date)
15293 $year = '([0-9]{4})';
15294 $month = $day = $hour = $minute = $second = '([0-9]{2})';
15295 $decimal = '([0-9]*)';
15296 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
15297 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
15299 if (preg_match($pcre, $date, $match))
15302 Capturing subpatterns:
15309 7: Decimal fraction of a second
15313 11: Timezone minutes
15316 // Fill in empty matches
15317 for ($i = count($match); $i <= 3; $i++
)
15322 for ($i = count($match); $i <= 7; $i++
)
15327 // Numeric timezone
15328 if (isset($match[9]) && $match[9] !== '')
15330 $timezone = $match[10] * 3600;
15331 $timezone +
= $match[11] * 60;
15332 if ($match[9] === '-')
15334 $timezone = 0 - $timezone;
15342 // Convert the number of seconds to an integer, taking decimals into account
15343 $second = round($match[6] +
$match[7] / pow(10, strlen($match[7])));
15345 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
15354 * Remove RFC822 comments
15356 * @access protected
15357 * @param string $data Data to strip comments from
15358 * @return string Comment stripped string
15360 public function remove_rfc2822_comments($string)
15362 $string = (string) $string;
15364 $length = strlen($string);
15369 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
15371 $output .= substr($string, $position, $pos - $position);
15372 $position = $pos +
1;
15373 if ($string[$pos - 1] !== '\\')
15376 while ($depth && $position < $length)
15378 $position +
= strcspn($string, '()', $position);
15379 if ($string[$position - 1] === '\\')
15384 elseif (isset($string[$position]))
15386 switch ($string[$position])
15409 $output .= substr($string, $position);
15415 * Parse RFC2822's date format
15417 * @access protected
15418 * @return int Timestamp
15420 public function date_rfc2822($date)
15425 $wsp = '[\x09\x20]';
15426 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
15427 $optional_fws = $fws . '?';
15428 $day_name = $this->day_pcre
;
15429 $month = $this->month_pcre
;
15430 $day = '([0-9]{1,2})';
15431 $hour = $minute = $second = '([0-9]{2})';
15432 $year = '([0-9]{2,4})';
15433 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
15434 $character_zone = '([A-Z]{1,5})';
15435 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
15436 $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';
15438 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
15441 Capturing subpatterns:
15451 10: Timezone minutes
15452 11: Alphabetic timezone
15455 // Find the month number
15456 $month = $this->month
[strtolower($match[3])];
15458 // Numeric timezone
15459 if ($match[8] !== '')
15461 $timezone = $match[9] * 3600;
15462 $timezone +
= $match[10] * 60;
15463 if ($match[8] === '-')
15465 $timezone = 0 - $timezone;
15468 // Character timezone
15469 elseif (isset($this->timezone
[strtoupper($match[11])]))
15471 $timezone = $this->timezone
[strtoupper($match[11])];
15473 // Assume everything else to be -0000
15479 // Deal with 2/3 digit years
15480 if ($match[4] < 50)
15484 elseif ($match[4] < 1000)
15489 // Second is optional, if it is empty set it to zero
15490 if ($match[7] !== '')
15492 $second = $match[7];
15499 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
15508 * Parse RFC850's date format
15510 * @access protected
15511 * @return int Timestamp
15513 public function date_rfc850($date)
15518 $space = '[\x09\x20]+';
15519 $day_name = $this->day_pcre
;
15520 $month = $this->month_pcre
;
15521 $day = '([0-9]{1,2})';
15522 $year = $hour = $minute = $second = '([0-9]{2})';
15523 $zone = '([A-Z]{1,5})';
15524 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
15526 if (preg_match($pcre, $date, $match))
15529 Capturing subpatterns:
15541 $month = $this->month
[strtolower($match[3])];
15543 // Character timezone
15544 if (isset($this->timezone
[strtoupper($match[8])]))
15546 $timezone = $this->timezone
[strtoupper($match[8])];
15548 // Assume everything else to be -0000
15554 // Deal with 2 digit year
15555 if ($match[4] < 50)
15564 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
15573 * Parse C99's asctime()'s date format
15575 * @access protected
15576 * @return int Timestamp
15578 public function date_asctime($date)
15583 $space = '[\x09\x20]+';
15584 $wday_name = $this->day_pcre
;
15585 $mon_name = $this->month_pcre
;
15586 $day = '([0-9]{1,2})';
15587 $hour = $sec = $min = '([0-9]{2})';
15588 $year = '([0-9]{4})';
15589 $terminator = '\x0A?\x00?';
15590 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
15592 if (preg_match($pcre, $date, $match))
15595 Capturing subpatterns:
15605 $month = $this->month
[strtolower($match[2])];
15606 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
15615 * Parse dates using strtotime()
15617 * @access protected
15618 * @return int Timestamp
15620 public function date_strtotime($date)
15622 $strtotime = strtotime($date);
15623 if ($strtotime === -1 ||
$strtotime === false)
15635 * Parses XML into something sane
15638 * This class can be overloaded with {@see SimplePie::set_parser_class()}
15640 * @package SimplePie
15641 * @subpackage Parsing
15643 class SimplePie_Parser
15648 var $current_column;
15650 var $separator = ' ';
15651 var $namespace = array('');
15652 var $element = array('');
15653 var $xml_base = array('');
15654 var $xml_base_explicit = array(false);
15655 var $xml_lang = array('');
15656 var $data = array();
15657 var $datas = array(array());
15658 var $current_xhtml_construct = -1;
15660 protected $registry;
15662 public function set_registry(SimplePie_Registry
$registry)
15664 $this->registry
= $registry;
15667 public function parse(&$data, $encoding)
15669 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
15670 if (strtoupper($encoding) === 'US-ASCII')
15672 $this->encoding
= 'UTF-8';
15676 $this->encoding
= $encoding;
15680 // UTF-32 Big Endian BOM
15681 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
15683 $data = substr($data, 4);
15685 // UTF-32 Little Endian BOM
15686 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
15688 $data = substr($data, 4);
15690 // UTF-16 Big Endian BOM
15691 elseif (substr($data, 0, 2) === "\xFE\xFF")
15693 $data = substr($data, 2);
15695 // UTF-16 Little Endian BOM
15696 elseif (substr($data, 0, 2) === "\xFF\xFE")
15698 $data = substr($data, 2);
15701 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
15703 $data = substr($data, 3);
15706 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
15708 $declaration = $this->registry
->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
15709 if ($declaration->parse())
15711 $data = substr($data, $pos +
2);
15712 $data = '<?xml version="' . $declaration->version
. '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone
) ?
'yes' : 'no') . '"?>' . $data;
15716 $this->error_string
= 'SimplePie bug! Please report this!';
15723 static $xml_is_sane = null;
15724 if ($xml_is_sane === null)
15726 $parser_check = xml_parser_create();
15727 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
15728 xml_parser_free($parser_check);
15729 $xml_is_sane = isset($values[0]['value']);
15732 // Create the parser
15735 $xml = xml_parser_create_ns($this->encoding
, $this->separator
);
15736 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE
, 1);
15737 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING
, 0);
15738 xml_set_object($xml, $this);
15739 xml_set_character_data_handler($xml, 'cdata');
15740 xml_set_element_handler($xml, 'tag_open', 'tag_close');
15743 if (!xml_parse($xml, $data, true))
15745 $this->error_code
= xml_get_error_code($xml);
15746 $this->error_string
= xml_error_string($this->error_code
);
15749 $this->current_line
= xml_get_current_line_number($xml);
15750 $this->current_column
= xml_get_current_column_number($xml);
15751 $this->current_byte
= xml_get_current_byte_index($xml);
15752 xml_parser_free($xml);
15757 libxml_clear_errors();
15758 $xml = new XMLReader();
15760 while (@$xml->read())
15762 switch ($xml->nodeType
)
15765 case constant('XMLReader::END_ELEMENT'):
15766 if ($xml->namespaceURI
!== '')
15768 $tagName = $xml->namespaceURI
. $this->separator
. $xml->localName
;
15772 $tagName = $xml->localName
;
15774 $this->tag_close(null, $tagName);
15776 case constant('XMLReader::ELEMENT'):
15777 $empty = $xml->isEmptyElement
;
15778 if ($xml->namespaceURI
!== '')
15780 $tagName = $xml->namespaceURI
. $this->separator
. $xml->localName
;
15784 $tagName = $xml->localName
;
15786 $attributes = array();
15787 while ($xml->moveToNextAttribute())
15789 if ($xml->namespaceURI
!== '')
15791 $attrName = $xml->namespaceURI
. $this->separator
. $xml->localName
;
15795 $attrName = $xml->localName
;
15797 $attributes[$attrName] = $xml->value
;
15799 $this->tag_open(null, $tagName, $attributes);
15802 $this->tag_close(null, $tagName);
15805 case constant('XMLReader::TEXT'):
15807 case constant('XMLReader::CDATA'):
15808 $this->cdata(null, $xml->value
);
15812 if ($error = libxml_get_last_error())
15814 $this->error_code
= $error->code
;
15815 $this->error_string
= $error->message
;
15816 $this->current_line
= $error->line
;
15817 $this->current_column
= $error->column
;
15827 public function get_error_code()
15829 return $this->error_code
;
15832 public function get_error_string()
15834 return $this->error_string
;
15837 public function get_current_line()
15839 return $this->current_line
;
15842 public function get_current_column()
15844 return $this->current_column
;
15847 public function get_current_byte()
15849 return $this->current_byte
;
15852 public function get_data()
15854 return $this->data
;
15857 public function tag_open($parser, $tag, $attributes)
15859 list($this->namespace[], $this->element
[]) = $this->split_ns($tag);
15861 $attribs = array();
15862 foreach ($attributes as $name => $value)
15864 list($attrib_namespace, $attribute) = $this->split_ns($name);
15865 $attribs[$attrib_namespace][$attribute] = $value;
15868 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML
]['base']))
15870 $base = $this->registry
->call('Misc', 'absolutize_url', array($attribs[SIMPLEPIE_NAMESPACE_XML
]['base'], end($this->xml_base
)));
15871 if ($base !== false)
15873 $this->xml_base
[] = $base;
15874 $this->xml_base_explicit
[] = true;
15879 $this->xml_base
[] = end($this->xml_base
);
15880 $this->xml_base_explicit
[] = end($this->xml_base_explicit
);
15883 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML
]['lang']))
15885 $this->xml_lang
[] = $attribs[SIMPLEPIE_NAMESPACE_XML
]['lang'];
15889 $this->xml_lang
[] = end($this->xml_lang
);
15892 if ($this->current_xhtml_construct
>= 0)
15894 $this->current_xhtml_construct++
;
15895 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML
)
15897 $this->data
['data'] .= '<' . end($this->element
);
15898 if (isset($attribs['']))
15900 foreach ($attribs[''] as $name => $value)
15902 $this->data
['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT
, $this->encoding
) . '"';
15905 $this->data
['data'] .= '>';
15910 $this->datas
[] =& $this->data
;
15911 $this->data
=& $this->data
['child'][end($this->namespace)][end($this->element
)][];
15912 $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
));
15913 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')
15914 ||
(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')
15915 ||
(end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_20
&& in_array(end($this->element
), array('title')))
15916 ||
(end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_090
&& in_array(end($this->element
), array('title')))
15917 ||
(end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_10
&& in_array(end($this->element
), array('title'))))
15919 $this->current_xhtml_construct
= 0;
15924 public function cdata($parser, $cdata)
15926 if ($this->current_xhtml_construct
>= 0)
15928 $this->data
['data'] .= htmlspecialchars($cdata, ENT_QUOTES
, $this->encoding
);
15932 $this->data
['data'] .= $cdata;
15936 public function tag_close($parser, $tag)
15938 if ($this->current_xhtml_construct
>= 0)
15940 $this->current_xhtml_construct
--;
15941 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')))
15943 $this->data
['data'] .= '</' . end($this->element
) . '>';
15946 if ($this->current_xhtml_construct
=== -1)
15948 $this->data
=& $this->datas
[count($this->datas
) - 1];
15949 array_pop($this->datas
);
15952 array_pop($this->element
);
15953 array_pop($this->namespace);
15954 array_pop($this->xml_base
);
15955 array_pop($this->xml_base_explicit
);
15956 array_pop($this->xml_lang
);
15959 public function split_ns($string)
15961 static $cache = array();
15962 if (!isset($cache[$string]))
15964 if ($pos = strpos($string, $this->separator
))
15966 static $separator_length;
15967 if (!$separator_length)
15969 $separator_length = strlen($this->separator
);
15971 $namespace = substr($string, 0, $pos);
15972 $local_name = substr($string, $pos +
$separator_length);
15973 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES
)
15975 $namespace = SIMPLEPIE_NAMESPACE_ITUNES
;
15978 // Normalize the Media RSS namespaces
15979 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||
15980 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||
15981 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||
15982 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||
15983 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5
)
15985 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS
;
15987 $cache[$string] = array($namespace, $local_name);
15991 $cache[$string] = array('', $string);
15994 return $cache[$string];
15999 * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively
16001 * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()}
16003 * This class can be overloaded with {@see SimplePie::set_rating_class()}
16005 * @package SimplePie
16008 class SimplePie_Rating
16014 * @see get_scheme()
16027 * Constructor, used to input the data
16029 * For documentation on all the parameters, see the corresponding
16030 * properties and their accessors
16032 public function __construct($scheme = null, $value = null)
16034 $this->scheme
= $scheme;
16035 $this->value
= $value;
16039 * String-ified version
16043 public function __toString()
16045 // There is no $this->data here
16046 return md5(serialize($this));
16050 * Get the organizational scheme for the rating
16052 * @return string|null
16054 public function get_scheme()
16056 if ($this->scheme
!== null)
16058 return $this->scheme
;
16067 * Get the value of the rating
16069 * @return string|null
16071 public function get_value()
16073 if ($this->value
!== null)
16075 return $this->value
;
16085 * Handles creating objects and calling methods
16087 * Access this via {@see SimplePie::get_registry()}
16089 * @package SimplePie
16091 class SimplePie_Registry
16094 * Default class mapping
16096 * Overriding classes *must* subclass these.
16100 protected $default = array(
16101 'Cache' => 'SimplePie_Cache',
16102 'Locator' => 'SimplePie_Locator',
16103 'Parser' => 'SimplePie_Parser',
16104 'File' => 'SimplePie_File',
16105 'Sanitize' => 'SimplePie_Sanitize',
16106 'Item' => 'SimplePie_Item',
16107 'Author' => 'SimplePie_Author',
16108 'Category' => 'SimplePie_Category',
16109 'Enclosure' => 'SimplePie_Enclosure',
16110 'Caption' => 'SimplePie_Caption',
16111 'Copyright' => 'SimplePie_Copyright',
16112 'Credit' => 'SimplePie_Credit',
16113 'Rating' => 'SimplePie_Rating',
16114 'Restriction' => 'SimplePie_Restriction',
16115 'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer',
16116 'Source' => 'SimplePie_Source',
16117 'Misc' => 'SimplePie_Misc',
16118 'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser',
16119 'Parse_Date' => 'SimplePie_Parse_Date',
16128 protected $classes = array();
16136 protected $legacy = array();
16143 public function __construct() { }
16148 * @param string $type See {@see $default} for names
16149 * @param string $class Class name, must subclass the corresponding default
16150 * @param bool $legacy Whether to enable legacy support for this class
16151 * @return bool Successfulness
16153 public function register($type, $class, $legacy = false)
16155 if (!is_subclass_of($class, $this->default[$type]))
16160 $this->classes
[$type] = $class;
16164 $this->legacy
[] = $class;
16171 * Get the class registered for a type
16173 * Where possible, use {@see create()} or {@see call()} instead
16175 * @param string $type
16176 * @return string|null
16178 public function get_class($type)
16180 if (!empty($this->classes
[$type]))
16182 return $this->classes
[$type];
16184 if (!empty($this->default[$type]))
16186 return $this->default[$type];
16193 * Create a new instance of a given type
16195 * @param string $type
16196 * @param array $parameters Parameters to pass to the constructor
16197 * @return object Instance of class
16199 public function &create($type, $parameters = array())
16201 $class = $this->get_class($type);
16203 if (in_array($class, $this->legacy
))
16208 // Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class
16209 // Specified: file, timeout, useragent, max_checked_feeds
16210 $replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer'));
16211 array_splice($parameters, 3, 1, $replacement);
16216 if (!method_exists($class, '__construct'))
16218 $instance = new $class;
16222 $reflector = new ReflectionClass($class);
16223 $instance = $reflector->newInstanceArgs($parameters);
16226 if (method_exists($instance, 'set_registry'))
16228 $instance->set_registry($this);
16234 * Call a static method for a type
16236 * @param string $type
16237 * @param string $method
16238 * @param array $parameters
16241 public function &call($type, $method, $parameters = array())
16243 $class = $this->get_class($type);
16245 if (in_array($class, $this->legacy
))
16250 // For backwards compatibility with old non-static
16251 // Cache::create() methods
16252 if ($method === 'get_handler')
16254 $result = @call_user_func_array
(array($class, 'create'), $parameters);
16261 $result = call_user_func_array(array($class, $method), $parameters);
16267 * Handles `<media:restriction>` as defined in Media RSS
16269 * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()}
16271 * This class can be overloaded with {@see SimplePie::set_restriction_class()}
16273 * @package SimplePie
16276 class SimplePie_Restriction
16279 * Relationship ('allow'/'deny')
16282 * @see get_relationship()
16287 * Type of restriction
16295 * Restricted values
16303 * Constructor, used to input the data
16305 * For documentation on all the parameters, see the corresponding
16306 * properties and their accessors
16308 public function __construct($relationship = null, $type = null, $value = null)
16310 $this->relationship
= $relationship;
16311 $this->type
= $type;
16312 $this->value
= $value;
16316 * String-ified version
16320 public function __toString()
16322 // There is no $this->data here
16323 return md5(serialize($this));
16327 * Get the relationship
16329 * @return string|null Either 'allow' or 'deny'
16331 public function get_relationship()
16333 if ($this->relationship
!== null)
16335 return $this->relationship
;
16346 * @return string|null
16348 public function get_type()
16350 if ($this->type
!== null)
16352 return $this->type
;
16361 * Get the list of restricted things
16363 * @return string|null
16365 public function get_value()
16367 if ($this->value
!== null)
16369 return $this->value
;
16379 * Used for data cleanup and post-processing
16382 * This class can be overloaded with {@see SimplePie::set_sanitize_class()}
16384 * @package SimplePie
16385 * @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
16387 class SimplePie_Sanitize
16393 var $remove_div = true;
16394 var $image_handler = '';
16395 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
16396 var $encode_instead_of_strip = false;
16397 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
16398 var $strip_comments = false;
16399 var $output_encoding = 'UTF-8';
16400 var $enable_cache = true;
16401 var $cache_location = './cache';
16402 var $cache_name_function = 'md5';
16404 var $useragent = '';
16405 var $force_fsockopen = false;
16406 var $replace_url_attributes = null;
16408 public function __construct()
16411 $this->set_url_replacements(null);
16414 public function remove_div($enable = true)
16416 $this->remove_div
= (bool) $enable;
16419 public function set_image_handler($page = false)
16423 $this->image_handler
= (string) $page;
16427 $this->image_handler
= false;
16431 public function set_registry(SimplePie_Registry
$registry)
16433 $this->registry
= $registry;
16436 public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
16438 if (isset($enable_cache))
16440 $this->enable_cache
= (bool) $enable_cache;
16443 if ($cache_location)
16445 $this->cache_location
= (string) $cache_location;
16448 if ($cache_name_function)
16450 $this->cache_name_function
= (string) $cache_name_function;
16454 public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
16458 $this->timeout
= (string) $timeout;
16463 $this->useragent
= (string) $useragent;
16466 if ($force_fsockopen)
16468 $this->force_fsockopen
= (string) $force_fsockopen;
16472 public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
16476 if (is_array($tags))
16478 $this->strip_htmltags
= $tags;
16482 $this->strip_htmltags
= explode(',', $tags);
16487 $this->strip_htmltags
= false;
16491 public function encode_instead_of_strip($encode = false)
16493 $this->encode_instead_of_strip
= (bool) $encode;
16496 public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
16500 if (is_array($attribs))
16502 $this->strip_attributes
= $attribs;
16506 $this->strip_attributes
= explode(',', $attribs);
16511 $this->strip_attributes
= false;
16515 public function strip_comments($strip = false)
16517 $this->strip_comments
= (bool) $strip;
16520 public function set_output_encoding($encoding = 'UTF-8')
16522 $this->output_encoding
= (string) $encoding;
16526 * Set element/attribute key/value pairs of HTML attributes
16527 * containing URLs that need to be resolved relative to the feed
16529 * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
16530 * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
16534 * @param array|null $element_attribute Element/attribute key/value pairs, null for default
16536 public function set_url_replacements($element_attribute = null)
16538 if ($element_attribute === null)
16540 $element_attribute = array(
16543 'blockquote' => 'cite',
16545 'form' => 'action',
16555 $this->replace_url_attributes
= (array) $element_attribute;
16558 public function sanitize($data, $type, $base = '')
16560 $data = trim($data);
16561 if ($data !== '' ||
$type & SIMPLEPIE_CONSTRUCT_IRI
)
16563 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML
)
16565 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))
16567 $type |
= SIMPLEPIE_CONSTRUCT_HTML
;
16571 $type |
= SIMPLEPIE_CONSTRUCT_TEXT
;
16575 if ($type & SIMPLEPIE_CONSTRUCT_BASE64
)
16577 $data = base64_decode($data);
16580 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML
))
16582 if (!class_exists('DOMDocument'))
16584 $this->registry
->call('Misc', 'error', array('DOMDocument not found, unable to use sanitizer', E_USER_WARNING
, __FILE__
, __LINE__
));
16587 $document = new DOMDocument();
16588 $document->encoding
= 'UTF-8';
16589 $data = $this->preprocess($data, $type);
16591 set_error_handler(array('SimplePie_Misc', 'silence_errors'));
16592 $document->loadHTML($data);
16593 restore_error_handler();
16596 if ($this->strip_comments
)
16598 $xpath = new DOMXPath($document);
16599 $comments = $xpath->query('//comment()');
16601 foreach ($comments as $comment)
16603 $comment->parentNode
->removeChild($comment);
16607 // Strip out HTML tags and attributes that might cause various security problems.
16608 // Based on recommendations by Mark Pilgrim at:
16609 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
16610 if ($this->strip_htmltags
)
16612 foreach ($this->strip_htmltags
as $tag)
16614 $this->strip_tag($tag, $document, $type);
16618 if ($this->strip_attributes
)
16620 foreach ($this->strip_attributes
as $attrib)
16622 $this->strip_attr($attrib, $document);
16626 // Replace relative URLs
16627 $this->base
= $base;
16628 foreach ($this->replace_url_attributes
as $element => $attributes)
16630 $this->replace_urls($document, $element, $attributes);
16633 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
16634 if (isset($this->image_handler
) && ((string) $this->image_handler
) !== '' && $this->enable_cache
)
16636 $images = $document->getElementsByTagName('img');
16637 foreach ($images as $img)
16639 if ($img->hasAttribute('src'))
16641 $image_url = call_user_func($this->cache_name_function
, $img->getAttribute('src'));
16642 $cache = $this->registry
->call('Cache', 'get_handler', array($this->cache_location
, $image_url, 'spi'));
16644 if ($cache->load())
16646 $img->setAttribute('src', $this->image_handler
. $image_url);
16650 $file = $this->registry
->create('File', array($img['attribs']['src']['data'], $this->timeout
, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent
, $this->force_fsockopen
));
16651 $headers = $file->headers
;
16653 if ($file->success
&& ($file->method
& SIMPLEPIE_FILE_SOURCE_REMOTE
=== 0 ||
($file->status_code
=== 200 ||
$file->status_code
> 206 && $file->status_code
< 300)))
16655 if ($cache->save(array('headers' => $file->headers
, 'body' => $file->body
)))
16657 $img->setAttribute('src', $this->image_handler
. $image_url);
16661 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
);
16669 // Remove the DOCTYPE
16670 // Seems to cause segfaulting if we don't do this
16671 if ($document->firstChild
instanceof DOMDocumentType
)
16673 $document->removeChild($document->firstChild
);
16676 // Move everything from the body to the root
16677 $real_body = $document->getElementsByTagName('body')->item(0)->childNodes
->item(0);
16678 $document->replaceChild($real_body, $document->firstChild
);
16680 // Finally, convert to a HTML string
16681 $data = trim($document->saveHTML());
16683 if ($this->remove_div
)
16685 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE
. '>/', '', $data);
16686 $data = preg_replace('/<\/div>$/', '', $data);
16690 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE
. '>/', '<div>', $data);
16694 if ($type & SIMPLEPIE_CONSTRUCT_IRI
)
16696 $absolute = $this->registry
->call('Misc', 'absolutize_url', array($data, $base));
16697 if ($absolute !== false)
16703 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI
))
16705 $data = htmlspecialchars($data, ENT_COMPAT
, 'UTF-8');
16708 if ($this->output_encoding
!== 'UTF-8')
16710 $data = $this->registry
->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding
));
16716 protected function preprocess($html, $type)
16719 if ($type & ~SIMPLEPIE_CONSTRUCT_XHTML
)
16721 // Atom XHTML constructs are wrapped with a div by default
16722 // Note: No protection if $html contains a stray </div>!
16723 $html = '<div>' . $html . '</div>';
16724 $ret .= '<!DOCTYPE html>';
16725 $content_type = 'text/html';
16729 $ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
16730 $content_type = 'application/xhtml+xml';
16733 $ret .= '<html><head>';
16734 $ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />';
16735 $ret .= '</head><body>' . $html . '</body></html>';
16739 public function replace_urls($document, $tag, $attributes)
16741 if (!is_array($attributes))
16743 $attributes = array($attributes);
16746 if (!is_array($this->strip_htmltags
) ||
!in_array($tag, $this->strip_htmltags
))
16748 $elements = $document->getElementsByTagName($tag);
16749 foreach ($elements as $element)
16751 foreach ($attributes as $attribute)
16753 if ($element->hasAttribute($attribute))
16755 $value = $this->registry
->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base
));
16756 if ($value !== false)
16758 $element->setAttribute($attribute, $value);
16766 public function do_strip_htmltags($match)
16768 if ($this->encode_instead_of_strip
)
16770 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
16772 $match[1] = htmlspecialchars($match[1], ENT_COMPAT
, 'UTF-8');
16773 $match[2] = htmlspecialchars($match[2], ENT_COMPAT
, 'UTF-8');
16774 return "<$match[1]$match[2]>$match[3]</$match[1]>";
16778 return htmlspecialchars($match[0], ENT_COMPAT
, 'UTF-8');
16781 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
16791 protected function strip_tag($tag, $document, $type)
16793 $xpath = new DOMXPath($document);
16794 $elements = $xpath->query('body//' . $tag);
16795 if ($this->encode_instead_of_strip
)
16797 foreach ($elements as $element)
16799 $fragment = $document->createDocumentFragment();
16801 // For elements which aren't script or style, include the tag itself
16802 if (!in_array($tag, array('script', 'style')))
16804 $text = '<' . $tag;
16805 if ($element->hasAttributes())
16808 foreach ($element->attributes
as $name => $attr)
16810 $value = $attr->value
;
16812 // In XHTML, empty values should never exist, so we repeat the value
16813 if (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML
))
16817 // For HTML, empty is fine
16818 elseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML
))
16824 // Standard attribute text
16825 $attrs[] = $name . '="' . $attr->value
. '"';
16827 $text .= ' ' . implode(' ', $attrs);
16830 $fragment->appendChild(new DOMText($text));
16833 $number = $element->childNodes
->length
;
16834 for ($i = $number; $i > 0; $i--)
16836 $child = $element->childNodes
->item(0);
16837 $fragment->appendChild($child);
16840 if (!in_array($tag, array('script', 'style')))
16842 $fragment->appendChild(new DOMText('</' . $tag . '>'));
16845 $element->parentNode
->replaceChild($fragment, $element);
16850 elseif (in_array($tag, array('script', 'style')))
16852 foreach ($elements as $element)
16854 $element->parentNode
->removeChild($element);
16861 foreach ($elements as $element)
16863 $fragment = $document->createDocumentFragment();
16864 $number = $element->childNodes
->length
;
16865 for ($i = $number; $i > 0; $i--)
16867 $child = $element->childNodes
->item(0);
16868 $fragment->appendChild($child);
16871 $element->parentNode
->replaceChild($fragment, $element);
16876 protected function strip_attr($attrib, $document)
16878 $xpath = new DOMXPath($document);
16879 $elements = $xpath->query('//*[@' . $attrib . ']');
16881 foreach ($elements as $element)
16883 $element->removeAttribute($attrib);
16889 * Handles `<atom:source>`
16891 * Used by {@see SimplePie_Item::get_source()}
16893 * This class can be overloaded with {@see SimplePie::set_source_class()}
16895 * @package SimplePie
16898 class SimplePie_Source
16901 var $data = array();
16902 protected $registry;
16904 public function __construct($item, $data)
16906 $this->item
= $item;
16907 $this->data
= $data;
16910 public function set_registry(SimplePie_Registry
$registry)
16912 $this->registry
= $registry;
16915 public function __toString()
16917 return md5(serialize($this->data
));
16920 public function get_source_tags($namespace, $tag)
16922 if (isset($this->data
['child'][$namespace][$tag]))
16924 return $this->data
['child'][$namespace][$tag];
16932 public function get_base($element = array())
16934 return $this->item
->get_base($element);
16937 public function sanitize($data, $type, $base = '')
16939 return $this->item
->sanitize($data, $type, $base);
16942 public function get_item()
16944 return $this->item
;
16947 public function get_title()
16949 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'title'))
16951 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
16953 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'title'))
16955 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
16957 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'title'))
16959 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
16961 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'title'))
16963 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
16965 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'title'))
16967 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
16969 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'title'))
16971 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
16973 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'title'))
16975 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
16983 public function get_category($key = 0)
16985 $categories = $this->get_categories();
16986 if (isset($categories[$key]))
16988 return $categories[$key];
16996 public function get_categories()
16998 $categories = array();
17000 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'category') as $category)
17005 if (isset($category['attribs']['']['term']))
17007 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT
);
17009 if (isset($category['attribs']['']['scheme']))
17011 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT
);
17013 if (isset($category['attribs']['']['label']))
17015 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT
);
17017 $categories[] = $this->registry
->create('Category', array($term, $scheme, $label));
17019 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'category') as $category)
17021 // This is really the label, but keep this as the term also for BC.
17022 // Label will also work on retrieving because that falls back to term.
17023 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17024 if (isset($category['attribs']['']['domain']))
17026 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT
);
17032 $categories[] = $this->registry
->create('Category', array($term, $scheme, null));
17034 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'subject') as $category)
17036 $categories[] = $this->registry
->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
17038 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'subject') as $category)
17040 $categories[] = $this->registry
->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
17043 if (!empty($categories))
17045 return array_unique($categories);
17053 public function get_author($key = 0)
17055 $authors = $this->get_authors();
17056 if (isset($authors[$key]))
17058 return $authors[$key];
17066 public function get_authors()
17068 $authors = array();
17069 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'author') as $author)
17074 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data']))
17076 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17078 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['uri'][0]['data']))
17080 $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]));
17082 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data']))
17084 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17086 if ($name !== null ||
$email !== null ||
$uri !== null)
17088 $authors[] = $this->registry
->create('Author', array($name, $uri, $email));
17091 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'author'))
17096 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data']))
17098 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17100 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['url'][0]['data']))
17102 $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]));
17104 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data']))
17106 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17108 if ($name !== null ||
$email !== null ||
$url !== null)
17110 $authors[] = $this->registry
->create('Author', array($name, $url, $email));
17113 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'creator') as $author)
17115 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
17117 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'creator') as $author)
17119 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
17121 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'author') as $author)
17123 $authors[] = $this->registry
->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT
), null, null));
17126 if (!empty($authors))
17128 return array_unique($authors);
17136 public function get_contributor($key = 0)
17138 $contributors = $this->get_contributors();
17139 if (isset($contributors[$key]))
17141 return $contributors[$key];
17149 public function get_contributors()
17151 $contributors = array();
17152 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'contributor') as $contributor)
17157 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data']))
17159 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17161 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['uri'][0]['data']))
17163 $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]));
17165 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data']))
17167 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17169 if ($name !== null ||
$email !== null ||
$uri !== null)
17171 $contributors[] = $this->registry
->create('Author', array($name, $uri, $email));
17174 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'contributor') as $contributor)
17179 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data']))
17181 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17183 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['url'][0]['data']))
17185 $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]));
17187 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data']))
17189 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03
]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17191 if ($name !== null ||
$email !== null ||
$url !== null)
17193 $contributors[] = $this->registry
->create('Author', array($name, $url, $email));
17197 if (!empty($contributors))
17199 return array_unique($contributors);
17207 public function get_link($key = 0, $rel = 'alternate')
17209 $links = $this->get_links($rel);
17210 if (isset($links[$key]))
17212 return $links[$key];
17221 * Added for parity between the parent-level and the item/entry-level.
17223 public function get_permalink()
17225 return $this->get_link(0);
17228 public function get_links($rel = 'alternate')
17230 if (!isset($this->data
['links']))
17232 $this->data
['links'] = array();
17233 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'link'))
17235 foreach ($links as $link)
17237 if (isset($link['attribs']['']['href']))
17239 $link_rel = (isset($link['attribs']['']['rel'])) ?
$link['attribs']['']['rel'] : 'alternate';
17240 $this->data
['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
17244 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'link'))
17246 foreach ($links as $link)
17248 if (isset($link['attribs']['']['href']))
17250 $link_rel = (isset($link['attribs']['']['rel'])) ?
$link['attribs']['']['rel'] : 'alternate';
17251 $this->data
['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($link));
17256 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'link'))
17258 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
17260 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'link'))
17262 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
17264 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'link'))
17266 $this->data
['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($links[0]));
17269 $keys = array_keys($this->data
['links']);
17270 foreach ($keys as $key)
17272 if ($this->registry
->call('Misc', 'is_isegment_nz_nc', array($key)))
17274 if (isset($this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key]))
17276 $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key] = array_merge($this->data
['links'][$key], $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key]);
17277 $this->data
['links'][$key] =& $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key];
17281 $this->data
['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
. $key] =& $this->data
['links'][$key];
17284 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY
)
17286 $this->data
['links'][substr($key, 41)] =& $this->data
['links'][$key];
17288 $this->data
['links'][$key] = array_unique($this->data
['links'][$key]);
17292 if (isset($this->data
['links'][$rel]))
17294 return $this->data
['links'][$rel];
17302 public function get_description()
17304 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'subtitle'))
17306 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17308 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'tagline'))
17310 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17312 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10
, 'description'))
17314 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
17316 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090
, 'description'))
17318 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
17320 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'description'))
17322 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML
, $this->get_base($return[0]));
17324 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'description'))
17326 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17328 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'description'))
17330 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17332 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'summary'))
17334 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
17336 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'subtitle'))
17338 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML
, $this->get_base($return[0]));
17346 public function get_copyright()
17348 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'rights'))
17350 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17352 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03
, 'copyright'))
17354 return $this->sanitize($return[0]['data'], $this->registry
->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
17356 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'copyright'))
17358 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17360 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'rights'))
17362 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17364 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'rights'))
17366 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17374 public function get_language()
17376 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20
, 'language'))
17378 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17380 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11
, 'language'))
17382 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17384 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10
, 'language'))
17386 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT
);
17388 elseif (isset($this->data
['xml_lang']))
17390 return $this->sanitize($this->data
['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT
);
17398 public function get_latitude()
17400 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'lat'))
17402 return (float) $return[0]['data'];
17404 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))
17406 return (float) $match[1];
17414 public function get_longitude()
17416 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'long'))
17418 return (float) $return[0]['data'];
17420 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO
, 'lon'))
17422 return (float) $return[0]['data'];
17424 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))
17426 return (float) $match[2];
17434 public function get_image_url()
17436 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES
, 'image'))
17438 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI
);
17440 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'logo'))
17442 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
17444 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10
, 'icon'))
17446 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI
, $this->get_base($return[0]));
17456 * Parses the XML Declaration
17458 * @package SimplePie
17459 * @subpackage Parsing
17461 class SimplePie_XML_Declaration_Parser
17469 var $version = '1.0';
17477 var $encoding = 'UTF-8';
17485 var $standalone = false;
17488 * Current state of the state machine
17493 var $state = 'before_version_name';
17504 * Input data length (to avoid calling strlen() everytime this is needed)
17509 var $data_length = 0;
17512 * Current position of the pointer
17520 * Create an instance of the class with the input data
17523 * @param string $data Input data
17525 public function __construct($data)
17527 $this->data
= $data;
17528 $this->data_length
= strlen($this->data
);
17532 * Parse the input data
17535 * @return bool true on success, false on failure
17537 public function parse()
17539 while ($this->state
&& $this->state
!== 'emit' && $this->has_data())
17541 $state = $this->state
;
17545 if ($this->state
=== 'emit')
17551 $this->version
= '';
17552 $this->encoding
= '';
17553 $this->standalone
= '';
17559 * Check whether there is data beyond the pointer
17562 * @return bool true if there is further data, false if not
17564 public function has_data()
17566 return (bool) ($this->position
< $this->data_length
);
17570 * Advance past any whitespace
17572 * @return int Number of whitespace characters passed
17574 public function skip_whitespace()
17576 $whitespace = strspn($this->data
, "\x09\x0A\x0D\x20", $this->position
);
17577 $this->position +
= $whitespace;
17578 return $whitespace;
17584 public function get_value()
17586 $quote = substr($this->data
, $this->position
, 1);
17587 if ($quote === '"' ||
$quote === "'")
17590 $len = strcspn($this->data
, $quote, $this->position
);
17591 if ($this->has_data())
17593 $value = substr($this->data
, $this->position
, $len);
17594 $this->position +
= $len +
1;
17601 public function before_version_name()
17603 if ($this->skip_whitespace())
17605 $this->state
= 'version_name';
17609 $this->state
= false;
17613 public function version_name()
17615 if (substr($this->data
, $this->position
, 7) === 'version')
17617 $this->position +
= 7;
17618 $this->skip_whitespace();
17619 $this->state
= 'version_equals';
17623 $this->state
= false;
17627 public function version_equals()
17629 if (substr($this->data
, $this->position
, 1) === '=')
17632 $this->skip_whitespace();
17633 $this->state
= 'version_value';
17637 $this->state
= false;
17641 public function version_value()
17643 if ($this->version
= $this->get_value())
17645 $this->skip_whitespace();
17646 if ($this->has_data())
17648 $this->state
= 'encoding_name';
17652 $this->state
= 'emit';
17657 $this->state
= false;
17661 public function encoding_name()
17663 if (substr($this->data
, $this->position
, 8) === 'encoding')
17665 $this->position +
= 8;
17666 $this->skip_whitespace();
17667 $this->state
= 'encoding_equals';
17671 $this->state
= 'standalone_name';
17675 public function encoding_equals()
17677 if (substr($this->data
, $this->position
, 1) === '=')
17680 $this->skip_whitespace();
17681 $this->state
= 'encoding_value';
17685 $this->state
= false;
17689 public function encoding_value()
17691 if ($this->encoding
= $this->get_value())
17693 $this->skip_whitespace();
17694 if ($this->has_data())
17696 $this->state
= 'standalone_name';
17700 $this->state
= 'emit';
17705 $this->state
= false;
17709 public function standalone_name()
17711 if (substr($this->data
, $this->position
, 10) === 'standalone')
17713 $this->position +
= 10;
17714 $this->skip_whitespace();
17715 $this->state
= 'standalone_equals';
17719 $this->state
= false;
17723 public function standalone_equals()
17725 if (substr($this->data
, $this->position
, 1) === '=')
17728 $this->skip_whitespace();
17729 $this->state
= 'standalone_value';
17733 $this->state
= false;
17737 public function standalone_value()
17739 if ($standalone = $this->get_value())
17741 switch ($standalone)
17744 $this->standalone
= true;
17748 $this->standalone
= false;
17752 $this->state
= false;
17756 $this->skip_whitespace();
17757 if ($this->has_data())
17759 $this->state
= false;
17763 $this->state
= 'emit';
17768 $this->state
= false;