MDL-36204 Improve moodle1 conversion of embedded files
[moodle.git] / lib / simplepie / simplepie.class.php
blob2aeb1ff569e2bddbbe8abb2760312488f3e3690d
1 <?php
2 /**
3 * SimplePie
5 * A PHP-Based RSS and Atom Feed Framework.
6 * Takes the hard work out of managing a complete RSS/Atom solution.
8 * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without modification, are
12 * permitted provided that the following conditions are met:
14 * * Redistributions of source code must retain the above copyright notice, this list of
15 * conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright notice, this list
18 * of conditions and the following disclaimer in the documentation and/or other materials
19 * provided with the distribution.
21 * * Neither the name of the SimplePie Team nor the names of its contributors may be used
22 * to endorse or promote products derived from this software without specific prior
23 * written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * @package SimplePie
36 * @version 1.3-dev
37 * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon, Ryan McCue
38 * @author Ryan Parman
39 * @author Geoffrey Sneddon
40 * @author Ryan McCue
41 * @link http://simplepie.org/ SimplePie
42 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @todo phpDoc comments
46 /**
47 * SimplePie Name
49 define('SIMPLEPIE_NAME', 'SimplePie');
51 /**
52 * SimplePie Version
54 define('SIMPLEPIE_VERSION', '1.3-dev');
56 /**
57 * SimplePie Build
58 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
60 define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
62 /**
63 * SimplePie Website URL
65 define('SIMPLEPIE_URL', 'http://simplepie.org');
67 /**
68 * SimplePie Useragent
69 * @see SimplePie::set_useragent()
71 define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
73 /**
74 * SimplePie Linkback
76 define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
78 /**
79 * No Autodiscovery
80 * @see SimplePie::set_autodiscovery_level()
82 define('SIMPLEPIE_LOCATOR_NONE', 0);
84 /**
85 * Feed Link Element Autodiscovery
86 * @see SimplePie::set_autodiscovery_level()
88 define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
90 /**
91 * Local Feed Extension Autodiscovery
92 * @see SimplePie::set_autodiscovery_level()
94 define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
96 /**
97 * Local Feed Body Autodiscovery
98 * @see SimplePie::set_autodiscovery_level()
100 define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
103 * Remote Feed Extension Autodiscovery
104 * @see SimplePie::set_autodiscovery_level()
106 define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
109 * Remote Feed Body Autodiscovery
110 * @see SimplePie::set_autodiscovery_level()
112 define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
115 * All Feed Autodiscovery
116 * @see SimplePie::set_autodiscovery_level()
118 define('SIMPLEPIE_LOCATOR_ALL', 31);
121 * No known feed type
123 define('SIMPLEPIE_TYPE_NONE', 0);
126 * RSS 0.90
128 define('SIMPLEPIE_TYPE_RSS_090', 1);
131 * RSS 0.91 (Netscape)
133 define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
136 * RSS 0.91 (Userland)
138 define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
141 * RSS 0.91 (both Netscape and Userland)
143 define('SIMPLEPIE_TYPE_RSS_091', 6);
146 * RSS 0.92
148 define('SIMPLEPIE_TYPE_RSS_092', 8);
151 * RSS 0.93
153 define('SIMPLEPIE_TYPE_RSS_093', 16);
156 * RSS 0.94
158 define('SIMPLEPIE_TYPE_RSS_094', 32);
161 * RSS 1.0
163 define('SIMPLEPIE_TYPE_RSS_10', 64);
166 * RSS 2.0
168 define('SIMPLEPIE_TYPE_RSS_20', 128);
171 * RDF-based RSS
173 define('SIMPLEPIE_TYPE_RSS_RDF', 65);
176 * Non-RDF-based RSS (truly intended as syndication format)
178 define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
181 * All RSS
183 define('SIMPLEPIE_TYPE_RSS_ALL', 255);
186 * Atom 0.3
188 define('SIMPLEPIE_TYPE_ATOM_03', 256);
191 * Atom 1.0
193 define('SIMPLEPIE_TYPE_ATOM_10', 512);
196 * All Atom
198 define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
201 * All feed types
203 define('SIMPLEPIE_TYPE_ALL', 1023);
206 * No construct
208 define('SIMPLEPIE_CONSTRUCT_NONE', 0);
211 * Text construct
213 define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
216 * HTML construct
218 define('SIMPLEPIE_CONSTRUCT_HTML', 2);
221 * XHTML construct
223 define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
226 * base64-encoded construct
228 define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
231 * IRI construct
233 define('SIMPLEPIE_CONSTRUCT_IRI', 16);
236 * A construct that might be HTML
238 define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
241 * All constructs
243 define('SIMPLEPIE_CONSTRUCT_ALL', 63);
246 * Don't change case
248 define('SIMPLEPIE_SAME_CASE', 1);
251 * Change to lowercase
253 define('SIMPLEPIE_LOWERCASE', 2);
256 * Change to uppercase
258 define('SIMPLEPIE_UPPERCASE', 4);
261 * PCRE for HTML attributes
263 define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
266 * PCRE for XML attributes
268 define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
271 * XML Namespace
273 define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
276 * Atom 1.0 Namespace
278 define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
281 * Atom 0.3 Namespace
283 define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
286 * RDF Namespace
288 define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
291 * RSS 0.90 Namespace
293 define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
296 * RSS 1.0 Namespace
298 define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
301 * RSS 1.0 Content Module Namespace
303 define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
306 * RSS 2.0 Namespace
307 * (Stupid, I know, but I'm certain it will confuse people less with support.)
309 define('SIMPLEPIE_NAMESPACE_RSS_20', '');
312 * DC 1.0 Namespace
314 define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
317 * DC 1.1 Namespace
319 define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
322 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
324 define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
327 * GeoRSS Namespace
329 define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
332 * Media RSS Namespace
334 define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
337 * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
339 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
342 * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
344 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
347 * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
349 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
352 * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
354 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
357 * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
359 define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
362 * iTunes RSS Namespace
364 define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
367 * XHTML Namespace
369 define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
372 * IANA Link Relations Registry
374 define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
377 * Whether we're running on PHP5
379 define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
382 * No file source
384 define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
387 * Remote file source
389 define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
392 * Local file source
394 define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
397 * fsockopen() file source
399 define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
402 * cURL file source
404 define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
407 * file_get_contents() file source
409 define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
412 * SimplePie
414 * @package SimplePie
416 class SimplePie
419 * @var array Raw data
420 * @access private
422 public $data = array();
425 * @var mixed Error string
426 * @access private
428 public $error;
431 * @var object Instance of SimplePie_Sanitize (or other class)
432 * @see SimplePie::set_sanitize_class()
433 * @access private
435 public $sanitize;
438 * @var string SimplePie Useragent
439 * @see SimplePie::set_useragent()
440 * @access private
442 public $useragent = SIMPLEPIE_USERAGENT;
445 * @var string Feed URL
446 * @see SimplePie::set_feed_url()
447 * @access private
449 public $feed_url;
452 * @var object Instance of SimplePie_File to use as a feed
453 * @see SimplePie::set_file()
454 * @access private
456 public $file;
459 * @var string Raw feed data
460 * @see SimplePie::set_raw_data()
461 * @access private
463 public $raw_data;
466 * @var int Timeout for fetching remote files
467 * @see SimplePie::set_timeout()
468 * @access private
470 public $timeout = 10;
473 * @var bool Forces fsockopen() to be used for remote files instead
474 * of cURL, even if a new enough version is installed
475 * @see SimplePie::force_fsockopen()
476 * @access private
478 public $force_fsockopen = false;
481 * @var bool Force the given data/URL to be treated as a feed no matter what
482 * it appears like
483 * @see SimplePie::force_feed()
484 * @access private
486 public $force_feed = false;
489 * @var bool Enable/Disable XML dump
490 * @see SimplePie::enable_xml_dump()
491 * @access private
493 public $xml_dump = false;
496 * @var bool Enable/Disable Caching
497 * @see SimplePie::enable_cache()
498 * @access private
500 public $cache = true;
503 * @var int Cache duration (in seconds)
504 * @see SimplePie::set_cache_duration()
505 * @access private
507 public $cache_duration = 3600;
510 * @var int Auto-discovery cache duration (in seconds)
511 * @see SimplePie::set_autodiscovery_cache_duration()
512 * @access private
514 public $autodiscovery_cache_duration = 604800; // 7 Days.
517 * @var string Cache location (relative to executing script)
518 * @see SimplePie::set_cache_location()
519 * @access private
521 public $cache_location = './cache';
524 * @var string Function that creates the cache filename
525 * @see SimplePie::set_cache_name_function()
526 * @access private
528 public $cache_name_function = 'md5';
531 * @var bool Reorder feed by date descending
532 * @see SimplePie::enable_order_by_date()
533 * @access private
535 public $order_by_date = true;
538 * @var mixed Force input encoding to be set to the follow value
539 * (false, or anything type-cast to false, disables this feature)
540 * @see SimplePie::set_input_encoding()
541 * @access private
543 public $input_encoding = false;
546 * @var int Feed Autodiscovery Level
547 * @see SimplePie::set_autodiscovery_level()
548 * @access private
550 public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
553 * @var string Class used for caching feeds
554 * @see SimplePie::set_cache_class()
555 * @access private
557 public $cache_class = 'SimplePie_Cache';
560 * @var string Class used for locating feeds
561 * @see SimplePie::set_locator_class()
562 * @access private
564 public $locator_class = 'SimplePie_Locator';
567 * @var string Class used for parsing feeds
568 * @see SimplePie::set_parser_class()
569 * @access private
571 public $parser_class = 'SimplePie_Parser';
574 * @var string Class used for fetching feeds
575 * @see SimplePie::set_file_class()
576 * @access private
578 public $file_class = 'SimplePie_File';
581 * @var string Class used for items
582 * @see SimplePie::set_item_class()
583 * @access private
585 public $item_class = 'SimplePie_Item';
588 * @var string Class used for authors
589 * @see SimplePie::set_author_class()
590 * @access private
592 public $author_class = 'SimplePie_Author';
595 * @var string Class used for categories
596 * @see SimplePie::set_category_class()
597 * @access private
599 public $category_class = 'SimplePie_Category';
602 * @var string Class used for enclosures
603 * @see SimplePie::set_enclosures_class()
604 * @access private
606 public $enclosure_class = 'SimplePie_Enclosure';
609 * @var string Class used for Media RSS <media:text> captions
610 * @see SimplePie::set_caption_class()
611 * @access private
613 public $caption_class = 'SimplePie_Caption';
616 * @var string Class used for Media RSS <media:copyright>
617 * @see SimplePie::set_copyright_class()
618 * @access private
620 public $copyright_class = 'SimplePie_Copyright';
623 * @var string Class used for Media RSS <media:credit>
624 * @see SimplePie::set_credit_class()
625 * @access private
627 public $credit_class = 'SimplePie_Credit';
630 * @var string Class used for Media RSS <media:rating>
631 * @see SimplePie::set_rating_class()
632 * @access private
634 public $rating_class = 'SimplePie_Rating';
637 * @var string Class used for Media RSS <media:restriction>
638 * @see SimplePie::set_restriction_class()
639 * @access private
641 public $restriction_class = 'SimplePie_Restriction';
644 * @var string Class used for content-type sniffing
645 * @see SimplePie::set_content_type_sniffer_class()
646 * @access private
648 public $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
651 * @var string Class used for item sources.
652 * @see SimplePie::set_source_class()
653 * @access private
655 public $source_class = 'SimplePie_Source';
658 * @var mixed Set javascript query string parameter (false, or
659 * anything type-cast to false, disables this feature)
660 * @see SimplePie::set_javascript()
661 * @access private
663 public $javascript = 'js';
666 * @var int Maximum number of feeds to check with autodiscovery
667 * @see SimplePie::set_max_checked_feeds()
668 * @access private
670 public $max_checked_feeds = 10;
673 * @var array All the feeds found during the autodiscovery process
674 * @see SimplePie::get_all_discovered_feeds()
675 * @access private
677 public $all_discovered_feeds = array();
680 * @var string Web-accessible path to the handler_image.php file.
681 * @see SimplePie::set_image_handler()
682 * @access private
684 public $image_handler = '';
687 * @var array Stores the URLs when multiple feeds are being initialized.
688 * @see SimplePie::set_feed_url()
689 * @access private
691 public $multifeed_url = array();
694 * @var array Stores SimplePie objects when multiple feeds initialized.
695 * @access private
697 public $multifeed_objects = array();
700 * @var array Stores the get_object_vars() array for use with multifeeds.
701 * @see SimplePie::set_feed_url()
702 * @access private
704 public $config_settings = null;
707 * @var integer Stores the number of items to return per-feed with multifeeds.
708 * @see SimplePie::set_item_limit()
709 * @access private
711 public $item_limit = 0;
714 * @var array Stores the default attributes to be stripped by strip_attributes().
715 * @see SimplePie::strip_attributes()
716 * @access private
718 public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
721 * @var array Stores the default tags to be stripped by strip_htmltags().
722 * @see SimplePie::strip_htmltags()
723 * @access private
725 public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
728 * The SimplePie class contains feed level data and options
730 * There are two ways that you can create a new SimplePie object. The first
731 * is by passing a feed URL as a parameter to the SimplePie constructor
732 * (as well as optionally setting the cache location and cache expiry). This
733 * will initialise the whole feed with all of the default settings, and you
734 * can begin accessing methods and properties immediately.
736 * The second way is to create the SimplePie object with no parameters
737 * at all. This will enable you to set configuration options. After setting
738 * them, you must initialise the feed using $feed->init(). At that point the
739 * object's methods and properties will be available to you. This format is
740 * what is used throughout this documentation.
742 * @access public
743 * @since 1.0 Preview Release
745 public function __construct()
747 if (version_compare(PHP_VERSION, '5.0', '<'))
749 trigger_error('PHP 4.x is no longer supported. Please upgrade to PHP 5.2 or newer.');
750 die();
753 // Other objects, instances created here so we can set options on them
754 $this->sanitize = new SimplePie_Sanitize();
756 if (func_num_args() > 0)
758 trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.');
763 * Used for converting object to a string
765 public function __toString()
767 return md5(serialize($this->data));
771 * Remove items that link back to this before destroying this object
773 public function __destruct()
775 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
777 if (!empty($this->data['items']))
779 foreach ($this->data['items'] as $item)
781 $item->__destruct();
783 unset($item, $this->data['items']);
785 if (!empty($this->data['ordered_items']))
787 foreach ($this->data['ordered_items'] as $item)
789 $item->__destruct();
791 unset($item, $this->data['ordered_items']);
797 * Force the given data/URL to be treated as a feed no matter what it
798 * appears like
800 * @access public
801 * @since 1.1
802 * @param bool $enable Force the given data/URL to be treated as a feed
804 public function force_feed($enable = false)
806 $this->force_feed = (bool) $enable;
810 * This is the URL of the feed you want to parse.
812 * This allows you to enter the URL of the feed you want to parse, or the
813 * website you want to try to use auto-discovery on. This takes priority
814 * over any set raw data.
816 * You can set multiple feeds to mash together by passing an array instead
817 * of a string for the $url. Remember that with each additional feed comes
818 * additional processing and resources.
820 * @access public
821 * @since 1.0 Preview Release
822 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
823 * @see SimplePie::set_raw_data()
825 public function set_feed_url($url)
827 if (is_array($url))
829 $this->multifeed_url = array();
830 foreach ($url as $value)
832 $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
835 else
837 $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
842 * Provides an instance of SimplePie_File to use as a feed
844 * @access public
845 * @param object &$file Instance of SimplePie_File (or subclass)
846 * @return bool True on success, false on failure
848 public function set_file(&$file)
850 if (is_a($file, 'SimplePie_File'))
852 $this->feed_url = $file->url;
853 $this->file =& $file;
854 return true;
856 return false;
860 * Allows you to use a string of RSS/Atom data instead of a remote feed.
862 * If you have a feed available as a string in PHP, you can tell SimplePie
863 * to parse that data string instead of a remote feed. Any set feed URL
864 * takes precedence.
866 * @access public
867 * @since 1.0 Beta 3
868 * @param string $data RSS or Atom data as a string.
869 * @see SimplePie::set_feed_url()
871 public function set_raw_data($data)
873 $this->raw_data = $data;
877 * Allows you to override the default timeout for fetching remote feeds.
879 * This allows you to change the maximum time the feed's server to respond
880 * and send the feed back.
882 * @access public
883 * @since 1.0 Beta 3
884 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
886 public function set_timeout($timeout = 10)
888 $this->timeout = (int) $timeout;
892 * Forces SimplePie to use fsockopen() instead of the preferred cURL
893 * functions.
895 * @access public
896 * @since 1.0 Beta 3
897 * @param bool $enable Force fsockopen() to be used
899 public function force_fsockopen($enable = false)
901 $this->force_fsockopen = (bool) $enable;
905 * Enables/disables caching in SimplePie.
907 * This option allows you to disable caching all-together in SimplePie.
908 * However, disabling the cache can lead to longer load times.
910 * @access public
911 * @since 1.0 Preview Release
912 * @param bool $enable Enable caching
914 public function enable_cache($enable = true)
916 $this->cache = (bool) $enable;
920 * Set the length of time (in seconds) that the contents of a feed
921 * will be cached.
923 * @access public
924 * @param int $seconds The feed content cache duration.
926 public function set_cache_duration($seconds = 3600)
928 $this->cache_duration = (int) $seconds;
932 * Set the length of time (in seconds) that the autodiscovered feed
933 * URL will be cached.
935 * @access public
936 * @param int $seconds The autodiscovered feed URL cache duration.
938 public function set_autodiscovery_cache_duration($seconds = 604800)
940 $this->autodiscovery_cache_duration = (int) $seconds;
944 * Set the file system location where the cached files should be stored.
946 * @access public
947 * @param string $location The file system location.
949 public function set_cache_location($location = './cache')
951 $this->cache_location = (string) $location;
955 * Determines whether feed items should be sorted into reverse chronological order.
957 * @access public
958 * @param bool $enable Sort as reverse chronological order.
960 public function enable_order_by_date($enable = true)
962 $this->order_by_date = (bool) $enable;
966 * Allows you to override the character encoding reported by the feed.
968 * @access public
969 * @param string $encoding Character encoding.
971 public function set_input_encoding($encoding = false)
973 if ($encoding)
975 $this->input_encoding = (string) $encoding;
977 else
979 $this->input_encoding = false;
984 * Set how much feed autodiscovery to do
986 * @access public
987 * @see SIMPLEPIE_LOCATOR_NONE
988 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
989 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
990 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
991 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
992 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
993 * @see SIMPLEPIE_LOCATOR_ALL
994 * @param int $level Feed Autodiscovery Level (level can be a
995 * combination of the above constants, see bitwise OR operator)
997 public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
999 $this->autodiscovery = (int) $level;
1003 * Allows you to change which class SimplePie uses for caching.
1004 * Useful when you are overloading or extending SimplePie's default classes.
1006 * @access public
1007 * @param string $class Name of custom class.
1008 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1010 public function set_cache_class($class = 'SimplePie_Cache')
1012 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
1014 $this->cache_class = $class;
1015 return true;
1017 return false;
1021 * Allows you to change which class SimplePie uses for auto-discovery.
1022 * Useful when you are overloading or extending SimplePie's default classes.
1024 * @access public
1025 * @param string $class Name of custom class.
1026 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1028 public function set_locator_class($class = 'SimplePie_Locator')
1030 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
1032 $this->locator_class = $class;
1033 return true;
1035 return false;
1039 * Allows you to change which class SimplePie uses for XML parsing.
1040 * Useful when you are overloading or extending SimplePie's default classes.
1042 * @access public
1043 * @param string $class Name of custom class.
1044 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1046 public function set_parser_class($class = 'SimplePie_Parser')
1048 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
1050 $this->parser_class = $class;
1051 return true;
1053 return false;
1057 * Allows you to change which class SimplePie uses for remote file fetching.
1058 * Useful when you are overloading or extending SimplePie's default classes.
1060 * @access public
1061 * @param string $class Name of custom class.
1062 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1064 public function set_file_class($class = 'SimplePie_File')
1066 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
1068 $this->file_class = $class;
1069 return true;
1071 return false;
1075 * Allows you to change which class SimplePie uses for data sanitization.
1076 * Useful when you are overloading or extending SimplePie's default classes.
1078 * @access public
1079 * @param string $class Name of custom class.
1080 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1082 public function set_sanitize_class($class = 'SimplePie_Sanitize')
1084 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
1086 $this->sanitize = new $class();
1087 return true;
1089 return false;
1093 * Allows you to change which class SimplePie uses for handling feed items.
1094 * Useful when you are overloading or extending SimplePie's default classes.
1096 * @access public
1097 * @param string $class Name of custom class.
1098 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1100 public function set_item_class($class = 'SimplePie_Item')
1102 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
1104 $this->item_class = $class;
1105 return true;
1107 return false;
1111 * Allows you to change which class SimplePie uses for handling author data.
1112 * Useful when you are overloading or extending SimplePie's default classes.
1114 * @access public
1115 * @param string $class Name of custom class.
1116 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1118 public function set_author_class($class = 'SimplePie_Author')
1120 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
1122 $this->author_class = $class;
1123 return true;
1125 return false;
1129 * Allows you to change which class SimplePie uses for handling category data.
1130 * Useful when you are overloading or extending SimplePie's default classes.
1132 * @access public
1133 * @param string $class Name of custom class.
1134 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1136 public function set_category_class($class = 'SimplePie_Category')
1138 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
1140 $this->category_class = $class;
1141 return true;
1143 return false;
1147 * Allows you to change which class SimplePie uses for feed enclosures.
1148 * Useful when you are overloading or extending SimplePie's default classes.
1150 * @access public
1151 * @param string $class Name of custom class.
1152 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1154 public function set_enclosure_class($class = 'SimplePie_Enclosure')
1156 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
1158 $this->enclosure_class = $class;
1159 return true;
1161 return false;
1165 * Allows you to change which class SimplePie uses for <media:text> captions
1166 * Useful when you are overloading or extending SimplePie's default classes.
1168 * @access public
1169 * @param string $class Name of custom class.
1170 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1172 public function set_caption_class($class = 'SimplePie_Caption')
1174 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
1176 $this->caption_class = $class;
1177 return true;
1179 return false;
1183 * Allows you to change which class SimplePie uses for <media:copyright>
1184 * Useful when you are overloading or extending SimplePie's default classes.
1186 * @access public
1187 * @param string $class Name of custom class.
1188 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1190 public function set_copyright_class($class = 'SimplePie_Copyright')
1192 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
1194 $this->copyright_class = $class;
1195 return true;
1197 return false;
1201 * Allows you to change which class SimplePie uses for <media:credit>
1202 * Useful when you are overloading or extending SimplePie's default classes.
1204 * @access public
1205 * @param string $class Name of custom class.
1206 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1208 public function set_credit_class($class = 'SimplePie_Credit')
1210 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
1212 $this->credit_class = $class;
1213 return true;
1215 return false;
1219 * Allows you to change which class SimplePie uses for <media:rating>
1220 * Useful when you are overloading or extending SimplePie's default classes.
1222 * @access public
1223 * @param string $class Name of custom class.
1224 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1226 public function set_rating_class($class = 'SimplePie_Rating')
1228 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
1230 $this->rating_class = $class;
1231 return true;
1233 return false;
1237 * Allows you to change which class SimplePie uses for <media:restriction>
1238 * Useful when you are overloading or extending SimplePie's default classes.
1240 * @access public
1241 * @param string $class Name of custom class.
1242 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1244 public function set_restriction_class($class = 'SimplePie_Restriction')
1246 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
1248 $this->restriction_class = $class;
1249 return true;
1251 return false;
1255 * Allows you to change which class SimplePie uses for content-type sniffing.
1256 * Useful when you are overloading or extending SimplePie's default classes.
1258 * @access public
1259 * @param string $class Name of custom class.
1260 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1262 public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1264 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
1266 $this->content_type_sniffer_class = $class;
1267 return true;
1269 return false;
1273 * Allows you to change which class SimplePie uses item sources.
1274 * Useful when you are overloading or extending SimplePie's default classes.
1276 * @access public
1277 * @param string $class Name of custom class.
1278 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
1280 public function set_source_class($class = 'SimplePie_Source')
1282 if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
1284 $this->source_class = $class;
1285 return true;
1287 return false;
1291 * Allows you to override the default user agent string.
1293 * @access public
1294 * @param string $ua New user agent string.
1296 public function set_useragent($ua = SIMPLEPIE_USERAGENT)
1298 $this->useragent = (string) $ua;
1302 * Set callback function to create cache filename with
1304 * @access public
1305 * @param mixed $function Callback function
1307 public function set_cache_name_function($function = 'md5')
1309 if (is_callable($function))
1311 $this->cache_name_function = $function;
1316 * Set javascript query string parameter
1318 * @access public
1319 * @param mixed $get Javascript query string parameter
1321 public function set_javascript($get = 'js')
1323 if ($get)
1325 $this->javascript = (string) $get;
1327 else
1329 $this->javascript = false;
1334 * Set options to make SP as fast as possible. Forgoes a
1335 * substantial amount of data sanitization in favor of speed.
1337 * @access public
1338 * @param bool $set Whether to set them or not
1340 public function set_stupidly_fast($set = false)
1342 if ($set)
1344 $this->enable_order_by_date(false);
1345 $this->remove_div(false);
1346 $this->strip_comments(false);
1347 $this->strip_htmltags(false);
1348 $this->strip_attributes(false);
1349 $this->set_image_handler(false);
1354 * Set maximum number of feeds to check with autodiscovery
1356 * @access public
1357 * @param int $max Maximum number of feeds to check
1359 public function set_max_checked_feeds($max = 10)
1361 $this->max_checked_feeds = (int) $max;
1364 public function remove_div($enable = true)
1366 $this->sanitize->remove_div($enable);
1369 public function strip_htmltags($tags = '', $encode = null)
1371 if ($tags === '')
1373 $tags = $this->strip_htmltags;
1375 $this->sanitize->strip_htmltags($tags);
1376 if ($encode !== null)
1378 $this->sanitize->encode_instead_of_strip($tags);
1382 public function encode_instead_of_strip($enable = true)
1384 $this->sanitize->encode_instead_of_strip($enable);
1387 public function strip_attributes($attribs = '')
1389 if ($attribs === '')
1391 $attribs = $this->strip_attributes;
1393 $this->sanitize->strip_attributes($attribs);
1396 public function set_output_encoding($encoding = 'UTF-8')
1398 $this->sanitize->set_output_encoding($encoding);
1401 public function strip_comments($strip = false)
1403 $this->sanitize->strip_comments($strip);
1407 * Set element/attribute key/value pairs of HTML attributes
1408 * containing URLs that need to be resolved relative to the feed
1410 * @access public
1411 * @since 1.0
1412 * @param array $element_attribute Element/attribute key/value pairs
1414 public function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
1416 $this->sanitize->set_url_replacements($element_attribute);
1420 * Set the handler to enable the display of cached images.
1422 * @access public
1423 * @param str $page Web-accessible path to the handler_image.php file.
1424 * @param str $qs The query string that the value should be passed to.
1426 public function set_image_handler($page = false, $qs = 'i')
1428 if ($page !== false)
1430 $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1432 else
1434 $this->image_handler = '';
1439 * Set the limit for items returned per-feed with multifeeds.
1441 * @access public
1442 * @param integer $limit The maximum number of items to return.
1444 public function set_item_limit($limit = 0)
1446 $this->item_limit = (int) $limit;
1449 public function init()
1451 // Check absolute bare minimum requirements.
1452 if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
1454 return false;
1456 // 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.
1457 elseif (!extension_loaded('xmlreader'))
1459 static $xml_is_sane = null;
1460 if ($xml_is_sane === null)
1462 $parser_check = xml_parser_create();
1463 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1464 xml_parser_free($parser_check);
1465 $xml_is_sane = isset($values[0]['value']);
1467 if (!$xml_is_sane)
1469 return false;
1473 if (isset($_GET[$this->javascript]))
1475 SimplePie_Misc::output_javascript();
1476 exit;
1479 // Pass whatever was set with config options over to the sanitizer.
1480 $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
1481 $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
1483 if ($this->feed_url !== null || $this->raw_data !== null)
1485 $this->error = null;
1486 $this->data = array();
1487 $this->multifeed_objects = array();
1488 $cache = false;
1490 if ($this->feed_url !== null)
1492 $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
1493 // Decide whether to enable caching
1494 if ($this->cache && $parsed_feed_url['scheme'] !== '')
1496 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
1498 // If it's enabled and we don't want an XML dump, use the cache
1499 if ($cache && !$this->xml_dump)
1501 // Load the Cache
1502 $this->data = $cache->load();
1503 if (!empty($this->data))
1505 // If the cache is for an outdated build of SimplePie
1506 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1508 $cache->unlink();
1509 $this->data = array();
1511 // If we've hit a collision just rerun it with caching disabled
1512 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1514 $cache = false;
1515 $this->data = array();
1517 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1518 elseif (isset($this->data['feed_url']))
1520 // If the autodiscovery cache is still valid use it.
1521 if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1523 // Do not need to do feed autodiscovery yet.
1524 if ($this->data['feed_url'] === $this->data['url'])
1526 $cache->unlink();
1527 $this->data = array();
1529 else
1531 $this->set_feed_url($this->data['feed_url']);
1532 return $this->init();
1536 // Check if the cache has been updated
1537 elseif ($cache->mtime() + $this->cache_duration < time())
1539 // If we have last-modified and/or etag set
1540 if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1542 $headers = array();
1543 if (isset($this->data['headers']['last-modified']))
1545 $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1547 if (isset($this->data['headers']['etag']))
1549 $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
1552 $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
1554 if ($file->success)
1556 if ($file->status_code === 304)
1558 $cache->touch();
1559 return true;
1561 else
1563 $headers = $file->headers;
1566 else
1568 unset($file);
1572 // If the cache is still valid, just return true
1573 else
1575 return true;
1578 // If the cache is empty, delete it
1579 else
1581 $cache->unlink();
1582 $this->data = array();
1585 // 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.
1586 if (!isset($file))
1588 if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
1590 $file =& $this->file;
1592 else
1594 $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
1597 // If the file connection has an error, set SimplePie::error to that and quit
1598 if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1600 $this->error = $file->error;
1601 if (!empty($this->data))
1603 return true;
1605 else
1607 return false;
1611 if (!$this->force_feed)
1613 // Check if the supplied URL is a feed, if it isn't, look for it.
1614 $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
1616 if (!$locate->is_feed($file))
1618 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1619 unset($file);
1620 if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
1622 if ($cache)
1624 $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1625 if (!$cache->save($this))
1627 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);
1629 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
1631 $this->feed_url = $file->url;
1633 else
1635 $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.";
1636 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1637 return false;
1640 $locate = null;
1643 $headers = $file->headers;
1644 $data = $file->body;
1645 $sniffer = new $this->content_type_sniffer_class($file);
1646 $sniffed = $sniffer->get_type();
1648 else
1650 $data = $this->raw_data;
1653 // Set up array of possible encodings
1654 $encodings = array();
1656 // First check to see if input has been overridden.
1657 if ($this->input_encoding !== false)
1659 $encodings[] = $this->input_encoding;
1662 $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1663 $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1665 // RFC 3023 (only applies to sniffed content)
1666 if (isset($sniffed))
1668 if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1670 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1672 $encodings[] = strtoupper($charset[1]);
1674 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1675 $encodings[] = 'UTF-8';
1677 elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1679 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1681 $encodings[] = $charset[1];
1683 $encodings[] = 'US-ASCII';
1685 // Text MIME-type default
1686 elseif (substr($sniffed, 0, 5) === 'text/')
1688 $encodings[] = 'US-ASCII';
1692 // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1693 $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
1694 $encodings[] = 'UTF-8';
1695 $encodings[] = 'ISO-8859-1';
1697 // There's no point in trying an encoding twice
1698 $encodings = array_unique($encodings);
1700 // If we want the XML, just output that with the most likely encoding and quit
1701 if ($this->xml_dump)
1703 header('Content-type: text/xml; charset=' . $encodings[0]);
1704 echo $data;
1705 exit;
1708 // Loop through each possible encoding, till we return something, or run out of possibilities
1709 foreach ($encodings as $encoding)
1711 // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1712 if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
1714 // Create new parser
1715 $parser = new $this->parser_class();
1717 // If it's parsed fine
1718 if ($parser->parse($utf8_data, 'UTF-8'))
1720 $this->data = $parser->get_data();
1721 if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
1723 if (isset($headers))
1725 $this->data['headers'] = $headers;
1727 $this->data['build'] = SIMPLEPIE_BUILD;
1729 // Cache the file if caching is enabled
1730 if ($cache && !$cache->save($this))
1732 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);
1734 return true;
1736 else
1738 $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1739 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1740 return false;
1746 if (isset($parser))
1748 // We have an error, just set SimplePie_Misc::error to it and quit
1749 $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());
1751 else
1753 $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.';
1756 SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
1758 return false;
1760 elseif (!empty($this->multifeed_url))
1762 $i = 0;
1763 $success = 0;
1764 $this->multifeed_objects = array();
1765 foreach ($this->multifeed_url as $url)
1767 $this->multifeed_objects[$i] = clone $this;
1768 $this->multifeed_objects[$i]->set_feed_url($url);
1769 $success |= $this->multifeed_objects[$i]->init();
1770 $i++;
1772 return (bool) $success;
1774 else
1776 return false;
1781 * Return the error message for the occured error
1783 * @access public
1784 * @return string Error message
1786 public function error()
1788 return $this->error;
1791 public function get_encoding()
1793 return $this->sanitize->output_encoding;
1796 public function handle_content_type($mime = 'text/html')
1798 if (!headers_sent())
1800 $header = "Content-type: $mime;";
1801 if ($this->get_encoding())
1803 $header .= ' charset=' . $this->get_encoding();
1805 else
1807 $header .= ' charset=UTF-8';
1809 header($header);
1813 public function get_type()
1815 if (!isset($this->data['type']))
1817 $this->data['type'] = SIMPLEPIE_TYPE_ALL;
1818 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1820 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1822 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1824 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1826 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1828 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1829 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1830 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1831 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1833 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1835 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1836 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1837 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1838 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1840 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1843 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1845 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1846 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1848 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1850 case '0.91':
1851 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1852 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1854 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1856 case '0':
1857 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1858 break;
1860 case '24':
1861 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1862 break;
1865 break;
1867 case '0.92':
1868 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1869 break;
1871 case '0.93':
1872 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1873 break;
1875 case '0.94':
1876 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1877 break;
1879 case '2.0':
1880 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1881 break;
1885 else
1887 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
1890 return $this->data['type'];
1894 * @todo If we have a perm redirect we should return the new URL
1895 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1896 * @todo Also, |atom:link|@rel=self
1898 public function subscribe_url()
1900 if ($this->feed_url !== null)
1902 return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1904 else
1906 return null;
1910 public function get_feed_tags($namespace, $tag)
1912 $type = $this->get_type();
1913 if ($type & SIMPLEPIE_TYPE_ATOM_10)
1915 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1917 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1920 if ($type & SIMPLEPIE_TYPE_ATOM_03)
1922 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1924 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1927 if ($type & SIMPLEPIE_TYPE_RSS_RDF)
1929 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1931 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
1934 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1936 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
1938 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
1941 return null;
1944 public function get_channel_tags($namespace, $tag)
1946 $type = $this->get_type();
1947 if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
1949 if ($return = $this->get_feed_tags($namespace, $tag))
1951 return $return;
1954 if ($type & SIMPLEPIE_TYPE_RSS_10)
1956 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
1958 if (isset($channel[0]['child'][$namespace][$tag]))
1960 return $channel[0]['child'][$namespace][$tag];
1964 if ($type & SIMPLEPIE_TYPE_RSS_090)
1966 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
1968 if (isset($channel[0]['child'][$namespace][$tag]))
1970 return $channel[0]['child'][$namespace][$tag];
1974 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1976 if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
1978 if (isset($channel[0]['child'][$namespace][$tag]))
1980 return $channel[0]['child'][$namespace][$tag];
1984 return null;
1987 public function get_image_tags($namespace, $tag)
1989 $type = $this->get_type();
1990 if ($type & SIMPLEPIE_TYPE_RSS_10)
1992 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
1994 if (isset($image[0]['child'][$namespace][$tag]))
1996 return $image[0]['child'][$namespace][$tag];
2000 if ($type & SIMPLEPIE_TYPE_RSS_090)
2002 if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
2004 if (isset($image[0]['child'][$namespace][$tag]))
2006 return $image[0]['child'][$namespace][$tag];
2010 if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
2012 if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
2014 if (isset($image[0]['child'][$namespace][$tag]))
2016 return $image[0]['child'][$namespace][$tag];
2020 return null;
2023 public function get_base($element = array())
2025 if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2027 return $element['xml_base'];
2029 elseif ($this->get_link() !== null)
2031 return $this->get_link();
2033 else
2035 return $this->subscribe_url();
2039 public function sanitize($data, $type, $base = '')
2041 return $this->sanitize->sanitize($data, $type, $base);
2044 public function get_title()
2046 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2048 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2050 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2052 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2054 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2056 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2058 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2060 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2062 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2064 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2066 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2068 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2070 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2072 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2074 else
2076 return null;
2080 public function get_category($key = 0)
2082 $categories = $this->get_categories();
2083 if (isset($categories[$key]))
2085 return $categories[$key];
2087 else
2089 return null;
2093 public function get_categories()
2095 $categories = array();
2097 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2099 $term = null;
2100 $scheme = null;
2101 $label = null;
2102 if (isset($category['attribs']['']['term']))
2104 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2106 if (isset($category['attribs']['']['scheme']))
2108 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2110 if (isset($category['attribs']['']['label']))
2112 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2114 $categories[] = new $this->category_class($term, $scheme, $label);
2116 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2118 // This is really the label, but keep this as the term also for BC.
2119 // Label will also work on retrieving because that falls back to term.
2120 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2121 if (isset($category['attribs']['']['domain']))
2123 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2125 else
2127 $scheme = null;
2129 $categories[] = new $this->category_class($term, $scheme, null);
2131 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2133 $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2135 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2137 $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2140 if (!empty($categories))
2142 return SimplePie_Misc::array_unique($categories);
2144 else
2146 return null;
2150 public function get_author($key = 0)
2152 $authors = $this->get_authors();
2153 if (isset($authors[$key]))
2155 return $authors[$key];
2157 else
2159 return null;
2163 public function get_authors()
2165 $authors = array();
2166 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2168 $name = null;
2169 $uri = null;
2170 $email = null;
2171 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2173 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2175 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2177 $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]));
2179 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2181 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2183 if ($name !== null || $email !== null || $uri !== null)
2185 $authors[] = new $this->author_class($name, $uri, $email);
2188 if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2190 $name = null;
2191 $url = null;
2192 $email = null;
2193 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2195 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2197 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2199 $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]));
2201 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2203 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2205 if ($name !== null || $email !== null || $url !== null)
2207 $authors[] = new $this->author_class($name, $url, $email);
2210 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2212 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2214 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2216 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2218 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2220 $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
2223 if (!empty($authors))
2225 return SimplePie_Misc::array_unique($authors);
2227 else
2229 return null;
2233 public function get_contributor($key = 0)
2235 $contributors = $this->get_contributors();
2236 if (isset($contributors[$key]))
2238 return $contributors[$key];
2240 else
2242 return null;
2246 public function get_contributors()
2248 $contributors = array();
2249 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2251 $name = null;
2252 $uri = null;
2253 $email = null;
2254 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2256 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2258 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2260 $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]));
2262 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2264 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2266 if ($name !== null || $email !== null || $uri !== null)
2268 $contributors[] = new $this->author_class($name, $uri, $email);
2271 foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2273 $name = null;
2274 $url = null;
2275 $email = null;
2276 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2278 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2280 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2282 $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]));
2284 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2286 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2288 if ($name !== null || $email !== null || $url !== null)
2290 $contributors[] = new $this->author_class($name, $url, $email);
2294 if (!empty($contributors))
2296 return SimplePie_Misc::array_unique($contributors);
2298 else
2300 return null;
2304 public function get_link($key = 0, $rel = 'alternate')
2306 $links = $this->get_links($rel);
2307 if (isset($links[$key]))
2309 return $links[$key];
2311 else
2313 return null;
2318 * Added for parity between the parent-level and the item/entry-level.
2320 public function get_permalink()
2322 return $this->get_link(0);
2325 public function get_links($rel = 'alternate')
2327 if (!isset($this->data['links']))
2329 $this->data['links'] = array();
2330 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2332 foreach ($links as $link)
2334 if (isset($link['attribs']['']['href']))
2336 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2337 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2341 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2343 foreach ($links as $link)
2345 if (isset($link['attribs']['']['href']))
2347 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2348 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2353 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2355 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2357 if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, '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_20, 'link'))
2363 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2366 $keys = array_keys($this->data['links']);
2367 foreach ($keys as $key)
2369 if (SimplePie_Misc::is_isegment_nz_nc($key))
2371 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2373 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2374 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2376 else
2378 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2381 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2383 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2385 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2389 if (isset($this->data['links'][$rel]))
2391 return $this->data['links'][$rel];
2393 else
2395 return null;
2399 public function get_all_discovered_feeds()
2401 return $this->all_discovered_feeds;
2404 public function get_description()
2406 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2408 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2410 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2412 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2414 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2416 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2418 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2420 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2422 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2424 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2426 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2428 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2430 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2432 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2434 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2436 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2438 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2440 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2442 else
2444 return null;
2448 public function get_copyright()
2450 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2452 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2454 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2456 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2458 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2460 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2462 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2464 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2466 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2468 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2470 else
2472 return null;
2476 public function get_language()
2478 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2480 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2482 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2484 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2486 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2488 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2490 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2492 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2494 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2496 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2498 elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2500 return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2502 elseif (isset($this->data['headers']['content-language']))
2504 return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2506 else
2508 return null;
2512 public function get_latitude()
2515 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2517 return (float) $return[0]['data'];
2519 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))
2521 return (float) $match[1];
2523 else
2525 return null;
2529 public function get_longitude()
2531 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2533 return (float) $return[0]['data'];
2535 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2537 return (float) $return[0]['data'];
2539 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))
2541 return (float) $match[2];
2543 else
2545 return null;
2549 public function get_image_title()
2551 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2553 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2555 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2557 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2559 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2561 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2563 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2565 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2567 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2569 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2571 else
2573 return null;
2577 public function get_image_url()
2579 if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2581 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2583 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2585 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2587 elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2589 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2591 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2593 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2595 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2597 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2599 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2601 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2603 else
2605 return null;
2609 public function get_image_link()
2611 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2613 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2615 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2617 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2619 elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2621 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2623 else
2625 return null;
2629 public function get_image_width()
2631 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2633 return round($return[0]['data']);
2635 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2637 return 88.0;
2639 else
2641 return null;
2645 public function get_image_height()
2647 if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2649 return round($return[0]['data']);
2651 elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2653 return 31.0;
2655 else
2657 return null;
2661 public function get_item_quantity($max = 0)
2663 $max = (int) $max;
2664 $qty = count($this->get_items());
2665 if ($max === 0)
2667 return $qty;
2669 else
2671 return ($qty > $max) ? $max : $qty;
2675 public function get_item($key = 0)
2677 $items = $this->get_items();
2678 if (isset($items[$key]))
2680 return $items[$key];
2682 else
2684 return null;
2688 public function get_items($start = 0, $end = 0)
2690 if (!isset($this->data['items']))
2692 if (!empty($this->multifeed_objects))
2694 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2696 else
2698 $this->data['items'] = array();
2699 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2701 $keys = array_keys($items);
2702 foreach ($keys as $key)
2704 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2707 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2709 $keys = array_keys($items);
2710 foreach ($keys as $key)
2712 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2715 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2717 $keys = array_keys($items);
2718 foreach ($keys as $key)
2720 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2723 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2725 $keys = array_keys($items);
2726 foreach ($keys as $key)
2728 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2731 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2733 $keys = array_keys($items);
2734 foreach ($keys as $key)
2736 $this->data['items'][] = new $this->item_class($this, $items[$key]);
2742 if (!empty($this->data['items']))
2744 // If we want to order it by date, check if all items have a date, and then sort it
2745 if ($this->order_by_date && empty($this->multifeed_objects))
2747 if (!isset($this->data['ordered_items']))
2749 $do_sort = true;
2750 foreach ($this->data['items'] as $item)
2752 if (!$item->get_date('U'))
2754 $do_sort = false;
2755 break;
2758 $item = null;
2759 $this->data['ordered_items'] = $this->data['items'];
2760 if ($do_sort)
2762 usort($this->data['ordered_items'], array(&$this, 'sort_items'));
2765 $items = $this->data['ordered_items'];
2767 else
2769 $items = $this->data['items'];
2772 // Slice the data as desired
2773 if ($end === 0)
2775 return array_slice($items, $start);
2777 else
2779 return array_slice($items, $start, $end);
2782 else
2784 return array();
2789 * @static
2791 public function sort_items($a, $b)
2793 return $a->get_date('U') <= $b->get_date('U');
2797 * @static
2799 public function merge_items($urls, $start = 0, $end = 0, $limit = 0)
2801 if (is_array($urls) && sizeof($urls) > 0)
2803 $items = array();
2804 foreach ($urls as $arg)
2806 if (is_a($arg, 'SimplePie'))
2808 $items = array_merge($items, $arg->get_items(0, $limit));
2810 else
2812 trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
2816 $do_sort = true;
2817 foreach ($items as $item)
2819 if (!$item->get_date('U'))
2821 $do_sort = false;
2822 break;
2825 $item = null;
2826 if ($do_sort)
2828 usort($items, array('SimplePie', 'sort_items'));
2831 if ($end === 0)
2833 return array_slice($items, $start);
2835 else
2837 return array_slice($items, $start, $end);
2840 else
2842 trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
2843 return array();
2848 class SimplePie_Item
2850 var $feed;
2851 var $data = array();
2853 public function __construct($feed, $data)
2855 $this->feed = $feed;
2856 $this->data = $data;
2859 public function __toString()
2861 return md5(serialize($this->data));
2865 * Remove items that link back to this before destroying this object
2867 public function __destruct()
2869 if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
2871 unset($this->feed);
2875 public function get_item_tags($namespace, $tag)
2877 if (isset($this->data['child'][$namespace][$tag]))
2879 return $this->data['child'][$namespace][$tag];
2881 else
2883 return null;
2887 public function get_base($element = array())
2889 return $this->feed->get_base($element);
2892 public function sanitize($data, $type, $base = '')
2894 return $this->feed->sanitize($data, $type, $base);
2897 public function get_feed()
2899 return $this->feed;
2902 public function get_id($hash = false)
2904 if (!$hash)
2906 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
2908 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2910 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
2912 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2914 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
2916 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2918 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
2920 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2922 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
2924 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2926 elseif (($return = $this->get_permalink()) !== null)
2928 return $return;
2930 elseif (($return = $this->get_title()) !== null)
2932 return $return;
2935 if ($this->get_permalink() !== null || $this->get_title() !== null)
2937 return md5($this->get_permalink() . $this->get_title());
2939 else
2941 return md5(serialize($this->data));
2945 public function get_title()
2947 if (!isset($this->data['title']))
2949 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2951 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2953 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2955 $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2957 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2959 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2961 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2963 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2965 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2967 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2969 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2971 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2973 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2975 $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2977 else
2979 $this->data['title'] = null;
2982 return $this->data['title'];
2985 public function get_description($description_only = false)
2987 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
2989 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2991 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
2993 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
2995 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2997 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2999 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
3001 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3003 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
3005 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3007 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
3009 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3011 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
3013 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3015 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
3017 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3019 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
3021 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
3024 elseif (!$description_only)
3026 return $this->get_content(true);
3028 else
3030 return null;
3034 public function get_content($content_only = false)
3036 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
3038 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3040 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
3042 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3044 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
3046 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
3048 elseif (!$content_only)
3050 return $this->get_description(true);
3052 else
3054 return null;
3058 public function get_category($key = 0)
3060 $categories = $this->get_categories();
3061 if (isset($categories[$key]))
3063 return $categories[$key];
3065 else
3067 return null;
3071 public function get_categories()
3073 $categories = array();
3075 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
3077 $term = null;
3078 $scheme = null;
3079 $label = null;
3080 if (isset($category['attribs']['']['term']))
3082 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
3084 if (isset($category['attribs']['']['scheme']))
3086 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3088 if (isset($category['attribs']['']['label']))
3090 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3092 $categories[] = new $this->feed->category_class($term, $scheme, $label);
3094 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
3096 // This is really the label, but keep this as the term also for BC.
3097 // Label will also work on retrieving because that falls back to term.
3098 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3099 if (isset($category['attribs']['']['domain']))
3101 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
3103 else
3105 $scheme = null;
3107 $categories[] = new $this->feed->category_class($term, $scheme, null);
3109 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
3111 $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3113 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
3115 $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3118 if (!empty($categories))
3120 return SimplePie_Misc::array_unique($categories);
3122 else
3124 return null;
3128 public function get_author($key = 0)
3130 $authors = $this->get_authors();
3131 if (isset($authors[$key]))
3133 return $authors[$key];
3135 else
3137 return null;
3141 public function get_contributor($key = 0)
3143 $contributors = $this->get_contributors();
3144 if (isset($contributors[$key]))
3146 return $contributors[$key];
3148 else
3150 return null;
3154 public function get_contributors()
3156 $contributors = array();
3157 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
3159 $name = null;
3160 $uri = null;
3161 $email = null;
3162 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3164 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3166 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3168 $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]));
3170 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3172 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3174 if ($name !== null || $email !== null || $uri !== null)
3176 $contributors[] = new $this->feed->author_class($name, $uri, $email);
3179 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
3181 $name = null;
3182 $url = null;
3183 $email = null;
3184 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3186 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3188 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3190 $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]));
3192 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3194 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3196 if ($name !== null || $email !== null || $url !== null)
3198 $contributors[] = new $this->feed->author_class($name, $url, $email);
3202 if (!empty($contributors))
3204 return SimplePie_Misc::array_unique($contributors);
3206 else
3208 return null;
3212 public function get_authors()
3214 $authors = array();
3215 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
3217 $name = null;
3218 $uri = null;
3219 $email = null;
3220 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
3222 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3224 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
3226 $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]));
3228 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
3230 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3232 if ($name !== null || $email !== null || $uri !== null)
3234 $authors[] = new $this->feed->author_class($name, $uri, $email);
3237 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
3239 $name = null;
3240 $url = null;
3241 $email = null;
3242 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
3244 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3246 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
3248 $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]));
3250 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
3252 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3254 if ($name !== null || $email !== null || $url !== null)
3256 $authors[] = new $this->feed->author_class($name, $url, $email);
3259 if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
3261 $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3263 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
3265 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3267 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
3269 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3271 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
3273 $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
3276 if (!empty($authors))
3278 return SimplePie_Misc::array_unique($authors);
3280 elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
3282 return $authors;
3284 elseif ($authors = $this->feed->get_authors())
3286 return $authors;
3288 else
3290 return null;
3294 public function get_copyright()
3296 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
3298 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
3300 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
3302 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3304 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
3306 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3308 else
3310 return null;
3314 public function get_date($date_format = 'j F Y, g:i a')
3316 if (!isset($this->data['date']))
3318 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
3320 $this->data['date']['raw'] = $return[0]['data'];
3322 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
3324 $this->data['date']['raw'] = $return[0]['data'];
3326 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
3328 $this->data['date']['raw'] = $return[0]['data'];
3330 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
3332 $this->data['date']['raw'] = $return[0]['data'];
3334 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
3336 $this->data['date']['raw'] = $return[0]['data'];
3338 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
3340 $this->data['date']['raw'] = $return[0]['data'];
3342 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
3344 $this->data['date']['raw'] = $return[0]['data'];
3346 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
3348 $this->data['date']['raw'] = $return[0]['data'];
3351 if (!empty($this->data['date']['raw']))
3353 $parser = SimplePie_Parse_Date::get();
3354 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
3356 else
3358 $this->data['date'] = null;
3361 if ($this->data['date'])
3363 $date_format = (string) $date_format;
3364 switch ($date_format)
3366 case '':
3367 return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
3369 case 'U':
3370 return $this->data['date']['parsed'];
3372 default:
3373 return date($date_format, $this->data['date']['parsed']);
3376 else
3378 return null;
3382 public function get_local_date($date_format = '%c')
3384 if (!$date_format)
3386 return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
3388 elseif (($date = $this->get_date('U')) !== null && $date !== false)
3390 return strftime($date_format, $date);
3392 else
3394 return null;
3398 public function get_permalink()
3400 $link = $this->get_link();
3401 $enclosure = $this->get_enclosure(0);
3402 if ($link !== null)
3404 return $link;
3406 elseif ($enclosure !== null)
3408 return $enclosure->get_link();
3410 else
3412 return null;
3416 public function get_link($key = 0, $rel = 'alternate')
3418 $links = $this->get_links($rel);
3419 if ($links[$key] !== null)
3421 return $links[$key];
3423 else
3425 return null;
3429 public function get_links($rel = 'alternate')
3431 if (!isset($this->data['links']))
3433 $this->data['links'] = array();
3434 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
3436 if (isset($link['attribs']['']['href']))
3438 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3439 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3443 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
3445 if (isset($link['attribs']['']['href']))
3447 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
3448 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
3451 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
3453 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3455 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
3457 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3459 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
3461 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3463 if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
3465 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
3467 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
3471 $keys = array_keys($this->data['links']);
3472 foreach ($keys as $key)
3474 if (SimplePie_Misc::is_isegment_nz_nc($key))
3476 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
3478 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
3479 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
3481 else
3483 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
3486 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
3488 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
3490 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
3493 if (isset($this->data['links'][$rel]))
3495 return $this->data['links'][$rel];
3497 else
3499 return null;
3504 * @todo Add ability to prefer one type of content over another (in a media group).
3506 public function get_enclosure($key = 0, $prefer = null)
3508 $enclosures = $this->get_enclosures();
3509 if (isset($enclosures[$key]))
3511 return $enclosures[$key];
3513 else
3515 return null;
3520 * Grabs all available enclosures (podcasts, etc.)
3522 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
3524 * At this point, we're pretty much assuming that all enclosures for an item are the same content. Anything else is too complicated to properly support.
3526 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
3527 * @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).
3529 public function get_enclosures()
3531 if (!isset($this->data['enclosures']))
3533 $this->data['enclosures'] = array();
3535 // Elements
3536 $captions_parent = null;
3537 $categories_parent = null;
3538 $copyrights_parent = null;
3539 $credits_parent = null;
3540 $description_parent = null;
3541 $duration_parent = null;
3542 $hashes_parent = null;
3543 $keywords_parent = null;
3544 $player_parent = null;
3545 $ratings_parent = null;
3546 $restrictions_parent = null;
3547 $thumbnails_parent = null;
3548 $title_parent = null;
3550 // Let's do the channel and item-level ones first, and just re-use them if we need to.
3551 $parent = $this->get_feed();
3553 // CAPTIONS
3554 if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3556 foreach ($captions as $caption)
3558 $caption_type = null;
3559 $caption_lang = null;
3560 $caption_startTime = null;
3561 $caption_endTime = null;
3562 $caption_text = null;
3563 if (isset($caption['attribs']['']['type']))
3565 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3567 if (isset($caption['attribs']['']['lang']))
3569 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3571 if (isset($caption['attribs']['']['start']))
3573 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3575 if (isset($caption['attribs']['']['end']))
3577 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3579 if (isset($caption['data']))
3581 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3583 $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3586 elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
3588 foreach ($captions as $caption)
3590 $caption_type = null;
3591 $caption_lang = null;
3592 $caption_startTime = null;
3593 $caption_endTime = null;
3594 $caption_text = null;
3595 if (isset($caption['attribs']['']['type']))
3597 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
3599 if (isset($caption['attribs']['']['lang']))
3601 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
3603 if (isset($caption['attribs']['']['start']))
3605 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
3607 if (isset($caption['attribs']['']['end']))
3609 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
3611 if (isset($caption['data']))
3613 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3615 $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
3618 if (is_array($captions_parent))
3620 $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
3623 // CATEGORIES
3624 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3626 $term = null;
3627 $scheme = null;
3628 $label = null;
3629 if (isset($category['data']))
3631 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3633 if (isset($category['attribs']['']['scheme']))
3635 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3637 else
3639 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3641 if (isset($category['attribs']['']['label']))
3643 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3645 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3647 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
3649 $term = null;
3650 $scheme = null;
3651 $label = null;
3652 if (isset($category['data']))
3654 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3656 if (isset($category['attribs']['']['scheme']))
3658 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3660 else
3662 $scheme = 'http://search.yahoo.com/mrss/category_schema';
3664 if (isset($category['attribs']['']['label']))
3666 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
3668 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3670 foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
3672 $term = null;
3673 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
3674 $label = null;
3675 if (isset($category['attribs']['']['text']))
3677 $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3679 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3681 if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
3683 foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
3685 if (isset($subcategory['attribs']['']['text']))
3687 $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
3689 $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
3693 if (is_array($categories_parent))
3695 $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
3698 // COPYRIGHT
3699 if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3701 $copyright_url = null;
3702 $copyright_label = null;
3703 if (isset($copyright[0]['attribs']['']['url']))
3705 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3707 if (isset($copyright[0]['data']))
3709 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3711 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
3713 elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
3715 $copyright_url = null;
3716 $copyright_label = null;
3717 if (isset($copyright[0]['attribs']['']['url']))
3719 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
3721 if (isset($copyright[0]['data']))
3723 $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3725 $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
3728 // CREDITS
3729 if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3731 foreach ($credits as $credit)
3733 $credit_role = null;
3734 $credit_scheme = null;
3735 $credit_name = null;
3736 if (isset($credit['attribs']['']['role']))
3738 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3740 if (isset($credit['attribs']['']['scheme']))
3742 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3744 else
3746 $credit_scheme = 'urn:ebu';
3748 if (isset($credit['data']))
3750 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3752 $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
3755 elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
3757 foreach ($credits as $credit)
3759 $credit_role = null;
3760 $credit_scheme = null;
3761 $credit_name = null;
3762 if (isset($credit['attribs']['']['role']))
3764 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
3766 if (isset($credit['attribs']['']['scheme']))
3768 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3770 else
3772 $credit_scheme = 'urn:ebu';
3774 if (isset($credit['data']))
3776 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3778 $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
3781 if (is_array($credits_parent))
3783 $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
3786 // DESCRIPTION
3787 if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
3789 if (isset($description_parent[0]['data']))
3791 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3794 elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
3796 if (isset($description_parent[0]['data']))
3798 $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3802 // DURATION
3803 if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
3805 $seconds = null;
3806 $minutes = null;
3807 $hours = null;
3808 if (isset($duration_parent[0]['data']))
3810 $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3811 if (sizeof($temp) > 0)
3813 $seconds = (int) array_pop($temp);
3815 if (sizeof($temp) > 0)
3817 $minutes = (int) array_pop($temp);
3818 $seconds += $minutes * 60;
3820 if (sizeof($temp) > 0)
3822 $hours = (int) array_pop($temp);
3823 $seconds += $hours * 3600;
3825 unset($temp);
3826 $duration_parent = $seconds;
3830 // HASHES
3831 if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
3833 foreach ($hashes_iterator as $hash)
3835 $value = null;
3836 $algo = null;
3837 if (isset($hash['data']))
3839 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3841 if (isset($hash['attribs']['']['algo']))
3843 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
3845 else
3847 $algo = 'md5';
3849 $hashes_parent[] = $algo.':'.$value;
3852 elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
3854 foreach ($hashes_iterator as $hash)
3856 $value = null;
3857 $algo = null;
3858 if (isset($hash['data']))
3860 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3862 if (isset($hash['attribs']['']['algo']))
3864 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
3866 else
3868 $algo = 'md5';
3870 $hashes_parent[] = $algo.':'.$value;
3873 if (is_array($hashes_parent))
3875 $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
3878 // KEYWORDS
3879 if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
3881 if (isset($keywords[0]['data']))
3883 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3884 foreach ($temp as $word)
3886 $keywords_parent[] = trim($word);
3889 unset($temp);
3891 elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
3893 if (isset($keywords[0]['data']))
3895 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3896 foreach ($temp as $word)
3898 $keywords_parent[] = trim($word);
3901 unset($temp);
3903 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
3905 if (isset($keywords[0]['data']))
3907 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3908 foreach ($temp as $word)
3910 $keywords_parent[] = trim($word);
3913 unset($temp);
3915 elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
3917 if (isset($keywords[0]['data']))
3919 $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
3920 foreach ($temp as $word)
3922 $keywords_parent[] = trim($word);
3925 unset($temp);
3927 if (is_array($keywords_parent))
3929 $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
3932 // PLAYER
3933 if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
3935 if (isset($player_parent[0]['attribs']['']['url']))
3937 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3940 elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
3942 if (isset($player_parent[0]['attribs']['']['url']))
3944 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
3948 // RATINGS
3949 if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
3951 foreach ($ratings as $rating)
3953 $rating_scheme = null;
3954 $rating_value = null;
3955 if (isset($rating['attribs']['']['scheme']))
3957 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3959 else
3961 $rating_scheme = 'urn:simple';
3963 if (isset($rating['data']))
3965 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3967 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
3970 elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
3972 foreach ($ratings as $rating)
3974 $rating_scheme = 'urn:itunes';
3975 $rating_value = null;
3976 if (isset($rating['data']))
3978 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
3980 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
3983 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
3985 foreach ($ratings as $rating)
3987 $rating_scheme = null;
3988 $rating_value = null;
3989 if (isset($rating['attribs']['']['scheme']))
3991 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
3993 else
3995 $rating_scheme = 'urn:simple';
3997 if (isset($rating['data']))
3999 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4001 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4004 elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
4006 foreach ($ratings as $rating)
4008 $rating_scheme = 'urn:itunes';
4009 $rating_value = null;
4010 if (isset($rating['data']))
4012 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4014 $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4017 if (is_array($ratings_parent))
4019 $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
4022 // RESTRICTIONS
4023 if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4025 foreach ($restrictions as $restriction)
4027 $restriction_relationship = null;
4028 $restriction_type = null;
4029 $restriction_value = null;
4030 if (isset($restriction['attribs']['']['relationship']))
4032 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4034 if (isset($restriction['attribs']['']['type']))
4036 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4038 if (isset($restriction['data']))
4040 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4042 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4045 elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4047 foreach ($restrictions as $restriction)
4049 $restriction_relationship = 'allow';
4050 $restriction_type = null;
4051 $restriction_value = 'itunes';
4052 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4054 $restriction_relationship = 'deny';
4056 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4059 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
4061 foreach ($restrictions as $restriction)
4063 $restriction_relationship = null;
4064 $restriction_type = null;
4065 $restriction_value = null;
4066 if (isset($restriction['attribs']['']['relationship']))
4068 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4070 if (isset($restriction['attribs']['']['type']))
4072 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4074 if (isset($restriction['data']))
4076 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4078 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4081 elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
4083 foreach ($restrictions as $restriction)
4085 $restriction_relationship = 'allow';
4086 $restriction_type = null;
4087 $restriction_value = 'itunes';
4088 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
4090 $restriction_relationship = 'deny';
4092 $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4095 if (is_array($restrictions_parent))
4097 $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
4100 // THUMBNAILS
4101 if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4103 foreach ($thumbnails as $thumbnail)
4105 if (isset($thumbnail['attribs']['']['url']))
4107 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4111 elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
4113 foreach ($thumbnails as $thumbnail)
4115 if (isset($thumbnail['attribs']['']['url']))
4117 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4122 // TITLES
4123 if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4125 if (isset($title_parent[0]['data']))
4127 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4130 elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
4132 if (isset($title_parent[0]['data']))
4134 $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4138 // Clear the memory
4139 unset($parent);
4141 // Attributes
4142 $bitrate = null;
4143 $channels = null;
4144 $duration = null;
4145 $expression = null;
4146 $framerate = null;
4147 $height = null;
4148 $javascript = null;
4149 $lang = null;
4150 $length = null;
4151 $medium = null;
4152 $samplingrate = null;
4153 $type = null;
4154 $url = null;
4155 $width = null;
4157 // Elements
4158 $captions = null;
4159 $categories = null;
4160 $copyrights = null;
4161 $credits = null;
4162 $description = null;
4163 $hashes = null;
4164 $keywords = null;
4165 $player = null;
4166 $ratings = null;
4167 $restrictions = null;
4168 $thumbnails = null;
4169 $title = null;
4171 // If we have media:group tags, loop through them.
4172 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
4174 if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4176 // If we have media:content tags, loop through them.
4177 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4179 if (isset($content['attribs']['']['url']))
4181 // Attributes
4182 $bitrate = null;
4183 $channels = null;
4184 $duration = null;
4185 $expression = null;
4186 $framerate = null;
4187 $height = null;
4188 $javascript = null;
4189 $lang = null;
4190 $length = null;
4191 $medium = null;
4192 $samplingrate = null;
4193 $type = null;
4194 $url = null;
4195 $width = null;
4197 // Elements
4198 $captions = null;
4199 $categories = null;
4200 $copyrights = null;
4201 $credits = null;
4202 $description = null;
4203 $hashes = null;
4204 $keywords = null;
4205 $player = null;
4206 $ratings = null;
4207 $restrictions = null;
4208 $thumbnails = null;
4209 $title = null;
4211 // Start checking the attributes of media:content
4212 if (isset($content['attribs']['']['bitrate']))
4214 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4216 if (isset($content['attribs']['']['channels']))
4218 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4220 if (isset($content['attribs']['']['duration']))
4222 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4224 else
4226 $duration = $duration_parent;
4228 if (isset($content['attribs']['']['expression']))
4230 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4232 if (isset($content['attribs']['']['framerate']))
4234 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4236 if (isset($content['attribs']['']['height']))
4238 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4240 if (isset($content['attribs']['']['lang']))
4242 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4244 if (isset($content['attribs']['']['fileSize']))
4246 $length = ceil($content['attribs']['']['fileSize']);
4248 if (isset($content['attribs']['']['medium']))
4250 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4252 if (isset($content['attribs']['']['samplingrate']))
4254 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4256 if (isset($content['attribs']['']['type']))
4258 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4260 if (isset($content['attribs']['']['width']))
4262 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4264 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4266 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4268 // CAPTIONS
4269 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4271 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4273 $caption_type = null;
4274 $caption_lang = null;
4275 $caption_startTime = null;
4276 $caption_endTime = null;
4277 $caption_text = null;
4278 if (isset($caption['attribs']['']['type']))
4280 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4282 if (isset($caption['attribs']['']['lang']))
4284 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4286 if (isset($caption['attribs']['']['start']))
4288 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4290 if (isset($caption['attribs']['']['end']))
4292 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4294 if (isset($caption['data']))
4296 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4298 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4300 if (is_array($captions))
4302 $captions = array_values(SimplePie_Misc::array_unique($captions));
4305 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4307 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4309 $caption_type = null;
4310 $caption_lang = null;
4311 $caption_startTime = null;
4312 $caption_endTime = null;
4313 $caption_text = null;
4314 if (isset($caption['attribs']['']['type']))
4316 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4318 if (isset($caption['attribs']['']['lang']))
4320 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4322 if (isset($caption['attribs']['']['start']))
4324 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4326 if (isset($caption['attribs']['']['end']))
4328 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4330 if (isset($caption['data']))
4332 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4334 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4336 if (is_array($captions))
4338 $captions = array_values(SimplePie_Misc::array_unique($captions));
4341 else
4343 $captions = $captions_parent;
4346 // CATEGORIES
4347 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4349 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4351 $term = null;
4352 $scheme = null;
4353 $label = null;
4354 if (isset($category['data']))
4356 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4358 if (isset($category['attribs']['']['scheme']))
4360 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4362 else
4364 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4366 if (isset($category['attribs']['']['label']))
4368 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4370 $categories[] = new $this->feed->category_class($term, $scheme, $label);
4373 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4375 foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4377 $term = null;
4378 $scheme = null;
4379 $label = null;
4380 if (isset($category['data']))
4382 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4384 if (isset($category['attribs']['']['scheme']))
4386 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4388 else
4390 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4392 if (isset($category['attribs']['']['label']))
4394 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4396 $categories[] = new $this->feed->category_class($term, $scheme, $label);
4399 if (is_array($categories) && is_array($categories_parent))
4401 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4403 elseif (is_array($categories))
4405 $categories = array_values(SimplePie_Misc::array_unique($categories));
4407 elseif (is_array($categories_parent))
4409 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4412 // COPYRIGHTS
4413 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4415 $copyright_url = null;
4416 $copyright_label = null;
4417 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4419 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4421 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4423 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4425 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4427 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4429 $copyright_url = null;
4430 $copyright_label = null;
4431 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4433 $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4435 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4437 $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4439 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4441 else
4443 $copyrights = $copyrights_parent;
4446 // CREDITS
4447 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4449 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4451 $credit_role = null;
4452 $credit_scheme = null;
4453 $credit_name = null;
4454 if (isset($credit['attribs']['']['role']))
4456 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4458 if (isset($credit['attribs']['']['scheme']))
4460 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4462 else
4464 $credit_scheme = 'urn:ebu';
4466 if (isset($credit['data']))
4468 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4470 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4472 if (is_array($credits))
4474 $credits = array_values(SimplePie_Misc::array_unique($credits));
4477 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
4479 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
4481 $credit_role = null;
4482 $credit_scheme = null;
4483 $credit_name = null;
4484 if (isset($credit['attribs']['']['role']))
4486 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
4488 if (isset($credit['attribs']['']['scheme']))
4490 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4492 else
4494 $credit_scheme = 'urn:ebu';
4496 if (isset($credit['data']))
4498 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4500 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
4502 if (is_array($credits))
4504 $credits = array_values(SimplePie_Misc::array_unique($credits));
4507 else
4509 $credits = $credits_parent;
4512 // DESCRIPTION
4513 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4515 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4517 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
4519 $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4521 else
4523 $description = $description_parent;
4526 // HASHES
4527 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4529 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4531 $value = null;
4532 $algo = null;
4533 if (isset($hash['data']))
4535 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4537 if (isset($hash['attribs']['']['algo']))
4539 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4541 else
4543 $algo = 'md5';
4545 $hashes[] = $algo.':'.$value;
4547 if (is_array($hashes))
4549 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4552 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
4554 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
4556 $value = null;
4557 $algo = null;
4558 if (isset($hash['data']))
4560 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4562 if (isset($hash['attribs']['']['algo']))
4564 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
4566 else
4568 $algo = 'md5';
4570 $hashes[] = $algo.':'.$value;
4572 if (is_array($hashes))
4574 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
4577 else
4579 $hashes = $hashes_parent;
4582 // KEYWORDS
4583 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4585 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4587 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4588 foreach ($temp as $word)
4590 $keywords[] = trim($word);
4592 unset($temp);
4594 if (is_array($keywords))
4596 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4599 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
4601 if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
4603 $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
4604 foreach ($temp as $word)
4606 $keywords[] = trim($word);
4608 unset($temp);
4610 if (is_array($keywords))
4612 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
4615 else
4617 $keywords = $keywords_parent;
4620 // PLAYER
4621 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4623 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4625 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4627 $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4629 else
4631 $player = $player_parent;
4634 // RATINGS
4635 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4637 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4639 $rating_scheme = null;
4640 $rating_value = null;
4641 if (isset($rating['attribs']['']['scheme']))
4643 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4645 else
4647 $rating_scheme = 'urn:simple';
4649 if (isset($rating['data']))
4651 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4653 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4655 if (is_array($ratings))
4657 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4660 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
4662 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
4664 $rating_scheme = null;
4665 $rating_value = null;
4666 if (isset($rating['attribs']['']['scheme']))
4668 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4670 else
4672 $rating_scheme = 'urn:simple';
4674 if (isset($rating['data']))
4676 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4678 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
4680 if (is_array($ratings))
4682 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
4685 else
4687 $ratings = $ratings_parent;
4690 // RESTRICTIONS
4691 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4693 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4695 $restriction_relationship = null;
4696 $restriction_type = null;
4697 $restriction_value = null;
4698 if (isset($restriction['attribs']['']['relationship']))
4700 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4702 if (isset($restriction['attribs']['']['type']))
4704 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4706 if (isset($restriction['data']))
4708 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4710 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4712 if (is_array($restrictions))
4714 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4717 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
4719 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
4721 $restriction_relationship = null;
4722 $restriction_type = null;
4723 $restriction_value = null;
4724 if (isset($restriction['attribs']['']['relationship']))
4726 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
4728 if (isset($restriction['attribs']['']['type']))
4730 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4732 if (isset($restriction['data']))
4734 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4736 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
4738 if (is_array($restrictions))
4740 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
4743 else
4745 $restrictions = $restrictions_parent;
4748 // THUMBNAILS
4749 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4751 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4753 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4755 if (is_array($thumbnails))
4757 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4760 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
4762 foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
4764 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4766 if (is_array($thumbnails))
4768 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
4771 else
4773 $thumbnails = $thumbnails_parent;
4776 // TITLES
4777 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4779 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4781 elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
4783 $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4785 else
4787 $title = $title_parent;
4790 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
4796 // If we have standalone media:content tags, loop through them.
4797 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
4799 foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
4801 if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
4803 // Attributes
4804 $bitrate = null;
4805 $channels = null;
4806 $duration = null;
4807 $expression = null;
4808 $framerate = null;
4809 $height = null;
4810 $javascript = null;
4811 $lang = null;
4812 $length = null;
4813 $medium = null;
4814 $samplingrate = null;
4815 $type = null;
4816 $url = null;
4817 $width = null;
4819 // Elements
4820 $captions = null;
4821 $categories = null;
4822 $copyrights = null;
4823 $credits = null;
4824 $description = null;
4825 $hashes = null;
4826 $keywords = null;
4827 $player = null;
4828 $ratings = null;
4829 $restrictions = null;
4830 $thumbnails = null;
4831 $title = null;
4833 // Start checking the attributes of media:content
4834 if (isset($content['attribs']['']['bitrate']))
4836 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4838 if (isset($content['attribs']['']['channels']))
4840 $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
4842 if (isset($content['attribs']['']['duration']))
4844 $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
4846 else
4848 $duration = $duration_parent;
4850 if (isset($content['attribs']['']['expression']))
4852 $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
4854 if (isset($content['attribs']['']['framerate']))
4856 $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
4858 if (isset($content['attribs']['']['height']))
4860 $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
4862 if (isset($content['attribs']['']['lang']))
4864 $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4866 if (isset($content['attribs']['']['fileSize']))
4868 $length = ceil($content['attribs']['']['fileSize']);
4870 if (isset($content['attribs']['']['medium']))
4872 $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
4874 if (isset($content['attribs']['']['samplingrate']))
4876 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
4878 if (isset($content['attribs']['']['type']))
4880 $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4882 if (isset($content['attribs']['']['width']))
4884 $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
4886 if (isset($content['attribs']['']['url']))
4888 $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
4890 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
4892 // CAPTIONS
4893 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
4895 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
4897 $caption_type = null;
4898 $caption_lang = null;
4899 $caption_startTime = null;
4900 $caption_endTime = null;
4901 $caption_text = null;
4902 if (isset($caption['attribs']['']['type']))
4904 $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
4906 if (isset($caption['attribs']['']['lang']))
4908 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
4910 if (isset($caption['attribs']['']['start']))
4912 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
4914 if (isset($caption['attribs']['']['end']))
4916 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
4918 if (isset($caption['data']))
4920 $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4922 $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
4924 if (is_array($captions))
4926 $captions = array_values(SimplePie_Misc::array_unique($captions));
4929 else
4931 $captions = $captions_parent;
4934 // CATEGORIES
4935 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
4937 foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
4939 $term = null;
4940 $scheme = null;
4941 $label = null;
4942 if (isset($category['data']))
4944 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4946 if (isset($category['attribs']['']['scheme']))
4948 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
4950 else
4952 $scheme = 'http://search.yahoo.com/mrss/category_schema';
4954 if (isset($category['attribs']['']['label']))
4956 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
4958 $categories[] = new $this->feed->category_class($term, $scheme, $label);
4961 if (is_array($categories) && is_array($categories_parent))
4963 $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
4965 elseif (is_array($categories))
4967 $categories = array_values(SimplePie_Misc::array_unique($categories));
4969 elseif (is_array($categories_parent))
4971 $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
4973 else
4975 $categories = null;
4978 // COPYRIGHTS
4979 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
4981 $copyright_url = null;
4982 $copyright_label = null;
4983 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
4985 $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
4987 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
4989 $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
4991 $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
4993 else
4995 $copyrights = $copyrights_parent;
4998 // CREDITS
4999 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
5001 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
5003 $credit_role = null;
5004 $credit_scheme = null;
5005 $credit_name = null;
5006 if (isset($credit['attribs']['']['role']))
5008 $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
5010 if (isset($credit['attribs']['']['scheme']))
5012 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5014 else
5016 $credit_scheme = 'urn:ebu';
5018 if (isset($credit['data']))
5020 $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5022 $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
5024 if (is_array($credits))
5026 $credits = array_values(SimplePie_Misc::array_unique($credits));
5029 else
5031 $credits = $credits_parent;
5034 // DESCRIPTION
5035 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
5037 $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5039 else
5041 $description = $description_parent;
5044 // HASHES
5045 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
5047 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
5049 $value = null;
5050 $algo = null;
5051 if (isset($hash['data']))
5053 $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5055 if (isset($hash['attribs']['']['algo']))
5057 $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
5059 else
5061 $algo = 'md5';
5063 $hashes[] = $algo.':'.$value;
5065 if (is_array($hashes))
5067 $hashes = array_values(SimplePie_Misc::array_unique($hashes));
5070 else
5072 $hashes = $hashes_parent;
5075 // KEYWORDS
5076 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
5078 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
5080 $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
5081 foreach ($temp as $word)
5083 $keywords[] = trim($word);
5085 unset($temp);
5087 if (is_array($keywords))
5089 $keywords = array_values(SimplePie_Misc::array_unique($keywords));
5092 else
5094 $keywords = $keywords_parent;
5097 // PLAYER
5098 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
5100 $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5102 else
5104 $player = $player_parent;
5107 // RATINGS
5108 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
5110 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
5112 $rating_scheme = null;
5113 $rating_value = null;
5114 if (isset($rating['attribs']['']['scheme']))
5116 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5118 else
5120 $rating_scheme = 'urn:simple';
5122 if (isset($rating['data']))
5124 $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5126 $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
5128 if (is_array($ratings))
5130 $ratings = array_values(SimplePie_Misc::array_unique($ratings));
5133 else
5135 $ratings = $ratings_parent;
5138 // RESTRICTIONS
5139 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
5141 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
5143 $restriction_relationship = null;
5144 $restriction_type = null;
5145 $restriction_value = null;
5146 if (isset($restriction['attribs']['']['relationship']))
5148 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
5150 if (isset($restriction['attribs']['']['type']))
5152 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5154 if (isset($restriction['data']))
5156 $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5158 $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
5160 if (is_array($restrictions))
5162 $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
5165 else
5167 $restrictions = $restrictions_parent;
5170 // THUMBNAILS
5171 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
5173 foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
5175 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
5177 if (is_array($thumbnails))
5179 $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
5182 else
5184 $thumbnails = $thumbnails_parent;
5187 // TITLES
5188 if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
5190 $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5192 else
5194 $title = $title_parent;
5197 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
5202 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
5204 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5206 // Attributes
5207 $bitrate = null;
5208 $channels = null;
5209 $duration = null;
5210 $expression = null;
5211 $framerate = null;
5212 $height = null;
5213 $javascript = null;
5214 $lang = null;
5215 $length = null;
5216 $medium = null;
5217 $samplingrate = null;
5218 $type = null;
5219 $url = null;
5220 $width = null;
5222 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5223 if (isset($link['attribs']['']['type']))
5225 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5227 if (isset($link['attribs']['']['length']))
5229 $length = ceil($link['attribs']['']['length']);
5232 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5233 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5237 foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
5239 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
5241 // Attributes
5242 $bitrate = null;
5243 $channels = null;
5244 $duration = null;
5245 $expression = null;
5246 $framerate = null;
5247 $height = null;
5248 $javascript = null;
5249 $lang = null;
5250 $length = null;
5251 $medium = null;
5252 $samplingrate = null;
5253 $type = null;
5254 $url = null;
5255 $width = null;
5257 $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5258 if (isset($link['attribs']['']['type']))
5260 $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5262 if (isset($link['attribs']['']['length']))
5264 $length = ceil($link['attribs']['']['length']);
5267 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5268 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5272 if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
5274 if (isset($enclosure[0]['attribs']['']['url']))
5276 // Attributes
5277 $bitrate = null;
5278 $channels = null;
5279 $duration = null;
5280 $expression = null;
5281 $framerate = null;
5282 $height = null;
5283 $javascript = null;
5284 $lang = null;
5285 $length = null;
5286 $medium = null;
5287 $samplingrate = null;
5288 $type = null;
5289 $url = null;
5290 $width = null;
5292 $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
5293 if (isset($enclosure[0]['attribs']['']['type']))
5295 $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
5297 if (isset($enclosure[0]['attribs']['']['length']))
5299 $length = ceil($enclosure[0]['attribs']['']['length']);
5302 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5303 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5307 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))
5309 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
5310 $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
5313 $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
5315 if (!empty($this->data['enclosures']))
5317 return $this->data['enclosures'];
5319 else
5321 return null;
5325 public function get_latitude()
5327 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5329 return (float) $return[0]['data'];
5331 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))
5333 return (float) $match[1];
5335 else
5337 return null;
5341 public function get_longitude()
5343 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5345 return (float) $return[0]['data'];
5347 elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5349 return (float) $return[0]['data'];
5351 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))
5353 return (float) $match[2];
5355 else
5357 return null;
5361 public function get_source()
5363 if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
5365 return new $this->feed->source_class($this, $return[0]);
5367 else
5369 return null;
5374 class SimplePie_Source
5376 var $item;
5377 var $data = array();
5379 public function __construct($item, $data)
5381 $this->item = $item;
5382 $this->data = $data;
5385 public function __toString()
5387 return md5(serialize($this->data));
5390 public function get_source_tags($namespace, $tag)
5392 if (isset($this->data['child'][$namespace][$tag]))
5394 return $this->data['child'][$namespace][$tag];
5396 else
5398 return null;
5402 public function get_base($element = array())
5404 return $this->item->get_base($element);
5407 public function sanitize($data, $type, $base = '')
5409 return $this->item->sanitize($data, $type, $base);
5412 public function get_item()
5414 return $this->item;
5417 public function get_title()
5419 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
5421 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5423 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
5425 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5427 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
5429 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5431 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
5433 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5435 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
5437 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5439 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
5441 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5443 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
5445 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5447 else
5449 return null;
5453 public function get_category($key = 0)
5455 $categories = $this->get_categories();
5456 if (isset($categories[$key]))
5458 return $categories[$key];
5460 else
5462 return null;
5466 public function get_categories()
5468 $categories = array();
5470 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
5472 $term = null;
5473 $scheme = null;
5474 $label = null;
5475 if (isset($category['attribs']['']['term']))
5477 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
5479 if (isset($category['attribs']['']['scheme']))
5481 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
5483 if (isset($category['attribs']['']['label']))
5485 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
5487 $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
5489 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
5491 // This is really the label, but keep this as the term also for BC.
5492 // Label will also work on retrieving because that falls back to term.
5493 $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5494 if (isset($category['attribs']['']['domain']))
5496 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
5498 else
5500 $scheme = null;
5502 $categories[] = new $this->item->feed->category_class($term, $scheme, null);
5504 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
5506 $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5508 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
5510 $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5513 if (!empty($categories))
5515 return SimplePie_Misc::array_unique($categories);
5517 else
5519 return null;
5523 public function get_author($key = 0)
5525 $authors = $this->get_authors();
5526 if (isset($authors[$key]))
5528 return $authors[$key];
5530 else
5532 return null;
5536 public function get_authors()
5538 $authors = array();
5539 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
5541 $name = null;
5542 $uri = null;
5543 $email = null;
5544 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5546 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5548 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5550 $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]));
5552 if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5554 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5556 if ($name !== null || $email !== null || $uri !== null)
5558 $authors[] = new $this->item->feed->author_class($name, $uri, $email);
5561 if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
5563 $name = null;
5564 $url = null;
5565 $email = null;
5566 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5568 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5570 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5572 $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]));
5574 if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5576 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5578 if ($name !== null || $email !== null || $url !== null)
5580 $authors[] = new $this->item->feed->author_class($name, $url, $email);
5583 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
5585 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5587 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
5589 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5591 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
5593 $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
5596 if (!empty($authors))
5598 return SimplePie_Misc::array_unique($authors);
5600 else
5602 return null;
5606 public function get_contributor($key = 0)
5608 $contributors = $this->get_contributors();
5609 if (isset($contributors[$key]))
5611 return $contributors[$key];
5613 else
5615 return null;
5619 public function get_contributors()
5621 $contributors = array();
5622 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
5624 $name = null;
5625 $uri = null;
5626 $email = null;
5627 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
5629 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5631 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
5633 $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]));
5635 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
5637 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5639 if ($name !== null || $email !== null || $uri !== null)
5641 $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
5644 foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
5646 $name = null;
5647 $url = null;
5648 $email = null;
5649 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
5651 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5653 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
5655 $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]));
5657 if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
5659 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5661 if ($name !== null || $email !== null || $url !== null)
5663 $contributors[] = new $this->item->feed->author_class($name, $url, $email);
5667 if (!empty($contributors))
5669 return SimplePie_Misc::array_unique($contributors);
5671 else
5673 return null;
5677 public function get_link($key = 0, $rel = 'alternate')
5679 $links = $this->get_links($rel);
5680 if (isset($links[$key]))
5682 return $links[$key];
5684 else
5686 return null;
5691 * Added for parity between the parent-level and the item/entry-level.
5693 public function get_permalink()
5695 return $this->get_link(0);
5698 public function get_links($rel = 'alternate')
5700 if (!isset($this->data['links']))
5702 $this->data['links'] = array();
5703 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
5705 foreach ($links as $link)
5707 if (isset($link['attribs']['']['href']))
5709 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
5710 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5714 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
5716 foreach ($links as $link)
5718 if (isset($link['attribs']['']['href']))
5720 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
5721 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
5726 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
5728 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
5730 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
5732 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
5734 if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
5736 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
5739 $keys = array_keys($this->data['links']);
5740 foreach ($keys as $key)
5742 if (SimplePie_Misc::is_isegment_nz_nc($key))
5744 if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
5746 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
5747 $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
5749 else
5751 $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
5754 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
5756 $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
5758 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
5762 if (isset($this->data['links'][$rel]))
5764 return $this->data['links'][$rel];
5766 else
5768 return null;
5772 public function get_description()
5774 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
5776 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5778 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
5780 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5782 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
5784 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5786 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
5788 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5790 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
5792 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
5794 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
5796 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5798 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
5800 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5802 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
5804 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
5806 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
5808 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
5810 else
5812 return null;
5816 public function get_copyright()
5818 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
5820 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5822 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
5824 return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
5826 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
5828 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5830 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
5832 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5834 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
5836 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5838 else
5840 return null;
5844 public function get_language()
5846 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
5848 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5850 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
5852 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5854 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
5856 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
5858 elseif (isset($this->data['xml_lang']))
5860 return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
5862 else
5864 return null;
5868 public function get_latitude()
5870 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
5872 return (float) $return[0]['data'];
5874 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))
5876 return (float) $match[1];
5878 else
5880 return null;
5884 public function get_longitude()
5886 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
5888 return (float) $return[0]['data'];
5890 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
5892 return (float) $return[0]['data'];
5894 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))
5896 return (float) $match[2];
5898 else
5900 return null;
5904 public function get_image_url()
5906 if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
5908 return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
5910 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
5912 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
5914 elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
5916 return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
5918 else
5920 return null;
5925 class SimplePie_Author
5927 var $name;
5928 var $link;
5929 var $email;
5931 // Constructor, used to input the data
5932 public function __construct($name = null, $link = null, $email = null)
5934 $this->name = $name;
5935 $this->link = $link;
5936 $this->email = $email;
5939 public function __toString()
5941 // There is no $this->data here
5942 return md5(serialize($this));
5945 public function get_name()
5947 if ($this->name !== null)
5949 return $this->name;
5951 else
5953 return null;
5957 public function get_link()
5959 if ($this->link !== null)
5961 return $this->link;
5963 else
5965 return null;
5969 public function get_email()
5971 if ($this->email !== null)
5973 return $this->email;
5975 else
5977 return null;
5982 class SimplePie_Category
5984 var $term;
5985 var $scheme;
5986 var $label;
5988 // Constructor, used to input the data
5989 public function __construct($term = null, $scheme = null, $label = null)
5991 $this->term = $term;
5992 $this->scheme = $scheme;
5993 $this->label = $label;
5996 public function __toString()
5998 // There is no $this->data here
5999 return md5(serialize($this));
6002 public function get_term()
6004 if ($this->term !== null)
6006 return $this->term;
6008 else
6010 return null;
6014 public function get_scheme()
6016 if ($this->scheme !== null)
6018 return $this->scheme;
6020 else
6022 return null;
6026 public function get_label()
6028 if ($this->label !== null)
6030 return $this->label;
6032 else
6034 return $this->get_term();
6039 class SimplePie_Enclosure
6041 var $bitrate;
6042 var $captions;
6043 var $categories;
6044 var $channels;
6045 var $copyright;
6046 var $credits;
6047 var $description;
6048 var $duration;
6049 var $expression;
6050 var $framerate;
6051 var $handler;
6052 var $hashes;
6053 var $height;
6054 var $javascript;
6055 var $keywords;
6056 var $lang;
6057 var $length;
6058 var $link;
6059 var $medium;
6060 var $player;
6061 var $ratings;
6062 var $restrictions;
6063 var $samplingrate;
6064 var $thumbnails;
6065 var $title;
6066 var $type;
6067 var $width;
6069 // Constructor, used to input the data
6070 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)
6072 $this->bitrate = $bitrate;
6073 $this->captions = $captions;
6074 $this->categories = $categories;
6075 $this->channels = $channels;
6076 $this->copyright = $copyright;
6077 $this->credits = $credits;
6078 $this->description = $description;
6079 $this->duration = $duration;
6080 $this->expression = $expression;
6081 $this->framerate = $framerate;
6082 $this->hashes = $hashes;
6083 $this->height = $height;
6084 $this->javascript = $javascript;
6085 $this->keywords = $keywords;
6086 $this->lang = $lang;
6087 $this->length = $length;
6088 $this->link = $link;
6089 $this->medium = $medium;
6090 $this->player = $player;
6091 $this->ratings = $ratings;
6092 $this->restrictions = $restrictions;
6093 $this->samplingrate = $samplingrate;
6094 $this->thumbnails = $thumbnails;
6095 $this->title = $title;
6096 $this->type = $type;
6097 $this->width = $width;
6099 if (class_exists('idna_convert'))
6101 $idn = new idna_convert();
6102 $parsed = SimplePie_Misc::parse_url($link);
6103 $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
6105 $this->handler = $this->get_handler(); // Needs to load last
6108 public function __toString()
6110 // There is no $this->data here
6111 return md5(serialize($this));
6114 public function get_bitrate()
6116 if ($this->bitrate !== null)
6118 return $this->bitrate;
6120 else
6122 return null;
6126 public function get_caption($key = 0)
6128 $captions = $this->get_captions();
6129 if (isset($captions[$key]))
6131 return $captions[$key];
6133 else
6135 return null;
6139 public function get_captions()
6141 if ($this->captions !== null)
6143 return $this->captions;
6145 else
6147 return null;
6151 public function get_category($key = 0)
6153 $categories = $this->get_categories();
6154 if (isset($categories[$key]))
6156 return $categories[$key];
6158 else
6160 return null;
6164 public function get_categories()
6166 if ($this->categories !== null)
6168 return $this->categories;
6170 else
6172 return null;
6176 public function get_channels()
6178 if ($this->channels !== null)
6180 return $this->channels;
6182 else
6184 return null;
6188 public function get_copyright()
6190 if ($this->copyright !== null)
6192 return $this->copyright;
6194 else
6196 return null;
6200 public function get_credit($key = 0)
6202 $credits = $this->get_credits();
6203 if (isset($credits[$key]))
6205 return $credits[$key];
6207 else
6209 return null;
6213 public function get_credits()
6215 if ($this->credits !== null)
6217 return $this->credits;
6219 else
6221 return null;
6225 public function get_description()
6227 if ($this->description !== null)
6229 return $this->description;
6231 else
6233 return null;
6237 public function get_duration($convert = false)
6239 if ($this->duration !== null)
6241 if ($convert)
6243 $time = SimplePie_Misc::time_hms($this->duration);
6244 return $time;
6246 else
6248 return $this->duration;
6251 else
6253 return null;
6257 public function get_expression()
6259 if ($this->expression !== null)
6261 return $this->expression;
6263 else
6265 return 'full';
6269 public function get_extension()
6271 if ($this->link !== null)
6273 $url = SimplePie_Misc::parse_url($this->link);
6274 if ($url['path'] !== '')
6276 return pathinfo($url['path'], PATHINFO_EXTENSION);
6279 return null;
6282 public function get_framerate()
6284 if ($this->framerate !== null)
6286 return $this->framerate;
6288 else
6290 return null;
6294 public function get_handler()
6296 return $this->get_real_type(true);
6299 public function get_hash($key = 0)
6301 $hashes = $this->get_hashes();
6302 if (isset($hashes[$key]))
6304 return $hashes[$key];
6306 else
6308 return null;
6312 public function get_hashes()
6314 if ($this->hashes !== null)
6316 return $this->hashes;
6318 else
6320 return null;
6324 public function get_height()
6326 if ($this->height !== null)
6328 return $this->height;
6330 else
6332 return null;
6336 public function get_language()
6338 if ($this->lang !== null)
6340 return $this->lang;
6342 else
6344 return null;
6348 public function get_keyword($key = 0)
6350 $keywords = $this->get_keywords();
6351 if (isset($keywords[$key]))
6353 return $keywords[$key];
6355 else
6357 return null;
6361 public function get_keywords()
6363 if ($this->keywords !== null)
6365 return $this->keywords;
6367 else
6369 return null;
6373 public function get_length()
6375 if ($this->length !== null)
6377 return $this->length;
6379 else
6381 return null;
6385 public function get_link()
6387 if ($this->link !== null)
6389 return urldecode($this->link);
6391 else
6393 return null;
6397 public function get_medium()
6399 if ($this->medium !== null)
6401 return $this->medium;
6403 else
6405 return null;
6409 public function get_player()
6411 if ($this->player !== null)
6413 return $this->player;
6415 else
6417 return null;
6421 public function get_rating($key = 0)
6423 $ratings = $this->get_ratings();
6424 if (isset($ratings[$key]))
6426 return $ratings[$key];
6428 else
6430 return null;
6434 public function get_ratings()
6436 if ($this->ratings !== null)
6438 return $this->ratings;
6440 else
6442 return null;
6446 public function get_restriction($key = 0)
6448 $restrictions = $this->get_restrictions();
6449 if (isset($restrictions[$key]))
6451 return $restrictions[$key];
6453 else
6455 return null;
6459 public function get_restrictions()
6461 if ($this->restrictions !== null)
6463 return $this->restrictions;
6465 else
6467 return null;
6471 public function get_sampling_rate()
6473 if ($this->samplingrate !== null)
6475 return $this->samplingrate;
6477 else
6479 return null;
6483 public function get_size()
6485 $length = $this->get_length();
6486 if ($length !== null)
6488 return round($length/1048576, 2);
6490 else
6492 return null;
6496 public function get_thumbnail($key = 0)
6498 $thumbnails = $this->get_thumbnails();
6499 if (isset($thumbnails[$key]))
6501 return $thumbnails[$key];
6503 else
6505 return null;
6509 public function get_thumbnails()
6511 if ($this->thumbnails !== null)
6513 return $this->thumbnails;
6515 else
6517 return null;
6521 public function get_title()
6523 if ($this->title !== null)
6525 return $this->title;
6527 else
6529 return null;
6533 public function get_type()
6535 if ($this->type !== null)
6537 return $this->type;
6539 else
6541 return null;
6545 public function get_width()
6547 if ($this->width !== null)
6549 return $this->width;
6551 else
6553 return null;
6557 public function native_embed($options='')
6559 return $this->embed($options, true);
6563 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
6565 public function embed($options = '', $native = false)
6567 // Set up defaults
6568 $audio = '';
6569 $video = '';
6570 $alt = '';
6571 $altclass = '';
6572 $loop = 'false';
6573 $width = 'auto';
6574 $height = 'auto';
6575 $bgcolor = '#ffffff';
6576 $mediaplayer = '';
6577 $widescreen = false;
6578 $handler = $this->get_handler();
6579 $type = $this->get_real_type();
6581 // Process options and reassign values as necessary
6582 if (is_array($options))
6584 extract($options);
6586 else
6588 $options = explode(',', $options);
6589 foreach($options as $option)
6591 $opt = explode(':', $option, 2);
6592 if (isset($opt[0], $opt[1]))
6594 $opt[0] = trim($opt[0]);
6595 $opt[1] = trim($opt[1]);
6596 switch ($opt[0])
6598 case 'audio':
6599 $audio = $opt[1];
6600 break;
6602 case 'video':
6603 $video = $opt[1];
6604 break;
6606 case 'alt':
6607 $alt = $opt[1];
6608 break;
6610 case 'altclass':
6611 $altclass = $opt[1];
6612 break;
6614 case 'loop':
6615 $loop = $opt[1];
6616 break;
6618 case 'width':
6619 $width = $opt[1];
6620 break;
6622 case 'height':
6623 $height = $opt[1];
6624 break;
6626 case 'bgcolor':
6627 $bgcolor = $opt[1];
6628 break;
6630 case 'mediaplayer':
6631 $mediaplayer = $opt[1];
6632 break;
6634 case 'widescreen':
6635 $widescreen = $opt[1];
6636 break;
6642 $mime = explode('/', $type, 2);
6643 $mime = $mime[0];
6645 // Process values for 'auto'
6646 if ($width === 'auto')
6648 if ($mime === 'video')
6650 if ($height === 'auto')
6652 $width = 480;
6654 elseif ($widescreen)
6656 $width = round((intval($height)/9)*16);
6658 else
6660 $width = round((intval($height)/3)*4);
6663 else
6665 $width = '100%';
6669 if ($height === 'auto')
6671 if ($mime === 'audio')
6673 $height = 0;
6675 elseif ($mime === 'video')
6677 if ($width === 'auto')
6679 if ($widescreen)
6681 $height = 270;
6683 else
6685 $height = 360;
6688 elseif ($widescreen)
6690 $height = round((intval($width)/16)*9);
6692 else
6694 $height = round((intval($width)/4)*3);
6697 else
6699 $height = 376;
6702 elseif ($mime === 'audio')
6704 $height = 0;
6707 // Set proper placeholder value
6708 if ($mime === 'audio')
6710 $placeholder = $audio;
6712 elseif ($mime === 'video')
6714 $placeholder = $video;
6717 $embed = '';
6719 // Make sure the JS library is included
6720 if (!$native)
6722 static $javascript_outputted = null;
6723 if (!$javascript_outputted && $this->javascript)
6725 $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
6726 $javascript_outputted = true;
6730 // Odeo Feed MP3's
6731 if ($handler === 'odeo')
6733 if ($native)
6735 $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
6737 else
6739 $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
6743 // Flash
6744 elseif ($handler === 'flash')
6746 if ($native)
6748 $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>";
6750 else
6752 $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
6756 // Flash Media Player file types.
6757 // Preferred handler for MP3 file types.
6758 elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
6760 $height += 20;
6761 if ($native)
6763 $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>";
6765 else
6767 $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
6771 // QuickTime 7 file types. Need to test with QuickTime 6.
6772 // Only handle MP3's if the Flash Media Player is not present.
6773 elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
6775 $height += 16;
6776 if ($native)
6778 if ($placeholder !== '')
6780 $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>";
6782 else
6784 $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>";
6787 else
6789 $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
6793 // Windows Media
6794 elseif ($handler === 'wmedia')
6796 $height += 45;
6797 if ($native)
6799 $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>";
6801 else
6803 $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
6807 // Everything else
6808 else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
6810 return $embed;
6813 public function get_real_type($find_handler = false)
6815 // If it's Odeo, let's get it out of the way.
6816 if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
6818 return 'odeo';
6821 // Mime-types by handler.
6822 $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
6823 $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
6824 $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
6825 $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
6826 $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
6828 if ($this->get_type() !== null)
6830 $type = strtolower($this->type);
6832 else
6834 $type = null;
6837 // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
6838 if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
6840 switch (strtolower($this->get_extension()))
6842 // Audio mime-types
6843 case 'aac':
6844 case 'adts':
6845 $type = 'audio/acc';
6846 break;
6848 case 'aif':
6849 case 'aifc':
6850 case 'aiff':
6851 case 'cdda':
6852 $type = 'audio/aiff';
6853 break;
6855 case 'bwf':
6856 $type = 'audio/wav';
6857 break;
6859 case 'kar':
6860 case 'mid':
6861 case 'midi':
6862 case 'smf':
6863 $type = 'audio/midi';
6864 break;
6866 case 'm4a':
6867 $type = 'audio/x-m4a';
6868 break;
6870 case 'mp3':
6871 case 'swa':
6872 $type = 'audio/mp3';
6873 break;
6875 case 'wav':
6876 $type = 'audio/wav';
6877 break;
6879 case 'wax':
6880 $type = 'audio/x-ms-wax';
6881 break;
6883 case 'wma':
6884 $type = 'audio/x-ms-wma';
6885 break;
6887 // Video mime-types
6888 case '3gp':
6889 case '3gpp':
6890 $type = 'video/3gpp';
6891 break;
6893 case '3g2':
6894 case '3gp2':
6895 $type = 'video/3gpp2';
6896 break;
6898 case 'asf':
6899 $type = 'video/x-ms-asf';
6900 break;
6902 case 'flv':
6903 $type = 'video/x-flv';
6904 break;
6906 case 'm1a':
6907 case 'm1s':
6908 case 'm1v':
6909 case 'm15':
6910 case 'm75':
6911 case 'mp2':
6912 case 'mpa':
6913 case 'mpeg':
6914 case 'mpg':
6915 case 'mpm':
6916 case 'mpv':
6917 $type = 'video/mpeg';
6918 break;
6920 case 'm4v':
6921 $type = 'video/x-m4v';
6922 break;
6924 case 'mov':
6925 case 'qt':
6926 $type = 'video/quicktime';
6927 break;
6929 case 'mp4':
6930 case 'mpg4':
6931 $type = 'video/mp4';
6932 break;
6934 case 'sdv':
6935 $type = 'video/sd-video';
6936 break;
6938 case 'wm':
6939 $type = 'video/x-ms-wm';
6940 break;
6942 case 'wmv':
6943 $type = 'video/x-ms-wmv';
6944 break;
6946 case 'wvx':
6947 $type = 'video/x-ms-wvx';
6948 break;
6950 // Flash mime-types
6951 case 'spl':
6952 $type = 'application/futuresplash';
6953 break;
6955 case 'swf':
6956 $type = 'application/x-shockwave-flash';
6957 break;
6961 if ($find_handler)
6963 if (in_array($type, $types_flash))
6965 return 'flash';
6967 elseif (in_array($type, $types_fmedia))
6969 return 'fmedia';
6971 elseif (in_array($type, $types_quicktime))
6973 return 'quicktime';
6975 elseif (in_array($type, $types_wmedia))
6977 return 'wmedia';
6979 elseif (in_array($type, $types_mp3))
6981 return 'mp3';
6983 else
6985 return null;
6988 else
6990 return $type;
6995 class SimplePie_Caption
6997 var $type;
6998 var $lang;
6999 var $startTime;
7000 var $endTime;
7001 var $text;
7003 // Constructor, used to input the data
7004 public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
7006 $this->type = $type;
7007 $this->lang = $lang;
7008 $this->startTime = $startTime;
7009 $this->endTime = $endTime;
7010 $this->text = $text;
7013 public function __toString()
7015 // There is no $this->data here
7016 return md5(serialize($this));
7019 public function get_endtime()
7021 if ($this->endTime !== null)
7023 return $this->endTime;
7025 else
7027 return null;
7031 public function get_language()
7033 if ($this->lang !== null)
7035 return $this->lang;
7037 else
7039 return null;
7043 public function get_starttime()
7045 if ($this->startTime !== null)
7047 return $this->startTime;
7049 else
7051 return null;
7055 public function get_text()
7057 if ($this->text !== null)
7059 return $this->text;
7061 else
7063 return null;
7067 public function get_type()
7069 if ($this->type !== null)
7071 return $this->type;
7073 else
7075 return null;
7080 class SimplePie_Credit
7082 var $role;
7083 var $scheme;
7084 var $name;
7086 // Constructor, used to input the data
7087 public function __construct($role = null, $scheme = null, $name = null)
7089 $this->role = $role;
7090 $this->scheme = $scheme;
7091 $this->name = $name;
7094 public function __toString()
7096 // There is no $this->data here
7097 return md5(serialize($this));
7100 public function get_role()
7102 if ($this->role !== null)
7104 return $this->role;
7106 else
7108 return null;
7112 public function get_scheme()
7114 if ($this->scheme !== null)
7116 return $this->scheme;
7118 else
7120 return null;
7124 public function get_name()
7126 if ($this->name !== null)
7128 return $this->name;
7130 else
7132 return null;
7137 class SimplePie_Copyright
7139 var $url;
7140 var $label;
7142 // Constructor, used to input the data
7143 public function __construct($url = null, $label = null)
7145 $this->url = $url;
7146 $this->label = $label;
7149 public function __toString()
7151 // There is no $this->data here
7152 return md5(serialize($this));
7155 public function get_url()
7157 if ($this->url !== null)
7159 return $this->url;
7161 else
7163 return null;
7167 public function get_attribution()
7169 if ($this->label !== null)
7171 return $this->label;
7173 else
7175 return null;
7180 class SimplePie_Rating
7182 var $scheme;
7183 var $value;
7185 // Constructor, used to input the data
7186 public function __construct($scheme = null, $value = null)
7188 $this->scheme = $scheme;
7189 $this->value = $value;
7192 public function __toString()
7194 // There is no $this->data here
7195 return md5(serialize($this));
7198 public function get_scheme()
7200 if ($this->scheme !== null)
7202 return $this->scheme;
7204 else
7206 return null;
7210 public function get_value()
7212 if ($this->value !== null)
7214 return $this->value;
7216 else
7218 return null;
7223 class SimplePie_Restriction
7225 var $relationship;
7226 var $type;
7227 var $value;
7229 // Constructor, used to input the data
7230 public function __construct($relationship = null, $type = null, $value = null)
7232 $this->relationship = $relationship;
7233 $this->type = $type;
7234 $this->value = $value;
7237 public function __toString()
7239 // There is no $this->data here
7240 return md5(serialize($this));
7243 public function get_relationship()
7245 if ($this->relationship !== null)
7247 return $this->relationship;
7249 else
7251 return null;
7255 public function get_type()
7257 if ($this->type !== null)
7259 return $this->type;
7261 else
7263 return null;
7267 public function get_value()
7269 if ($this->value !== null)
7271 return $this->value;
7273 else
7275 return null;
7281 * @todo Move to properly supporting RFC2616 (HTTP/1.1)
7283 class SimplePie_File
7285 var $url;
7286 var $useragent;
7287 var $success = true;
7288 var $headers = array();
7289 var $body;
7290 var $status_code;
7291 var $redirects = 0;
7292 var $error;
7293 var $method = SIMPLEPIE_FILE_SOURCE_NONE;
7295 public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
7297 if (class_exists('idna_convert'))
7299 $idn = new idna_convert();
7300 $parsed = SimplePie_Misc::parse_url($url);
7301 $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
7303 $this->url = $url;
7304 $this->useragent = $useragent;
7305 if (preg_match('/^http(s)?:\/\//i', $url))
7307 if ($useragent === null)
7309 $useragent = ini_get('user_agent');
7310 $this->useragent = $useragent;
7312 if (!is_array($headers))
7314 $headers = array();
7316 if (!$force_fsockopen && function_exists('curl_exec'))
7318 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
7319 $fp = curl_init();
7320 $headers2 = array();
7321 foreach ($headers as $key => $value)
7323 $headers2[] = "$key: $value";
7325 if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
7327 curl_setopt($fp, CURLOPT_ENCODING, '');
7329 curl_setopt($fp, CURLOPT_URL, $url);
7330 curl_setopt($fp, CURLOPT_HEADER, 1);
7331 curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
7332 curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
7333 curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
7334 curl_setopt($fp, CURLOPT_REFERER, $url);
7335 curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
7336 curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
7337 if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
7339 curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
7340 curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
7343 $this->headers = curl_exec($fp);
7344 if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
7346 curl_setopt($fp, CURLOPT_ENCODING, 'none');
7347 $this->headers = curl_exec($fp);
7349 if (curl_errno($fp))
7351 $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
7352 $this->success = false;
7354 else
7356 $info = curl_getinfo($fp);
7357 curl_close($fp);
7358 $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
7359 $this->headers = array_pop($this->headers);
7360 $parser = new SimplePie_HTTP_Parser($this->headers);
7361 if ($parser->parse())
7363 $this->headers = $parser->headers;
7364 $this->body = $parser->body;
7365 $this->status_code = $parser->status_code;
7366 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)
7368 $this->redirects++;
7369 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7370 return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7375 else
7377 $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
7378 $url_parts = parse_url($url);
7379 if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
7381 $url_parts['host'] = "ssl://$url_parts[host]";
7382 $url_parts['port'] = 443;
7384 if (!isset($url_parts['port']))
7386 $url_parts['port'] = 80;
7388 $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
7389 if (!$fp)
7391 $this->error = 'fsockopen error: ' . $errstr;
7392 $this->success = false;
7394 else
7396 stream_set_timeout($fp, $timeout);
7397 if (isset($url_parts['path']))
7399 if (isset($url_parts['query']))
7401 $get = "$url_parts[path]?$url_parts[query]";
7403 else
7405 $get = $url_parts['path'];
7408 else
7410 $get = '/';
7412 $out = "GET $get HTTP/1.0\r\n";
7413 $out .= "Host: $url_parts[host]\r\n";
7414 $out .= "User-Agent: $useragent\r\n";
7415 if (extension_loaded('zlib'))
7417 $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
7420 if (isset($url_parts['user']) && isset($url_parts['pass']))
7422 $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
7424 foreach ($headers as $key => $value)
7426 $out .= "$key: $value\r\n";
7428 $out .= "Connection: Close\r\n\r\n";
7429 fwrite($fp, $out);
7431 $info = stream_get_meta_data($fp);
7433 $this->headers = '';
7434 while (!$info['eof'] && !$info['timed_out'])
7436 $this->headers .= fread($fp, 1160);
7437 $info = stream_get_meta_data($fp);
7439 if (!$info['timed_out'])
7441 $parser = new SimplePie_HTTP_Parser($this->headers);
7442 if ($parser->parse())
7444 $this->headers = $parser->headers;
7445 $this->body = $parser->body;
7446 $this->status_code = $parser->status_code;
7447 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)
7449 $this->redirects++;
7450 $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
7451 return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
7453 if (isset($this->headers['content-encoding']))
7455 // Hey, we act dumb elsewhere, so let's do that here too
7456 switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
7458 case 'gzip':
7459 case 'x-gzip':
7460 $decoder = new SimplePie_gzdecode($this->body);
7461 if (!$decoder->parse())
7463 $this->error = 'Unable to decode HTTP "gzip" stream';
7464 $this->success = false;
7466 else
7468 $this->body = $decoder->data;
7470 break;
7472 case 'deflate':
7473 if (($body = gzuncompress($this->body)) === false)
7475 if (($body = gzinflate($this->body)) === false)
7477 $this->error = 'Unable to decode HTTP "deflate" stream';
7478 $this->success = false;
7481 $this->body = $body;
7482 break;
7484 default:
7485 $this->error = 'Unknown content coding';
7486 $this->success = false;
7491 else
7493 $this->error = 'fsocket timed out';
7494 $this->success = false;
7496 fclose($fp);
7500 else
7502 $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
7503 if (!$this->body = file_get_contents($url))
7505 $this->error = 'file_get_contents could not read the file';
7506 $this->success = false;
7513 * HTTP Response Parser
7515 * @package SimplePie
7517 class SimplePie_HTTP_Parser
7520 * HTTP Version
7522 * @access public
7523 * @var float
7525 var $http_version = 0.0;
7528 * Status code
7530 * @access public
7531 * @var int
7533 var $status_code = 0;
7536 * Reason phrase
7538 * @access public
7539 * @var string
7541 var $reason = '';
7544 * Key/value pairs of the headers
7546 * @access public
7547 * @var array
7549 var $headers = array();
7552 * Body of the response
7554 * @access public
7555 * @var string
7557 var $body = '';
7560 * Current state of the state machine
7562 * @access private
7563 * @var string
7565 var $state = 'http_version';
7568 * Input data
7570 * @access private
7571 * @var string
7573 var $data = '';
7576 * Input data length (to avoid calling strlen() everytime this is needed)
7578 * @access private
7579 * @var int
7581 var $data_length = 0;
7584 * Current position of the pointer
7586 * @var int
7587 * @access private
7589 var $position = 0;
7592 * Name of the hedaer currently being parsed
7594 * @access private
7595 * @var string
7597 var $name = '';
7600 * Value of the hedaer currently being parsed
7602 * @access private
7603 * @var string
7605 var $value = '';
7608 * Create an instance of the class with the input data
7610 * @access public
7611 * @param string $data Input data
7613 public function __construct($data)
7615 $this->data = $data;
7616 $this->data_length = strlen($this->data);
7620 * Parse the input data
7622 * @access public
7623 * @return bool true on success, false on failure
7625 public function parse()
7627 while ($this->state && $this->state !== 'emit' && $this->has_data())
7629 $state = $this->state;
7630 $this->$state();
7632 $this->data = '';
7633 if ($this->state === 'emit' || $this->state === 'body')
7635 return true;
7637 else
7639 $this->http_version = '';
7640 $this->status_code = '';
7641 $this->reason = '';
7642 $this->headers = array();
7643 $this->body = '';
7644 return false;
7649 * Check whether there is data beyond the pointer
7651 * @access private
7652 * @return bool true if there is further data, false if not
7654 public function has_data()
7656 return (bool) ($this->position < $this->data_length);
7660 * See if the next character is LWS
7662 * @access private
7663 * @return bool true if the next character is LWS, false if not
7665 public function is_linear_whitespace()
7667 return (bool) ($this->data[$this->position] === "\x09"
7668 || $this->data[$this->position] === "\x20"
7669 || ($this->data[$this->position] === "\x0A"
7670 && isset($this->data[$this->position + 1])
7671 && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
7675 * Parse the HTTP version
7677 * @access private
7679 public function http_version()
7681 if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
7683 $len = strspn($this->data, '0123456789.', 5);
7684 $this->http_version = substr($this->data, 5, $len);
7685 $this->position += 5 + $len;
7686 if (substr_count($this->http_version, '.') <= 1)
7688 $this->http_version = (float) $this->http_version;
7689 $this->position += strspn($this->data, "\x09\x20", $this->position);
7690 $this->state = 'status';
7692 else
7694 $this->state = false;
7697 else
7699 $this->state = false;
7704 * Parse the status code
7706 * @access private
7708 public function status()
7710 if ($len = strspn($this->data, '0123456789', $this->position))
7712 $this->status_code = (int) substr($this->data, $this->position, $len);
7713 $this->position += $len;
7714 $this->state = 'reason';
7716 else
7718 $this->state = false;
7723 * Parse the reason phrase
7725 * @access private
7727 public function reason()
7729 $len = strcspn($this->data, "\x0A", $this->position);
7730 $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
7731 $this->position += $len + 1;
7732 $this->state = 'new_line';
7736 * Deal with a new line, shifting data around as needed
7738 * @access private
7740 public function new_line()
7742 $this->value = trim($this->value, "\x0D\x20");
7743 if ($this->name !== '' && $this->value !== '')
7745 $this->name = strtolower($this->name);
7746 if (isset($this->headers[$this->name]))
7748 $this->headers[$this->name] .= ', ' . $this->value;
7750 else
7752 $this->headers[$this->name] = $this->value;
7755 $this->name = '';
7756 $this->value = '';
7757 if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
7759 $this->position += 2;
7760 $this->state = 'body';
7762 elseif ($this->data[$this->position] === "\x0A")
7764 $this->position++;
7765 $this->state = 'body';
7767 else
7769 $this->state = 'name';
7774 * Parse a header name
7776 * @access private
7778 public function name()
7780 $len = strcspn($this->data, "\x0A:", $this->position);
7781 if (isset($this->data[$this->position + $len]))
7783 if ($this->data[$this->position + $len] === "\x0A")
7785 $this->position += $len;
7786 $this->state = 'new_line';
7788 else
7790 $this->name = substr($this->data, $this->position, $len);
7791 $this->position += $len + 1;
7792 $this->state = 'value';
7795 else
7797 $this->state = false;
7802 * Parse LWS, replacing consecutive LWS characters with a single space
7804 * @access private
7806 public function linear_whitespace()
7810 if (substr($this->data, $this->position, 2) === "\x0D\x0A")
7812 $this->position += 2;
7814 elseif ($this->data[$this->position] === "\x0A")
7816 $this->position++;
7818 $this->position += strspn($this->data, "\x09\x20", $this->position);
7819 } while ($this->has_data() && $this->is_linear_whitespace());
7820 $this->value .= "\x20";
7824 * See what state to move to while within non-quoted header values
7826 * @access private
7828 public function value()
7830 if ($this->is_linear_whitespace())
7832 $this->linear_whitespace();
7834 else
7836 switch ($this->data[$this->position])
7838 case '"':
7839 $this->position++;
7840 $this->state = 'quote';
7841 break;
7843 case "\x0A":
7844 $this->position++;
7845 $this->state = 'new_line';
7846 break;
7848 default:
7849 $this->state = 'value_char';
7850 break;
7856 * Parse a header value while outside quotes
7858 * @access private
7860 public function value_char()
7862 $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
7863 $this->value .= substr($this->data, $this->position, $len);
7864 $this->position += $len;
7865 $this->state = 'value';
7869 * See what state to move to while within quoted header values
7871 * @access private
7873 public function quote()
7875 if ($this->is_linear_whitespace())
7877 $this->linear_whitespace();
7879 else
7881 switch ($this->data[$this->position])
7883 case '"':
7884 $this->position++;
7885 $this->state = 'value';
7886 break;
7888 case "\x0A":
7889 $this->position++;
7890 $this->state = 'new_line';
7891 break;
7893 case '\\':
7894 $this->position++;
7895 $this->state = 'quote_escaped';
7896 break;
7898 default:
7899 $this->state = 'quote_char';
7900 break;
7906 * Parse a header value while within quotes
7908 * @access private
7910 public function quote_char()
7912 $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
7913 $this->value .= substr($this->data, $this->position, $len);
7914 $this->position += $len;
7915 $this->state = 'value';
7919 * Parse an escaped character within quotes
7921 * @access private
7923 public function quote_escaped()
7925 $this->value .= $this->data[$this->position];
7926 $this->position++;
7927 $this->state = 'quote';
7931 * Parse the body
7933 * @access private
7935 public function body()
7937 $this->body = substr($this->data, $this->position);
7938 $this->state = 'emit';
7943 * gzdecode
7945 * @package SimplePie
7947 class SimplePie_gzdecode
7950 * Compressed data
7952 * @access private
7953 * @see gzdecode::$data
7955 var $compressed_data;
7958 * Size of compressed data
7960 * @access private
7962 var $compressed_size;
7965 * Minimum size of a valid gzip string
7967 * @access private
7969 var $min_compressed_size = 18;
7972 * Current position of pointer
7974 * @access private
7976 var $position = 0;
7979 * Flags (FLG)
7981 * @access private
7983 var $flags;
7986 * Uncompressed data
7988 * @access public
7989 * @see gzdecode::$compressed_data
7991 var $data;
7994 * Modified time
7996 * @access public
7998 var $MTIME;
8001 * Extra Flags
8003 * @access public
8005 var $XFL;
8008 * Operating System
8010 * @access public
8012 var $OS;
8015 * Subfield ID 1
8017 * @access public
8018 * @see gzdecode::$extra_field
8019 * @see gzdecode::$SI2
8021 var $SI1;
8024 * Subfield ID 2
8026 * @access public
8027 * @see gzdecode::$extra_field
8028 * @see gzdecode::$SI1
8030 var $SI2;
8033 * Extra field content
8035 * @access public
8036 * @see gzdecode::$SI1
8037 * @see gzdecode::$SI2
8039 var $extra_field;
8042 * Original filename
8044 * @access public
8046 var $filename;
8049 * Human readable comment
8051 * @access public
8053 var $comment;
8056 * Don't allow anything to be set
8058 * @access public
8060 public function __set($name, $value)
8062 trigger_error("Cannot write property $name", E_USER_ERROR);
8066 * Set the compressed string and related properties
8068 * @access public
8070 public function __construct($data)
8072 $this->compressed_data = $data;
8073 $this->compressed_size = strlen($data);
8077 * Decode the GZIP stream
8079 * @access public
8081 public function parse()
8083 if ($this->compressed_size >= $this->min_compressed_size)
8085 // Check ID1, ID2, and CM
8086 if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
8088 return false;
8091 // Get the FLG (FLaGs)
8092 $this->flags = ord($this->compressed_data[3]);
8094 // FLG bits above (1 << 4) are reserved
8095 if ($this->flags > 0x1F)
8097 return false;
8100 // Advance the pointer after the above
8101 $this->position += 4;
8103 // MTIME
8104 $mtime = substr($this->compressed_data, $this->position, 4);
8105 // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
8106 if (current(unpack('S', "\x00\x01")) === 1)
8108 $mtime = strrev($mtime);
8110 $this->MTIME = current(unpack('l', $mtime));
8111 $this->position += 4;
8113 // Get the XFL (eXtra FLags)
8114 $this->XFL = ord($this->compressed_data[$this->position++]);
8116 // Get the OS (Operating System)
8117 $this->OS = ord($this->compressed_data[$this->position++]);
8119 // Parse the FEXTRA
8120 if ($this->flags & 4)
8122 // Read subfield IDs
8123 $this->SI1 = $this->compressed_data[$this->position++];
8124 $this->SI2 = $this->compressed_data[$this->position++];
8126 // SI2 set to zero is reserved for future use
8127 if ($this->SI2 === "\x00")
8129 return false;
8132 // Get the length of the extra field
8133 $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8134 $position += 2;
8136 // Check the length of the string is still valid
8137 $this->min_compressed_size += $len + 4;
8138 if ($this->compressed_size >= $this->min_compressed_size)
8140 // Set the extra field to the given data
8141 $this->extra_field = substr($this->compressed_data, $this->position, $len);
8142 $this->position += $len;
8144 else
8146 return false;
8150 // Parse the FNAME
8151 if ($this->flags & 8)
8153 // Get the length of the filename
8154 $len = strcspn($this->compressed_data, "\x00", $this->position);
8156 // Check the length of the string is still valid
8157 $this->min_compressed_size += $len + 1;
8158 if ($this->compressed_size >= $this->min_compressed_size)
8160 // Set the original filename to the given string
8161 $this->filename = substr($this->compressed_data, $this->position, $len);
8162 $this->position += $len + 1;
8164 else
8166 return false;
8170 // Parse the FCOMMENT
8171 if ($this->flags & 16)
8173 // Get the length of the comment
8174 $len = strcspn($this->compressed_data, "\x00", $this->position);
8176 // Check the length of the string is still valid
8177 $this->min_compressed_size += $len + 1;
8178 if ($this->compressed_size >= $this->min_compressed_size)
8180 // Set the original comment to the given string
8181 $this->comment = substr($this->compressed_data, $this->position, $len);
8182 $this->position += $len + 1;
8184 else
8186 return false;
8190 // Parse the FHCRC
8191 if ($this->flags & 2)
8193 // Check the length of the string is still valid
8194 $this->min_compressed_size += $len + 2;
8195 if ($this->compressed_size >= $this->min_compressed_size)
8197 // Read the CRC
8198 $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
8200 // Check the CRC matches
8201 if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
8203 $this->position += 2;
8205 else
8207 return false;
8210 else
8212 return false;
8216 // Decompress the actual data
8217 if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
8219 return false;
8221 else
8223 $this->position = $this->compressed_size - 8;
8226 // Check CRC of data
8227 $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8228 $this->position += 4;
8229 /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
8231 return false;
8234 // Check ISIZE of data
8235 $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
8236 $this->position += 4;
8237 if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
8239 return false;
8242 // Wow, against all odds, we've actually got a valid gzip string
8243 return true;
8245 else
8247 return false;
8252 class SimplePie_Cache
8255 * Don't call the constructor. Please.
8257 * @access private
8259 private function __construct()
8261 trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
8265 * Create a new SimplePie_Cache object
8267 * @static
8268 * @access public
8270 public static function create($location, $filename, $extension)
8272 $location_iri = new SimplePie_IRI($location);
8273 switch ($location_iri->get_scheme())
8275 case 'mysql':
8276 if (extension_loaded('mysql'))
8278 return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
8280 break;
8282 default:
8283 return new SimplePie_Cache_File($location, $filename, $extension);
8288 class SimplePie_Cache_File
8290 var $location;
8291 var $filename;
8292 var $extension;
8293 var $name;
8295 public function __construct($location, $filename, $extension)
8297 $this->location = $location;
8298 $this->filename = $filename;
8299 $this->extension = $extension;
8300 $this->name = "$this->location/$this->filename.$this->extension";
8303 public function save($data)
8305 if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
8307 if (is_a($data, 'SimplePie'))
8309 $data = $data->data;
8312 $data = serialize($data);
8313 return (bool) file_put_contents($this->name, $data);
8315 return false;
8318 public function load()
8320 if (file_exists($this->name) && is_readable($this->name))
8322 return unserialize(file_get_contents($this->name));
8324 return false;
8327 public function mtime()
8329 if (file_exists($this->name))
8331 return filemtime($this->name);
8333 return false;
8336 public function touch()
8338 if (file_exists($this->name))
8340 return touch($this->name);
8342 return false;
8345 public function unlink()
8347 if (file_exists($this->name))
8349 return unlink($this->name);
8351 return false;
8355 class SimplePie_Cache_DB
8357 public function prepare_simplepie_object_for_cache($data)
8359 $items = $data->get_items();
8360 $items_by_id = array();
8362 if (!empty($items))
8364 foreach ($items as $item)
8366 $items_by_id[$item->get_id()] = $item;
8369 if (count($items_by_id) !== count($items))
8371 $items_by_id = array();
8372 foreach ($items as $item)
8374 $items_by_id[$item->get_id(true)] = $item;
8378 if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8380 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8382 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8384 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8386 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8388 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8390 elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
8392 $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
8394 else
8396 $channel = null;
8399 if ($channel !== null)
8401 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
8403 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
8405 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
8407 unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
8409 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
8411 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
8413 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
8415 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
8417 if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
8419 unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
8422 if (isset($data->data['items']))
8424 unset($data->data['items']);
8426 if (isset($data->data['ordered_items']))
8428 unset($data->data['ordered_items']);
8431 return array(serialize($data->data), $items_by_id);
8435 class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
8437 var $mysql;
8438 var $options;
8439 var $id;
8441 public function __construct($mysql_location, $name, $extension)
8443 $host = $mysql_location->get_host();
8444 if (stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
8446 $server = ':' . substr($host, 5, -1);
8448 else
8450 $server = $host;
8451 if ($mysql_location->get_port() !== null)
8453 $server .= ':' . $mysql_location->get_port();
8457 if (strpos($mysql_location->get_userinfo(), ':') !== false)
8459 list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
8461 else
8463 $username = $mysql_location->get_userinfo();
8464 $password = null;
8467 if ($this->mysql = mysql_connect($server, $username, $password))
8469 $this->id = $name . $extension;
8470 $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
8471 if (!isset($this->options['prefix'][0]))
8473 $this->options['prefix'][0] = '';
8476 if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
8477 && mysql_query('SET NAMES utf8')
8478 && ($query = mysql_unbuffered_query('SHOW TABLES')))
8480 $db = array();
8481 while ($row = mysql_fetch_row($query))
8483 $db[] = $row[0];
8486 if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
8488 if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
8490 $this->mysql = null;
8494 if (!in_array($this->options['prefix'][0] . 'items', $db))
8496 if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
8498 $this->mysql = null;
8502 else
8504 $this->mysql = null;
8509 public function save($data)
8511 if ($this->mysql)
8513 $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
8515 if (is_a($data, 'SimplePie'))
8517 $data = clone $data;
8519 $prepared = $this->prepare_simplepie_object_for_cache($data);
8521 if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8523 if (mysql_num_rows($query))
8525 $items = count($prepared[1]);
8526 if ($items)
8528 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8530 else
8532 $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
8535 if (!mysql_query($sql, $this->mysql))
8537 return false;
8540 elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
8542 return false;
8545 $ids = array_keys($prepared[1]);
8546 if (!empty($ids))
8548 foreach ($ids as $id)
8550 $database_ids[] = mysql_real_escape_string($id);
8553 if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
8555 $existing_ids = array();
8556 while ($row = mysql_fetch_row($query))
8558 $existing_ids[] = $row[0];
8561 $new_ids = array_diff($ids, $existing_ids);
8563 foreach ($new_ids as $new_id)
8565 if (!($date = $prepared[1][$new_id]->get_date('U')))
8567 $date = time();
8570 if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
8572 return false;
8575 return true;
8578 else
8580 return true;
8584 elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
8586 if (mysql_num_rows($query))
8588 if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
8590 return true;
8593 elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
8595 return true;
8599 return false;
8602 public function load()
8604 if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
8606 $data = unserialize($row[1]);
8608 if (isset($this->options['items'][0]))
8610 $items = (int) $this->options['items'][0];
8612 else
8614 $items = (int) $row[0];
8617 if ($items !== 0)
8619 if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
8621 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
8623 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
8625 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
8627 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
8629 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
8631 elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
8633 $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
8635 else
8637 $feed = null;
8640 if ($feed !== null)
8642 $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
8643 if ($items > 0)
8645 $sql .= ' LIMIT ' . $items;
8648 if ($query = mysql_unbuffered_query($sql, $this->mysql))
8650 while ($row = mysql_fetch_row($query))
8652 $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
8655 else
8657 return false;
8661 return $data;
8663 return false;
8666 public function mtime()
8668 if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
8670 return $row[0];
8672 else
8674 return false;
8678 public function touch()
8680 if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
8682 return true;
8684 else
8686 return false;
8690 public function unlink()
8692 if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
8694 return true;
8696 else
8698 return false;
8703 class SimplePie_Misc
8705 public static function time_hms($seconds)
8707 $time = '';
8709 $hours = floor($seconds / 3600);
8710 $remainder = $seconds % 3600;
8711 if ($hours > 0)
8713 $time .= $hours.':';
8716 $minutes = floor($remainder / 60);
8717 $seconds = $remainder % 60;
8718 if ($minutes < 10 && $hours > 0)
8720 $minutes = '0' . $minutes;
8722 if ($seconds < 10)
8724 $seconds = '0' . $seconds;
8727 $time .= $minutes.':';
8728 $time .= $seconds;
8730 return $time;
8733 public static function absolutize_url($relative, $base)
8735 $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
8736 return $iri->get_iri();
8739 public static function remove_dot_segments($input)
8741 $output = '';
8742 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
8744 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
8745 if (strpos($input, '../') === 0)
8747 $input = substr($input, 3);
8749 elseif (strpos($input, './') === 0)
8751 $input = substr($input, 2);
8753 // 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,
8754 elseif (strpos($input, '/./') === 0)
8756 $input = substr_replace($input, '/', 0, 3);
8758 elseif ($input === '/.')
8760 $input = '/';
8762 // 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,
8763 elseif (strpos($input, '/../') === 0)
8765 $input = substr_replace($input, '/', 0, 4);
8766 $output = substr_replace($output, '', strrpos($output, '/'));
8768 elseif ($input === '/..')
8770 $input = '/';
8771 $output = substr_replace($output, '', strrpos($output, '/'));
8773 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
8774 elseif ($input === '.' || $input === '..')
8776 $input = '';
8778 // 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
8779 elseif (($pos = strpos($input, '/', 1)) !== false)
8781 $output .= substr($input, 0, $pos);
8782 $input = substr_replace($input, '', 0, $pos);
8784 else
8786 $output .= $input;
8787 $input = '';
8790 return $output . $input;
8793 public static function get_element($realname, $string)
8795 $return = array();
8796 $name = preg_quote($realname, '/');
8797 if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
8799 for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
8801 $return[$i]['tag'] = $realname;
8802 $return[$i]['full'] = $matches[$i][0][0];
8803 $return[$i]['offset'] = $matches[$i][0][1];
8804 if (strlen($matches[$i][3][0]) <= 2)
8806 $return[$i]['self_closing'] = true;
8808 else
8810 $return[$i]['self_closing'] = false;
8811 $return[$i]['content'] = $matches[$i][4][0];
8813 $return[$i]['attribs'] = array();
8814 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))
8816 for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
8818 if (count($attribs[$j]) === 2)
8820 $attribs[$j][2] = $attribs[$j][1];
8822 $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
8827 return $return;
8830 public static function element_implode($element)
8832 $full = "<$element[tag]";
8833 foreach ($element['attribs'] as $key => $value)
8835 $key = strtolower($key);
8836 $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
8838 if ($element['self_closing'])
8840 $full .= ' />';
8842 else
8844 $full .= ">$element[content]</$element[tag]>";
8846 return $full;
8849 public static function error($message, $level, $file, $line)
8851 if ((ini_get('error_reporting') & $level) > 0)
8853 switch ($level)
8855 case E_USER_ERROR:
8856 $note = 'PHP Error';
8857 break;
8858 case E_USER_WARNING:
8859 $note = 'PHP Warning';
8860 break;
8861 case E_USER_NOTICE:
8862 $note = 'PHP Notice';
8863 break;
8864 default:
8865 $note = 'Unknown Error';
8866 break;
8869 $log_error = true;
8870 if (!function_exists('error_log'))
8872 $log_error = false;
8875 $log_file = @ini_get('error_log');
8876 if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
8878 $log_error = false;
8881 if ($log_error)
8883 @error_log("$note: $message in $file on line $line", 0);
8887 return $message;
8890 public static function fix_protocol($url, $http = 1)
8892 $url = SimplePie_Misc::normalize_url($url);
8893 $parsed = SimplePie_Misc::parse_url($url);
8894 if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
8896 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
8899 if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
8901 return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
8904 if ($http === 2 && $parsed['scheme'] !== '')
8906 return "feed:$url";
8908 elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
8910 return substr_replace($url, 'podcast', 0, 4);
8912 elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
8914 return substr_replace($url, 'itpc', 0, 4);
8916 else
8918 return $url;
8922 public static function parse_url($url)
8924 $iri = new SimplePie_IRI($url);
8925 return array(
8926 'scheme' => (string) $iri->get_scheme(),
8927 'authority' => (string) $iri->get_authority(),
8928 'path' => (string) $iri->get_path(),
8929 'query' => (string) $iri->get_query(),
8930 'fragment' => (string) $iri->get_fragment()
8934 public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
8936 $iri = new SimplePie_IRI('');
8937 $iri->set_scheme($scheme);
8938 $iri->set_authority($authority);
8939 $iri->set_path($path);
8940 $iri->set_query($query);
8941 $iri->set_fragment($fragment);
8942 return $iri->get_iri();
8945 public static function normalize_url($url)
8947 $iri = new SimplePie_IRI($url);
8948 return $iri->get_iri();
8951 public static function percent_encoding_normalization($match)
8953 $integer = hexdec($match[1]);
8954 if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
8956 return chr($integer);
8958 else
8960 return strtoupper($match[0]);
8965 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
8967 * @static
8968 * @access public
8969 * @param string $string Windows-1252 encoded string
8970 * @return string UTF-8 encoded string
8972 public static function windows_1252_to_utf8($string)
8974 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");
8976 return strtr($string, $convert_table);
8979 public static function change_encoding($data, $input, $output)
8981 $input = SimplePie_Misc::encoding($input);
8982 $output = SimplePie_Misc::encoding($output);
8984 // We fail to fail on non US-ASCII bytes
8985 if ($input === 'US-ASCII')
8987 static $non_ascii_octects = '';
8988 if (!$non_ascii_octects)
8990 for ($i = 0x80; $i <= 0xFF; $i++)
8992 $non_ascii_octects .= chr($i);
8995 $data = substr($data, 0, strcspn($data, $non_ascii_octects));
8998 // This is first, as behaviour of this is completely predictable
8999 if ($input === 'windows-1252' && $output === 'UTF-8')
9001 return SimplePie_Misc::windows_1252_to_utf8($data);
9003 // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
9004 elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
9006 return $return;
9008 // This is last, as behaviour of this varies with OS userland and PHP version
9009 elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
9011 return $return;
9013 // If we can't do anything, just fail
9014 else
9016 return false;
9021 * Normalize an encoding name
9023 * This is automatically generated by create.php
9025 * To generate it, run `php create.php` on the command line, and copy the
9026 * output to replace this function.
9028 * @param string $charset Character set to standardise
9029 * @return string Standardised name
9031 public static function encoding($charset)
9033 // Normalization from UTS #22
9034 switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
9036 case 'adobestandardencoding':
9037 case 'csadobestandardencoding':
9038 return 'Adobe-Standard-Encoding';
9040 case 'adobesymbolencoding':
9041 case 'cshppsmath':
9042 return 'Adobe-Symbol-Encoding';
9044 case 'ami1251':
9045 case 'amiga1251':
9046 return 'Amiga-1251';
9048 case 'ansix31101983':
9049 case 'csat5001983':
9050 case 'csiso99naplps':
9051 case 'isoir99':
9052 case 'naplps':
9053 return 'ANSI_X3.110-1983';
9055 case 'arabic7':
9056 case 'asmo449':
9057 case 'csiso89asmo449':
9058 case 'iso9036':
9059 case 'isoir89':
9060 return 'ASMO_449';
9062 case 'big5':
9063 case 'csbig5':
9064 return 'Big5';
9066 case 'big5hkscs':
9067 return 'Big5-HKSCS';
9069 case 'bocu1':
9070 case 'csbocu1':
9071 return 'BOCU-1';
9073 case 'brf':
9074 case 'csbrf':
9075 return 'BRF';
9077 case 'bs4730':
9078 case 'csiso4unitedkingdom':
9079 case 'gb':
9080 case 'iso646gb':
9081 case 'isoir4':
9082 case 'uk':
9083 return 'BS_4730';
9085 case 'bsviewdata':
9086 case 'csiso47bsviewdata':
9087 case 'isoir47':
9088 return 'BS_viewdata';
9090 case 'cesu8':
9091 case 'cscesu8':
9092 return 'CESU-8';
9094 case 'ca':
9095 case 'csa71':
9096 case 'csaz243419851':
9097 case 'csiso121canadian1':
9098 case 'iso646ca':
9099 case 'isoir121':
9100 return 'CSA_Z243.4-1985-1';
9102 case 'csa72':
9103 case 'csaz243419852':
9104 case 'csiso122canadian2':
9105 case 'iso646ca2':
9106 case 'isoir122':
9107 return 'CSA_Z243.4-1985-2';
9109 case 'csaz24341985gr':
9110 case 'csiso123csaz24341985gr':
9111 case 'isoir123':
9112 return 'CSA_Z243.4-1985-gr';
9114 case 'csiso139csn369103':
9115 case 'csn369103':
9116 case 'isoir139':
9117 return 'CSN_369103';
9119 case 'csdecmcs':
9120 case 'dec':
9121 case 'decmcs':
9122 return 'DEC-MCS';
9124 case 'csiso21german':
9125 case 'de':
9126 case 'din66003':
9127 case 'iso646de':
9128 case 'isoir21':
9129 return 'DIN_66003';
9131 case 'csdkus':
9132 case 'dkus':
9133 return 'dk-us';
9135 case 'csiso646danish':
9136 case 'dk':
9137 case 'ds2089':
9138 case 'iso646dk':
9139 return 'DS_2089';
9141 case 'csibmebcdicatde':
9142 case 'ebcdicatde':
9143 return 'EBCDIC-AT-DE';
9145 case 'csebcdicatdea':
9146 case 'ebcdicatdea':
9147 return 'EBCDIC-AT-DE-A';
9149 case 'csebcdiccafr':
9150 case 'ebcdiccafr':
9151 return 'EBCDIC-CA-FR';
9153 case 'csebcdicdkno':
9154 case 'ebcdicdkno':
9155 return 'EBCDIC-DK-NO';
9157 case 'csebcdicdknoa':
9158 case 'ebcdicdknoa':
9159 return 'EBCDIC-DK-NO-A';
9161 case 'csebcdices':
9162 case 'ebcdices':
9163 return 'EBCDIC-ES';
9165 case 'csebcdicesa':
9166 case 'ebcdicesa':
9167 return 'EBCDIC-ES-A';
9169 case 'csebcdicess':
9170 case 'ebcdicess':
9171 return 'EBCDIC-ES-S';
9173 case 'csebcdicfise':
9174 case 'ebcdicfise':
9175 return 'EBCDIC-FI-SE';
9177 case 'csebcdicfisea':
9178 case 'ebcdicfisea':
9179 return 'EBCDIC-FI-SE-A';
9181 case 'csebcdicfr':
9182 case 'ebcdicfr':
9183 return 'EBCDIC-FR';
9185 case 'csebcdicit':
9186 case 'ebcdicit':
9187 return 'EBCDIC-IT';
9189 case 'csebcdicpt':
9190 case 'ebcdicpt':
9191 return 'EBCDIC-PT';
9193 case 'csebcdicuk':
9194 case 'ebcdicuk':
9195 return 'EBCDIC-UK';
9197 case 'csebcdicus':
9198 case 'ebcdicus':
9199 return 'EBCDIC-US';
9201 case 'csiso111ecmacyrillic':
9202 case 'ecmacyrillic':
9203 case 'isoir111':
9204 case 'koi8e':
9205 return 'ECMA-cyrillic';
9207 case 'csiso17spanish':
9208 case 'es':
9209 case 'iso646es':
9210 case 'isoir17':
9211 return 'ES';
9213 case 'csiso85spanish2':
9214 case 'es2':
9215 case 'iso646es2':
9216 case 'isoir85':
9217 return 'ES2';
9219 case 'cseucpkdfmtjapanese':
9220 case 'eucjp':
9221 case 'extendedunixcodepackedformatforjapanese':
9222 return 'EUC-JP';
9224 case 'cseucfixwidjapanese':
9225 case 'extendedunixcodefixedwidthforjapanese':
9226 return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
9228 case 'gb18030':
9229 return 'GB18030';
9231 case 'chinese':
9232 case 'cp936':
9233 case 'csgb2312':
9234 case 'csiso58gb231280':
9235 case 'gb2312':
9236 case 'gb231280':
9237 case 'gbk':
9238 case 'isoir58':
9239 case 'ms936':
9240 case 'windows936':
9241 return 'GBK';
9243 case 'cn':
9244 case 'csiso57gb1988':
9245 case 'gb198880':
9246 case 'iso646cn':
9247 case 'isoir57':
9248 return 'GB_1988-80';
9250 case 'csiso153gost1976874':
9251 case 'gost1976874':
9252 case 'isoir153':
9253 case 'stsev35888':
9254 return 'GOST_19768-74';
9256 case 'csiso150':
9257 case 'csiso150greekccitt':
9258 case 'greekccitt':
9259 case 'isoir150':
9260 return 'greek-ccitt';
9262 case 'csiso88greek7':
9263 case 'greek7':
9264 case 'isoir88':
9265 return 'greek7';
9267 case 'csiso18greek7old':
9268 case 'greek7old':
9269 case 'isoir18':
9270 return 'greek7-old';
9272 case 'cshpdesktop':
9273 case 'hpdesktop':
9274 return 'HP-DeskTop';
9276 case 'cshplegal':
9277 case 'hplegal':
9278 return 'HP-Legal';
9280 case 'cshpmath8':
9281 case 'hpmath8':
9282 return 'HP-Math8';
9284 case 'cshppifont':
9285 case 'hppifont':
9286 return 'HP-Pi-font';
9288 case 'cshproman8':
9289 case 'hproman8':
9290 case 'r8':
9291 case 'roman8':
9292 return 'hp-roman8';
9294 case 'hzgb2312':
9295 return 'HZ-GB-2312';
9297 case 'csibmsymbols':
9298 case 'ibmsymbols':
9299 return 'IBM-Symbols';
9301 case 'csibmthai':
9302 case 'ibmthai':
9303 return 'IBM-Thai';
9305 case 'cp37':
9306 case 'csibm37':
9307 case 'ebcdiccpca':
9308 case 'ebcdiccpnl':
9309 case 'ebcdiccpus':
9310 case 'ebcdiccpwt':
9311 case 'ibm37':
9312 return 'IBM037';
9314 case 'cp38':
9315 case 'csibm38':
9316 case 'ebcdicint':
9317 case 'ibm38':
9318 return 'IBM038';
9320 case 'cp273':
9321 case 'csibm273':
9322 case 'ibm273':
9323 return 'IBM273';
9325 case 'cp274':
9326 case 'csibm274':
9327 case 'ebcdicbe':
9328 case 'ibm274':
9329 return 'IBM274';
9331 case 'cp275':
9332 case 'csibm275':
9333 case 'ebcdicbr':
9334 case 'ibm275':
9335 return 'IBM275';
9337 case 'csibm277':
9338 case 'ebcdiccpdk':
9339 case 'ebcdiccpno':
9340 case 'ibm277':
9341 return 'IBM277';
9343 case 'cp278':
9344 case 'csibm278':
9345 case 'ebcdiccpfi':
9346 case 'ebcdiccpse':
9347 case 'ibm278':
9348 return 'IBM278';
9350 case 'cp280':
9351 case 'csibm280':
9352 case 'ebcdiccpit':
9353 case 'ibm280':
9354 return 'IBM280';
9356 case 'cp281':
9357 case 'csibm281':
9358 case 'ebcdicjpe':
9359 case 'ibm281':
9360 return 'IBM281';
9362 case 'cp284':
9363 case 'csibm284':
9364 case 'ebcdiccpes':
9365 case 'ibm284':
9366 return 'IBM284';
9368 case 'cp285':
9369 case 'csibm285':
9370 case 'ebcdiccpgb':
9371 case 'ibm285':
9372 return 'IBM285';
9374 case 'cp290':
9375 case 'csibm290':
9376 case 'ebcdicjpkana':
9377 case 'ibm290':
9378 return 'IBM290';
9380 case 'cp297':
9381 case 'csibm297':
9382 case 'ebcdiccpfr':
9383 case 'ibm297':
9384 return 'IBM297';
9386 case 'cp420':
9387 case 'csibm420':
9388 case 'ebcdiccpar1':
9389 case 'ibm420':
9390 return 'IBM420';
9392 case 'cp423':
9393 case 'csibm423':
9394 case 'ebcdiccpgr':
9395 case 'ibm423':
9396 return 'IBM423';
9398 case 'cp424':
9399 case 'csibm424':
9400 case 'ebcdiccphe':
9401 case 'ibm424':
9402 return 'IBM424';
9404 case '437':
9405 case 'cp437':
9406 case 'cspc8codepage437':
9407 case 'ibm437':
9408 return 'IBM437';
9410 case 'cp500':
9411 case 'csibm500':
9412 case 'ebcdiccpbe':
9413 case 'ebcdiccpch':
9414 case 'ibm500':
9415 return 'IBM500';
9417 case 'cp775':
9418 case 'cspc775baltic':
9419 case 'ibm775':
9420 return 'IBM775';
9422 case '850':
9423 case 'cp850':
9424 case 'cspc850multilingual':
9425 case 'ibm850':
9426 return 'IBM850';
9428 case '851':
9429 case 'cp851':
9430 case 'csibm851':
9431 case 'ibm851':
9432 return 'IBM851';
9434 case '852':
9435 case 'cp852':
9436 case 'cspcp852':
9437 case 'ibm852':
9438 return 'IBM852';
9440 case '855':
9441 case 'cp855':
9442 case 'csibm855':
9443 case 'ibm855':
9444 return 'IBM855';
9446 case '857':
9447 case 'cp857':
9448 case 'csibm857':
9449 case 'ibm857':
9450 return 'IBM857';
9452 case 'ccsid858':
9453 case 'cp858':
9454 case 'ibm858':
9455 case 'pcmultilingual850euro':
9456 return 'IBM00858';
9458 case '860':
9459 case 'cp860':
9460 case 'csibm860':
9461 case 'ibm860':
9462 return 'IBM860';
9464 case '861':
9465 case 'cp861':
9466 case 'cpis':
9467 case 'csibm861':
9468 case 'ibm861':
9469 return 'IBM861';
9471 case '862':
9472 case 'cp862':
9473 case 'cspc862latinhebrew':
9474 case 'ibm862':
9475 return 'IBM862';
9477 case '863':
9478 case 'cp863':
9479 case 'csibm863':
9480 case 'ibm863':
9481 return 'IBM863';
9483 case 'cp864':
9484 case 'csibm864':
9485 case 'ibm864':
9486 return 'IBM864';
9488 case '865':
9489 case 'cp865':
9490 case 'csibm865':
9491 case 'ibm865':
9492 return 'IBM865';
9494 case '866':
9495 case 'cp866':
9496 case 'csibm866':
9497 case 'ibm866':
9498 return 'IBM866';
9500 case 'cp868':
9501 case 'cpar':
9502 case 'csibm868':
9503 case 'ibm868':
9504 return 'IBM868';
9506 case '869':
9507 case 'cp869':
9508 case 'cpgr':
9509 case 'csibm869':
9510 case 'ibm869':
9511 return 'IBM869';
9513 case 'cp870':
9514 case 'csibm870':
9515 case 'ebcdiccproece':
9516 case 'ebcdiccpyu':
9517 case 'ibm870':
9518 return 'IBM870';
9520 case 'cp871':
9521 case 'csibm871':
9522 case 'ebcdiccpis':
9523 case 'ibm871':
9524 return 'IBM871';
9526 case 'cp880':
9527 case 'csibm880':
9528 case 'ebcdiccyrillic':
9529 case 'ibm880':
9530 return 'IBM880';
9532 case 'cp891':
9533 case 'csibm891':
9534 case 'ibm891':
9535 return 'IBM891';
9537 case 'cp903':
9538 case 'csibm903':
9539 case 'ibm903':
9540 return 'IBM903';
9542 case '904':
9543 case 'cp904':
9544 case 'csibbm904':
9545 case 'ibm904':
9546 return 'IBM904';
9548 case 'cp905':
9549 case 'csibm905':
9550 case 'ebcdiccptr':
9551 case 'ibm905':
9552 return 'IBM905';
9554 case 'cp918':
9555 case 'csibm918':
9556 case 'ebcdiccpar2':
9557 case 'ibm918':
9558 return 'IBM918';
9560 case 'ccsid924':
9561 case 'cp924':
9562 case 'ebcdiclatin9euro':
9563 case 'ibm924':
9564 return 'IBM00924';
9566 case 'cp1026':
9567 case 'csibm1026':
9568 case 'ibm1026':
9569 return 'IBM1026';
9571 case 'ibm1047':
9572 return 'IBM1047';
9574 case 'ccsid1140':
9575 case 'cp1140':
9576 case 'ebcdicus37euro':
9577 case 'ibm1140':
9578 return 'IBM01140';
9580 case 'ccsid1141':
9581 case 'cp1141':
9582 case 'ebcdicde273euro':
9583 case 'ibm1141':
9584 return 'IBM01141';
9586 case 'ccsid1142':
9587 case 'cp1142':
9588 case 'ebcdicdk277euro':
9589 case 'ebcdicno277euro':
9590 case 'ibm1142':
9591 return 'IBM01142';
9593 case 'ccsid1143':
9594 case 'cp1143':
9595 case 'ebcdicfi278euro':
9596 case 'ebcdicse278euro':
9597 case 'ibm1143':
9598 return 'IBM01143';
9600 case 'ccsid1144':
9601 case 'cp1144':
9602 case 'ebcdicit280euro':
9603 case 'ibm1144':
9604 return 'IBM01144';
9606 case 'ccsid1145':
9607 case 'cp1145':
9608 case 'ebcdices284euro':
9609 case 'ibm1145':
9610 return 'IBM01145';
9612 case 'ccsid1146':
9613 case 'cp1146':
9614 case 'ebcdicgb285euro':
9615 case 'ibm1146':
9616 return 'IBM01146';
9618 case 'ccsid1147':
9619 case 'cp1147':
9620 case 'ebcdicfr297euro':
9621 case 'ibm1147':
9622 return 'IBM01147';
9624 case 'ccsid1148':
9625 case 'cp1148':
9626 case 'ebcdicinternational500euro':
9627 case 'ibm1148':
9628 return 'IBM01148';
9630 case 'ccsid1149':
9631 case 'cp1149':
9632 case 'ebcdicis871euro':
9633 case 'ibm1149':
9634 return 'IBM01149';
9636 case 'csiso143iecp271':
9637 case 'iecp271':
9638 case 'isoir143':
9639 return 'IEC_P27-1';
9641 case 'csiso49inis':
9642 case 'inis':
9643 case 'isoir49':
9644 return 'INIS';
9646 case 'csiso50inis8':
9647 case 'inis8':
9648 case 'isoir50':
9649 return 'INIS-8';
9651 case 'csiso51iniscyrillic':
9652 case 'iniscyrillic':
9653 case 'isoir51':
9654 return 'INIS-cyrillic';
9656 case 'csinvariant':
9657 case 'invariant':
9658 return 'INVARIANT';
9660 case 'iso2022cn':
9661 return 'ISO-2022-CN';
9663 case 'iso2022cnext':
9664 return 'ISO-2022-CN-EXT';
9666 case 'csiso2022jp':
9667 case 'iso2022jp':
9668 return 'ISO-2022-JP';
9670 case 'csiso2022jp2':
9671 case 'iso2022jp2':
9672 return 'ISO-2022-JP-2';
9674 case 'csiso2022kr':
9675 case 'iso2022kr':
9676 return 'ISO-2022-KR';
9678 case 'cswindows30latin1':
9679 case 'iso88591windows30latin1':
9680 return 'ISO-8859-1-Windows-3.0-Latin-1';
9682 case 'cswindows31latin1':
9683 case 'iso88591windows31latin1':
9684 return 'ISO-8859-1-Windows-3.1-Latin-1';
9686 case 'csisolatin2':
9687 case 'iso88592':
9688 case 'iso885921987':
9689 case 'isoir101':
9690 case 'l2':
9691 case 'latin2':
9692 return 'ISO-8859-2';
9694 case 'cswindows31latin2':
9695 case 'iso88592windowslatin2':
9696 return 'ISO-8859-2-Windows-Latin-2';
9698 case 'csisolatin3':
9699 case 'iso88593':
9700 case 'iso885931988':
9701 case 'isoir109':
9702 case 'l3':
9703 case 'latin3':
9704 return 'ISO-8859-3';
9706 case 'csisolatin4':
9707 case 'iso88594':
9708 case 'iso885941988':
9709 case 'isoir110':
9710 case 'l4':
9711 case 'latin4':
9712 return 'ISO-8859-4';
9714 case 'csisolatincyrillic':
9715 case 'cyrillic':
9716 case 'iso88595':
9717 case 'iso885951988':
9718 case 'isoir144':
9719 return 'ISO-8859-5';
9721 case 'arabic':
9722 case 'asmo708':
9723 case 'csisolatinarabic':
9724 case 'ecma114':
9725 case 'iso88596':
9726 case 'iso885961987':
9727 case 'isoir127':
9728 return 'ISO-8859-6';
9730 case 'csiso88596e':
9731 case 'iso88596e':
9732 return 'ISO-8859-6-E';
9734 case 'csiso88596i':
9735 case 'iso88596i':
9736 return 'ISO-8859-6-I';
9738 case 'csisolatingreek':
9739 case 'ecma118':
9740 case 'elot928':
9741 case 'greek':
9742 case 'greek8':
9743 case 'iso88597':
9744 case 'iso885971987':
9745 case 'isoir126':
9746 return 'ISO-8859-7';
9748 case 'csisolatinhebrew':
9749 case 'hebrew':
9750 case 'iso88598':
9751 case 'iso885981988':
9752 case 'isoir138':
9753 return 'ISO-8859-8';
9755 case 'csiso88598e':
9756 case 'iso88598e':
9757 return 'ISO-8859-8-E';
9759 case 'csiso88598i':
9760 case 'iso88598i':
9761 return 'ISO-8859-8-I';
9763 case 'cswindows31latin5':
9764 case 'iso88599windowslatin5':
9765 return 'ISO-8859-9-Windows-Latin-5';
9767 case 'csisolatin6':
9768 case 'iso885910':
9769 case 'iso8859101992':
9770 case 'isoir157':
9771 case 'l6':
9772 case 'latin6':
9773 return 'ISO-8859-10';
9775 case 'iso885913':
9776 return 'ISO-8859-13';
9778 case 'iso885914':
9779 case 'iso8859141998':
9780 case 'isoceltic':
9781 case 'isoir199':
9782 case 'l8':
9783 case 'latin8':
9784 return 'ISO-8859-14';
9786 case 'iso885915':
9787 case 'latin9':
9788 return 'ISO-8859-15';
9790 case 'iso885916':
9791 case 'iso8859162001':
9792 case 'isoir226':
9793 case 'l10':
9794 case 'latin10':
9795 return 'ISO-8859-16';
9797 case 'iso10646j1':
9798 return 'ISO-10646-J-1';
9800 case 'csunicode':
9801 case 'iso10646ucs2':
9802 return 'ISO-10646-UCS-2';
9804 case 'csucs4':
9805 case 'iso10646ucs4':
9806 return 'ISO-10646-UCS-4';
9808 case 'csunicodeascii':
9809 case 'iso10646ucsbasic':
9810 return 'ISO-10646-UCS-Basic';
9812 case 'csunicodelatin1':
9813 case 'iso10646':
9814 case 'iso10646unicodelatin1':
9815 return 'ISO-10646-Unicode-Latin1';
9817 case 'csiso10646utf1':
9818 case 'iso10646utf1':
9819 return 'ISO-10646-UTF-1';
9821 case 'csiso115481':
9822 case 'iso115481':
9823 case 'isotr115481':
9824 return 'ISO-11548-1';
9826 case 'csiso90':
9827 case 'isoir90':
9828 return 'iso-ir-90';
9830 case 'csunicodeibm1261':
9831 case 'isounicodeibm1261':
9832 return 'ISO-Unicode-IBM-1261';
9834 case 'csunicodeibm1264':
9835 case 'isounicodeibm1264':
9836 return 'ISO-Unicode-IBM-1264';
9838 case 'csunicodeibm1265':
9839 case 'isounicodeibm1265':
9840 return 'ISO-Unicode-IBM-1265';
9842 case 'csunicodeibm1268':
9843 case 'isounicodeibm1268':
9844 return 'ISO-Unicode-IBM-1268';
9846 case 'csunicodeibm1276':
9847 case 'isounicodeibm1276':
9848 return 'ISO-Unicode-IBM-1276';
9850 case 'csiso646basic1983':
9851 case 'iso646basic1983':
9852 case 'ref':
9853 return 'ISO_646.basic:1983';
9855 case 'csiso2intlrefversion':
9856 case 'irv':
9857 case 'iso646irv1983':
9858 case 'isoir2':
9859 return 'ISO_646.irv:1983';
9861 case 'csiso2033':
9862 case 'e13b':
9863 case 'iso20331983':
9864 case 'isoir98':
9865 return 'ISO_2033-1983';
9867 case 'csiso5427cyrillic':
9868 case 'iso5427':
9869 case 'isoir37':
9870 return 'ISO_5427';
9872 case 'iso5427cyrillic1981':
9873 case 'iso54271981':
9874 case 'isoir54':
9875 return 'ISO_5427:1981';
9877 case 'csiso5428greek':
9878 case 'iso54281980':
9879 case 'isoir55':
9880 return 'ISO_5428:1980';
9882 case 'csiso6937add':
9883 case 'iso6937225':
9884 case 'isoir152':
9885 return 'ISO_6937-2-25';
9887 case 'csisotextcomm':
9888 case 'iso69372add':
9889 case 'isoir142':
9890 return 'ISO_6937-2-add';
9892 case 'csiso8859supp':
9893 case 'iso8859supp':
9894 case 'isoir154':
9895 case 'latin125':
9896 return 'ISO_8859-supp';
9898 case 'csiso10367box':
9899 case 'iso10367box':
9900 case 'isoir155':
9901 return 'ISO_10367-box';
9903 case 'csiso15italian':
9904 case 'iso646it':
9905 case 'isoir15':
9906 case 'it':
9907 return 'IT';
9909 case 'csiso13jisc6220jp':
9910 case 'isoir13':
9911 case 'jisc62201969':
9912 case 'jisc62201969jp':
9913 case 'katakana':
9914 case 'x2017':
9915 return 'JIS_C6220-1969-jp';
9917 case 'csiso14jisc6220ro':
9918 case 'iso646jp':
9919 case 'isoir14':
9920 case 'jisc62201969ro':
9921 case 'jp':
9922 return 'JIS_C6220-1969-ro';
9924 case 'csiso42jisc62261978':
9925 case 'isoir42':
9926 case 'jisc62261978':
9927 return 'JIS_C6226-1978';
9929 case 'csiso87jisx208':
9930 case 'isoir87':
9931 case 'jisc62261983':
9932 case 'jisx2081983':
9933 case 'x208':
9934 return 'JIS_C6226-1983';
9936 case 'csiso91jisc62291984a':
9937 case 'isoir91':
9938 case 'jisc62291984a':
9939 case 'jpocra':
9940 return 'JIS_C6229-1984-a';
9942 case 'csiso92jisc62991984b':
9943 case 'iso646jpocrb':
9944 case 'isoir92':
9945 case 'jisc62291984b':
9946 case 'jpocrb':
9947 return 'JIS_C6229-1984-b';
9949 case 'csiso93jis62291984badd':
9950 case 'isoir93':
9951 case 'jisc62291984badd':
9952 case 'jpocrbadd':
9953 return 'JIS_C6229-1984-b-add';
9955 case 'csiso94jis62291984hand':
9956 case 'isoir94':
9957 case 'jisc62291984hand':
9958 case 'jpocrhand':
9959 return 'JIS_C6229-1984-hand';
9961 case 'csiso95jis62291984handadd':
9962 case 'isoir95':
9963 case 'jisc62291984handadd':
9964 case 'jpocrhandadd':
9965 return 'JIS_C6229-1984-hand-add';
9967 case 'csiso96jisc62291984kana':
9968 case 'isoir96':
9969 case 'jisc62291984kana':
9970 return 'JIS_C6229-1984-kana';
9972 case 'csjisencoding':
9973 case 'jisencoding':
9974 return 'JIS_Encoding';
9976 case 'cshalfwidthkatakana':
9977 case 'jisx201':
9978 case 'x201':
9979 return 'JIS_X0201';
9981 case 'csiso159jisx2121990':
9982 case 'isoir159':
9983 case 'jisx2121990':
9984 case 'x212':
9985 return 'JIS_X0212-1990';
9987 case 'csiso141jusib1002':
9988 case 'iso646yu':
9989 case 'isoir141':
9990 case 'js':
9991 case 'jusib1002':
9992 case 'yu':
9993 return 'JUS_I.B1.002';
9995 case 'csiso147macedonian':
9996 case 'isoir147':
9997 case 'jusib1003mac':
9998 case 'macedonian':
9999 return 'JUS_I.B1.003-mac';
10001 case 'csiso146serbian':
10002 case 'isoir146':
10003 case 'jusib1003serb':
10004 case 'serbian':
10005 return 'JUS_I.B1.003-serb';
10007 case 'koi7switched':
10008 return 'KOI7-switched';
10010 case 'cskoi8r':
10011 case 'koi8r':
10012 return 'KOI8-R';
10014 case 'koi8u':
10015 return 'KOI8-U';
10017 case 'csksc5636':
10018 case 'iso646kr':
10019 case 'ksc5636':
10020 return 'KSC5636';
10022 case 'cskz1048':
10023 case 'kz1048':
10024 case 'rk1048':
10025 case 'strk10482002':
10026 return 'KZ-1048';
10028 case 'csiso19latingreek':
10029 case 'isoir19':
10030 case 'latingreek':
10031 return 'latin-greek';
10033 case 'csiso27latingreek1':
10034 case 'isoir27':
10035 case 'latingreek1':
10036 return 'Latin-greek-1';
10038 case 'csiso158lap':
10039 case 'isoir158':
10040 case 'lap':
10041 case 'latinlap':
10042 return 'latin-lap';
10044 case 'csmacintosh':
10045 case 'mac':
10046 case 'macintosh':
10047 return 'macintosh';
10049 case 'csmicrosoftpublishing':
10050 case 'microsoftpublishing':
10051 return 'Microsoft-Publishing';
10053 case 'csmnem':
10054 case 'mnem':
10055 return 'MNEM';
10057 case 'csmnemonic':
10058 case 'mnemonic':
10059 return 'MNEMONIC';
10061 case 'csiso86hungarian':
10062 case 'hu':
10063 case 'iso646hu':
10064 case 'isoir86':
10065 case 'msz77953':
10066 return 'MSZ_7795.3';
10068 case 'csnatsdano':
10069 case 'isoir91':
10070 case 'natsdano':
10071 return 'NATS-DANO';
10073 case 'csnatsdanoadd':
10074 case 'isoir92':
10075 case 'natsdanoadd':
10076 return 'NATS-DANO-ADD';
10078 case 'csnatssefi':
10079 case 'isoir81':
10080 case 'natssefi':
10081 return 'NATS-SEFI';
10083 case 'csnatssefiadd':
10084 case 'isoir82':
10085 case 'natssefiadd':
10086 return 'NATS-SEFI-ADD';
10088 case 'csiso151cuba':
10089 case 'cuba':
10090 case 'iso646cu':
10091 case 'isoir151':
10092 case 'ncnc1081':
10093 return 'NC_NC00-10:81';
10095 case 'csiso69french':
10096 case 'fr':
10097 case 'iso646fr':
10098 case 'isoir69':
10099 case 'nfz62010':
10100 return 'NF_Z_62-010';
10102 case 'csiso25french':
10103 case 'iso646fr1':
10104 case 'isoir25':
10105 case 'nfz620101973':
10106 return 'NF_Z_62-010_(1973)';
10108 case 'csiso60danishnorwegian':
10109 case 'csiso60norwegian1':
10110 case 'iso646no':
10111 case 'isoir60':
10112 case 'no':
10113 case 'ns45511':
10114 return 'NS_4551-1';
10116 case 'csiso61norwegian2':
10117 case 'iso646no2':
10118 case 'isoir61':
10119 case 'no2':
10120 case 'ns45512':
10121 return 'NS_4551-2';
10123 case 'osdebcdicdf3irv':
10124 return 'OSD_EBCDIC_DF03_IRV';
10126 case 'osdebcdicdf41':
10127 return 'OSD_EBCDIC_DF04_1';
10129 case 'osdebcdicdf415':
10130 return 'OSD_EBCDIC_DF04_15';
10132 case 'cspc8danishnorwegian':
10133 case 'pc8danishnorwegian':
10134 return 'PC8-Danish-Norwegian';
10136 case 'cspc8turkish':
10137 case 'pc8turkish':
10138 return 'PC8-Turkish';
10140 case 'csiso16portuguese':
10141 case 'iso646pt':
10142 case 'isoir16':
10143 case 'pt':
10144 return 'PT';
10146 case 'csiso84portuguese2':
10147 case 'iso646pt2':
10148 case 'isoir84':
10149 case 'pt2':
10150 return 'PT2';
10152 case 'cp154':
10153 case 'csptcp154':
10154 case 'cyrillicasian':
10155 case 'pt154':
10156 case 'ptcp154':
10157 return 'PTCP154';
10159 case 'scsu':
10160 return 'SCSU';
10162 case 'csiso10swedish':
10163 case 'fi':
10164 case 'iso646fi':
10165 case 'iso646se':
10166 case 'isoir10':
10167 case 'se':
10168 case 'sen850200b':
10169 return 'SEN_850200_B';
10171 case 'csiso11swedishfornames':
10172 case 'iso646se2':
10173 case 'isoir11':
10174 case 'se2':
10175 case 'sen850200c':
10176 return 'SEN_850200_C';
10178 case 'csiso102t617bit':
10179 case 'isoir102':
10180 case 't617bit':
10181 return 'T.61-7bit';
10183 case 'csiso103t618bit':
10184 case 'isoir103':
10185 case 't61':
10186 case 't618bit':
10187 return 'T.61-8bit';
10189 case 'csiso128t101g2':
10190 case 'isoir128':
10191 case 't101g2':
10192 return 'T.101-G2';
10194 case 'cstscii':
10195 case 'tscii':
10196 return 'TSCII';
10198 case 'csunicode11':
10199 case 'unicode11':
10200 return 'UNICODE-1-1';
10202 case 'csunicode11utf7':
10203 case 'unicode11utf7':
10204 return 'UNICODE-1-1-UTF-7';
10206 case 'csunknown8bit':
10207 case 'unknown8bit':
10208 return 'UNKNOWN-8BIT';
10210 case 'ansix341968':
10211 case 'ansix341986':
10212 case 'ascii':
10213 case 'cp367':
10214 case 'csascii':
10215 case 'ibm367':
10216 case 'iso646irv1991':
10217 case 'iso646us':
10218 case 'isoir6':
10219 case 'us':
10220 case 'usascii':
10221 return 'US-ASCII';
10223 case 'csusdk':
10224 case 'usdk':
10225 return 'us-dk';
10227 case 'utf7':
10228 return 'UTF-7';
10230 case 'utf8':
10231 return 'UTF-8';
10233 case 'utf16':
10234 return 'UTF-16';
10236 case 'utf16be':
10237 return 'UTF-16BE';
10239 case 'utf16le':
10240 return 'UTF-16LE';
10242 case 'utf32':
10243 return 'UTF-32';
10245 case 'utf32be':
10246 return 'UTF-32BE';
10248 case 'utf32le':
10249 return 'UTF-32LE';
10251 case 'csventurainternational':
10252 case 'venturainternational':
10253 return 'Ventura-International';
10255 case 'csventuramath':
10256 case 'venturamath':
10257 return 'Ventura-Math';
10259 case 'csventuraus':
10260 case 'venturaus':
10261 return 'Ventura-US';
10263 case 'csiso70videotexsupp1':
10264 case 'isoir70':
10265 case 'videotexsuppl':
10266 return 'videotex-suppl';
10268 case 'csviqr':
10269 case 'viqr':
10270 return 'VIQR';
10272 case 'csviscii':
10273 case 'viscii':
10274 return 'VISCII';
10276 case 'csshiftjis':
10277 case 'cswindows31j':
10278 case 'mskanji':
10279 case 'shiftjis':
10280 case 'windows31j':
10281 return 'Windows-31J';
10283 case 'iso885911':
10284 case 'tis620':
10285 return 'windows-874';
10287 case 'cseuckr':
10288 case 'csksc56011987':
10289 case 'euckr':
10290 case 'isoir149':
10291 case 'korean':
10292 case 'ksc5601':
10293 case 'ksc56011987':
10294 case 'ksc56011989':
10295 case 'windows949':
10296 return 'windows-949';
10298 case 'windows1250':
10299 return 'windows-1250';
10301 case 'windows1251':
10302 return 'windows-1251';
10304 case 'cp819':
10305 case 'csisolatin1':
10306 case 'ibm819':
10307 case 'iso88591':
10308 case 'iso885911987':
10309 case 'isoir100':
10310 case 'l1':
10311 case 'latin1':
10312 case 'windows1252':
10313 return 'windows-1252';
10315 case 'windows1253':
10316 return 'windows-1253';
10318 case 'csisolatin5':
10319 case 'iso88599':
10320 case 'iso885991989':
10321 case 'isoir148':
10322 case 'l5':
10323 case 'latin5':
10324 case 'windows1254':
10325 return 'windows-1254';
10327 case 'windows1255':
10328 return 'windows-1255';
10330 case 'windows1256':
10331 return 'windows-1256';
10333 case 'windows1257':
10334 return 'windows-1257';
10336 case 'windows1258':
10337 return 'windows-1258';
10339 default:
10340 return $charset;
10344 public static function get_curl_version()
10346 if (is_array($curl = curl_version()))
10348 $curl = $curl['version'];
10350 elseif (substr($curl, 0, 5) === 'curl/')
10352 $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
10354 elseif (substr($curl, 0, 8) === 'libcurl/')
10356 $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
10358 else
10360 $curl = 0;
10362 return $curl;
10365 public static function is_subclass_of($class1, $class2)
10367 if (func_num_args() !== 2)
10369 trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
10371 elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
10373 return is_subclass_of($class1, $class2);
10375 elseif (is_string($class1) && is_string($class2))
10377 if (class_exists($class1))
10379 if (class_exists($class2))
10381 $class2 = strtolower($class2);
10382 while ($class1 = strtolower(get_parent_class($class1)))
10384 if ($class1 === $class2)
10386 return true;
10391 else
10393 trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
10396 return false;
10400 * Strip HTML comments
10402 * @access public
10403 * @param string $data Data to strip comments from
10404 * @return string Comment stripped string
10406 public static function strip_comments($data)
10408 $output = '';
10409 while (($start = strpos($data, '<!--')) !== false)
10411 $output .= substr($data, 0, $start);
10412 if (($end = strpos($data, '-->', $start)) !== false)
10414 $data = substr_replace($data, '', 0, $end + 3);
10416 else
10418 $data = '';
10421 return $output . $data;
10424 public static function parse_date($dt)
10426 $parser = SimplePie_Parse_Date::get();
10427 return $parser->parse($dt);
10431 * Decode HTML entities
10433 * @static
10434 * @access public
10435 * @param string $data Input data
10436 * @return string Output data
10438 public static function entities_decode($data)
10440 $decoder = new SimplePie_Decode_HTML_Entities($data);
10441 return $decoder->parse();
10445 * Remove RFC822 comments
10447 * @access public
10448 * @param string $data Data to strip comments from
10449 * @return string Comment stripped string
10451 public static function uncomment_rfc822($string)
10453 $string = (string) $string;
10454 $position = 0;
10455 $length = strlen($string);
10456 $depth = 0;
10458 $output = '';
10460 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
10462 $output .= substr($string, $position, $pos - $position);
10463 $position = $pos + 1;
10464 if ($string[$pos - 1] !== '\\')
10466 $depth++;
10467 while ($depth && $position < $length)
10469 $position += strcspn($string, '()', $position);
10470 if ($string[$position - 1] === '\\')
10472 $position++;
10473 continue;
10475 elseif (isset($string[$position]))
10477 switch ($string[$position])
10479 case '(':
10480 $depth++;
10481 break;
10483 case ')':
10484 $depth--;
10485 break;
10487 $position++;
10489 else
10491 break;
10495 else
10497 $output .= '(';
10500 $output .= substr($string, $position);
10502 return $output;
10505 public static function parse_mime($mime)
10507 if (($pos = strpos($mime, ';')) === false)
10509 return trim($mime);
10511 else
10513 return trim(substr($mime, 0, $pos));
10517 public static function htmlspecialchars_decode($string, $quote_style)
10519 if (function_exists('htmlspecialchars_decode'))
10521 return htmlspecialchars_decode($string, $quote_style);
10523 else
10525 return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
10529 public static function atom_03_construct_type($attribs)
10531 if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
10533 $mode = SIMPLEPIE_CONSTRUCT_BASE64;
10535 else
10537 $mode = SIMPLEPIE_CONSTRUCT_NONE;
10539 if (isset($attribs['']['type']))
10541 switch (strtolower(trim($attribs['']['type'])))
10543 case 'text':
10544 case 'text/plain':
10545 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10547 case 'html':
10548 case 'text/html':
10549 return SIMPLEPIE_CONSTRUCT_HTML | $mode;
10551 case 'xhtml':
10552 case 'application/xhtml+xml':
10553 return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
10555 default:
10556 return SIMPLEPIE_CONSTRUCT_NONE | $mode;
10559 else
10561 return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
10565 public static function atom_10_construct_type($attribs)
10567 if (isset($attribs['']['type']))
10569 switch (strtolower(trim($attribs['']['type'])))
10571 case 'text':
10572 return SIMPLEPIE_CONSTRUCT_TEXT;
10574 case 'html':
10575 return SIMPLEPIE_CONSTRUCT_HTML;
10577 case 'xhtml':
10578 return SIMPLEPIE_CONSTRUCT_XHTML;
10580 default:
10581 return SIMPLEPIE_CONSTRUCT_NONE;
10584 return SIMPLEPIE_CONSTRUCT_TEXT;
10587 public static function atom_10_content_construct_type($attribs)
10589 if (isset($attribs['']['type']))
10591 $type = strtolower(trim($attribs['']['type']));
10592 switch ($type)
10594 case 'text':
10595 return SIMPLEPIE_CONSTRUCT_TEXT;
10597 case 'html':
10598 return SIMPLEPIE_CONSTRUCT_HTML;
10600 case 'xhtml':
10601 return SIMPLEPIE_CONSTRUCT_XHTML;
10603 if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
10605 return SIMPLEPIE_CONSTRUCT_NONE;
10607 else
10609 return SIMPLEPIE_CONSTRUCT_BASE64;
10612 else
10614 return SIMPLEPIE_CONSTRUCT_TEXT;
10618 public static function is_isegment_nz_nc($string)
10620 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);
10623 public static function space_seperated_tokens($string)
10625 $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
10626 $string_length = strlen($string);
10628 $position = strspn($string, $space_characters);
10629 $tokens = array();
10631 while ($position < $string_length)
10633 $len = strcspn($string, $space_characters, $position);
10634 $tokens[] = substr($string, $position, $len);
10635 $position += $len;
10636 $position += strspn($string, $space_characters, $position);
10639 return $tokens;
10642 public static function array_unique($array)
10644 if (version_compare(PHP_VERSION, '5.2', '>='))
10646 return array_unique($array);
10648 else
10650 $array = (array) $array;
10651 $new_array = array();
10652 $new_array_strings = array();
10653 foreach ($array as $key => $value)
10655 if (is_object($value))
10657 if (method_exists($value, '__toString'))
10659 $cmp = $value->__toString();
10661 else
10663 trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
10666 elseif (is_array($value))
10668 $cmp = (string) reset($value);
10670 else
10672 $cmp = (string) $value;
10674 if (!in_array($cmp, $new_array_strings))
10676 $new_array[$key] = $value;
10677 $new_array_strings[] = $cmp;
10680 return $new_array;
10685 * Converts a unicode codepoint to a UTF-8 character
10687 * @static
10688 * @access public
10689 * @param int $codepoint Unicode codepoint
10690 * @return string UTF-8 character
10692 public static function codepoint_to_utf8($codepoint)
10694 $codepoint = (int) $codepoint;
10695 if ($codepoint < 0)
10697 return false;
10699 else if ($codepoint <= 0x7f)
10701 return chr($codepoint);
10703 else if ($codepoint <= 0x7ff)
10705 return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
10707 else if ($codepoint <= 0xffff)
10709 return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
10711 else if ($codepoint <= 0x10ffff)
10713 return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
10715 else
10717 // U+FFFD REPLACEMENT CHARACTER
10718 return "\xEF\xBF\xBD";
10723 * Similar to parse_str()
10725 * Returns an associative array of name/value pairs, where the value is an
10726 * array of values that have used the same name
10728 * @static
10729 * @access string
10730 * @param string $str The input string.
10731 * @return array
10733 public static function parse_str($str)
10735 $return = array();
10736 $str = explode('&', $str);
10738 foreach ($str as $section)
10740 if (strpos($section, '=') !== false)
10742 list($name, $value) = explode('=', $section, 2);
10743 $return[urldecode($name)][] = urldecode($value);
10745 else
10747 $return[urldecode($section)][] = null;
10751 return $return;
10755 * Detect XML encoding, as per XML 1.0 Appendix F.1
10757 * @todo Add support for EBCDIC
10758 * @param string $data XML data
10759 * @return array Possible encodings
10761 public static function xml_encoding($data)
10763 // UTF-32 Big Endian BOM
10764 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
10766 $encoding[] = 'UTF-32BE';
10768 // UTF-32 Little Endian BOM
10769 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
10771 $encoding[] = 'UTF-32LE';
10773 // UTF-16 Big Endian BOM
10774 elseif (substr($data, 0, 2) === "\xFE\xFF")
10776 $encoding[] = 'UTF-16BE';
10778 // UTF-16 Little Endian BOM
10779 elseif (substr($data, 0, 2) === "\xFF\xFE")
10781 $encoding[] = 'UTF-16LE';
10783 // UTF-8 BOM
10784 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
10786 $encoding[] = 'UTF-8';
10788 // UTF-32 Big Endian Without BOM
10789 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")
10791 if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
10793 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
10794 if ($parser->parse())
10796 $encoding[] = $parser->encoding;
10799 $encoding[] = 'UTF-32BE';
10801 // UTF-32 Little Endian Without BOM
10802 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")
10804 if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
10806 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
10807 if ($parser->parse())
10809 $encoding[] = $parser->encoding;
10812 $encoding[] = 'UTF-32LE';
10814 // UTF-16 Big Endian Without BOM
10815 elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
10817 if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
10819 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
10820 if ($parser->parse())
10822 $encoding[] = $parser->encoding;
10825 $encoding[] = 'UTF-16BE';
10827 // UTF-16 Little Endian Without BOM
10828 elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
10830 if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
10832 $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
10833 if ($parser->parse())
10835 $encoding[] = $parser->encoding;
10838 $encoding[] = 'UTF-16LE';
10840 // US-ASCII (or superset)
10841 elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
10843 if ($pos = strpos($data, "\x3F\x3E"))
10845 $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
10846 if ($parser->parse())
10848 $encoding[] = $parser->encoding;
10851 $encoding[] = 'UTF-8';
10853 // Fallback to UTF-8
10854 else
10856 $encoding[] = 'UTF-8';
10858 return $encoding;
10861 public static function output_javascript()
10863 if (function_exists('ob_gzhandler'))
10865 ob_start('ob_gzhandler');
10867 header('Content-type: text/javascript; charset: UTF-8');
10868 header('Cache-Control: must-revalidate');
10869 header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
10871 function embed_odeo(link) {
10872 document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
10875 function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
10876 if (placeholder != '') {
10877 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>');
10879 else {
10880 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>');
10884 function embed_flash(bgcolor, width, height, link, loop, type) {
10885 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>');
10888 function embed_flv(width, height, link, placeholder, loop, player) {
10889 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>');
10892 function embed_wmedia(width, height, link) {
10893 document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
10895 <?php
10900 * Decode HTML Entities
10902 * This implements HTML5 as of revision 967 (2007-06-28)
10904 * @package SimplePie
10906 class SimplePie_Decode_HTML_Entities
10909 * Data to be parsed
10911 * @access private
10912 * @var string
10914 var $data = '';
10917 * Currently consumed bytes
10919 * @access private
10920 * @var string
10922 var $consumed = '';
10925 * Position of the current byte being parsed
10927 * @access private
10928 * @var int
10930 var $position = 0;
10933 * Create an instance of the class with the input data
10935 * @access public
10936 * @param string $data Input data
10938 public function __construct($data)
10940 $this->data = $data;
10944 * Parse the input data
10946 * @access public
10947 * @return string Output data
10949 public function parse()
10951 while (($this->position = strpos($this->data, '&', $this->position)) !== false)
10953 $this->consume();
10954 $this->entity();
10955 $this->consumed = '';
10957 return $this->data;
10961 * Consume the next byte
10963 * @access private
10964 * @return mixed The next byte, or false, if there is no more data
10966 public function consume()
10968 if (isset($this->data[$this->position]))
10970 $this->consumed .= $this->data[$this->position];
10971 return $this->data[$this->position++];
10973 else
10975 return false;
10980 * Consume a range of characters
10982 * @access private
10983 * @param string $chars Characters to consume
10984 * @return mixed A series of characters that match the range, or false
10986 public function consume_range($chars)
10988 if ($len = strspn($this->data, $chars, $this->position))
10990 $data = substr($this->data, $this->position, $len);
10991 $this->consumed .= $data;
10992 $this->position += $len;
10993 return $data;
10995 else
10997 return false;
11002 * Unconsume one byte
11004 * @access private
11006 public function unconsume()
11008 $this->consumed = substr($this->consumed, 0, -1);
11009 $this->position--;
11013 * Decode an entity
11015 * @access private
11017 public function entity()
11019 switch ($this->consume())
11021 case "\x09":
11022 case "\x0A":
11023 case "\x0B":
11024 case "\x0B":
11025 case "\x0C":
11026 case "\x20":
11027 case "\x3C":
11028 case "\x26":
11029 case false:
11030 break;
11032 case "\x23":
11033 switch ($this->consume())
11035 case "\x78":
11036 case "\x58":
11037 $range = '0123456789ABCDEFabcdef';
11038 $hex = true;
11039 break;
11041 default:
11042 $range = '0123456789';
11043 $hex = false;
11044 $this->unconsume();
11045 break;
11048 if ($codepoint = $this->consume_range($range))
11050 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");
11052 if ($hex)
11054 $codepoint = hexdec($codepoint);
11056 else
11058 $codepoint = intval($codepoint);
11061 if (isset($windows_1252_specials[$codepoint]))
11063 $replacement = $windows_1252_specials[$codepoint];
11065 else
11067 $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
11070 if (!in_array($this->consume(), array(';', false), true))
11072 $this->unconsume();
11075 $consumed_length = strlen($this->consumed);
11076 $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
11077 $this->position += strlen($replacement) - $consumed_length;
11079 break;
11081 default:
11082 static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
11084 for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
11086 $consumed = substr($this->consumed, 1);
11087 if (isset($entities[$consumed]))
11089 $match = $consumed;
11093 if ($match !== null)
11095 $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
11096 $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
11098 break;
11104 * IRI parser/serialiser
11106 * @package SimplePie
11108 class SimplePie_IRI
11111 * Scheme
11113 * @access private
11114 * @var string
11116 var $scheme;
11119 * User Information
11121 * @access private
11122 * @var string
11124 var $userinfo;
11127 * Host
11129 * @access private
11130 * @var string
11132 var $host;
11135 * Port
11137 * @access private
11138 * @var string
11140 var $port;
11143 * Path
11145 * @access private
11146 * @var string
11148 var $path;
11151 * Query
11153 * @access private
11154 * @var string
11156 var $query;
11159 * Fragment
11161 * @access private
11162 * @var string
11164 var $fragment;
11167 * Whether the object represents a valid IRI
11169 * @access private
11170 * @var array
11172 var $valid = array();
11175 * Return the entire IRI when you try and read the object as a string
11177 * @access public
11178 * @return string
11180 public function __toString()
11182 return $this->get_iri();
11186 * Create a new IRI object, from a specified string
11188 * @access public
11189 * @param string $iri
11190 * @return SimplePie_IRI
11192 public function __construct($iri)
11194 $iri = (string) $iri;
11195 if ($iri !== '')
11197 $parsed = $this->parse_iri($iri);
11198 $this->set_scheme($parsed['scheme']);
11199 $this->set_authority($parsed['authority']);
11200 $this->set_path($parsed['path']);
11201 $this->set_query($parsed['query']);
11202 $this->set_fragment($parsed['fragment']);
11207 * Create a new IRI object by resolving a relative IRI
11209 * @static
11210 * @access public
11211 * @param SimplePie_IRI $base Base IRI
11212 * @param string $relative Relative IRI
11213 * @return SimplePie_IRI
11215 public static function absolutize($base, $relative)
11217 $relative = (string) $relative;
11218 if ($relative !== '')
11220 $relative = new SimplePie_IRI($relative);
11221 if ($relative->get_scheme() !== null)
11223 $target = $relative;
11225 elseif ($base->get_iri() !== null)
11227 if ($relative->get_authority() !== null)
11229 $target = $relative;
11230 $target->set_scheme($base->get_scheme());
11232 else
11234 $target = new SimplePie_IRI('');
11235 $target->set_scheme($base->get_scheme());
11236 $target->set_userinfo($base->get_userinfo());
11237 $target->set_host($base->get_host());
11238 $target->set_port($base->get_port());
11239 if ($relative->get_path() !== null)
11241 if (strpos($relative->get_path(), '/') === 0)
11243 $target->set_path($relative->get_path());
11245 elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
11247 $target->set_path('/' . $relative->get_path());
11249 elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
11251 $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
11253 else
11255 $target->set_path($relative->get_path());
11257 $target->set_query($relative->get_query());
11259 else
11261 $target->set_path($base->get_path());
11262 if ($relative->get_query() !== null)
11264 $target->set_query($relative->get_query());
11266 elseif ($base->get_query() !== null)
11268 $target->set_query($base->get_query());
11272 $target->set_fragment($relative->get_fragment());
11274 else
11276 // No base URL, just return the relative URL
11277 $target = $relative;
11280 else
11282 $target = $base;
11284 return $target;
11288 * Parse an IRI into scheme/authority/path/query/fragment segments
11290 * @access private
11291 * @param string $iri
11292 * @return array
11294 public function parse_iri($iri)
11296 preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
11297 for ($i = count($match); $i <= 9; $i++)
11299 $match[$i] = '';
11301 return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
11305 * Remove dot segments from a path
11307 * @access private
11308 * @param string $input
11309 * @return string
11311 public function remove_dot_segments($input)
11313 $output = '';
11314 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
11316 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
11317 if (strpos($input, '../') === 0)
11319 $input = substr($input, 3);
11321 elseif (strpos($input, './') === 0)
11323 $input = substr($input, 2);
11325 // 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,
11326 elseif (strpos($input, '/./') === 0)
11328 $input = substr_replace($input, '/', 0, 3);
11330 elseif ($input === '/.')
11332 $input = '/';
11334 // 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,
11335 elseif (strpos($input, '/../') === 0)
11337 $input = substr_replace($input, '/', 0, 4);
11338 $output = substr_replace($output, '', strrpos($output, '/'));
11340 elseif ($input === '/..')
11342 $input = '/';
11343 $output = substr_replace($output, '', strrpos($output, '/'));
11345 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
11346 elseif ($input === '.' || $input === '..')
11348 $input = '';
11350 // 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
11351 elseif (($pos = strpos($input, '/', 1)) !== false)
11353 $output .= substr($input, 0, $pos);
11354 $input = substr_replace($input, '', 0, $pos);
11356 else
11358 $output .= $input;
11359 $input = '';
11362 return $output . $input;
11366 * Replace invalid character with percent encoding
11368 * @access private
11369 * @param string $string Input string
11370 * @param string $valid_chars Valid characters
11371 * @param int $case Normalise case
11372 * @return string
11374 public function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
11376 // Normalise case
11377 if ($case & SIMPLEPIE_LOWERCASE)
11379 $string = strtolower($string);
11381 elseif ($case & SIMPLEPIE_UPPERCASE)
11383 $string = strtoupper($string);
11386 // Store position and string length (to avoid constantly recalculating this)
11387 $position = 0;
11388 $strlen = strlen($string);
11390 // Loop as long as we have invalid characters, advancing the position to the next invalid character
11391 while (($position += strspn($string, $valid_chars, $position)) < $strlen)
11393 // If we have a % character
11394 if ($string[$position] === '%')
11396 // If we have a pct-encoded section
11397 if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
11399 // Get the the represented character
11400 $chr = chr(hexdec(substr($string, $position + 1, 2)));
11402 // If the character is valid, replace the pct-encoded with the actual character while normalising case
11403 if (strpos($valid_chars, $chr) !== false)
11405 if ($case & SIMPLEPIE_LOWERCASE)
11407 $chr = strtolower($chr);
11409 elseif ($case & SIMPLEPIE_UPPERCASE)
11411 $chr = strtoupper($chr);
11413 $string = substr_replace($string, $chr, $position, 3);
11414 $strlen -= 2;
11415 $position++;
11418 // Otherwise just normalise the pct-encoded to uppercase
11419 else
11421 $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
11422 $position += 3;
11425 // If we don't have a pct-encoded section, just replace the % with its own esccaped form
11426 else
11428 $string = substr_replace($string, '%25', $position, 1);
11429 $strlen += 2;
11430 $position += 3;
11433 // If we have an invalid character, change into its pct-encoded form
11434 else
11436 $replacement = sprintf("%%%02X", ord($string[$position]));
11437 $string = str_replace($string[$position], $replacement, $string);
11438 $strlen = strlen($string);
11441 return $string;
11445 * Check if the object represents a valid IRI
11447 * @access public
11448 * @return bool
11450 public function is_valid()
11452 return array_sum($this->valid) === count($this->valid);
11456 * Set the scheme. Returns true on success, false on failure (if there are
11457 * any invalid characters).
11459 * @access public
11460 * @param string $scheme
11461 * @return bool
11463 public function set_scheme($scheme)
11465 if ($scheme === null || $scheme === '')
11467 $this->scheme = null;
11469 else
11471 $len = strlen($scheme);
11472 switch (true)
11474 case $len > 1:
11475 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
11477 $this->scheme = null;
11478 $this->valid[__FUNCTION__] = false;
11479 return false;
11482 case $len > 0:
11483 if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
11485 $this->scheme = null;
11486 $this->valid[__FUNCTION__] = false;
11487 return false;
11490 $this->scheme = strtolower($scheme);
11492 $this->valid[__FUNCTION__] = true;
11493 return true;
11497 * Set the authority. Returns true on success, false on failure (if there are
11498 * any invalid characters).
11500 * @access public
11501 * @param string $authority
11502 * @return bool
11504 public function set_authority($authority)
11506 if (($userinfo_end = strrpos($authority, '@')) !== false)
11508 $userinfo = substr($authority, 0, $userinfo_end);
11509 $authority = substr($authority, $userinfo_end + 1);
11511 else
11513 $userinfo = null;
11516 if (($port_start = strpos($authority, ':')) !== false)
11518 $port = substr($authority, $port_start + 1);
11519 $authority = substr($authority, 0, $port_start);
11521 else
11523 $port = null;
11526 return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
11530 * Set the userinfo.
11532 * @access public
11533 * @param string $userinfo
11534 * @return bool
11536 public function set_userinfo($userinfo)
11538 if ($userinfo === null || $userinfo === '')
11540 $this->userinfo = null;
11542 else
11544 $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
11546 $this->valid[__FUNCTION__] = true;
11547 return true;
11551 * Set the host. Returns true on success, false on failure (if there are
11552 * any invalid characters).
11554 * @access public
11555 * @param string $host
11556 * @return bool
11558 public function set_host($host)
11560 if ($host === null || $host === '')
11562 $this->host = null;
11563 $this->valid[__FUNCTION__] = true;
11564 return true;
11566 elseif ($host[0] === '[' && substr($host, -1) === ']')
11568 if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
11570 $this->host = $host;
11571 $this->valid[__FUNCTION__] = true;
11572 return true;
11574 else
11576 $this->host = null;
11577 $this->valid[__FUNCTION__] = false;
11578 return false;
11581 else
11583 $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
11584 $this->valid[__FUNCTION__] = true;
11585 return true;
11590 * Set the port. Returns true on success, false on failure (if there are
11591 * any invalid characters).
11593 * @access public
11594 * @param string $port
11595 * @return bool
11597 public function set_port($port)
11599 if ($port === null || $port === '')
11601 $this->port = null;
11602 $this->valid[__FUNCTION__] = true;
11603 return true;
11605 elseif (strspn($port, '0123456789') === strlen($port))
11607 $this->port = (int) $port;
11608 $this->valid[__FUNCTION__] = true;
11609 return true;
11611 else
11613 $this->port = null;
11614 $this->valid[__FUNCTION__] = false;
11615 return false;
11620 * Set the path.
11622 * @access public
11623 * @param string $path
11624 * @return bool
11626 public function set_path($path)
11628 if ($path === null || $path === '')
11630 $this->path = null;
11631 $this->valid[__FUNCTION__] = true;
11632 return true;
11634 elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
11636 $this->path = null;
11637 $this->valid[__FUNCTION__] = false;
11638 return false;
11640 else
11642 $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
11643 if ($this->scheme !== null)
11645 $this->path = $this->remove_dot_segments($this->path);
11647 $this->valid[__FUNCTION__] = true;
11648 return true;
11653 * Set the query.
11655 * @access public
11656 * @param string $query
11657 * @return bool
11659 public function set_query($query)
11661 if ($query === null || $query === '')
11663 $this->query = null;
11665 else
11667 $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
11669 $this->valid[__FUNCTION__] = true;
11670 return true;
11674 * Set the fragment.
11676 * @access public
11677 * @param string $fragment
11678 * @return bool
11680 public function set_fragment($fragment)
11682 if ($fragment === null || $fragment === '')
11684 $this->fragment = null;
11686 else
11688 $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
11690 $this->valid[__FUNCTION__] = true;
11691 return true;
11695 * Get the complete IRI
11697 * @access public
11698 * @return string
11700 public function get_iri()
11702 $iri = '';
11703 if ($this->scheme !== null)
11705 $iri .= $this->scheme . ':';
11707 if (($authority = $this->get_authority()) !== null)
11709 $iri .= '//' . $authority;
11711 if ($this->path !== null)
11713 $iri .= $this->path;
11715 if ($this->query !== null)
11717 $iri .= '?' . $this->query;
11719 if ($this->fragment !== null)
11721 $iri .= '#' . $this->fragment;
11724 if ($iri !== '')
11726 return $iri;
11728 else
11730 return null;
11735 * Get the scheme
11737 * @access public
11738 * @return string
11740 public function get_scheme()
11742 return $this->scheme;
11746 * Get the complete authority
11748 * @access public
11749 * @return string
11751 public function get_authority()
11753 $authority = '';
11754 if ($this->userinfo !== null)
11756 $authority .= $this->userinfo . '@';
11758 if ($this->host !== null)
11760 $authority .= $this->host;
11762 if ($this->port !== null)
11764 $authority .= ':' . $this->port;
11767 if ($authority !== '')
11769 return $authority;
11771 else
11773 return null;
11778 * Get the user information
11780 * @access public
11781 * @return string
11783 public function get_userinfo()
11785 return $this->userinfo;
11789 * Get the host
11791 * @access public
11792 * @return string
11794 public function get_host()
11796 return $this->host;
11800 * Get the port
11802 * @access public
11803 * @return string
11805 public function get_port()
11807 return $this->port;
11811 * Get the path
11813 * @access public
11814 * @return string
11816 public function get_path()
11818 return $this->path;
11822 * Get the query
11824 * @access public
11825 * @return string
11827 public function get_query()
11829 return $this->query;
11833 * Get the fragment
11835 * @access public
11836 * @return string
11838 public function get_fragment()
11840 return $this->fragment;
11845 * Class to validate and to work with IPv6 addresses.
11847 * @package SimplePie
11848 * @copyright 2003-2005 The PHP Group
11849 * @license http://www.opensource.org/licenses/bsd-license.php
11850 * @link http://pear.php.net/package/Net_IPv6
11851 * @author Alexander Merz <alexander.merz@web.de>
11852 * @author elfrink at introweb dot nl
11853 * @author Josh Peck <jmp at joshpeck dot org>
11854 * @author Geoffrey Sneddon <geoffers@gmail.com>
11856 class SimplePie_Net_IPv6
11859 * Removes a possible existing netmask specification of an IP address.
11861 * @param string $ip the (compressed) IP as Hex representation
11862 * @return string the IP the without netmask
11863 * @since 1.1.0
11864 * @access public
11865 * @static
11867 public static function removeNetmaskSpec($ip)
11869 if (strpos($ip, '/') !== false)
11871 list($addr, $nm) = explode('/', $ip);
11873 else
11875 $addr = $ip;
11877 return $addr;
11881 * Uncompresses an IPv6 address
11883 * RFC 2373 allows you to compress zeros in an address to '::'. This
11884 * function expects an valid IPv6 address and expands the '::' to
11885 * the required zeros.
11887 * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
11888 * ::1 -> 0:0:0:0:0:0:0:1
11890 * @access public
11891 * @static
11892 * @param string $ip a valid IPv6-address (hex format)
11893 * @return string the uncompressed IPv6-address (hex format)
11895 public static function Uncompress($ip)
11897 $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
11898 $c1 = -1;
11899 $c2 = -1;
11900 if (strpos($ip, '::') !== false)
11902 list($ip1, $ip2) = explode('::', $ip);
11903 if ($ip1 === '')
11905 $c1 = -1;
11907 else
11909 $pos = 0;
11910 if (($pos = substr_count($ip1, ':')) > 0)
11912 $c1 = $pos;
11914 else
11916 $c1 = 0;
11919 if ($ip2 === '')
11921 $c2 = -1;
11923 else
11925 $pos = 0;
11926 if (($pos = substr_count($ip2, ':')) > 0)
11928 $c2 = $pos;
11930 else
11932 $c2 = 0;
11935 if (strstr($ip2, '.'))
11937 $c2++;
11939 // ::
11940 if ($c1 === -1 && $c2 === -1)
11942 $uip = '0:0:0:0:0:0:0:0';
11944 // ::xxx
11945 else if ($c1 === -1)
11947 $fill = str_repeat('0:', 7 - $c2);
11948 $uip = str_replace('::', $fill, $uip);
11950 // xxx::
11951 else if ($c2 === -1)
11953 $fill = str_repeat(':0', 7 - $c1);
11954 $uip = str_replace('::', $fill, $uip);
11956 // xxx::xxx
11957 else
11959 $fill = str_repeat(':0:', 6 - $c2 - $c1);
11960 $uip = str_replace('::', $fill, $uip);
11961 $uip = str_replace('::', ':', $uip);
11964 return $uip;
11968 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
11970 * RFC 2373 allows you to note the last two parts of an IPv6 address as
11971 * an IPv4 compatible address
11973 * Example: 0:0:0:0:0:0:13.1.68.3
11974 * 0:0:0:0:0:FFFF:129.144.52.38
11976 * @access public
11977 * @static
11978 * @param string $ip a valid IPv6-address (hex format)
11979 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
11981 public static function SplitV64($ip)
11983 $ip = SimplePie_Net_IPv6::Uncompress($ip);
11984 if (strstr($ip, '.'))
11986 $pos = strrpos($ip, ':');
11987 $ip[$pos] = '_';
11988 $ipPart = explode('_', $ip);
11989 return $ipPart;
11991 else
11993 return array($ip, '');
11998 * Checks an IPv6 address
12000 * Checks if the given IP is IPv6-compatible
12002 * @access public
12003 * @static
12004 * @param string $ip a valid IPv6-address
12005 * @return bool true if $ip is an IPv6 address
12007 public static function checkIPv6($ip)
12009 $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
12010 $count = 0;
12011 if (!empty($ipPart[0]))
12013 $ipv6 = explode(':', $ipPart[0]);
12014 for ($i = 0; $i < count($ipv6); $i++)
12016 $dec = hexdec($ipv6[$i]);
12017 $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
12018 if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
12020 $count++;
12023 if ($count === 8)
12025 return true;
12027 elseif ($count === 6 && !empty($ipPart[1]))
12029 $ipv4 = explode('.', $ipPart[1]);
12030 $count = 0;
12031 foreach ($ipv4 as $ipv4_part)
12033 if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
12035 $count++;
12038 if ($count === 4)
12040 return true;
12043 else
12045 return false;
12049 else
12051 return false;
12057 * Date Parser
12059 * @package SimplePie
12061 class SimplePie_Parse_Date
12064 * Input data
12066 * @access protected
12067 * @var string
12069 var $date;
12072 * List of days, calendar day name => ordinal day number in the week
12074 * @access protected
12075 * @var array
12077 var $day = array(
12078 // English
12079 'mon' => 1,
12080 'monday' => 1,
12081 'tue' => 2,
12082 'tuesday' => 2,
12083 'wed' => 3,
12084 'wednesday' => 3,
12085 'thu' => 4,
12086 'thursday' => 4,
12087 'fri' => 5,
12088 'friday' => 5,
12089 'sat' => 6,
12090 'saturday' => 6,
12091 'sun' => 7,
12092 'sunday' => 7,
12093 // Dutch
12094 'maandag' => 1,
12095 'dinsdag' => 2,
12096 'woensdag' => 3,
12097 'donderdag' => 4,
12098 'vrijdag' => 5,
12099 'zaterdag' => 6,
12100 'zondag' => 7,
12101 // French
12102 'lundi' => 1,
12103 'mardi' => 2,
12104 'mercredi' => 3,
12105 'jeudi' => 4,
12106 'vendredi' => 5,
12107 'samedi' => 6,
12108 'dimanche' => 7,
12109 // German
12110 'montag' => 1,
12111 'dienstag' => 2,
12112 'mittwoch' => 3,
12113 'donnerstag' => 4,
12114 'freitag' => 5,
12115 'samstag' => 6,
12116 'sonnabend' => 6,
12117 'sonntag' => 7,
12118 // Italian
12119 'lunedì' => 1,
12120 'martedì' => 2,
12121 'mercoledì' => 3,
12122 'giovedì' => 4,
12123 'venerdì' => 5,
12124 'sabato' => 6,
12125 'domenica' => 7,
12126 // Spanish
12127 'lunes' => 1,
12128 'martes' => 2,
12129 'miércoles' => 3,
12130 'jueves' => 4,
12131 'viernes' => 5,
12132 'sábado' => 6,
12133 'domingo' => 7,
12134 // Finnish
12135 'maanantai' => 1,
12136 'tiistai' => 2,
12137 'keskiviikko' => 3,
12138 'torstai' => 4,
12139 'perjantai' => 5,
12140 'lauantai' => 6,
12141 'sunnuntai' => 7,
12142 // Hungarian
12143 'hétfő' => 1,
12144 'kedd' => 2,
12145 'szerda' => 3,
12146 'csütörtok' => 4,
12147 'péntek' => 5,
12148 'szombat' => 6,
12149 'vasárnap' => 7,
12150 // Greek
12151 'Δευ' => 1,
12152 'Τρι' => 2,
12153 'Τετ' => 3,
12154 'Πεμ' => 4,
12155 'Παρ' => 5,
12156 'Σαβ' => 6,
12157 'Κυρ' => 7,
12161 * List of months, calendar month name => calendar month number
12163 * @access protected
12164 * @var array
12166 var $month = array(
12167 // English
12168 'jan' => 1,
12169 'january' => 1,
12170 'feb' => 2,
12171 'february' => 2,
12172 'mar' => 3,
12173 'march' => 3,
12174 'apr' => 4,
12175 'april' => 4,
12176 'may' => 5,
12177 // No long form of May
12178 'jun' => 6,
12179 'june' => 6,
12180 'jul' => 7,
12181 'july' => 7,
12182 'aug' => 8,
12183 'august' => 8,
12184 'sep' => 9,
12185 'september' => 8,
12186 'oct' => 10,
12187 'october' => 10,
12188 'nov' => 11,
12189 'november' => 11,
12190 'dec' => 12,
12191 'december' => 12,
12192 // Dutch
12193 'januari' => 1,
12194 'februari' => 2,
12195 'maart' => 3,
12196 'april' => 4,
12197 'mei' => 5,
12198 'juni' => 6,
12199 'juli' => 7,
12200 'augustus' => 8,
12201 'september' => 9,
12202 'oktober' => 10,
12203 'november' => 11,
12204 'december' => 12,
12205 // French
12206 'janvier' => 1,
12207 'février' => 2,
12208 'mars' => 3,
12209 'avril' => 4,
12210 'mai' => 5,
12211 'juin' => 6,
12212 'juillet' => 7,
12213 'août' => 8,
12214 'septembre' => 9,
12215 'octobre' => 10,
12216 'novembre' => 11,
12217 'décembre' => 12,
12218 // German
12219 'januar' => 1,
12220 'februar' => 2,
12221 'märz' => 3,
12222 'april' => 4,
12223 'mai' => 5,
12224 'juni' => 6,
12225 'juli' => 7,
12226 'august' => 8,
12227 'september' => 9,
12228 'oktober' => 10,
12229 'november' => 11,
12230 'dezember' => 12,
12231 // Italian
12232 'gennaio' => 1,
12233 'febbraio' => 2,
12234 'marzo' => 3,
12235 'aprile' => 4,
12236 'maggio' => 5,
12237 'giugno' => 6,
12238 'luglio' => 7,
12239 'agosto' => 8,
12240 'settembre' => 9,
12241 'ottobre' => 10,
12242 'novembre' => 11,
12243 'dicembre' => 12,
12244 // Spanish
12245 'enero' => 1,
12246 'febrero' => 2,
12247 'marzo' => 3,
12248 'abril' => 4,
12249 'mayo' => 5,
12250 'junio' => 6,
12251 'julio' => 7,
12252 'agosto' => 8,
12253 'septiembre' => 9,
12254 'setiembre' => 9,
12255 'octubre' => 10,
12256 'noviembre' => 11,
12257 'diciembre' => 12,
12258 // Finnish
12259 'tammikuu' => 1,
12260 'helmikuu' => 2,
12261 'maaliskuu' => 3,
12262 'huhtikuu' => 4,
12263 'toukokuu' => 5,
12264 'kesäkuu' => 6,
12265 'heinäkuu' => 7,
12266 'elokuu' => 8,
12267 'suuskuu' => 9,
12268 'lokakuu' => 10,
12269 'marras' => 11,
12270 'joulukuu' => 12,
12271 // Hungarian
12272 'január' => 1,
12273 'február' => 2,
12274 'március' => 3,
12275 'április' => 4,
12276 'május' => 5,
12277 'június' => 6,
12278 'július' => 7,
12279 'augusztus' => 8,
12280 'szeptember' => 9,
12281 'október' => 10,
12282 'november' => 11,
12283 'december' => 12,
12284 // Greek
12285 'Ιαν' => 1,
12286 'Φεβ' => 2,
12287 'Μάώ' => 3,
12288 'Μαώ' => 3,
12289 'Απρ' => 4,
12290 'Μάι' => 5,
12291 'Μαϊ' => 5,
12292 'Μαι' => 5,
12293 'Ιούν' => 6,
12294 'Ιον' => 6,
12295 'Ιούλ' => 7,
12296 'Ιολ' => 7,
12297 'Αύγ' => 8,
12298 'Αυγ' => 8,
12299 'Σεπ' => 9,
12300 'Οκτ' => 10,
12301 'Νοέ' => 11,
12302 'Δεκ' => 12,
12306 * List of timezones, abbreviation => offset from UTC
12308 * @access protected
12309 * @var array
12311 var $timezone = array(
12312 'ACDT' => 37800,
12313 'ACIT' => 28800,
12314 'ACST' => 34200,
12315 'ACT' => -18000,
12316 'ACWDT' => 35100,
12317 'ACWST' => 31500,
12318 'AEDT' => 39600,
12319 'AEST' => 36000,
12320 'AFT' => 16200,
12321 'AKDT' => -28800,
12322 'AKST' => -32400,
12323 'AMDT' => 18000,
12324 'AMT' => -14400,
12325 'ANAST' => 46800,
12326 'ANAT' => 43200,
12327 'ART' => -10800,
12328 'AZOST' => -3600,
12329 'AZST' => 18000,
12330 'AZT' => 14400,
12331 'BIOT' => 21600,
12332 'BIT' => -43200,
12333 'BOT' => -14400,
12334 'BRST' => -7200,
12335 'BRT' => -10800,
12336 'BST' => 3600,
12337 'BTT' => 21600,
12338 'CAST' => 18000,
12339 'CAT' => 7200,
12340 'CCT' => 23400,
12341 'CDT' => -18000,
12342 'CEDT' => 7200,
12343 'CET' => 3600,
12344 'CGST' => -7200,
12345 'CGT' => -10800,
12346 'CHADT' => 49500,
12347 'CHAST' => 45900,
12348 'CIST' => -28800,
12349 'CKT' => -36000,
12350 'CLDT' => -10800,
12351 'CLST' => -14400,
12352 'COT' => -18000,
12353 'CST' => -21600,
12354 'CVT' => -3600,
12355 'CXT' => 25200,
12356 'DAVT' => 25200,
12357 'DTAT' => 36000,
12358 'EADT' => -18000,
12359 'EAST' => -21600,
12360 'EAT' => 10800,
12361 'ECT' => -18000,
12362 'EDT' => -14400,
12363 'EEST' => 10800,
12364 'EET' => 7200,
12365 'EGT' => -3600,
12366 'EKST' => 21600,
12367 'EST' => -18000,
12368 'FJT' => 43200,
12369 'FKDT' => -10800,
12370 'FKST' => -14400,
12371 'FNT' => -7200,
12372 'GALT' => -21600,
12373 'GEDT' => 14400,
12374 'GEST' => 10800,
12375 'GFT' => -10800,
12376 'GILT' => 43200,
12377 'GIT' => -32400,
12378 'GST' => 14400,
12379 'GST' => -7200,
12380 'GYT' => -14400,
12381 'HAA' => -10800,
12382 'HAC' => -18000,
12383 'HADT' => -32400,
12384 'HAE' => -14400,
12385 'HAP' => -25200,
12386 'HAR' => -21600,
12387 'HAST' => -36000,
12388 'HAT' => -9000,
12389 'HAY' => -28800,
12390 'HKST' => 28800,
12391 'HMT' => 18000,
12392 'HNA' => -14400,
12393 'HNC' => -21600,
12394 'HNE' => -18000,
12395 'HNP' => -28800,
12396 'HNR' => -25200,
12397 'HNT' => -12600,
12398 'HNY' => -32400,
12399 'IRDT' => 16200,
12400 'IRKST' => 32400,
12401 'IRKT' => 28800,
12402 'IRST' => 12600,
12403 'JFDT' => -10800,
12404 'JFST' => -14400,
12405 'JST' => 32400,
12406 'KGST' => 21600,
12407 'KGT' => 18000,
12408 'KOST' => 39600,
12409 'KOVST' => 28800,
12410 'KOVT' => 25200,
12411 'KRAST' => 28800,
12412 'KRAT' => 25200,
12413 'KST' => 32400,
12414 'LHDT' => 39600,
12415 'LHST' => 37800,
12416 'LINT' => 50400,
12417 'LKT' => 21600,
12418 'MAGST' => 43200,
12419 'MAGT' => 39600,
12420 'MAWT' => 21600,
12421 'MDT' => -21600,
12422 'MESZ' => 7200,
12423 'MEZ' => 3600,
12424 'MHT' => 43200,
12425 'MIT' => -34200,
12426 'MNST' => 32400,
12427 'MSDT' => 14400,
12428 'MSST' => 10800,
12429 'MST' => -25200,
12430 'MUT' => 14400,
12431 'MVT' => 18000,
12432 'MYT' => 28800,
12433 'NCT' => 39600,
12434 'NDT' => -9000,
12435 'NFT' => 41400,
12436 'NMIT' => 36000,
12437 'NOVST' => 25200,
12438 'NOVT' => 21600,
12439 'NPT' => 20700,
12440 'NRT' => 43200,
12441 'NST' => -12600,
12442 'NUT' => -39600,
12443 'NZDT' => 46800,
12444 'NZST' => 43200,
12445 'OMSST' => 25200,
12446 'OMST' => 21600,
12447 'PDT' => -25200,
12448 'PET' => -18000,
12449 'PETST' => 46800,
12450 'PETT' => 43200,
12451 'PGT' => 36000,
12452 'PHOT' => 46800,
12453 'PHT' => 28800,
12454 'PKT' => 18000,
12455 'PMDT' => -7200,
12456 'PMST' => -10800,
12457 'PONT' => 39600,
12458 'PST' => -28800,
12459 'PWT' => 32400,
12460 'PYST' => -10800,
12461 'PYT' => -14400,
12462 'RET' => 14400,
12463 'ROTT' => -10800,
12464 'SAMST' => 18000,
12465 'SAMT' => 14400,
12466 'SAST' => 7200,
12467 'SBT' => 39600,
12468 'SCDT' => 46800,
12469 'SCST' => 43200,
12470 'SCT' => 14400,
12471 'SEST' => 3600,
12472 'SGT' => 28800,
12473 'SIT' => 28800,
12474 'SRT' => -10800,
12475 'SST' => -39600,
12476 'SYST' => 10800,
12477 'SYT' => 7200,
12478 'TFT' => 18000,
12479 'THAT' => -36000,
12480 'TJT' => 18000,
12481 'TKT' => -36000,
12482 'TMT' => 18000,
12483 'TOT' => 46800,
12484 'TPT' => 32400,
12485 'TRUT' => 36000,
12486 'TVT' => 43200,
12487 'TWT' => 28800,
12488 'UYST' => -7200,
12489 'UYT' => -10800,
12490 'UZT' => 18000,
12491 'VET' => -14400,
12492 'VLAST' => 39600,
12493 'VLAT' => 36000,
12494 'VOST' => 21600,
12495 'VUT' => 39600,
12496 'WAST' => 7200,
12497 'WAT' => 3600,
12498 'WDT' => 32400,
12499 'WEST' => 3600,
12500 'WFT' => 43200,
12501 'WIB' => 25200,
12502 'WIT' => 32400,
12503 'WITA' => 28800,
12504 'WKST' => 18000,
12505 'WST' => 28800,
12506 'YAKST' => 36000,
12507 'YAKT' => 32400,
12508 'YAPT' => 36000,
12509 'YEKST' => 21600,
12510 'YEKT' => 18000,
12514 * Cached PCRE for SimplePie_Parse_Date::$day
12516 * @access protected
12517 * @var string
12519 var $day_pcre;
12522 * Cached PCRE for SimplePie_Parse_Date::$month
12524 * @access protected
12525 * @var string
12527 var $month_pcre;
12530 * Array of user-added callback methods
12532 * @access private
12533 * @var array
12535 var $built_in = array();
12538 * Array of user-added callback methods
12540 * @access private
12541 * @var array
12543 var $user = array();
12546 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
12547 * self::month_pcre, and self::built_in
12549 * @access private
12551 public function __construct()
12553 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
12554 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
12556 static $cache;
12557 if (!isset($cache[get_class($this)]))
12559 $all_methods = get_class_methods($this);
12561 foreach ($all_methods as $method)
12563 if (strtolower(substr($method, 0, 5)) === 'date_')
12565 $cache[get_class($this)][] = $method;
12570 foreach ($cache[get_class($this)] as $method)
12572 $this->built_in[] = $method;
12577 * Get the object
12579 * @access public
12581 public static function get()
12583 static $object;
12584 if (!$object)
12586 $object = new SimplePie_Parse_Date;
12588 return $object;
12592 * Parse a date
12594 * @final
12595 * @access public
12596 * @param string $date Date to parse
12597 * @return int Timestamp corresponding to date string, or false on failure
12599 public function parse($date)
12601 foreach ($this->user as $method)
12603 if (($returned = call_user_func($method, $date)) !== false)
12605 return $returned;
12609 foreach ($this->built_in as $method)
12611 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
12613 return $returned;
12617 return false;
12621 * Add a callback method to parse a date
12623 * @final
12624 * @access public
12625 * @param callback $callback
12627 public function add_callback($callback)
12629 if (is_callable($callback))
12631 $this->user[] = $callback;
12633 else
12635 trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
12640 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
12641 * well as allowing any of upper or lower case "T", horizontal tabs, or
12642 * spaces to be used as the time seperator (including more than one))
12644 * @access protected
12645 * @return int Timestamp
12647 public function date_w3cdtf($date)
12649 static $pcre;
12650 if (!$pcre)
12652 $year = '([0-9]{4})';
12653 $month = $day = $hour = $minute = $second = '([0-9]{2})';
12654 $decimal = '([0-9]*)';
12655 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
12656 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
12658 if (preg_match($pcre, $date, $match))
12661 Capturing subpatterns:
12662 1: Year
12663 2: Month
12664 3: Day
12665 4: Hour
12666 5: Minute
12667 6: Second
12668 7: Decimal fraction of a second
12669 8: Zulu
12670 9: Timezone ±
12671 10: Timezone hours
12672 11: Timezone minutes
12675 // Fill in empty matches
12676 for ($i = count($match); $i <= 3; $i++)
12678 $match[$i] = '1';
12681 for ($i = count($match); $i <= 7; $i++)
12683 $match[$i] = '0';
12686 // Numeric timezone
12687 if (isset($match[9]) && $match[9] !== '')
12689 $timezone = $match[10] * 3600;
12690 $timezone += $match[11] * 60;
12691 if ($match[9] === '-')
12693 $timezone = 0 - $timezone;
12696 else
12698 $timezone = 0;
12701 // Convert the number of seconds to an integer, taking decimals into account
12702 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
12704 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
12706 else
12708 return false;
12713 * Remove RFC822 comments
12715 * @access protected
12716 * @param string $data Data to strip comments from
12717 * @return string Comment stripped string
12719 public function remove_rfc2822_comments($string)
12721 $string = (string) $string;
12722 $position = 0;
12723 $length = strlen($string);
12724 $depth = 0;
12726 $output = '';
12728 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
12730 $output .= substr($string, $position, $pos - $position);
12731 $position = $pos + 1;
12732 if ($string[$pos - 1] !== '\\')
12734 $depth++;
12735 while ($depth && $position < $length)
12737 $position += strcspn($string, '()', $position);
12738 if ($string[$position - 1] === '\\')
12740 $position++;
12741 continue;
12743 elseif (isset($string[$position]))
12745 switch ($string[$position])
12747 case '(':
12748 $depth++;
12749 break;
12751 case ')':
12752 $depth--;
12753 break;
12755 $position++;
12757 else
12759 break;
12763 else
12765 $output .= '(';
12768 $output .= substr($string, $position);
12770 return $output;
12774 * Parse RFC2822's date format
12776 * @access protected
12777 * @return int Timestamp
12779 public function date_rfc2822($date)
12781 static $pcre;
12782 if (!$pcre)
12784 $wsp = '[\x09\x20]';
12785 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
12786 $optional_fws = $fws . '?';
12787 $day_name = $this->day_pcre;
12788 $month = $this->month_pcre;
12789 $day = '([0-9]{1,2})';
12790 $hour = $minute = $second = '([0-9]{2})';
12791 $year = '([0-9]{2,4})';
12792 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
12793 $character_zone = '([A-Z]{1,5})';
12794 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
12795 $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';
12797 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
12800 Capturing subpatterns:
12801 1: Day name
12802 2: Day
12803 3: Month
12804 4: Year
12805 5: Hour
12806 6: Minute
12807 7: Second
12808 8: Timezone ±
12809 9: Timezone hours
12810 10: Timezone minutes
12811 11: Alphabetic timezone
12814 // Find the month number
12815 $month = $this->month[strtolower($match[3])];
12817 // Numeric timezone
12818 if ($match[8] !== '')
12820 $timezone = $match[9] * 3600;
12821 $timezone += $match[10] * 60;
12822 if ($match[8] === '-')
12824 $timezone = 0 - $timezone;
12827 // Character timezone
12828 elseif (isset($this->timezone[strtoupper($match[11])]))
12830 $timezone = $this->timezone[strtoupper($match[11])];
12832 // Assume everything else to be -0000
12833 else
12835 $timezone = 0;
12838 // Deal with 2/3 digit years
12839 if ($match[4] < 50)
12841 $match[4] += 2000;
12843 elseif ($match[4] < 1000)
12845 $match[4] += 1900;
12848 // Second is optional, if it is empty set it to zero
12849 if ($match[7] !== '')
12851 $second = $match[7];
12853 else
12855 $second = 0;
12858 return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
12860 else
12862 return false;
12867 * Parse RFC850's date format
12869 * @access protected
12870 * @return int Timestamp
12872 public function date_rfc850($date)
12874 static $pcre;
12875 if (!$pcre)
12877 $space = '[\x09\x20]+';
12878 $day_name = $this->day_pcre;
12879 $month = $this->month_pcre;
12880 $day = '([0-9]{1,2})';
12881 $year = $hour = $minute = $second = '([0-9]{2})';
12882 $zone = '([A-Z]{1,5})';
12883 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
12885 if (preg_match($pcre, $date, $match))
12888 Capturing subpatterns:
12889 1: Day name
12890 2: Day
12891 3: Month
12892 4: Year
12893 5: Hour
12894 6: Minute
12895 7: Second
12896 8: Timezone
12899 // Month
12900 $month = $this->month[strtolower($match[3])];
12902 // Character timezone
12903 if (isset($this->timezone[strtoupper($match[8])]))
12905 $timezone = $this->timezone[strtoupper($match[8])];
12907 // Assume everything else to be -0000
12908 else
12910 $timezone = 0;
12913 // Deal with 2 digit year
12914 if ($match[4] < 50)
12916 $match[4] += 2000;
12918 else
12920 $match[4] += 1900;
12923 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
12925 else
12927 return false;
12932 * Parse C99's asctime()'s date format
12934 * @access protected
12935 * @return int Timestamp
12937 public function date_asctime($date)
12939 static $pcre;
12940 if (!$pcre)
12942 $space = '[\x09\x20]+';
12943 $wday_name = $this->day_pcre;
12944 $mon_name = $this->month_pcre;
12945 $day = '([0-9]{1,2})';
12946 $hour = $sec = $min = '([0-9]{2})';
12947 $year = '([0-9]{4})';
12948 $terminator = '\x0A?\x00?';
12949 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
12951 if (preg_match($pcre, $date, $match))
12954 Capturing subpatterns:
12955 1: Day name
12956 2: Month
12957 3: Day
12958 4: Hour
12959 5: Minute
12960 6: Second
12961 7: Year
12964 $month = $this->month[strtolower($match[2])];
12965 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
12967 else
12969 return false;
12974 * Parse dates using strtotime()
12976 * @access protected
12977 * @return int Timestamp
12979 public function date_strtotime($date)
12981 $strtotime = strtotime($date);
12982 if ($strtotime === -1 || $strtotime === false)
12984 return false;
12986 else
12988 return $strtotime;
12994 * Content-type sniffing
12996 * @package SimplePie
12998 class SimplePie_Content_Type_Sniffer
13001 * File object
13003 * @var SimplePie_File
13004 * @access private
13006 var $file;
13009 * Create an instance of the class with the input file
13011 * @access public
13012 * @param SimplePie_Content_Type_Sniffer $file Input file
13014 public function __construct($file)
13016 $this->file = $file;
13020 * Get the Content-Type of the specified file
13022 * @access public
13023 * @return string Actual Content-Type
13025 public function get_type()
13027 if (isset($this->file->headers['content-type']))
13029 if (!isset($this->file->headers['content-encoding'])
13030 && ($this->file->headers['content-type'] === 'text/plain'
13031 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
13032 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
13034 return $this->text_or_binary();
13037 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
13039 $official = substr($this->file->headers['content-type'], 0, $pos);
13041 else
13043 $official = $this->file->headers['content-type'];
13045 $official = strtolower($official);
13047 if ($official === 'unknown/unknown'
13048 || $official === 'application/unknown')
13050 return $this->unknown();
13052 elseif (substr($official, -4) === '+xml'
13053 || $official === 'text/xml'
13054 || $official === 'application/xml')
13056 return $official;
13058 elseif (substr($official, 0, 6) === 'image/')
13060 if ($return = $this->image())
13062 return $return;
13064 else
13066 return $official;
13069 elseif ($official === 'text/html')
13071 return $this->feed_or_html();
13073 else
13075 return $official;
13078 else
13080 return $this->unknown();
13085 * Sniff text or binary
13087 * @access private
13088 * @return string Actual Content-Type
13090 public function text_or_binary()
13092 if (substr($this->file->body, 0, 2) === "\xFE\xFF"
13093 || substr($this->file->body, 0, 2) === "\xFF\xFE"
13094 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
13095 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
13097 return 'text/plain';
13099 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
13101 return 'application/octect-stream';
13103 else
13105 return 'text/plain';
13110 * Sniff unknown
13112 * @access private
13113 * @return string Actual Content-Type
13115 public function unknown()
13117 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
13118 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
13119 || strtolower(substr($this->file->body, $ws, 5)) === '<html'
13120 || strtolower(substr($this->file->body, $ws, 7)) === '<script')
13122 return 'text/html';
13124 elseif (substr($this->file->body, 0, 5) === '%PDF-')
13126 return 'application/pdf';
13128 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
13130 return 'application/postscript';
13132 elseif (substr($this->file->body, 0, 6) === 'GIF87a'
13133 || substr($this->file->body, 0, 6) === 'GIF89a')
13135 return 'image/gif';
13137 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13139 return 'image/png';
13141 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13143 return 'image/jpeg';
13145 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13147 return 'image/bmp';
13149 else
13151 return $this->text_or_binary();
13156 * Sniff images
13158 * @access private
13159 * @return string Actual Content-Type
13161 public function image()
13163 if (substr($this->file->body, 0, 6) === 'GIF87a'
13164 || substr($this->file->body, 0, 6) === 'GIF89a')
13166 return 'image/gif';
13168 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
13170 return 'image/png';
13172 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
13174 return 'image/jpeg';
13176 elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
13178 return 'image/bmp';
13180 else
13182 return false;
13187 * Sniff HTML
13189 * @access private
13190 * @return string Actual Content-Type
13192 public function feed_or_html()
13194 $len = strlen($this->file->body);
13195 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
13197 while ($pos < $len)
13199 switch ($this->file->body[$pos])
13201 case "\x09":
13202 case "\x0A":
13203 case "\x0D":
13204 case "\x20":
13205 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
13206 continue 2;
13208 case '<':
13209 $pos++;
13210 break;
13212 default:
13213 return 'text/html';
13216 if (substr($this->file->body, $pos, 3) === '!--')
13218 $pos += 3;
13219 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
13221 $pos += 3;
13223 else
13225 return 'text/html';
13228 elseif (substr($this->file->body, $pos, 1) === '!')
13230 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
13232 $pos++;
13234 else
13236 return 'text/html';
13239 elseif (substr($this->file->body, $pos, 1) === '?')
13241 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
13243 $pos += 2;
13245 else
13247 return 'text/html';
13250 elseif (substr($this->file->body, $pos, 3) === 'rss'
13251 || substr($this->file->body, $pos, 7) === 'rdf:RDF')
13253 return 'application/rss+xml';
13255 elseif (substr($this->file->body, $pos, 4) === 'feed')
13257 return 'application/atom+xml';
13259 else
13261 return 'text/html';
13265 return 'text/html';
13270 * Parses the XML Declaration
13272 * @package SimplePie
13274 class SimplePie_XML_Declaration_Parser
13277 * XML Version
13279 * @access public
13280 * @var string
13282 var $version = '1.0';
13285 * Encoding
13287 * @access public
13288 * @var string
13290 var $encoding = 'UTF-8';
13293 * Standalone
13295 * @access public
13296 * @var bool
13298 var $standalone = false;
13301 * Current state of the state machine
13303 * @access private
13304 * @var string
13306 var $state = 'before_version_name';
13309 * Input data
13311 * @access private
13312 * @var string
13314 var $data = '';
13317 * Input data length (to avoid calling strlen() everytime this is needed)
13319 * @access private
13320 * @var int
13322 var $data_length = 0;
13325 * Current position of the pointer
13327 * @var int
13328 * @access private
13330 var $position = 0;
13333 * Create an instance of the class with the input data
13335 * @access public
13336 * @param string $data Input data
13338 public function __construct($data)
13340 $this->data = $data;
13341 $this->data_length = strlen($this->data);
13345 * Parse the input data
13347 * @access public
13348 * @return bool true on success, false on failure
13350 public function parse()
13352 while ($this->state && $this->state !== 'emit' && $this->has_data())
13354 $state = $this->state;
13355 $this->$state();
13357 $this->data = '';
13358 if ($this->state === 'emit')
13360 return true;
13362 else
13364 $this->version = '';
13365 $this->encoding = '';
13366 $this->standalone = '';
13367 return false;
13372 * Check whether there is data beyond the pointer
13374 * @access private
13375 * @return bool true if there is further data, false if not
13377 public function has_data()
13379 return (bool) ($this->position < $this->data_length);
13383 * Advance past any whitespace
13385 * @return int Number of whitespace characters passed
13387 public function skip_whitespace()
13389 $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
13390 $this->position += $whitespace;
13391 return $whitespace;
13395 * Read value
13397 public function get_value()
13399 $quote = substr($this->data, $this->position, 1);
13400 if ($quote === '"' || $quote === "'")
13402 $this->position++;
13403 $len = strcspn($this->data, $quote, $this->position);
13404 if ($this->has_data())
13406 $value = substr($this->data, $this->position, $len);
13407 $this->position += $len + 1;
13408 return $value;
13411 return false;
13414 public function before_version_name()
13416 if ($this->skip_whitespace())
13418 $this->state = 'version_name';
13420 else
13422 $this->state = false;
13426 public function version_name()
13428 if (substr($this->data, $this->position, 7) === 'version')
13430 $this->position += 7;
13431 $this->skip_whitespace();
13432 $this->state = 'version_equals';
13434 else
13436 $this->state = false;
13440 public function version_equals()
13442 if (substr($this->data, $this->position, 1) === '=')
13444 $this->position++;
13445 $this->skip_whitespace();
13446 $this->state = 'version_value';
13448 else
13450 $this->state = false;
13454 public function version_value()
13456 if ($this->version = $this->get_value())
13458 $this->skip_whitespace();
13459 if ($this->has_data())
13461 $this->state = 'encoding_name';
13463 else
13465 $this->state = 'emit';
13468 else
13470 $this->state = false;
13474 public function encoding_name()
13476 if (substr($this->data, $this->position, 8) === 'encoding')
13478 $this->position += 8;
13479 $this->skip_whitespace();
13480 $this->state = 'encoding_equals';
13482 else
13484 $this->state = 'standalone_name';
13488 public function encoding_equals()
13490 if (substr($this->data, $this->position, 1) === '=')
13492 $this->position++;
13493 $this->skip_whitespace();
13494 $this->state = 'encoding_value';
13496 else
13498 $this->state = false;
13502 public function encoding_value()
13504 if ($this->encoding = $this->get_value())
13506 $this->skip_whitespace();
13507 if ($this->has_data())
13509 $this->state = 'standalone_name';
13511 else
13513 $this->state = 'emit';
13516 else
13518 $this->state = false;
13522 public function standalone_name()
13524 if (substr($this->data, $this->position, 10) === 'standalone')
13526 $this->position += 10;
13527 $this->skip_whitespace();
13528 $this->state = 'standalone_equals';
13530 else
13532 $this->state = false;
13536 public function standalone_equals()
13538 if (substr($this->data, $this->position, 1) === '=')
13540 $this->position++;
13541 $this->skip_whitespace();
13542 $this->state = 'standalone_value';
13544 else
13546 $this->state = false;
13550 public function standalone_value()
13552 if ($standalone = $this->get_value())
13554 switch ($standalone)
13556 case 'yes':
13557 $this->standalone = true;
13558 break;
13560 case 'no':
13561 $this->standalone = false;
13562 break;
13564 default:
13565 $this->state = false;
13566 return;
13569 $this->skip_whitespace();
13570 if ($this->has_data())
13572 $this->state = false;
13574 else
13576 $this->state = 'emit';
13579 else
13581 $this->state = false;
13586 class SimplePie_Locator
13588 var $useragent;
13589 var $timeout;
13590 var $file;
13591 var $local = array();
13592 var $elsewhere = array();
13593 var $file_class = 'SimplePie_File';
13594 var $cached_entities = array();
13595 var $http_base;
13596 var $base;
13597 var $base_location = 0;
13598 var $checked_feeds = 0;
13599 var $max_checked_feeds = 10;
13600 var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
13602 public function __construct(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
13604 $this->file =& $file;
13605 $this->file_class = $file_class;
13606 $this->useragent = $useragent;
13607 $this->timeout = $timeout;
13608 $this->max_checked_feeds = $max_checked_feeds;
13609 $this->content_type_sniffer_class = $content_type_sniffer_class;
13612 public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
13614 if ($this->is_feed($this->file))
13616 return $this->file;
13619 if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
13621 $sniffer = new $this->content_type_sniffer_class($this->file);
13622 if ($sniffer->get_type() !== 'text/html')
13624 return null;
13628 if ($type & ~SIMPLEPIE_LOCATOR_NONE)
13630 $this->get_base();
13633 if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
13635 return $working[0];
13638 if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
13640 if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
13642 return $working;
13645 if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
13647 return $working;
13650 if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
13652 return $working;
13655 if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
13657 return $working;
13660 return null;
13663 public function is_feed(&$file)
13665 if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
13667 $sniffer = new $this->content_type_sniffer_class($file);
13668 $sniffed = $sniffer->get_type();
13669 if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
13671 return true;
13673 else
13675 return false;
13678 elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
13680 return true;
13682 else
13684 return false;
13688 public function get_base()
13690 $this->http_base = $this->file->url;
13691 $this->base = $this->http_base;
13692 $elements = SimplePie_Misc::get_element('base', $this->file->body);
13693 foreach ($elements as $element)
13695 if ($element['attribs']['href']['data'] !== '')
13697 $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
13698 $this->base_location = $element['offset'];
13699 break;
13704 public function autodiscovery()
13706 $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
13707 $done = array();
13708 $feeds = array();
13709 foreach ($links as $link)
13711 if ($this->checked_feeds === $this->max_checked_feeds)
13713 break;
13715 if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
13717 $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
13719 if ($this->base_location < $link['offset'])
13721 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
13723 else
13725 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
13728 if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
13730 $this->checked_feeds++;
13731 $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
13732 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))
13734 $feeds[$href] = $feed;
13737 $done[] = $href;
13741 if (!empty($feeds))
13743 return array_values($feeds);
13745 else {
13746 return null;
13750 public function get_links()
13752 $links = SimplePie_Misc::get_element('a', $this->file->body);
13753 foreach ($links as $link)
13755 if (isset($link['attribs']['href']['data']))
13757 $href = trim($link['attribs']['href']['data']);
13758 $parsed = SimplePie_Misc::parse_url($href);
13759 if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
13761 if ($this->base_location < $link['offset'])
13763 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
13765 else
13767 $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
13770 $current = SimplePie_Misc::parse_url($this->file->url);
13772 if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
13774 $this->local[] = $href;
13776 else
13778 $this->elsewhere[] = $href;
13783 $this->local = array_unique($this->local);
13784 $this->elsewhere = array_unique($this->elsewhere);
13785 if (!empty($this->local) || !empty($this->elsewhere))
13787 return true;
13789 return null;
13792 public function extension(&$array)
13794 foreach ($array as $key => $value)
13796 if ($this->checked_feeds === $this->max_checked_feeds)
13798 break;
13800 if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
13802 $this->checked_feeds++;
13803 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
13804 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))
13806 return $feed;
13808 else
13810 unset($array[$key]);
13814 return null;
13817 public function body(&$array)
13819 foreach ($array as $key => $value)
13821 if ($this->checked_feeds === $this->max_checked_feeds)
13823 break;
13825 if (preg_match('/(rss|rdf|atom|xml)/i', $value))
13827 $this->checked_feeds++;
13828 $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
13829 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))
13831 return $feed;
13833 else
13835 unset($array[$key]);
13839 return null;
13843 class SimplePie_Parser
13845 var $error_code;
13846 var $error_string;
13847 var $current_line;
13848 var $current_column;
13849 var $current_byte;
13850 var $separator = ' ';
13851 var $namespace = array('');
13852 var $element = array('');
13853 var $xml_base = array('');
13854 var $xml_base_explicit = array(false);
13855 var $xml_lang = array('');
13856 var $data = array();
13857 var $datas = array(array());
13858 var $current_xhtml_construct = -1;
13859 var $encoding;
13861 public function parse(&$data, $encoding)
13863 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
13864 if (strtoupper($encoding) === 'US-ASCII')
13866 $this->encoding = 'UTF-8';
13868 else
13870 $this->encoding = $encoding;
13873 // Strip BOM:
13874 // UTF-32 Big Endian BOM
13875 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
13877 $data = substr($data, 4);
13879 // UTF-32 Little Endian BOM
13880 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
13882 $data = substr($data, 4);
13884 // UTF-16 Big Endian BOM
13885 elseif (substr($data, 0, 2) === "\xFE\xFF")
13887 $data = substr($data, 2);
13889 // UTF-16 Little Endian BOM
13890 elseif (substr($data, 0, 2) === "\xFF\xFE")
13892 $data = substr($data, 2);
13894 // UTF-8 BOM
13895 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
13897 $data = substr($data, 3);
13900 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
13902 $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
13903 if ($declaration->parse())
13905 $data = substr($data, $pos + 2);
13906 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
13908 else
13910 $this->error_string = 'SimplePie bug! Please report this!';
13911 return false;
13915 $return = true;
13917 static $xml_is_sane = null;
13918 if ($xml_is_sane === null)
13920 $parser_check = xml_parser_create();
13921 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
13922 xml_parser_free($parser_check);
13923 $xml_is_sane = isset($values[0]['value']);
13926 // Create the parser
13927 if ($xml_is_sane)
13929 $xml = xml_parser_create_ns($this->encoding, $this->separator);
13930 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
13931 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
13932 xml_set_object($xml, $this);
13933 xml_set_character_data_handler($xml, 'cdata');
13934 xml_set_element_handler($xml, 'tag_open', 'tag_close');
13936 // Parse!
13937 if (!xml_parse($xml, $data, true))
13939 $this->error_code = xml_get_error_code($xml);
13940 $this->error_string = xml_error_string($this->error_code);
13941 $return = false;
13943 $this->current_line = xml_get_current_line_number($xml);
13944 $this->current_column = xml_get_current_column_number($xml);
13945 $this->current_byte = xml_get_current_byte_index($xml);
13946 xml_parser_free($xml);
13947 return $return;
13949 else
13951 libxml_clear_errors();
13952 $xml = new XMLReader();
13953 $xml->xml($data);
13954 while (@$xml->read())
13956 switch ($xml->nodeType)
13959 case constant('XMLReader::END_ELEMENT'):
13960 if ($xml->namespaceURI !== '')
13962 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
13964 else
13966 $tagName = $xml->localName;
13968 $this->tag_close(null, $tagName);
13969 break;
13970 case constant('XMLReader::ELEMENT'):
13971 $empty = $xml->isEmptyElement;
13972 if ($xml->namespaceURI !== '')
13974 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
13976 else
13978 $tagName = $xml->localName;
13980 $attributes = array();
13981 while ($xml->moveToNextAttribute())
13983 if ($xml->namespaceURI !== '')
13985 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
13987 else
13989 $attrName = $xml->localName;
13991 $attributes[$attrName] = $xml->value;
13993 $this->tag_open(null, $tagName, $attributes);
13994 if ($empty)
13996 $this->tag_close(null, $tagName);
13998 break;
13999 case constant('XMLReader::TEXT'):
14001 case constant('XMLReader::CDATA'):
14002 $this->cdata(null, $xml->value);
14003 break;
14006 if ($error = libxml_get_last_error())
14008 $this->error_code = $error->code;
14009 $this->error_string = $error->message;
14010 $this->current_line = $error->line;
14011 $this->current_column = $error->column;
14012 return false;
14014 else
14016 return true;
14021 public function get_error_code()
14023 return $this->error_code;
14026 public function get_error_string()
14028 return $this->error_string;
14031 public function get_current_line()
14033 return $this->current_line;
14036 public function get_current_column()
14038 return $this->current_column;
14041 public function get_current_byte()
14043 return $this->current_byte;
14046 public function get_data()
14048 return $this->data;
14051 public function tag_open($parser, $tag, $attributes)
14053 list($this->namespace[], $this->element[]) = $this->split_ns($tag);
14055 $attribs = array();
14056 foreach ($attributes as $name => $value)
14058 list($attrib_namespace, $attribute) = $this->split_ns($name);
14059 $attribs[$attrib_namespace][$attribute] = $value;
14062 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
14064 $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
14065 $this->xml_base_explicit[] = true;
14067 else
14069 $this->xml_base[] = end($this->xml_base);
14070 $this->xml_base_explicit[] = end($this->xml_base_explicit);
14073 if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
14075 $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
14077 else
14079 $this->xml_lang[] = end($this->xml_lang);
14082 if ($this->current_xhtml_construct >= 0)
14084 $this->current_xhtml_construct++;
14085 if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
14087 $this->data['data'] .= '<' . end($this->element);
14088 if (isset($attribs['']))
14090 foreach ($attribs[''] as $name => $value)
14092 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
14095 $this->data['data'] .= '>';
14098 else
14100 $this->datas[] =& $this->data;
14101 $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
14102 $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));
14103 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')
14104 || (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'))
14106 $this->current_xhtml_construct = 0;
14111 public function cdata($parser, $cdata)
14113 if ($this->current_xhtml_construct >= 0)
14115 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
14117 else
14119 $this->data['data'] .= $cdata;
14123 public function tag_close($parser, $tag)
14125 if ($this->current_xhtml_construct >= 0)
14127 $this->current_xhtml_construct--;
14128 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')))
14130 $this->data['data'] .= '</' . end($this->element) . '>';
14133 if ($this->current_xhtml_construct === -1)
14135 $this->data =& $this->datas[count($this->datas) - 1];
14136 array_pop($this->datas);
14139 array_pop($this->element);
14140 array_pop($this->namespace);
14141 array_pop($this->xml_base);
14142 array_pop($this->xml_base_explicit);
14143 array_pop($this->xml_lang);
14146 public function split_ns($string)
14148 static $cache = array();
14149 if (!isset($cache[$string]))
14151 if ($pos = strpos($string, $this->separator))
14153 static $separator_length;
14154 if (!$separator_length)
14156 $separator_length = strlen($this->separator);
14158 $namespace = substr($string, 0, $pos);
14159 $local_name = substr($string, $pos + $separator_length);
14160 if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
14162 $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
14165 // Normalize the Media RSS namespaces
14166 if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||
14167 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||
14168 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||
14169 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||
14170 $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 )
14172 $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
14174 $cache[$string] = array($namespace, $local_name);
14176 else
14178 $cache[$string] = array('', $string);
14181 return $cache[$string];
14186 * @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
14188 class SimplePie_Sanitize
14190 // Private vars
14191 var $base;
14193 // Options
14194 var $remove_div = true;
14195 var $image_handler = '';
14196 var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
14197 var $encode_instead_of_strip = false;
14198 var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
14199 var $strip_comments = false;
14200 var $output_encoding = 'UTF-8';
14201 var $enable_cache = true;
14202 var $cache_location = './cache';
14203 var $cache_name_function = 'md5';
14204 var $cache_class = 'SimplePie_Cache';
14205 var $file_class = 'SimplePie_File';
14206 var $timeout = 10;
14207 var $useragent = '';
14208 var $force_fsockopen = false;
14210 var $replace_url_attributes = array(
14211 'a' => 'href',
14212 'area' => 'href',
14213 'blockquote' => 'cite',
14214 'del' => 'cite',
14215 'form' => 'action',
14216 'img' => array('longdesc', 'src'),
14217 'input' => 'src',
14218 'ins' => 'cite',
14219 'q' => 'cite'
14222 public function remove_div($enable = true)
14224 $this->remove_div = (bool) $enable;
14227 public function set_image_handler($page = false)
14229 if ($page)
14231 $this->image_handler = (string) $page;
14233 else
14235 $this->image_handler = false;
14239 public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
14241 if (isset($enable_cache))
14243 $this->enable_cache = (bool) $enable_cache;
14246 if ($cache_location)
14248 $this->cache_location = (string) $cache_location;
14251 if ($cache_name_function)
14253 $this->cache_name_function = (string) $cache_name_function;
14256 if ($cache_class)
14258 $this->cache_class = (string) $cache_class;
14262 public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
14264 if ($file_class)
14266 $this->file_class = (string) $file_class;
14269 if ($timeout)
14271 $this->timeout = (string) $timeout;
14274 if ($useragent)
14276 $this->useragent = (string) $useragent;
14279 if ($force_fsockopen)
14281 $this->force_fsockopen = (string) $force_fsockopen;
14285 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'))
14287 if ($tags)
14289 if (is_array($tags))
14291 $this->strip_htmltags = $tags;
14293 else
14295 $this->strip_htmltags = explode(',', $tags);
14298 else
14300 $this->strip_htmltags = false;
14304 public function encode_instead_of_strip($encode = false)
14306 $this->encode_instead_of_strip = (bool) $encode;
14309 public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
14311 if ($attribs)
14313 if (is_array($attribs))
14315 $this->strip_attributes = $attribs;
14317 else
14319 $this->strip_attributes = explode(',', $attribs);
14322 else
14324 $this->strip_attributes = false;
14328 public function strip_comments($strip = false)
14330 $this->strip_comments = (bool) $strip;
14333 public function set_output_encoding($encoding = 'UTF-8')
14335 $this->output_encoding = (string) $encoding;
14339 * Set element/attribute key/value pairs of HTML attributes
14340 * containing URLs that need to be resolved relative to the feed
14342 * @access public
14343 * @since 1.0
14344 * @param array $element_attribute Element/attribute key/value pairs
14346 public function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
14348 $this->replace_url_attributes = (array) $element_attribute;
14351 public function sanitize($data, $type, $base = '')
14353 $data = trim($data);
14354 if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
14356 if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
14358 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))
14360 $type |= SIMPLEPIE_CONSTRUCT_HTML;
14362 else
14364 $type |= SIMPLEPIE_CONSTRUCT_TEXT;
14368 if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
14370 $data = base64_decode($data);
14373 if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
14375 if ($this->remove_div)
14377 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
14378 $data = preg_replace('/<\/div>$/', '', $data);
14380 else
14382 $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
14386 if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
14388 // Strip comments
14389 if ($this->strip_comments)
14391 $data = SimplePie_Misc::strip_comments($data);
14394 // Strip out HTML tags and attributes that might cause various security problems.
14395 // Based on recommendations by Mark Pilgrim at:
14396 // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
14397 if ($this->strip_htmltags)
14399 foreach ($this->strip_htmltags as $tag)
14401 $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
14402 while (preg_match($pcre, $data))
14404 $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
14409 if ($this->strip_attributes)
14411 foreach ($this->strip_attributes as $attrib)
14413 $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
14417 // Replace relative URLs
14418 $this->base = $base;
14419 foreach ($this->replace_url_attributes as $element => $attributes)
14421 $data = $this->replace_urls($data, $element, $attributes);
14424 // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
14425 if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
14427 $images = SimplePie_Misc::get_element('img', $data);
14428 foreach ($images as $img)
14430 if (isset($img['attribs']['src']['data']))
14432 $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
14433 $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
14435 if ($cache->load())
14437 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14438 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14440 else
14442 $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
14443 $headers = $file->headers;
14445 if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
14447 if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
14449 $img['attribs']['src']['data'] = $this->image_handler . $image_url;
14450 $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
14452 else
14454 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);
14462 // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
14463 $data = trim($data);
14466 if ($type & SIMPLEPIE_CONSTRUCT_IRI)
14468 $data = SimplePie_Misc::absolutize_url($data, $base);
14471 if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
14473 $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
14476 if ($this->output_encoding !== 'UTF-8')
14478 $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
14481 return $data;
14484 public function replace_urls($data, $tag, $attributes)
14486 if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
14488 $elements = SimplePie_Misc::get_element($tag, $data);
14489 foreach ($elements as $element)
14491 if (is_array($attributes))
14493 foreach ($attributes as $attribute)
14495 if (isset($element['attribs'][$attribute]['data']))
14497 $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
14498 $new_element = SimplePie_Misc::element_implode($element);
14499 $data = str_replace($element['full'], $new_element, $data);
14500 $element['full'] = $new_element;
14504 elseif (isset($element['attribs'][$attributes]['data']))
14506 $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
14507 $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
14511 return $data;
14514 public function do_strip_htmltags($match)
14516 if ($this->encode_instead_of_strip)
14518 if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14520 $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
14521 $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
14522 return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
14524 else
14526 return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
14529 elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
14531 return $match[4];
14533 else
14535 return '';