From 8f5d813459ebe822330e21662649353732159dc6 Mon Sep 17 00:00:00 2001 From: Keyvan Date: Wed, 23 Mar 2011 23:39:01 +0100 Subject: [PATCH] Full-Text RSS 2.5 --- changelog.txt | 10 + cleancache.php | 119 + config-sample.php => config.php | 153 +- css/feed.css | 30 + css/feed.xsl | 34 + css/niceforms-default.css | 4 +- images/background.png | Bin 34466 -> 0 bytes images/icon_feed.png | Bin 1255 -> 0 bytes images/tekzilla.jpg | Bin 58068 -> 0 bytes images/title.png | Bin 3329 -> 0 bytes index.html | 144 - index.php | 182 + js/jquery-1.3.2.min.js | 19 - js/jquery-1.4.4.min.js | 167 + libraries/Zend/Dom/Query/Css2Xpath.php | 169 + libraries/feedwriter/FeedWriter.php | 63 +- .../humble-http-agent/HumbleHttpAgent.php | 13 +- libraries/iri/iri.php | 642 +- libraries/readability/Readability.php | 4 - libraries/simplepie/simplepie.class.php | 13279 +++++++--------- makefulltextfeed.php | 336 +- 21 files changed, 7144 insertions(+), 8224 deletions(-) create mode 100644 cleancache.php rename config-sample.php => config.php (63%) create mode 100644 css/feed.css create mode 100644 css/feed.xsl delete mode 100644 images/background.png delete mode 100644 images/icon_feed.png delete mode 100644 images/tekzilla.jpg delete mode 100644 images/title.png delete mode 100644 index.html create mode 100644 index.php delete mode 100644 js/jquery-1.3.2.min.js create mode 100644 js/jquery-1.4.4.min.js create mode 100644 libraries/Zend/Dom/Query/Css2Xpath.php diff --git a/changelog.txt b/changelog.txt index 9ab591d..d90ad28 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,16 @@ FiveFilters.org: Full-Text RSS http://fivefilters.org/content-only/ CHANGELOG ------------------------------------ +2.5 (2011-01-08) + - New option: custom extraction pattern (CSS selectors) + - New option: allowed URLs (restrict service to pre-defined feeds/domains) + - New option: exclude items on fail (remove items from feed if content extraction fails) + - Remove 'http://' from URL before form submission (prevents errors on hosts which have overly vigilant security software) + - Allow overriding of index.php with custom_index.php + - config.php now required (override with custom_config.php) + - index.php now uses config.php to determine what to display + - Bug fix: occasional fatal error in IRI::__toString() (IRI updated) + - Bug fix: workaround for PHP bug http://bugs.php.net/51192 (fixed in HumbleHttpAgent.php) 2.2 (2010-10-30) - Character-encoding detection improved (minor change) diff --git a/cleancache.php b/cleancache.php new file mode 100644 index 0000000..49c6a3e --- /dev/null +++ b/cleancache.php @@ -0,0 +1,119 @@ +. +*/ + +// Usage +// ----- +// Set up your scheduler (e.g. cron) to request this file periodically. +// Note: this file must not be named cleancache.php so please rename it. +// We ask you to do this to prevent others from initiating +// the cache cleanup process. It will not run if it's called cleancache.php. + +error_reporting(E_ALL ^ E_NOTICE); +ini_set("display_errors", 1); +@set_time_limit(120); + +// check file name +if (basename(__FILE__) == 'cleancache.php') die('cleancache.php must be renamed'); + +// set include path +set_include_path(realpath(dirname(__FILE__).'/libraries').PATH_SEPARATOR.get_include_path()); + +// Autoloading of classes allows us to include files only when they're +// needed. If we've got a cached copy, for example, only Zend_Cache is loaded. +function __autoload($class_name) { + static $mapping = array( + 'Zend_Cache' => 'Zend/Cache.php' + ); + if (isset($mapping[$class_name])) { + //echo "Loading $class_name\n
"; + require_once $mapping[$class_name]; + return true; + } else { + return false; + } +} +require_once(dirname(__FILE__).'/config.php'); +if (!$options->caching) die('Caching is disabled'); + +// clean http response cache +$frontendOptions = array( + 'lifetime' => 30*60, // cache lifetime of 30 minutes + 'automatic_serialization' => true, + 'write_control' => false, + 'automatic_cleaning_factor' => 0, + 'ignore_user_abort' => false +); +$backendOptions = array( + 'cache_dir' => $options->cache_dir.'/http-responses/', + 'file_locking' => false, + 'read_control' => true, + 'read_control_type' => 'strlen', + 'hashed_directory_level' => $options->cache_directory_level, + 'hashed_directory_umask' => 0777, + 'cache_file_umask' => 0664, + 'file_name_prefix' => 'ff' +); +$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); +$cache->clean(Zend_Cache::CLEANING_MODE_OLD); + +// clean rss (non-key) cache +$frontendOptions = array( + 'lifetime' => 20*60, + 'automatic_serialization' => false, + 'write_control' => false, + 'automatic_cleaning_factor' => 0, + 'ignore_user_abort' => false +); +$backendOptions = array( + 'cache_dir' => $options->cache_dir.'/rss/', + 'file_locking' => false, + 'read_control' => true, + 'read_control_type' => 'strlen', + 'hashed_directory_level' => $options->cache_directory_level, + 'hashed_directory_umask' => 0777, + 'cache_file_umask' => 0664, + 'file_name_prefix' => 'ff' +); +$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); +$cache->clean(Zend_Cache::CLEANING_MODE_OLD); + +// clean rss (key) cache +$frontendOptions = array( + 'lifetime' => 20*60, + 'automatic_serialization' => false, + 'write_control' => false, + 'automatic_cleaning_factor' => 0, + 'ignore_user_abort' => false +); +$backendOptions = array( + 'cache_dir' => $options->cache_dir.'/rss-with-key/', + 'file_locking' => false, + 'read_control' => true, + 'read_control_type' => 'strlen', + 'hashed_directory_level' => $options->cache_directory_level, + 'hashed_directory_umask' => 0777, + 'cache_file_umask' => 0664, + 'file_name_prefix' => 'ff' +); +$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); +$cache->clean(Zend_Cache::CLEANING_MODE_OLD); + +?> \ No newline at end of file diff --git a/config-sample.php b/config.php similarity index 63% rename from config-sample.php rename to config.php index 0336ecb..b85f127 100644 --- a/config-sample.php +++ b/config.php @@ -1,5 +1,10 @@ enabled = true; -// Restrict service -// ---------------------- -// Set this to true if you'd like certain features -// to be available only to key holders. -// Affected features: -// * Link handling (disabled for non-key holders if set to true) -// * Cache time (20 minutes for non-key holders if set to true) -$options->restrict = false; - // Default entries (without API key) // ---------------------- // The number of feed items to process when no API key is supplied. @@ -35,6 +31,27 @@ $options->max_entries = 10; // the extracted content block. $options->rewrite_relative_urls = true; +// Exclude items if extraction fails +// --------------------------------- +// Excludes items from the resulting feed +// if we cannot extract any content from the +// item URL. +// Possible values... +// Enable: true +// Disable: false (default) +// User decides: 'user' (this option will appear on the form) +$options->exclude_items_on_fail = 'user'; + +// Extraction pattern +// --------------------------------- +// Specify what should get extracted +// Possible values: +// Auto detect: 'auto' +// Custom: css string (e.g. 'div#content') +// Element within auto-detected block: 'auto ' + css string (e.g. 'auto p') +// User decides: 'user' (default, this option will appear on the form) +$options->extraction_pattern = 'user'; + // Enable caching // ---------------------- // Enable this if you'd like to cache results @@ -58,9 +75,19 @@ $options->message_to_prepend = ''; // HTML to insert at the end of each feed item when no API key is supplied. $options->message_to_append = ''; +// URLs to allow +// ---------------------- +// List of URLs (or parts of a URL) which the service will accept. +// If the list is empty, all URLs (except those specified in the blocked list below) +// will be permitted. +// Empty: array(); +// Non-empty example: array('example.com', 'anothersite.org'); +$options->allowed_urls = array(); + // URLs to block // ---------------------- -// List of URLs (or parts of a URL) which the service should not accept +// List of URLs (or parts of a URL) which the service will not accept. +// Note: this list is ignored if allowed_urls is not empty $options->blocked_urls = array(); // Error message when content extraction fails (without API key) @@ -71,43 +98,6 @@ $options->error_message = '[unable to retrieve full-text content]'; /// ADVANCED OPTIONS //////////////////////////// ///////////////////////////////////////////////// -// API keys -// ---------------------- -// NOTE: You do not need an API key from fivefilters.org to run your own -// copy of the code. This is here if you'd like to offer others an API key -// to access _your_ copy. -// Keys let you group users - those with a key and those without - and -// restrict access to the service to those without a key. -// If you want everyone to access the service in the same way, you can -// leave the array below empty and ignore the API key options further down. -// The options further down in this file will allow you to specify -// how the service should behave in each mode. -$options->api_keys = array(); - -// Default entries (with API key) -// ---------------------- -// The number of feed items to process when a valid API key is supplied. -$options->default_entries_with_key = 5; - -// Max entries (with API key) -// ---------------------- -// The maximum number of feed items to process when a valid API key is supplied. -$options->max_entries_with_key = 10; - -// Message to prepend (with API key) -// ---------------------- -// HTML to insert at the beginning of each feed item when a valid API key is supplied. -$options->message_to_prepend_with_key = ''; - -// Message to append (with API key) -// ---------------------- -// HTML to insert at the end of each feed item when a valid API key is supplied. -$options->message_to_append_with_key = ''; - -// Error message when content extraction fails (with API key) -// ---------------------- -$options->error_message_with_key = '[unable to retrieve full-text content]'; - // Alternative Full-Text RSS service URL // ---------------------- // This option is to offer very simple load distribution for the service. @@ -127,4 +117,71 @@ $options->alternative_url = ''; // It's best not to change this if you're unsure. $options->cache_directory_level = 0; +// Cache cleanup +// ------------- +// 0 = script will not clean cache (rename cachecleanup.php and use it for scheduled (e.g. cron) cache cleanup) +// 1 = clean cache everytime the script runs (not recommended) +// 100 = (roughly) clean cache once out of every 100 script runs +// x = (roughly) clean cache once out of every x script runs +// ...you get the idea :) +$options->cache_cleanup = 100; + +///////////////////////////////////////////////// +/// DEPRECATED OPTIONS +/// THESE OPTIONS WILL CHANGE IN THE NEXT +/// VERSION, WE RECOMMEND YOU DO NOT USE THEM +///////////////////////////////////////////////// + +// Restrict service (deprecated) +// ----------------------------- +// Set this to true if you'd like certain features +// to be available only to key holders. +// Affected features: +// * Link handling (disabled for non-key holders if set to true) +// * Cache time (20 minutes for non-key holders if set to true) +$options->restrict = false; + +// API keys (deprecated) +// ---------------------- +// NOTE: You do not need an API key from fivefilters.org to run your own +// copy of the code. This is here if you'd like to offer others an API key +// to access _your_ copy. +// Keys let you group users - those with a key and those without - and +// restrict access to the service to those without a key. +// If you want everyone to access the service in the same way, you can +// leave the array below empty and ignore the API key options further down. +// The options further down in this file will allow you to specify +// how the service should behave in each mode. +$options->api_keys = array(); + +// Default entries (with API key) (deprecated) +// ---------------------- +// The number of feed items to process when a valid API key is supplied. +$options->default_entries_with_key = 5; + +// Max entries (with API key) (deprecated) +// ---------------------- +// The maximum number of feed items to process when a valid API key is supplied. +$options->max_entries_with_key = 10; + +// Message to prepend (with API key) (deprecated) +// ---------------------- +// HTML to insert at the beginning of each feed item when a valid API key is supplied. +$options->message_to_prepend_with_key = ''; + +// Message to append (with API key) (deprecated) +// ---------------------- +// HTML to insert at the end of each feed item when a valid API key is supplied. +$options->message_to_append_with_key = ''; + +// Error message when content extraction fails (with API key) (deprecated) +// ---------------------- +$options->error_message_with_key = '[unable to retrieve full-text content]'; + +///////////////////////////////////////////////// +/// DO NOT CHANGE ANYTHING BELOW THIS /////////// +///////////////////////////////////////////////// + +if (!defined('_FF_FTR_VERSION')) define('_FF_FTR_VERSION', '2.5'); + ?> \ No newline at end of file diff --git a/css/feed.css b/css/feed.css new file mode 100644 index 0000000..866ab76 --- /dev/null +++ b/css/feed.css @@ -0,0 +1,30 @@ +/* RSS CSS Document */ + +* { margin:0; padding:0; } + +p { padding: .5em 0; } + +h1,h2,h3,h4,h5,h6 { font-size: 1em; padding: .5em 0; } + +html { display:block; padding-bottom:50px; } +body { font:80% Verdana, sans-serif; color:#000; padding:25px 0 0 35px; } + +a { color:#5BAB03; text-decoration:none; } +a:hover { color:#5BAB03; text-decoration: underline;} + +ul { margin-left:1.5em; } +li { margin-bottom:0.4em; } +div#content>ul { list-style-type: none; } +div.article>li>a { font-weight:bold; font-size: 1.3em;} + + +div { line-height:1.6em; } + +div#content { background:#fff; margin-right:15px; padding-left:1em;} +div#content div { margin:0 1em 1em 0; } + +div#explanation { padding:1em 1em 0 1em; border:1px solid #ddd; background:#efefef; margin:0 2em 2em 0; } +div#explanation h1 { font-weight:normal; font-size:1.8em; margin-bottom:0.3em; } +div#explanation p { margin-bottom:1em; } + +.small { font-size: .7em; color: #666; } \ No newline at end of file diff --git a/css/feed.xsl b/css/feed.xsl new file mode 100644 index 0000000..216d34e --- /dev/null +++ b/css/feed.xsl @@ -0,0 +1,34 @@ + + + + + + + + <xsl:value-of select="$title"/> (full-text feed) + + + +
+

(full-text feed)

+

You are viewing an auto-generated full-text RSS feed. RSS feeds allow you to stay up to date with the latest news and features you want from websites. To subscribe to it, you will need a News Reader or other similar device.

+

Below is the latest content available from this feed.

+
+ +
+
    + +
    +
  • +
    +
  • +
    +
    +
+
+ + +
+
\ No newline at end of file diff --git a/css/niceforms-default.css b/css/niceforms-default.css index 060b867..7d29d41 100644 --- a/css/niceforms-default.css +++ b/css/niceforms-default.css @@ -7,8 +7,8 @@ legend {background:#bfbf30; color:#fff; font:17px/21px Calibri, Arial, Helvetica label {font-size:11px; font-weight:bold; color:#666;} label.opt {font-weight:normal;} dl {clear:both;} -dt {float:left; text-align:right; width:90px; line-height:25px; margin:0 10px 10px 0;} -dd {float:left; width:475px; line-height:25px; margin:0 0 10px 0;} +dt {float:left; text-align:right; width:100px; line-height:25px; margin:0 10px 10px 0;} +dd {float:left; width:465px; line-height:25px; margin:0 0 10px 0;} #footer {font-size:11px;} #container {width:700px; margin:0 auto;} diff --git a/images/background.png b/images/background.png deleted file mode 100644 index 24e9823960358085bceda244d7850d9fc5a4523b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34466 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 diff --git a/images/icon_feed.png b/images/icon_feed.png deleted file mode 100644 index 5346bbc7426abc4eb81460c6223ecda7f24df54d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1255 zcmVXP`+vV>ca_1pcy2zKd3|~`(Lq<8D~P#ir^;h>HQhm3 zueKHzh>Hb95fGXJ+0X!8hpftwR01R|T}|Cp67B>vl2_ITW3pU(Dmij(FI{2BWc+q^-;U*^L3%zkLZd@;xMOkp;|Ua2HrO1a7&`v!R=T+QOn; zK=ypB$=>B6yGX&umVYbpdtg5P76MOv4yE#5NG#>~-c^7*f`B#ZFrQ-V?vJYfPUl?u%F)szw$K%xq*40oK{ZC@S?!;QO%)* zqEIX9AZ|^9jrJlt+yiyX{m`0TgtGGhnL&s0@Ec?-1@`4r;Btw_niDvb;+T8s#K~uB zya6RoeN2wFz^AW*UF`uII1T%|mx0;8q3nOfzwDvcU`-|94E_QJ(^EjwL~#{vWnTM^ zru2&MhSvHjjH91Hsd@nH@<(ufdMAII3geMu;8F-Y=Xkz%XK~5>+A8^msLUA-U61+K(M0BF7j22Ry_#)KqvI}E@+27g(#^(_Qwyr zYUd7P&ru*;jr1id;lfWXW5<5q@2t3%DtX|-hO)U4a&@yWtk?-uw!oR6M(#qFFAGK? zZ)!v?F$lIe<9np;J_1y*zVs(EhZ>_4e3g8DI#nu7gJ2gK$kIEg;k<9|^e2jCiGqy^l%Z3#Tble&)2{YjZ`pK4f)$%%i2ziJ7tSr-AD3vREh# znc9>dAa%JPjHI;tz)*>;S4_yf?h!@Py_oZQK2_Pdsqv0*IDE0N^6EYig!uNx(6#2d z>!Ef%U~Y9WSG;pp6py@Ey`9s{S)52GZk|;n`GRDcD9G#^Pv;Hr|6}|kzyK_`;=D(A Ruz&yn002ovPDHLkV1fs3VR--m diff --git a/images/tekzilla.jpg b/images/tekzilla.jpg deleted file mode 100644 index 483cdaf15f1ac862d0a2763c4667e95350360e81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58068 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

0Q&pSw$B|9|Y_FV&z3!^Oz`46O{x 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 diff --git a/images/title.png b/images/title.png deleted file mode 100644 index d3539d2deee34d593c0060dcc18457aa29a04d88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3329 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 LNkvXXu0mjfI@@^{ diff --git a/index.html b/index.html deleted file mode 100644 index 20fd882..0000000 --- a/index.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - Full-Text RSS Feeds | from fivefilters.org - - - - - - - -

- - \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..a6787e5 --- /dev/null +++ b/index.php @@ -0,0 +1,182 @@ + + + + + Full-Text RSS Feeds | from fivefilters.org + + + + + + + + + + +
+

Full-Text RSS — from FiveFilters.org

+
+
+ Create full-text feed from feed or webpage URL +
+
+
+
+
+
+ Options + extraction_pattern == 'user') { ?> +
+
+
+
+ + api_keys) && !empty($options->api_keys)) { ?> +
+
+
+
+ +
+
+
+
+
+
+
+
+
+ exclude_items_on_fail == 'user') { ?> +
+
+
+
+ +
+
+ +
+
+ +
+ +

For the site owner

+ +

Thanks for downloading and setting this up. If you haven't done so already, check server compatibility + to see if your environment will support this application. Full-Text RSS runs on most shared web hosting environments.

+

Configure

+

In addition to the options above, Full-Text RSS comes with a configuration file which allows you to control how the application works. Features include:

+
    +
  • Restrict access to a pre-defined set of URLs or block certain URLs
  • +
  • Restrict the maximum number of feed items to be processed
  • +
  • Prepend or append an HTML fragment to each feed item processed
  • +
  • Caching
  • +
+

To change the configuration, save a copy of config.php as custom_config.php and make any changes you like to it.To change the configuration, edit custom_config.php and make any changes you like.

+ +

If everything works fine, feel free to modify this page by saving it as custom_index.php and change it to whatever you like.

+ +

Sharing is caring

+ If you plan to offer this service to others through your hosted copy, please keep a download link so users can grab a copy of the code if they + want it (you can either offer the download yourself, or link to the download page on fivefilters.org to support us). + That's one requirement of the license.

+

Thanks! :)

+ + +

To see if you're running the latest version, check for updates.

+ + +

We have more information in the section below, but if you need help with anything, please email fivefilters@fivefilters.org.

+ +
+ +

For everyone

+ +

About

+

This is a free software project to help people extract content from web pages. It can extract content from a standard HTML page and return a 1-item feed or it can transform an existing feed into a full-text feed. It is being developed as part of the Five Filters project to promote independent, non-corporate media.

+ +

Bookmarklet

+

To easily transform partial-feeds you encounter (or convert any content on a page into a 1-item feed), drag the link below to your browser's bookmarks toolbar. + Then whenever you'd like a full-text feed, click the bookmarklet.

+

Drag this: + + +

API

+

To extract content from a web page or to transform an existing partial feed to full text, pass the URL (encoded) in the querystring to the following URL:

+
    +
  • /makefulltextfeed.php?url=[url]
  • +
+

If you have an API key, add that to the querystring:

+
    +
  • /makefulltextfeed.php?key=[key]&url=[url]
  • +
  • /makefulltextfeed.php?key=[key]&max=[number of feed items]&url=[url]
  • +
+ +

All the parameters in the form above can be passed in this way. Examine the URL in the addressbar after you click 'Create Feed' to see the values.

+ +

Note: If you're not hosting this yourself, you do not have to rely on an external API if you don't want to — this is a free software (open source) + project licensed under the AGPL. You're free to download your own copy.

+ +

Source Code and Technologies

+

The application uses PHP, PHP Readability, SimplePie, FeedWriter, Humble HTTP Agent. Depending on configuration, these optional components may also be used: Zend Cache, Zend DOM Query and IRI. Readability is the magic piece of code that tries to identify and extract the content block from any given web page.

+ +

System Requirements

+ +

PHP 5.2 or above is required. A simple shared web hosting account will work fine. + The code has been tested on Windows and Linux using the Apache web server. If you're a Windows user, you can try it on your own machine using WampServer.

+ +

Download

+

Download from fivefilters.org - old versions are available in the code repository.

+ +

License

+

AGPL logo
This web application is licensed under the AGPL version 3 — which basically means if you use the code to offer the same or similar service for your users, you are also required to share the code with your users so they can run it for themselves. (More on why this is important.)

+

The libraries used by the application are licensed as follows...

+ + +
+ + \ No newline at end of file diff --git a/js/jquery-1.3.2.min.js b/js/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d..0000000 --- a/js/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/js/jquery-1.4.4.min.js b/js/jquery-1.4.4.min.js new file mode 100644 index 0000000..8f3ca2e --- /dev/null +++ b/js/jquery-1.4.4.min.js @@ -0,0 +1,167 @@ +/*! + * jQuery JavaScript Library v1.4.4 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Nov 11 19:04:53 2010 -0500 + */ +(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h= +h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, +"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, +e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, +"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ +a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, +C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, +s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, +j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, +toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== +-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; +if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", +b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& +!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& +l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H
a";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), +k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, +scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= +false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= +1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="
t
";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= +"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= +c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); +else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; +if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, +attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& +b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; +c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, +arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= +d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ +c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== +8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== +"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ +d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= +B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== +"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== +0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; +break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, +q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= +l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, +m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== +true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== +g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]- +0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== +i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; +if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, +g);else if(typeof g.length==="number")for(var p=g.length;n";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); +n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& +function(){var g=k,i=t.createElement("div");i.innerHTML="

";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| +p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= +t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? +function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= +h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): +c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, +2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, +b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& +e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1, +""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; +else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", +prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length- +1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); +d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, +jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, +zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), +h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); +if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= +d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; +e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/)<[^<]*)*<\/script>/gi, +ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== +"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("
").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& +!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, +getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", +script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| +!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= +false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; +A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", +b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& +c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| +c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= +encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", +[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), +e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); +if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", +3),a,b,d);else{d=0;for(var e=this.length;d=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, +d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* +Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} +var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; +this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| +this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= +c.timers,b=0;b-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, +e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& +c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); +c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ +b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/libraries/Zend/Dom/Query/Css2Xpath.php b/libraries/Zend/Dom/Query/Css2Xpath.php new file mode 100644 index 0000000..f91627f --- /dev/null +++ b/libraries/Zend/Dom/Query/Css2Xpath.php @@ -0,0 +1,169 @@ +\s+|', '>', $path); + $segments = preg_split('/\s+/', $path); + foreach ($segments as $key => $segment) { + $pathSegment = self::_tokenize($segment); + if (0 == $key) { + if (0 === strpos($pathSegment, '[contains(')) { + $paths[0] .= '*' . ltrim($pathSegment, '*'); + } else { + $paths[0] .= $pathSegment; + } + continue; + } + if (0 === strpos($pathSegment, '[contains(')) { + foreach ($paths as $key => $xpath) { + $paths[$key] .= '//*' . ltrim($pathSegment, '*'); + $paths[] = $xpath . $pathSegment; + } + } else { + foreach ($paths as $key => $xpath) { + $paths[$key] .= '//' . $pathSegment; + } + } + } + + if (1 == count($paths)) { + return $paths[0]; + } + return implode('|', $paths); + } + + /** + * Tokenize CSS expressions to XPath + * + * @param string $expression + * @return string + */ + protected static function _tokenize($expression) + { + // Child selectors + $expression = str_replace('>', '/', $expression); + + // IDs + $expression = preg_replace('|#([a-z][a-z0-9_-]*)|i', '[@id=\'$1\']', $expression); + $expression = preg_replace('|(? @@ -18,10 +20,13 @@ */ class FeedWriter { + private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html + private $hubs = array(); // PubSubHubbub hubs private $channels = array(); // Collection of channel elements private $items = array(); // Collection of items as object of FeedItem class. private $data = array(); // Store some other version wise data private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA + private $xsl = null; // stylesheet to render RSS (used by Chrome) private $version = null; @@ -113,7 +118,6 @@ $this->items[] = $feedItem; } - // Wrapper functions ------------------------------------------------------------------- /** @@ -128,6 +132,42 @@ $this->setChannelElement('title', $title); } + /** + * Add a hub to the channel element + * + * @access public + * @param string URL + * @return void + */ + public function addHub($hub) + { + $this->hubs[] = $hub; + } + + /** + * Set XSL URL + * + * @access public + * @param string URL + * @return void + */ + public function setXsl($xsl) + { + $this->xsl = $xsl; + } + + /** + * Set self URL + * + * @access public + * @param string URL + * @return void + */ + public function setSelf($self) + { + $this->self = $self; + } + /** * Set the 'description' channel element * @@ -213,6 +253,7 @@ if($this->version == RSS2) { + if ($this->xsl) $out .= 'xsl).'"?>' . PHP_EOL; $out .= '' . PHP_EOL; } elseif($this->version == RSS1) @@ -315,7 +356,17 @@ switch ($this->version) { case RSS2: - echo '' . PHP_EOL; + echo '' . PHP_EOL; + // add hubs + foreach ($this->hubs as $hub) { + //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom')); + echo '' . PHP_EOL; + } + // add self + if (isset($this->self)) { + //echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom')); + echo '' . PHP_EOL; + } break; case RSS1: echo (isset($this->data['ChannelAbout']))? "data['ChannelAbout']}\">" : "channels['link']}\">"; diff --git a/libraries/humble-http-agent/HumbleHttpAgent.php b/libraries/humble-http-agent/HumbleHttpAgent.php index b63805d..50a1d32 100644 --- a/libraries/humble-http-agent/HumbleHttpAgent.php +++ b/libraries/humble-http-agent/HumbleHttpAgent.php @@ -42,7 +42,9 @@ class HumbleHttpAgent $this->httpContext = stream_context_create(array( 'http' => array( 'timeout' => $this->requestOptions['timeout'], - 'max_redirects' => $this->requestOptions['redirect'] + 'max_redirects' => $this->requestOptions['redirect'], + 'header' => "User-Agent: PHP/5.2\r\n". + "Accept: */*\r\n" ) ) ); @@ -81,8 +83,13 @@ class HumbleHttpAgent } public function validateUrl($url) { - $url = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED); - if ($url !== false && $url !== null && preg_match('!^https?://!', $url)) { + //TODO: run sanitize filter first! + $test = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED); + // deal with bug http://bugs.php.net/51192 (present in PHP 5.2.13 and PHP 5.3.2) + if ($test === false) { + $test = filter_var(strtr($url, '-', '_'), FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED); + } + if ($test !== false && $test !== null && preg_match('!^https?://!', $url)) { return filter_var($url, FILTER_SANITIZE_URL); } else { return false; diff --git a/libraries/iri/iri.php b/libraries/iri/iri.php index a4788db..ed97a22 100644 --- a/libraries/iri/iri.php +++ b/libraries/iri/iri.php @@ -1,9 +1,8 @@ iri; + return $this->get_iri(); } /** @@ -162,13 +161,14 @@ class IRI */ public function __get($name) { - if (!$this->is_valid()) + if ( + $name === 'iri' || + $name === 'uri' || + $name === 'iauthority' || + $name === 'authority' + ) { - return false; - } - elseif (method_exists($this, 'get_' . $name)) - { - $return = call_user_func(array($this, 'get_' . $name)); + $return = $this->{"get_$name"}(); } elseif (isset($this->$name)) { @@ -239,83 +239,94 @@ class IRI * * Returns false if $base is not absolute, otherwise an IRI. * - * @param IRI $base (Absolute) Base IRI + * @param IRI|string $base (Absolute) Base IRI * @param IRI|string $relative Relative IRI * @return IRI|false */ - public static function absolutize(IRI $base, $relative) + public static function absolutize($base, $relative) { if (!($relative instanceof IRI)) { $relative = new IRI($relative); } - if ($base->scheme !== null) + if (!$relative->is_valid()) { - if ($relative->iri !== '' && $relative->iri !== null) - { - if ($relative->scheme !== null) - { - $target = clone $relative; - } - elseif ($relative->iauthority !== null) - { - $target = clone $relative; - $target->scheme = $base->scheme; - } - else - { - $target = new IRI; - $target->scheme = $base->scheme; - $target->iuserinfo = $base->iuserinfo; - $target->ihost = $base->ihost; - $target->port = $base->port; - if ($relative->ipath !== '') - { - if ($relative->ipath[0] === '/') - { - $target->ipath = $relative->ipath; - } - elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === null) - { - $target->ipath = '/' . $relative->ipath; - } - elseif (($last_segment = strrpos($base->ipath, '/')) !== false) - { - $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; - } - else - { - $target->ipath = $relative->ipath; - } - $target->ipath = $target->remove_dot_segments($target->ipath); - $target->iquery = $relative->iquery; - } - else - { - $target->ipath = $base->ipath; - if ($relative->iquery !== null) - { - $target->iquery = $relative->iquery; - } - elseif ($base->iquery !== null) - { - $target->iquery = $base->iquery; - } - } - $target->ifragment = $relative->ifragment; - } - } - else - { - $target = clone $base; - $target->ifragment = null; - } - $target->scheme_normalization(); - return $target; + return false; + } + elseif ($relative->scheme !== null) + { + return clone $relative; } else { - return false; + if (!($base instanceof IRI)) + { + $base = new IRI($base); + } + if ($base->scheme !== null && $base->is_valid()) + { + if ($relative->get_iri() !== '') + { + if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) + { + $target = clone $relative; + $target->scheme = $base->scheme; + } + else + { + $target = new IRI; + $target->scheme = $base->scheme; + $target->iuserinfo = $base->iuserinfo; + $target->ihost = $base->ihost; + $target->port = $base->port; + if ($relative->ipath !== '') + { + if ($relative->ipath[0] === '/') + { + $target->ipath = $relative->ipath; + } + elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') + { + $target->ipath = '/' . $relative->ipath; + } + elseif (($last_segment = strrpos($base->ipath, '/')) !== false) + { + $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; + } + else + { + $target->ipath = $relative->ipath; + } + $target->ipath = $target->remove_dot_segments($target->ipath); + $target->iquery = $relative->iquery; + } + else + { + $target->ipath = $base->ipath; + if ($relative->iquery !== null) + { + $target->iquery = $relative->iquery; + } + elseif ($base->iquery !== null) + { + $target->iquery = $base->iquery; + } + } + $target->ifragment = $relative->ifragment; + } + } + else + { + $target = clone $base; + $target->ifragment = null; + } + $target->scheme_normalization(); + return $target; + } + else + { + return false; + } } } @@ -339,24 +350,9 @@ class IRI private function parse_iri($iri) { $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); - static $cache = array(); - if (isset($cache[$iri])) + if (preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match)) { - return $cache[$iri]; - } - elseif ($iri === '') - { - return $cache[$iri] = array( - 'scheme' => null, - 'authority' => null, - 'path' => '', - 'query' => null, - 'fragment' => null - ); - } - elseif (preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match)) - { - if (!isset($match[1]) || $match[1] === '') + if ($match[1] === '') { $match['scheme'] = null; } @@ -364,7 +360,7 @@ class IRI { $match['authority'] = null; } - if (!isset($match[5]) || $match[5] === '') + if (!isset($match[5])) { $match['path'] = ''; } @@ -376,7 +372,12 @@ class IRI { $match['fragment'] = null; } - return $cache[$iri] = $match; + return $match; + } + else + { + trigger_error('This should never happen', E_USER_ERROR); + die; } } @@ -403,7 +404,7 @@ class IRI // 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, elseif (strpos($input, '/./') === 0) { - $input = substr_replace($input, '/', 0, 3); + $input = substr($input, 2); } elseif ($input === '/.') { @@ -412,7 +413,7 @@ class IRI // 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, elseif (strpos($input, '/../') === 0) { - $input = substr_replace($input, '/', 0, 4); + $input = substr($input, 3); $output = substr_replace($output, '', strrpos($output, '/')); } elseif ($input === '/..') @@ -451,12 +452,12 @@ class IRI */ private function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) { - // Replace invalid percent characters - $string = preg_replace('/%($|[^A-Fa-f0-9]|[A-Fa-f0-9][^A-Fa-f0-9])/', '%25\1', $string); - // Normalize as many pct-encoded sections as possible $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string); + // Replace invalid percent characters + $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); + // Add unreserved and % to $extra_chars (the latter is safe because all // pct-encoded sections are now valid). $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; @@ -733,7 +734,7 @@ class IRI } if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) { - $this->ipath = null; + $this->ipath = ''; } if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) { @@ -753,10 +754,19 @@ class IRI */ public function is_valid() { - if ($this->ipath !== null && ( - substr($this->ipath, 0, 2) === '//' && $this->get_iauthority() === null - || substr($this->ipath, 0, 1) !== '/' && $this->ipath !== '' && $this->get_iauthority() !== null - || strpos($this->ipath, ':') !== false && (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) && $this->scheme === null && $this->get_iauthority() === null + $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; + if ($this->ipath !== '' && + ( + $isauthority && ( + $this->ipath[0] !== '/' || + substr($this->ipath, 0, 2) === '//' + ) || + ( + $this->scheme === null && + !$isauthority && + strpos($this->ipath, ':') !== false && + (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) + ) ) ) { @@ -774,16 +784,22 @@ class IRI * @return bool */ private function set_iri($iri) - { - if ($iri !== null) + { + if ($iri === null) + { + return true; + } + else { $parsed = $this->parse_iri((string) $iri); - return $this->set_scheme($parsed['scheme']) + $return = $this->set_scheme($parsed['scheme']) && $this->set_authority($parsed['authority']) && $this->set_path($parsed['path']) && $this->set_query($parsed['query']) && $this->set_fragment($parsed['fragment']); + + return $return; } } @@ -800,14 +816,7 @@ class IRI { $this->scheme = null; } - elseif ( - !($scheme = (string) $scheme) - || !isset($scheme[0]) - || $scheme[0] < 'A' - || $scheme[0] > 'Z' && $scheme[0] < 'a' - || $scheme[0] > 'z' - || strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.') !== strlen($scheme) - ) + elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) { $this->scheme = null; return false; @@ -827,30 +836,45 @@ class IRI * @return bool */ private function set_authority($authority) - { - if (($iuserinfo_end = strrpos($authority, '@')) !== false) + { + if ($authority === null) { - $iuserinfo = substr($authority, 0, $iuserinfo_end); - $authority = substr($authority, $iuserinfo_end + 1); + $this->iuserinfo = null; + $this->ihost = null; + $this->port = null; + return true; } else { - $iuserinfo = null; - } - if (($port_start = strpos($authority, ':', strpos($authority, ']'))) !== false) - { - if (($port = substr($authority, $port_start + 1)) === false) + $remaining = $authority; + if (($iuserinfo_end = strrpos($remaining, '@')) !== false) + { + $iuserinfo = substr($remaining, 0, $iuserinfo_end); + $remaining = substr($remaining, $iuserinfo_end + 1); + } + else + { + $iuserinfo = null; + } + if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) + { + if (($port = substr($remaining, $port_start + 1)) === false) + { + $port = null; + } + $remaining = substr($remaining, 0, $port_start); + } + else { $port = null; } - $authority = substr($authority, 0, $port_start); + + $return = $this->set_userinfo($iuserinfo) && + $this->set_host($remaining) && + $this->set_port($port); + + return $return; } - else - { - $port = null; - } - - return $this->set_userinfo($iuserinfo) && $this->set_host($authority) && $this->set_port($port); } /** @@ -964,29 +988,16 @@ class IRI * @return bool */ private function set_path($ipath) - { - if ($ipath === null) - { - $this->ipath = null; - return true; - } - else - { - $ipath = explode('/', $ipath); - $this->ipath = ''; - foreach ($ipath as $segment) - { - $this->ipath .= $this->replace_invalid_with_pct_encoding($segment, '!$&\'()*+,;=@:'); - $this->ipath .= '/'; - } - $this->ipath = substr($this->ipath, 0, -1); - if ($this->scheme !== null) - { - $this->ipath = $this->remove_dot_segments($this->ipath); - } - $this->scheme_normalization(); - return true; - } + { + $ipath = (string) $ipath; + + $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); + $removed = $this->remove_dot_segments($valid); + + $this->ipath = ($this->scheme !== null) ? $removed : $valid; + + $this->scheme_normalization(); + return true; } /** @@ -1036,7 +1047,11 @@ class IRI */ private function to_uri($string) { - static $non_ascii = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; + static $non_ascii; + if (!$non_ascii) + { + $non_ascii = implode('', range("\x80", "\xFF")); + } $position = 0; $strlen = strlen($string); @@ -1057,21 +1072,21 @@ class IRI */ private function get_iri() { + if (!$this->is_valid()) + { + return false; + } + $iri = ''; - $defined = false; if ($this->scheme !== null) { $iri .= $this->scheme . ':'; } - if (($iauthority = $this->iauthority) !== null) + if (($iauthority = $this->get_iauthority()) !== null) { $iri .= '//' . $iauthority; } - if ($this->ipath !== null) - { - $iri .= $this->ipath; - $defined = true; - } + $iri .= $this->ipath; if ($this->iquery !== null) { $iri .= '?' . $this->iquery; @@ -1081,14 +1096,7 @@ class IRI $iri .= '#' . $this->ifragment; } - if ($iri !== '' || $defined) - { - return $iri; - } - else - { - return null; - } + return $iri; } /** @@ -1098,11 +1106,7 @@ class IRI */ private function get_uri() { - $iri = $this->iri; - if (is_string($iri)) - return $this->to_uri($iri); - else - return $iri; + return $this->to_uri($this->get_iri()); } /** @@ -1112,22 +1116,21 @@ class IRI */ private function get_iauthority() { - $iauthority = ''; - if ($this->iuserinfo !== null) - { - $iauthority .= $this->iuserinfo . '@'; - } - if ($this->ihost !== null) - { - $iauthority .= $this->ihost; - } - if ($this->port !== null) - { - $iauthority .= ':' . $this->port; - } - if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null) { + $iauthority = ''; + if ($this->iuserinfo !== null) + { + $iauthority .= $this->iuserinfo . '@'; + } + if ($this->ihost !== null) + { + $iauthority .= $this->ihost; + } + if ($this->port !== null) + { + $iauthority .= ':' . $this->port; + } return $iauthority; } else @@ -1143,255 +1146,10 @@ class IRI */ private function get_authority() { - $iauthority = $this->iauthority; + $iauthority = $this->get_iauthority(); if (is_string($iauthority)) return $this->to_uri($iauthority); else return $iauthority; } -} - -/** - * Class to validate and to work with IPv6 addresses. - * - * This was originally based on the PEAR class of the same name, but has been - * almost entirely rewritten. - */ -class Net_IPv6 -{ - /** - * Uncompresses an IPv6 address - * - * RFC 4291 allows you to compress concecutive zero pieces in an address to - * '::'. This method expects a valid IPv6 address and expands the '::' to - * the required number of zero pieces. - * - * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 - * ::1 -> 0:0:0:0:0:0:0:1 - * - * @author Alexander Merz - * @author elfrink at introweb dot nl - * @author Josh Peck - * @copyright 2003-2005 The PHP Group - * @license http://www.opensource.org/licenses/bsd-license.php - * @param string $ip An IPv6 address - * @return string The uncompressed IPv6 address - */ - public static function uncompress($ip) - { - $c1 = -1; - $c2 = -1; - if (substr_count($ip, '::') === 1) - { - list($ip1, $ip2) = explode('::', $ip); - if ($ip1 === '') - { - $c1 = -1; - } - else - { - $c1 = substr_count($ip1, ':'); - } - if ($ip2 === '') - { - $c2 = -1; - } - else - { - $c2 = substr_count($ip2, ':'); - } - if (strpos($ip2, '.') !== false) - { - $c2++; - } - // :: - if ($c1 === -1 && $c2 === -1) - { - $ip = '0:0:0:0:0:0:0:0'; - } - // ::xxx - else if ($c1 === -1) - { - $fill = str_repeat('0:', 7 - $c2); - $ip = str_replace('::', $fill, $ip); - } - // xxx:: - else if ($c2 === -1) - { - $fill = str_repeat(':0', 7 - $c1); - $ip = str_replace('::', $fill, $ip); - } - // xxx::xxx - else - { - $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); - $ip = str_replace('::', $fill, $ip); - } - } - return $ip; - } - - /** - * Compresses an IPv6 address - * - * RFC 4291 allows you to compress concecutive zero pieces in an address to - * '::'. This method expects a valid IPv6 address and compresses consecutive - * zero pieces to '::'. - * - * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 - * 0:0:0:0:0:0:0:1 -> ::1 - * - * @see uncompress() - * @param string $ip An IPv6 address - * @return string The compressed IPv6 address - */ - public static function compress($ip) - { - // Prepare the IP to be compressed - $ip = self::uncompress($ip); - $ip_parts = self::split_v6_v4($ip); - - // Break up the IP into each seperate part - $ipp = explode(':', $ip_parts[0]); - - // Initialise vars to count consecutive zero pieces - $consecutive_zeros = 0; - $max_consecutive_zeros = 0; - for ($i = 0; $i < count($ipp); $i++) - { - // Normalise the number (this changes things like 01 to 0) - $ipp[$i] = dechex(hexdec($ipp[$i])); - - // Count the zeros - if ($ipp[$i] === '0') - { - $consecutive_zeros++; - } - elseif ($consecutive_zeros > $max_consecutive_zeros) - { - $consecutive_zeros_pos = $i - $consecutive_zeros; - $max_consecutive_zeros = $consecutive_zeros; - $consecutive_zeros = 0; - } - } - if ($consecutive_zeros > $max_consecutive_zeros) - { - $consecutive_zeros_pos = $i - $consecutive_zeros; - $max_consecutive_zeros = $consecutive_zeros; - $consecutive_zeros = 0; - } - - // Rebuild the IP - if ($max_consecutive_zeros > 0) - { - $cip = ''; - for ($i = 0; $i < count($ipp); $i++) - { - // Add a : for the longest consecutive sequence, or :: if it's at the end - if ($i === $consecutive_zeros_pos) - { - if ($i === count($ipp) - $max_consecutive_zeros) - { - $cip .= '::'; - } - else - { - $cip .= ':'; - } - } - // Otherwise, just add the piece to the new output - elseif ($i < $consecutive_zeros_pos || $i >= $consecutive_zeros_pos + $max_consecutive_zeros) - { - if ($i !== 0) - { - $cip .= ':'; - } - $cip .= $ipp[$i]; - } - } - } - // Cheat if we don't have any zero pieces - else - { - $cip = implode(':', $ipp); - } - - // Re-add any IPv4 part of the address - if ($ip_parts[1] !== '') - { - $cip .= ":{$ip_parts[1]}"; - } - return $cip; - } - - /** - * Splits an IPv6 address into the IPv6 and IPv4 representation parts - * - * RFC 4291 allows you to represent the last two parts of an IPv6 address - * using the standard IPv4 representation - * - * Example: 0:0:0:0:0:0:13.1.68.3 - * 0:0:0:0:0:FFFF:129.144.52.38 - * - * @param string $ip An IPv6 address - * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part - */ - private static function split_v6_v4($ip) - { - if (strpos($ip, '.') !== false) - { - $pos = strrpos($ip, ':'); - $ipv6_part = substr($ip, 0, $pos); - $ipv4_part = substr($ip, $pos + 1); - return array($ipv6_part, $ipv4_part); - } - else - { - return array($ip, ''); - } - } - - /** - * Checks an IPv6 address - * - * Checks if the given IP is a valid IPv6 address - * - * @param string $ip An IPv6 address - * @return bool true if $ip is a valid IPv6 address - */ - public static function check_ipv6($ip) - { - $ip = self::uncompress($ip); - list($ipv6, $ipv4) = self::split_v6_v4($ip); - $ipv6 = explode(':', $ipv6); - $ipv4 = explode('.', $ipv4); - if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) - { - foreach ($ipv6 as $ipv6_part) - { - $ipv6_part = ltrim($ipv6_part, '0'); - if ($ipv6_part === '') - $ipv6_part = '0'; - $value = hexdec($ipv6_part); - if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) - return false; - } - if (count($ipv4) === 4) - { - foreach ($ipv4 as $ipv4_part) - { - $value = (int) $ipv4_part; - if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) - return false; - } - } - return true; - } - else - { - return false; - } - } -} - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/libraries/readability/Readability.php b/libraries/readability/Readability.php index 266ebca..b77a733 100644 --- a/libraries/readability/Readability.php +++ b/libraries/readability/Readability.php @@ -918,10 +918,6 @@ class Readability * @return void */ public function killBreaks($node) { - // we can't alter HTML directly through innerHTML as you can in JS - // so we go through the process of turning a DOM element to a string, - // doing the search and replace on the string, then turning it - // back into an element and replacing the old element with the new. $html = $node->innerHTML; $html = preg_replace($this->regexps['killBreaks'], '
', $html); $node->innerHTML = $html; diff --git a/libraries/simplepie/simplepie.class.php b/libraries/simplepie/simplepie.class.php index 059e58b..1a6c201 100644 --- a/libraries/simplepie/simplepie.class.php +++ b/libraries/simplepie/simplepie.class.php @@ -5,7 +5,7 @@ * A PHP-Based RSS and Atom Feed Framework. * Takes the hard work out of managing a complete RSS/Atom solution. * - * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * Copyright (c) 2004-2010, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are @@ -34,7 +34,7 @@ * * @package SimplePie * @version 1.3-dev - * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue * @author Ryan Parman * @author Geoffrey Sneddon * @author Ryan McCue @@ -43,705 +43,1309 @@ * @todo phpDoc comments */ -/** - * SimplePie Name - */ +class SimplePie extends SimplePie_Core +{ + +} + + + + +class SimplePie_Author +{ + var $name; + var $link; + var $email; + + public function __construct($name = null, $link = null, $email = null) + { + $this->name = $name; + $this->link = $link; + $this->email = $email; + } + + public function __toString() + { + return md5(serialize($this)); + } + + public function get_name() + { + if ($this->name !== null) + { + return $this->name; + } + else + { + return null; + } + } + + public function get_link() + { + if ($this->link !== null) + { + return $this->link; + } + else + { + return null; + } + } + + public function get_email() + { + if ($this->email !== null) + { + return $this->email; + } + else + { + return null; + } + } +} + + + + + +class SimplePie_Cache_DB +{ + public function prepare_simplepie_object_for_cache($data) + { + $items = $data->get_items(); + $items_by_id = array(); + + if (!empty($items)) + { + foreach ($items as $item) + { + $items_by_id[$item->get_id()] = $item; + } + + if (count($items_by_id) !== count($items)) + { + $items_by_id = array(); + foreach ($items as $item) + { + $items_by_id[$item->get_id(true)] = $item; + } + } + + if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; + } + elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; + } + elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; + } + elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]; + } + else + { + $channel = null; + } + + if ($channel !== null) + { + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']); + } + } + if (isset($data->data['items'])) + { + unset($data->data['items']); + } + if (isset($data->data['ordered_items'])) + { + unset($data->data['ordered_items']); + } + } + return array(serialize($data->data), $items_by_id); + } +} + + + + +class SimplePie_Cache_File +{ + var $location; + var $filename; + var $extension; + var $name; + + public function __construct($location, $filename, $extension) + { + $this->location = $location; + $this->filename = $filename; + $this->extension = $extension; + $this->name = "$this->location/$this->filename.$this->extension"; + } + + public function save($data) + { + if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location)) + { + if (is_a($data, 'SimplePie')) + { + $data = $data->data; + } + + $data = serialize($data); + return (bool) file_put_contents($this->name, $data); + } + return false; + } + + public function load() + { + if (file_exists($this->name) && is_readable($this->name)) + { + return unserialize(file_get_contents($this->name)); + } + return false; + } + + public function mtime() + { + if (file_exists($this->name)) + { + return filemtime($this->name); + } + return false; + } + + public function touch() + { + if (file_exists($this->name)) + { + return touch($this->name); + } + return false; + } + + public function unlink() + { + if (file_exists($this->name)) + { + return unlink($this->name); + } + return false; + } +} + + + + +class SimplePie_Cache_MySQL extends SimplePie_Cache_DB +{ + var $mysql; + var $options; + var $id; + + public function __construct($mysql_location, $name, $extension) + { + $host = $mysql_location->get_host(); + if (stripos($host, 'unix(') === 0 && substr($host, -1) === ')') + { + $server = ':' . substr($host, 5, -1); + } + else + { + $server = $host; + if ($mysql_location->get_port() !== null) + { + $server .= ':' . $mysql_location->get_port(); + } + } + + if (strpos($mysql_location->get_userinfo(), ':') !== false) + { + list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2); + } + else + { + $username = $mysql_location->get_userinfo(); + $password = null; + } + + if ($this->mysql = mysql_connect($server, $username, $password)) + { + $this->id = $name . $extension; + $this->options = SimplePie_Misc::parse_str($mysql_location->get_query()); + if (!isset($this->options['prefix'][0])) + { + $this->options['prefix'][0] = ''; + } + + if (mysql_select_db(ltrim($mysql_location->get_path(), '/')) + && mysql_query('SET NAMES utf8') + && ($query = mysql_unbuffered_query('SHOW TABLES'))) + { + $db = array(); + while ($row = mysql_fetch_row($query)) + { + $db[] = $row[0]; + } + + if (!in_array($this->options['prefix'][0] . 'cache_data', $db)) + { + 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)))')) + { + $this->mysql = null; + } + } + + if (!in_array($this->options['prefix'][0] . 'items', $db)) + { + 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)))')) + { + $this->mysql = null; + } + } + } + else + { + $this->mysql = null; + } + } + } + + public function save($data) + { + if ($this->mysql) + { + $feed_id = "'" . mysql_real_escape_string($this->id) . "'"; + + if (is_a($data, 'SimplePie')) + { + $data = clone $data; + + $prepared = $this->prepare_simplepie_object_for_cache($data); + + if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql)) + { + if (mysql_num_rows($query)) + { + $items = count($prepared[1]); + if ($items) + { + $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id; + } + else + { + $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id; + } + + if (!mysql_query($sql, $this->mysql)) + { + return false; + } + } + 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)) + { + return false; + } + + $ids = array_keys($prepared[1]); + if (!empty($ids)) + { + foreach ($ids as $id) + { + $database_ids[] = mysql_real_escape_string($id); + } + + 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)) + { + $existing_ids = array(); + while ($row = mysql_fetch_row($query)) + { + $existing_ids[] = $row[0]; + } + + $new_ids = array_diff($ids, $existing_ids); + + foreach ($new_ids as $new_id) + { + if (!($date = $prepared[1][$new_id]->get_date('U'))) + { + $date = time(); + } + + 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)) + { + return false; + } + } + return true; + } + } + else + { + return true; + } + } + } + elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql)) + { + if (mysql_num_rows($query)) + { + 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)) + { + return true; + } + } + 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)) + { + return true; + } + } + } + return false; + } + + public function load() + { + 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))) + { + $data = unserialize($row[1]); + + if (isset($this->options['items'][0])) + { + $items = (int) $this->options['items'][0]; + } + else + { + $items = (int) $row[0]; + } + + if ($items !== 0) + { + if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; + } + elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; + } + elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; + } + elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]; + } + else + { + $feed = null; + } + + if ($feed !== null) + { + $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC'; + if ($items > 0) + { + $sql .= ' LIMIT ' . $items; + } + + if ($query = mysql_unbuffered_query($sql, $this->mysql)) + { + while ($row = mysql_fetch_row($query)) + { + $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]); + } + } + else + { + return false; + } + } + } + return $data; + } + return false; + } + + public function mtime() + { + 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))) + { + return $row[0]; + } + else + { + return false; + } + } + + public function touch() + { + 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)) + { + return true; + } + else + { + return false; + } + } + + public function unlink() + { + 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))) + { + return true; + } + else + { + return false; + } + } +} + + + + +class SimplePie_Cache +{ + + private function __construct() + { + trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR); + } + + + public static function create($location, $filename, $extension) + { + $location_iri = new SimplePie_IRI($location); + switch ($location_iri->get_scheme()) + { + case 'mysql': + if (extension_loaded('mysql')) + { + return new SimplePie_Cache_MySQL($location_iri, $filename, $extension); + } + break; + + default: + return new SimplePie_Cache_File($location, $filename, $extension); + } + } +} + + + + + +class SimplePie_Caption +{ + var $type; + var $lang; + var $startTime; + var $endTime; + var $text; + + public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null) + { + $this->type = $type; + $this->lang = $lang; + $this->startTime = $startTime; + $this->endTime = $endTime; + $this->text = $text; + } + + public function __toString() + { + return md5(serialize($this)); + } + + public function get_endtime() + { + if ($this->endTime !== null) + { + return $this->endTime; + } + else + { + return null; + } + } + + public function get_language() + { + if ($this->lang !== null) + { + return $this->lang; + } + else + { + return null; + } + } + + public function get_starttime() + { + if ($this->startTime !== null) + { + return $this->startTime; + } + else + { + return null; + } + } + + public function get_text() + { + if ($this->text !== null) + { + return $this->text; + } + else + { + return null; + } + } + + public function get_type() + { + if ($this->type !== null) + { + return $this->type; + } + else + { + return null; + } + } +} + + + + + +class SimplePie_Category +{ + var $term; + var $scheme; + var $label; + + public function __construct($term = null, $scheme = null, $label = null) + { + $this->term = $term; + $this->scheme = $scheme; + $this->label = $label; + } + + public function __toString() + { + return md5(serialize($this)); + } + + public function get_term() + { + if ($this->term !== null) + { + return $this->term; + } + else + { + return null; + } + } + + public function get_scheme() + { + if ($this->scheme !== null) + { + return $this->scheme; + } + else + { + return null; + } + } + + public function get_label() + { + if ($this->label !== null) + { + return $this->label; + } + else + { + return $this->get_term(); + } + } +} + + + + + + +class SimplePie_Content_Type_Sniffer +{ + + var $file; + + + public function __construct($file) + { + $this->file = $file; + } + + + public function get_type() + { + if (isset($this->file->headers['content-type'])) + { + if (!isset($this->file->headers['content-encoding']) + && ($this->file->headers['content-type'] === 'text/plain' + || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' + || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1')) + { + return $this->text_or_binary(); + } + + if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) + { + $official = substr($this->file->headers['content-type'], 0, $pos); + } + else + { + $official = $this->file->headers['content-type']; + } + $official = strtolower($official); + + if ($official === 'unknown/unknown' + || $official === 'application/unknown') + { + return $this->unknown(); + } + elseif (substr($official, -4) === '+xml' + || $official === 'text/xml' + || $official === 'application/xml') + { + return $official; + } + elseif (substr($official, 0, 6) === 'image/') + { + if ($return = $this->image()) + { + return $return; + } + else + { + return $official; + } + } + elseif ($official === 'text/html') + { + return $this->feed_or_html(); + } + else + { + return $official; + } + } + else + { + return $this->unknown(); + } + } + + + public function text_or_binary() + { + if (substr($this->file->body, 0, 2) === "\xFE\xFF" + || substr($this->file->body, 0, 2) === "\xFF\xFE" + || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" + || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") + { + return 'text/plain'; + } + elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) + { + return 'application/octect-stream'; + } + else + { + return 'text/plain'; + } + } + + + public function unknown() + { + $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); + if (strtolower(substr($this->file->body, $ws, 14)) === 'file->body, $ws, 5)) === 'file->body, $ws, 7)) === 'file->body, 0, 5) === '%PDF-') + { + return 'application/pdf'; + } + elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') + { + return 'application/postscript'; + } + elseif (substr($this->file->body, 0, 6) === 'GIF87a' + || substr($this->file->body, 0, 6) === 'GIF89a') + { + return 'image/gif'; + } + elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") + { + return 'image/png'; + } + elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") + { + return 'image/jpeg'; + } + elseif (substr($this->file->body, 0, 2) === "\x42\x4D") + { + return 'image/bmp'; + } + else + { + return $this->text_or_binary(); + } + } + + + public function image() + { + if (substr($this->file->body, 0, 6) === 'GIF87a' + || substr($this->file->body, 0, 6) === 'GIF89a') + { + return 'image/gif'; + } + elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") + { + return 'image/png'; + } + elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") + { + return 'image/jpeg'; + } + elseif (substr($this->file->body, 0, 2) === "\x42\x4D") + { + return 'image/bmp'; + } + else + { + return false; + } + } + + + public function feed_or_html() + { + $len = strlen($this->file->body); + $pos = strspn($this->file->body, "\x09\x0A\x0D\x20"); + + while ($pos < $len) + { + switch ($this->file->body[$pos]) + { + case "\x09": + case "\x0A": + case "\x0D": + case "\x20": + $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); + continue 2; + + case '<': + $pos++; + break; + + default: + return 'text/html'; + } + + if (substr($this->file->body, $pos, 3) === '!--') + { + $pos += 3; + if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) + { + $pos += 3; + } + else + { + return 'text/html'; + } + } + elseif (substr($this->file->body, $pos, 1) === '!') + { + if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) + { + $pos++; + } + else + { + return 'text/html'; + } + } + elseif (substr($this->file->body, $pos, 1) === '?') + { + if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) + { + $pos += 2; + } + else + { + return 'text/html'; + } + } + elseif (substr($this->file->body, $pos, 3) === 'rss' + || substr($this->file->body, $pos, 7) === 'rdf:RDF') + { + return 'application/rss+xml'; + } + elseif (substr($this->file->body, $pos, 4) === 'feed') + { + return 'application/atom+xml'; + } + else + { + return 'text/html'; + } + } + + return 'text/html'; + } +} + + + + + +class SimplePie_Copyright +{ + var $url; + var $label; + + public function __construct($url = null, $label = null) + { + $this->url = $url; + $this->label = $label; + } + + public function __toString() + { + return md5(serialize($this)); + } + + public function get_url() + { + if ($this->url !== null) + { + return $this->url; + } + else + { + return null; + } + } + + public function get_attribution() + { + if ($this->label !== null) + { + return $this->label; + } + else + { + return null; + } + } +} + + + + + define('SIMPLEPIE_NAME', 'SimplePie'); -/** - * SimplePie Version - */ + define('SIMPLEPIE_VERSION', '1.3-dev'); -/** - * SimplePie Build - * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc) - */ + define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__))); -/** - * SimplePie Website URL - */ + define('SIMPLEPIE_URL', 'http://simplepie.org'); -/** - * SimplePie Useragent - * @see SimplePie::set_useragent() - */ + define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD); -/** - * SimplePie Linkback - */ + define('SIMPLEPIE_LINKBACK', '' . SIMPLEPIE_NAME . ''); -/** - * No Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_NONE', 0); -/** - * Feed Link Element Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1); -/** - * Local Feed Extension Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2); -/** - * Local Feed Body Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4); -/** - * Remote Feed Extension Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8); -/** - * Remote Feed Body Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16); -/** - * All Feed Autodiscovery - * @see SimplePie::set_autodiscovery_level() - */ + define('SIMPLEPIE_LOCATOR_ALL', 31); -/** - * No known feed type - */ + define('SIMPLEPIE_TYPE_NONE', 0); -/** - * RSS 0.90 - */ + define('SIMPLEPIE_TYPE_RSS_090', 1); -/** - * RSS 0.91 (Netscape) - */ + define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2); -/** - * RSS 0.91 (Userland) - */ + define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4); -/** - * RSS 0.91 (both Netscape and Userland) - */ + define('SIMPLEPIE_TYPE_RSS_091', 6); -/** - * RSS 0.92 - */ + define('SIMPLEPIE_TYPE_RSS_092', 8); -/** - * RSS 0.93 - */ + define('SIMPLEPIE_TYPE_RSS_093', 16); -/** - * RSS 0.94 - */ + define('SIMPLEPIE_TYPE_RSS_094', 32); -/** - * RSS 1.0 - */ + define('SIMPLEPIE_TYPE_RSS_10', 64); -/** - * RSS 2.0 - */ + define('SIMPLEPIE_TYPE_RSS_20', 128); -/** - * RDF-based RSS - */ + define('SIMPLEPIE_TYPE_RSS_RDF', 65); -/** - * Non-RDF-based RSS (truly intended as syndication format) - */ + define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190); -/** - * All RSS - */ + define('SIMPLEPIE_TYPE_RSS_ALL', 255); -/** - * Atom 0.3 - */ + define('SIMPLEPIE_TYPE_ATOM_03', 256); -/** - * Atom 1.0 - */ + define('SIMPLEPIE_TYPE_ATOM_10', 512); -/** - * All Atom - */ + define('SIMPLEPIE_TYPE_ATOM_ALL', 768); -/** - * All feed types - */ + define('SIMPLEPIE_TYPE_ALL', 1023); -/** - * No construct - */ + define('SIMPLEPIE_CONSTRUCT_NONE', 0); -/** - * Text construct - */ + define('SIMPLEPIE_CONSTRUCT_TEXT', 1); -/** - * HTML construct - */ + define('SIMPLEPIE_CONSTRUCT_HTML', 2); -/** - * XHTML construct - */ + define('SIMPLEPIE_CONSTRUCT_XHTML', 4); -/** - * base64-encoded construct - */ + define('SIMPLEPIE_CONSTRUCT_BASE64', 8); -/** - * IRI construct - */ + define('SIMPLEPIE_CONSTRUCT_IRI', 16); -/** - * A construct that might be HTML - */ + define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32); -/** - * All constructs - */ + define('SIMPLEPIE_CONSTRUCT_ALL', 63); -/** - * Don't change case - */ + define('SIMPLEPIE_SAME_CASE', 1); -/** - * Change to lowercase - */ + define('SIMPLEPIE_LOWERCASE', 2); -/** - * Change to uppercase - */ + define('SIMPLEPIE_UPPERCASE', 4); -/** - * PCRE for HTML attributes - */ + 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]*'); -/** - * PCRE for XML attributes - */ + define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*'); -/** - * XML Namespace - */ + define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace'); -/** - * Atom 1.0 Namespace - */ + define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom'); -/** - * Atom 0.3 Namespace - */ + define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#'); -/** - * RDF Namespace - */ + define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); -/** - * RSS 0.90 Namespace - */ + define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/'); -/** - * RSS 1.0 Namespace - */ + define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/'); -/** - * RSS 1.0 Content Module Namespace - */ + define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/'); -/** - * RSS 2.0 Namespace - * (Stupid, I know, but I'm certain it will confuse people less with support.) - */ + define('SIMPLEPIE_NAMESPACE_RSS_20', ''); -/** - * DC 1.0 Namespace - */ + define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/'); -/** - * DC 1.1 Namespace - */ + define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/'); -/** - * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace - */ + define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#'); -/** - * GeoRSS Namespace - */ + define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss'); -/** - * Media RSS Namespace - */ + define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/'); -/** - * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec. - */ + define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss'); -/** - * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5. - */ + define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss'); -/** - * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace. - */ + define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/'); -/** - * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace. - */ + define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss'); -/** - * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL. - */ + define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/'); -/** - * iTunes RSS Namespace - */ + define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd'); -/** - * XHTML Namespace - */ + define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml'); -/** - * IANA Link Relations Registry - */ + define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/'); -/** - * Whether we're running on PHP5 - */ + define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>=')); -/** - * No file source - */ + define('SIMPLEPIE_FILE_SOURCE_NONE', 0); -/** - * Remote file source - */ + define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1); -/** - * Local file source - */ + define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2); -/** - * fsockopen() file source - */ + define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4); -/** - * cURL file source - */ + define('SIMPLEPIE_FILE_SOURCE_CURL', 8); -/** - * file_get_contents() file source - */ + define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16); -/** - * SimplePie - * - * @package SimplePie - */ -class SimplePie + + + +class SimplePie_Core { - /** - * @var array Raw data - * @access private - */ + public $data = array(); - /** - * @var mixed Error string - * @access private - */ + public $error; - /** - * @var object Instance of SimplePie_Sanitize (or other class) - * @see SimplePie::set_sanitize_class() - * @access private - */ + public $sanitize; - /** - * @var string SimplePie Useragent - * @see SimplePie::set_useragent() - * @access private - */ + public $useragent = SIMPLEPIE_USERAGENT; - /** - * @var string Feed URL - * @see SimplePie::set_feed_url() - * @access private - */ + public $feed_url; - /** - * @var object Instance of SimplePie_File to use as a feed - * @see SimplePie::set_file() - * @access private - */ + public $file; - /** - * @var string Raw feed data - * @see SimplePie::set_raw_data() - * @access private - */ + public $raw_data; - /** - * @var int Timeout for fetching remote files - * @see SimplePie::set_timeout() - * @access private - */ + public $timeout = 10; - /** - * @var bool Forces fsockopen() to be used for remote files instead - * of cURL, even if a new enough version is installed - * @see SimplePie::force_fsockopen() - * @access private - */ + public $force_fsockopen = false; - /** - * @var bool Force the given data/URL to be treated as a feed no matter what - * it appears like - * @see SimplePie::force_feed() - * @access private - */ + public $force_feed = false; - /** - * @var bool Enable/Disable XML dump - * @see SimplePie::enable_xml_dump() - * @access private - */ + public $xml_dump = false; - /** - * @var bool Enable/Disable Caching - * @see SimplePie::enable_cache() - * @access private - */ + public $cache = true; - /** - * @var int Cache duration (in seconds) - * @see SimplePie::set_cache_duration() - * @access private - */ + public $cache_duration = 3600; - /** - * @var int Auto-discovery cache duration (in seconds) - * @see SimplePie::set_autodiscovery_cache_duration() - * @access private - */ - public $autodiscovery_cache_duration = 604800; // 7 Days. - - /** - * @var string Cache location (relative to executing script) - * @see SimplePie::set_cache_location() - * @access private - */ + + public $autodiscovery_cache_duration = 604800; + public $cache_location = './cache'; - /** - * @var string Function that creates the cache filename - * @see SimplePie::set_cache_name_function() - * @access private - */ + public $cache_name_function = 'md5'; - /** - * @var bool Reorder feed by date descending - * @see SimplePie::enable_order_by_date() - * @access private - */ + public $order_by_date = true; - /** - * @var mixed Force input encoding to be set to the follow value - * (false, or anything type-cast to false, disables this feature) - * @see SimplePie::set_input_encoding() - * @access private - */ + public $input_encoding = false; - /** - * @var int Feed Autodiscovery Level - * @see SimplePie::set_autodiscovery_level() - * @access private - */ + public $autodiscovery = SIMPLEPIE_LOCATOR_ALL; - /** - * @var string Class used for caching feeds - * @see SimplePie::set_cache_class() - * @access private - */ + public $cache_class = 'SimplePie_Cache'; - /** - * @var string Class used for locating feeds - * @see SimplePie::set_locator_class() - * @access private - */ + public $locator_class = 'SimplePie_Locator'; - /** - * @var string Class used for parsing feeds - * @see SimplePie::set_parser_class() - * @access private - */ + public $parser_class = 'SimplePie_Parser'; - /** - * @var string Class used for fetching feeds - * @see SimplePie::set_file_class() - * @access private - */ + public $file_class = 'SimplePie_File'; - /** - * @var string Class used for items - * @see SimplePie::set_item_class() - * @access private - */ + public $item_class = 'SimplePie_Item'; - /** - * @var string Class used for authors - * @see SimplePie::set_author_class() - * @access private - */ + public $author_class = 'SimplePie_Author'; - /** - * @var string Class used for categories - * @see SimplePie::set_category_class() - * @access private - */ + public $category_class = 'SimplePie_Category'; - /** - * @var string Class used for enclosures - * @see SimplePie::set_enclosures_class() - * @access private - */ + public $enclosure_class = 'SimplePie_Enclosure'; - /** - * @var string Class used for Media RSS captions - * @see SimplePie::set_caption_class() - * @access private - */ + public $caption_class = 'SimplePie_Caption'; - /** - * @var string Class used for Media RSS - * @see SimplePie::set_copyright_class() - * @access private - */ + public $copyright_class = 'SimplePie_Copyright'; - /** - * @var string Class used for Media RSS - * @see SimplePie::set_credit_class() - * @access private - */ + public $credit_class = 'SimplePie_Credit'; - /** - * @var string Class used for Media RSS - * @see SimplePie::set_rating_class() - * @access private - */ + public $rating_class = 'SimplePie_Rating'; - /** - * @var string Class used for Media RSS - * @see SimplePie::set_restriction_class() - * @access private - */ + public $restriction_class = 'SimplePie_Restriction'; - /** - * @var string Class used for content-type sniffing - * @see SimplePie::set_content_type_sniffer_class() - * @access private - */ + public $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer'; - /** - * @var string Class used for item sources. - * @see SimplePie::set_source_class() - * @access private - */ + public $source_class = 'SimplePie_Source'; - /** - * @var mixed Set javascript query string parameter (false, or - * anything type-cast to false, disables this feature) - * @see SimplePie::set_javascript() - * @access private - */ + public $javascript = 'js'; - /** - * @var int Maximum number of feeds to check with autodiscovery - * @see SimplePie::set_max_checked_feeds() - * @access private - */ + public $max_checked_feeds = 10; - /** - * @var array All the feeds found during the autodiscovery process - * @see SimplePie::get_all_discovered_feeds() - * @access private - */ + public $all_discovered_feeds = array(); - /** - * @var string Web-accessible path to the handler_image.php file. - * @see SimplePie::set_image_handler() - * @access private - */ + public $image_handler = ''; - /** - * @var array Stores the URLs when multiple feeds are being initialized. - * @see SimplePie::set_feed_url() - * @access private - */ + public $multifeed_url = array(); - /** - * @var array Stores SimplePie objects when multiple feeds initialized. - * @access private - */ + public $multifeed_objects = array(); - /** - * @var array Stores the get_object_vars() array for use with multifeeds. - * @see SimplePie::set_feed_url() - * @access private - */ + public $config_settings = null; - /** - * @var integer Stores the number of items to return per-feed with multifeeds. - * @see SimplePie::set_item_limit() - * @access private - */ + public $item_limit = 0; - /** - * @var array Stores the default attributes to be stripped by strip_attributes(). - * @see SimplePie::strip_attributes() - * @access private - */ + public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); - /** - * @var array Stores the default tags to be stripped by strip_htmltags(). - * @see SimplePie::strip_htmltags() - * @access private - */ + public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); - /** - * The SimplePie class contains feed level data and options - * - * There are two ways that you can create a new SimplePie object. The first - * is by passing a feed URL as a parameter to the SimplePie constructor - * (as well as optionally setting the cache location and cache expiry). This - * will initialise the whole feed with all of the default settings, and you - * can begin accessing methods and properties immediately. - * - * The second way is to create the SimplePie object with no parameters - * at all. This will enable you to set configuration options. After setting - * them, you must initialise the feed using $feed->init(). At that point the - * object's methods and properties will be available to you. This format is - * what is used throughout this documentation. - * - * @access public - * @since 1.0 Preview Release - */ + public function __construct() { if (version_compare(PHP_VERSION, '5.0', '<')) @@ -750,8 +1354,7 @@ class SimplePie die(); } - // Other objects, instances created here so we can set options on them - $this->sanitize = new SimplePie_Sanitize(); + $this->sanitize = new SimplePie_Sanitize(); if (func_num_args() > 0) { @@ -759,17 +1362,13 @@ class SimplePie } } - /** - * Used for converting object to a string - */ + public function __toString() { return md5(serialize($this->data)); } - /** - * Remove items that link back to this before destroying this object - */ + public function __destruct() { if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) @@ -793,35 +1392,13 @@ class SimplePie } } - /** - * Force the given data/URL to be treated as a feed no matter what it - * appears like - * - * @access public - * @since 1.1 - * @param bool $enable Force the given data/URL to be treated as a feed - */ + public function force_feed($enable = false) { $this->force_feed = (bool) $enable; } - /** - * This is the URL of the feed you want to parse. - * - * This allows you to enter the URL of the feed you want to parse, or the - * website you want to try to use auto-discovery on. This takes priority - * over any set raw data. - * - * You can set multiple feeds to mash together by passing an array instead - * of a string for the $url. Remember that with each additional feed comes - * additional processing and resources. - * - * @access public - * @since 1.0 Preview Release - * @param mixed $url This is the URL (or array of URLs) that you want to parse. - * @see SimplePie::set_raw_data() - */ + public function set_feed_url($url) { if (is_array($url)) @@ -838,13 +1415,7 @@ class SimplePie } } - /** - * Provides an instance of SimplePie_File to use as a feed - * - * @access public - * @param object &$file Instance of SimplePie_File (or subclass) - * @return bool True on success, false on failure - */ + public function set_file(&$file) { if (is_a($file, 'SimplePie_File')) @@ -856,118 +1427,55 @@ class SimplePie return false; } - /** - * Allows you to use a string of RSS/Atom data instead of a remote feed. - * - * If you have a feed available as a string in PHP, you can tell SimplePie - * to parse that data string instead of a remote feed. Any set feed URL - * takes precedence. - * - * @access public - * @since 1.0 Beta 3 - * @param string $data RSS or Atom data as a string. - * @see SimplePie::set_feed_url() - */ + public function set_raw_data($data) { $this->raw_data = $data; } - /** - * Allows you to override the default timeout for fetching remote feeds. - * - * This allows you to change the maximum time the feed's server to respond - * and send the feed back. - * - * @access public - * @since 1.0 Beta 3 - * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed. - */ + public function set_timeout($timeout = 10) { $this->timeout = (int) $timeout; } - /** - * Forces SimplePie to use fsockopen() instead of the preferred cURL - * functions. - * - * @access public - * @since 1.0 Beta 3 - * @param bool $enable Force fsockopen() to be used - */ + public function force_fsockopen($enable = false) { $this->force_fsockopen = (bool) $enable; } - /** - * Enables/disables caching in SimplePie. - * - * This option allows you to disable caching all-together in SimplePie. - * However, disabling the cache can lead to longer load times. - * - * @access public - * @since 1.0 Preview Release - * @param bool $enable Enable caching - */ + public function enable_cache($enable = true) { $this->cache = (bool) $enable; } - /** - * Set the length of time (in seconds) that the contents of a feed - * will be cached. - * - * @access public - * @param int $seconds The feed content cache duration. - */ + public function set_cache_duration($seconds = 3600) { $this->cache_duration = (int) $seconds; } - /** - * Set the length of time (in seconds) that the autodiscovered feed - * URL will be cached. - * - * @access public - * @param int $seconds The autodiscovered feed URL cache duration. - */ + public function set_autodiscovery_cache_duration($seconds = 604800) { $this->autodiscovery_cache_duration = (int) $seconds; } - /** - * Set the file system location where the cached files should be stored. - * - * @access public - * @param string $location The file system location. - */ + public function set_cache_location($location = './cache') { $this->cache_location = (string) $location; } - /** - * Determines whether feed items should be sorted into reverse chronological order. - * - * @access public - * @param bool $enable Sort as reverse chronological order. - */ + public function enable_order_by_date($enable = true) { $this->order_by_date = (bool) $enable; } - /** - * Allows you to override the character encoding reported by the feed. - * - * @access public - * @param string $encoding Character encoding. - */ + public function set_input_encoding($encoding = false) { if ($encoding) @@ -980,33 +1488,13 @@ class SimplePie } } - /** - * Set how much feed autodiscovery to do - * - * @access public - * @see SIMPLEPIE_LOCATOR_NONE - * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY - * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION - * @see SIMPLEPIE_LOCATOR_LOCAL_BODY - * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION - * @see SIMPLEPIE_LOCATOR_REMOTE_BODY - * @see SIMPLEPIE_LOCATOR_ALL - * @param int $level Feed Autodiscovery Level (level can be a - * combination of the above constants, see bitwise OR operator) - */ + public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL) { $this->autodiscovery = (int) $level; } - /** - * Allows you to change which class SimplePie uses for caching. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_cache_class($class = 'SimplePie_Cache') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache')) @@ -1017,14 +1505,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for auto-discovery. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_locator_class($class = 'SimplePie_Locator') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator')) @@ -1035,14 +1516,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for XML parsing. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_parser_class($class = 'SimplePie_Parser') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser')) @@ -1053,14 +1527,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for remote file fetching. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_file_class($class = 'SimplePie_File') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File')) @@ -1071,14 +1538,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for data sanitization. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_sanitize_class($class = 'SimplePie_Sanitize') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize')) @@ -1089,14 +1549,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for handling feed items. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_item_class($class = 'SimplePie_Item') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item')) @@ -1107,14 +1560,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for handling author data. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_author_class($class = 'SimplePie_Author') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author')) @@ -1125,14 +1571,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for handling category data. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_category_class($class = 'SimplePie_Category') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category')) @@ -1143,14 +1582,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for feed enclosures. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_enclosure_class($class = 'SimplePie_Enclosure') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure')) @@ -1161,14 +1593,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for captions - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_caption_class($class = 'SimplePie_Caption') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption')) @@ -1179,14 +1604,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_copyright_class($class = 'SimplePie_Copyright') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright')) @@ -1197,14 +1615,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_credit_class($class = 'SimplePie_Credit') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit')) @@ -1215,14 +1626,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_rating_class($class = 'SimplePie_Rating') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating')) @@ -1233,14 +1637,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_restriction_class($class = 'SimplePie_Restriction') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction')) @@ -1251,14 +1648,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses for content-type sniffing. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer')) @@ -1269,14 +1659,7 @@ class SimplePie return false; } - /** - * Allows you to change which class SimplePie uses item sources. - * Useful when you are overloading or extending SimplePie's default classes. - * - * @access public - * @param string $class Name of custom class. - * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation - */ + public function set_source_class($class = 'SimplePie_Source') { if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source')) @@ -1287,23 +1670,13 @@ class SimplePie return false; } - /** - * Allows you to override the default user agent string. - * - * @access public - * @param string $ua New user agent string. - */ + public function set_useragent($ua = SIMPLEPIE_USERAGENT) { $this->useragent = (string) $ua; } - /** - * Set callback function to create cache filename with - * - * @access public - * @param mixed $function Callback function - */ + public function set_cache_name_function($function = 'md5') { if (is_callable($function)) @@ -1312,12 +1685,7 @@ class SimplePie } } - /** - * Set javascript query string parameter - * - * @access public - * @param mixed $get Javascript query string parameter - */ + public function set_javascript($get = 'js') { if ($get) @@ -1330,13 +1698,7 @@ class SimplePie } } - /** - * Set options to make SP as fast as possible. Forgoes a - * substantial amount of data sanitization in favor of speed. - * - * @access public - * @param bool $set Whether to set them or not - */ + public function set_stupidly_fast($set = false) { if ($set) @@ -1350,12 +1712,7 @@ class SimplePie } } - /** - * Set maximum number of feeds to check with autodiscovery - * - * @access public - * @param int $max Maximum number of feeds to check - */ + public function set_max_checked_feeds($max = 10) { $this->max_checked_feeds = (int) $max; @@ -1403,26 +1760,13 @@ class SimplePie $this->sanitize->strip_comments($strip); } - /** - * Set element/attribute key/value pairs of HTML attributes - * containing URLs that need to be resolved relative to the feed - * - * @access public - * @since 1.0 - * @param array $element_attribute Element/attribute key/value pairs - */ + 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')) { $this->sanitize->set_url_replacements($element_attribute); } - /** - * Set the handler to enable the display of cached images. - * - * @access public - * @param str $page Web-accessible path to the handler_image.php file. - * @param str $qs The query string that the value should be passed to. - */ + public function set_image_handler($page = false, $qs = 'i') { if ($page !== false) @@ -1435,12 +1779,7 @@ class SimplePie } } - /** - * Set the limit for items returned per-feed with multifeeds. - * - * @access public - * @param integer $limit The maximum number of items to return. - */ + public function set_item_limit($limit = 0) { $this->item_limit = (int) $limit; @@ -1448,13 +1787,11 @@ class SimplePie public function init() { - // Check absolute bare minimum requirements. - if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre')) + if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre')) { return false; } - // 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. - elseif (!extension_loaded('xmlreader')) + elseif (!extension_loaded('xmlreader')) { static $xml_is_sane = null; if ($xml_is_sane === null) @@ -1476,8 +1813,7 @@ class SimplePie exit; } - // Pass whatever was set with config options over to the sanitizer. - $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class); + $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class); $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen); if ($this->feed_url !== null || $this->raw_data !== null) @@ -1490,38 +1826,30 @@ class SimplePie if ($this->feed_url !== null) { $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url); - // Decide whether to enable caching - if ($this->cache && $parsed_feed_url['scheme'] !== '') + if ($this->cache && $parsed_feed_url['scheme'] !== '') { $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'); } - // If it's enabled and we don't want an XML dump, use the cache - if ($cache && !$this->xml_dump) + if ($cache && !$this->xml_dump) { - // Load the Cache - $this->data = $cache->load(); + $this->data = $cache->load(); if (!empty($this->data)) { - // If the cache is for an outdated build of SimplePie - if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD) + if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD) { $cache->unlink(); $this->data = array(); } - // If we've hit a collision just rerun it with caching disabled - elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) + elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) { $cache = false; $this->data = array(); } - // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL. - elseif (isset($this->data['feed_url'])) + elseif (isset($this->data['feed_url'])) { - // If the autodiscovery cache is still valid use it. - if ($cache->mtime() + $this->autodiscovery_cache_duration > time()) + if ($cache->mtime() + $this->autodiscovery_cache_duration > time()) { - // Do not need to do feed autodiscovery yet. - if ($this->data['feed_url'] === $this->data['url']) + if ($this->data['feed_url'] === $this->data['url']) { $cache->unlink(); $this->data = array(); @@ -1533,11 +1861,9 @@ class SimplePie } } } - // Check if the cache has been updated - elseif ($cache->mtime() + $this->cache_duration < time()) + elseif ($cache->mtime() + $this->cache_duration < time()) { - // If we have last-modified and/or etag set - if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) + if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) { $headers = array(); if (isset($this->data['headers']['last-modified'])) @@ -1569,21 +1895,18 @@ class SimplePie } } } - // If the cache is still valid, just return true - else + else { return true; } } - // If the cache is empty, delete it - else + else { $cache->unlink(); $this->data = array(); } } - // 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. - if (!isset($file)) + if (!isset($file)) { if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url) { @@ -1594,8 +1917,7 @@ class SimplePie $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen); } } - // If the file connection has an error, set SimplePie::error to that and quit - if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) + if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) { $this->error = $file->error; if (!empty($this->data)) @@ -1610,13 +1932,11 @@ class SimplePie if (!$this->force_feed) { - // Check if the supplied URL is a feed, if it isn't, look for it. - $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class); + $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class); if (!$locate->is_feed($file)) { - // We need to unset this so that if SimplePie::set_file() has been called that object is untouched - unset($file); + unset($file); if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)) { if ($cache) @@ -1650,11 +1970,9 @@ class SimplePie $data = $this->raw_data; } - // Set up array of possible encodings - $encodings = array(); + $encodings = array(); - // First check to see if input has been overridden. - if ($this->input_encoding !== false) + if ($this->input_encoding !== false) { $encodings[] = $this->input_encoding; } @@ -1662,8 +1980,7 @@ class SimplePie $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity'); $text_types = array('text/xml', 'text/xml-external-parsed-entity'); - // RFC 3023 (only applies to sniffed content) - if (isset($sniffed)) + if (isset($sniffed)) { if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml') { @@ -1682,40 +1999,32 @@ class SimplePie } $encodings[] = 'US-ASCII'; } - // Text MIME-type default - elseif (substr($sniffed, 0, 5) === 'text/') + elseif (substr($sniffed, 0, 5) === 'text/') { $encodings[] = 'US-ASCII'; } } - // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1 - $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data)); + $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data)); $encodings[] = 'UTF-8'; $encodings[] = 'ISO-8859-1'; - // There's no point in trying an encoding twice - $encodings = array_unique($encodings); + $encodings = array_unique($encodings); - // If we want the XML, just output that with the most likely encoding and quit - if ($this->xml_dump) + if ($this->xml_dump) { header('Content-type: text/xml; charset=' . $encodings[0]); echo $data; exit; } - // Loop through each possible encoding, till we return something, or run out of possibilities - foreach ($encodings as $encoding) + foreach ($encodings as $encoding) { - // Change the encoding to UTF-8 (as we always use UTF-8 internally) - if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8')) + if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8')) { - // Create new parser - $parser = new $this->parser_class(); + $parser = new $this->parser_class(); - // If it's parsed fine - if ($parser->parse($utf8_data, 'UTF-8')) + if ($parser->parse($utf8_data, 'UTF-8')) { $this->data = $parser->get_data(); if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE) @@ -1726,8 +2035,7 @@ class SimplePie } $this->data['build'] = SIMPLEPIE_BUILD; - // Cache the file if caching is enabled - if ($cache && !$cache->save($this)) + if ($cache && !$cache->save($this)) { 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); } @@ -1745,8 +2053,7 @@ class SimplePie if (isset($parser)) { - // We have an error, just set SimplePie_Misc::error to it and quit - $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()); + $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()); } else { @@ -1777,12 +2084,7 @@ class SimplePie } } - /** - * Return the error message for the occured error - * - * @access public - * @return string Error message - */ + public function error() { return $this->error; @@ -1890,11 +2192,7 @@ class SimplePie return $this->data['type']; } - /** - * @todo If we have a perm redirect we should return the new URL - * @todo When we make the above change, let's support as well - * @todo Also, |atom:link|@rel=self - */ + public function subscribe_url() { if ($this->feed_url !== null) @@ -2115,9 +2413,7 @@ class SimplePie } foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) { - // This is really the label, but keep this as the term also for BC. - // Label will also work on retrieving because that falls back to term. - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); if (isset($category['attribs']['']['domain'])) { $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); @@ -2314,9 +2610,7 @@ class SimplePie } } - /** - * Added for parity between the parent-level and the item/entry-level. - */ + public function get_permalink() { return $this->get_link(0); @@ -2741,8 +3035,7 @@ class SimplePie if (!empty($this->data['items'])) { - // If we want to order it by date, check if all items have a date, and then sort it - if ($this->order_by_date && empty($this->multifeed_objects)) + if ($this->order_by_date && empty($this->multifeed_objects)) { if (!isset($this->data['ordered_items'])) { @@ -2769,8 +3062,7 @@ class SimplePie $items = $this->data['items']; } - // Slice the data as desired - if ($end === 0) + if ($end === 0) { return array_slice($items, $start); } @@ -2785,17 +3077,13 @@ class SimplePie } } - /** - * @static - */ + public function sort_items($a, $b) { return $a->get_date('U') <= $b->get_date('U'); } - /** - * @static - */ + public function merge_items($urls, $start = 0, $end = 0, $limit = 0) { if (is_array($urls) && sizeof($urls) > 0) @@ -2845,3165 +3133,32 @@ class SimplePie } } -class SimplePie_Item + + + +class SimplePie_Credit { - var $feed; - var $data = array(); - - public function __construct($feed, $data) - { - $this->feed = $feed; - $this->data = $data; - } - - public function __toString() - { - return md5(serialize($this->data)); - } - - /** - * Remove items that link back to this before destroying this object - */ - public function __destruct() - { - if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) - { - unset($this->feed); - } - } - - public function get_item_tags($namespace, $tag) - { - if (isset($this->data['child'][$namespace][$tag])) - { - return $this->data['child'][$namespace][$tag]; - } - else - { - return null; - } - } - - public function get_base($element = array()) - { - return $this->feed->get_base($element); - } - - public function sanitize($data, $type, $base = '') - { - return $this->feed->sanitize($data, $type, $base); - } - - public function get_feed() - { - return $this->feed; - } - - public function get_id($hash = false) - { - if (!$hash) - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif (($return = $this->get_permalink()) !== null) - { - return $return; - } - elseif (($return = $this->get_title()) !== null) - { - return $return; - } - } - if ($this->get_permalink() !== null || $this->get_title() !== null) - { - return md5($this->get_permalink() . $this->get_title()); - } - else - { - return md5(serialize($this->data)); - } - } - - public function get_title() - { - if (!isset($this->data['title'])) - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) - { - $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $this->data['title'] = null; - } - } - return $this->data['title']; - } - - public function get_description($description_only = false) - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML); - } - - elseif (!$description_only) - { - return $this->get_content(true); - } - else - { - return null; - } - } - - public function get_content($content_only = false) - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); - } - elseif (!$content_only) - { - return $this->get_description(true); - } - else - { - return null; - } - } - - public function get_category($key = 0) - { - $categories = $this->get_categories(); - if (isset($categories[$key])) - { - return $categories[$key]; - } - else - { - return null; - } - } - - public function get_categories() - { - $categories = array(); - - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['attribs']['']['term'])) - { - $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories[] = new $this->feed->category_class($term, $scheme, $label); - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) - { - // This is really the label, but keep this as the term also for BC. - // Label will also work on retrieving because that falls back to term. - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - if (isset($category['attribs']['']['domain'])) - { - $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = null; - } - $categories[] = new $this->feed->category_class($term, $scheme, null); - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) - { - $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) - { - $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - - if (!empty($categories)) - { - return SimplePie_Misc::array_unique($categories); - } - else - { - return null; - } - } - - public function get_author($key = 0) - { - $authors = $this->get_authors(); - if (isset($authors[$key])) - { - return $authors[$key]; - } - else - { - return null; - } - } - - public function get_contributor($key = 0) - { - $contributors = $this->get_contributors(); - if (isset($contributors[$key])) - { - return $contributors[$key]; - } - else - { - return null; - } - } - - public function get_contributors() - { - $contributors = array(); - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) - { - $name = null; - $uri = null; - $email = null; - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) - { - $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) - { - $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])); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) - { - $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $uri !== null) - { - $contributors[] = new $this->feed->author_class($name, $uri, $email); - } - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) - { - $name = null; - $url = null; - $email = null; - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) - { - $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) - { - $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])); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) - { - $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $url !== null) - { - $contributors[] = new $this->feed->author_class($name, $url, $email); - } - } - - if (!empty($contributors)) - { - return SimplePie_Misc::array_unique($contributors); - } - else - { - return null; - } - } - - public function get_authors() - { - $authors = array(); - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) - { - $name = null; - $uri = null; - $email = null; - if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) - { - $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) - { - $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])); - } - if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) - { - $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $uri !== null) - { - $authors[] = new $this->feed->author_class($name, $uri, $email); - } - } - if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) - { - $name = null; - $url = null; - $email = null; - if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) - { - $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) - { - $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])); - } - if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) - { - $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $url !== null) - { - $authors[] = new $this->feed->author_class($name, $url, $email); - } - } - if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author')) - { - $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) - { - $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) - { - $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) - { - $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - - if (!empty($authors)) - { - return SimplePie_Misc::array_unique($authors); - } - elseif (($source = $this->get_source()) && ($authors = $source->get_authors())) - { - return $authors; - } - elseif ($authors = $this->feed->get_authors()) - { - return $authors; - } - else - { - return null; - } - } - - public function get_copyright() - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - return null; - } - } - - public function get_date($date_format = 'j F Y, g:i a') - { - if (!isset($this->data['date'])) - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date')) - { - $this->data['date']['raw'] = $return[0]['data']; - } - - if (!empty($this->data['date']['raw'])) - { - $parser = SimplePie_Parse_Date::get(); - $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']); - } - else - { - $this->data['date'] = null; - } - } - if ($this->data['date']) - { - $date_format = (string) $date_format; - switch ($date_format) - { - case '': - return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT); - - case 'U': - return $this->data['date']['parsed']; - - default: - return date($date_format, $this->data['date']['parsed']); - } - } - else - { - return null; - } - } - - public function get_local_date($date_format = '%c') - { - if (!$date_format) - { - return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif (($date = $this->get_date('U')) !== null && $date !== false) - { - return strftime($date_format, $date); - } - else - { - return null; - } - } - - public function get_permalink() - { - $link = $this->get_link(); - $enclosure = $this->get_enclosure(0); - if ($link !== null) - { - return $link; - } - elseif ($enclosure !== null) - { - return $enclosure->get_link(); - } - else - { - return null; - } - } - - public function get_link($key = 0, $rel = 'alternate') - { - $links = $this->get_links($rel); - if ($links[$key] !== null) - { - return $links[$key]; - } - else - { - return null; - } - } - - public function get_links($rel = 'alternate') - { - if (!isset($this->data['links'])) - { - $this->data['links'] = array(); - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) - { - if (isset($link['attribs']['']['href'])) - { - $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; - $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - - } - } - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) - { - if (isset($link['attribs']['']['href'])) - { - $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; - $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - } - } - if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) - { - if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true') - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - } - - $keys = array_keys($this->data['links']); - foreach ($keys as $key) - { - if (SimplePie_Misc::is_isegment_nz_nc($key)) - { - if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) - { - $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); - $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; - } - else - { - $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; - } - } - elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) - { - $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; - } - $this->data['links'][$key] = array_unique($this->data['links'][$key]); - } - } - if (isset($this->data['links'][$rel])) - { - return $this->data['links'][$rel]; - } - else - { - return null; - } - } - - /** - * @todo Add ability to prefer one type of content over another (in a media group). - */ - public function get_enclosure($key = 0, $prefer = null) - { - $enclosures = $this->get_enclosures(); - if (isset($enclosures[$key])) - { - return $enclosures[$key]; - } - else - { - return null; - } - } - - /** - * Grabs all available enclosures (podcasts, etc.) - * - * Supports the RSS tag, as well as Media RSS and iTunes RSS. - * - * 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. - * - * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4). - * @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). - */ - public function get_enclosures() - { - if (!isset($this->data['enclosures'])) - { - $this->data['enclosures'] = array(); - - // Elements - $captions_parent = null; - $categories_parent = null; - $copyrights_parent = null; - $credits_parent = null; - $description_parent = null; - $duration_parent = null; - $hashes_parent = null; - $keywords_parent = null; - $player_parent = null; - $ratings_parent = null; - $restrictions_parent = null; - $thumbnails_parent = null; - $title_parent = null; - - // Let's do the channel and item-level ones first, and just re-use them if we need to. - $parent = $this->get_feed(); - - // CAPTIONS - if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) - { - foreach ($captions as $caption) - { - $caption_type = null; - $caption_lang = null; - $caption_startTime = null; - $caption_endTime = null; - $caption_text = null; - if (isset($caption['attribs']['']['type'])) - { - $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['lang'])) - { - $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['start'])) - { - $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['end'])) - { - $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['data'])) - { - $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); - } - } - elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) - { - foreach ($captions as $caption) - { - $caption_type = null; - $caption_lang = null; - $caption_startTime = null; - $caption_endTime = null; - $caption_text = null; - if (isset($caption['attribs']['']['type'])) - { - $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['lang'])) - { - $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['start'])) - { - $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['end'])) - { - $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['data'])) - { - $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); - } - } - if (is_array($captions_parent)) - { - $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent)); - } - - // CATEGORIES - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['data'])) - { - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = 'http://search.yahoo.com/mrss/category_schema'; - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); - } - foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['data'])) - { - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = 'http://search.yahoo.com/mrss/category_schema'; - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); - } - foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category) - { - $term = null; - $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; - $label = null; - if (isset($category['attribs']['']['text'])) - { - $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); - - if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'])) - { - foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory) - { - if (isset($subcategory['attribs']['']['text'])) - { - $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); - } - } - } - if (is_array($categories_parent)) - { - $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent)); - } - - // COPYRIGHT - if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) - { - $copyright_url = null; - $copyright_label = null; - if (isset($copyright[0]['attribs']['']['url'])) - { - $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($copyright[0]['data'])) - { - $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label); - } - elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) - { - $copyright_url = null; - $copyright_label = null; - if (isset($copyright[0]['attribs']['']['url'])) - { - $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($copyright[0]['data'])) - { - $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label); - } - - // CREDITS - if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) - { - foreach ($credits as $credit) - { - $credit_role = null; - $credit_scheme = null; - $credit_name = null; - if (isset($credit['attribs']['']['role'])) - { - $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($credit['attribs']['']['scheme'])) - { - $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $credit_scheme = 'urn:ebu'; - } - if (isset($credit['data'])) - { - $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); - } - } - elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) - { - foreach ($credits as $credit) - { - $credit_role = null; - $credit_scheme = null; - $credit_name = null; - if (isset($credit['attribs']['']['role'])) - { - $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($credit['attribs']['']['scheme'])) - { - $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $credit_scheme = 'urn:ebu'; - } - if (isset($credit['data'])) - { - $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); - } - } - if (is_array($credits_parent)) - { - $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent)); - } - - // DESCRIPTION - if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) - { - if (isset($description_parent[0]['data'])) - { - $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - } - elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) - { - if (isset($description_parent[0]['data'])) - { - $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - } - - // DURATION - if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration')) - { - $seconds = null; - $minutes = null; - $hours = null; - if (isset($duration_parent[0]['data'])) - { - $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - if (sizeof($temp) > 0) - { - $seconds = (int) array_pop($temp); - } - if (sizeof($temp) > 0) - { - $minutes = (int) array_pop($temp); - $seconds += $minutes * 60; - } - if (sizeof($temp) > 0) - { - $hours = (int) array_pop($temp); - $seconds += $hours * 3600; - } - unset($temp); - $duration_parent = $seconds; - } - } - - // HASHES - if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) - { - foreach ($hashes_iterator as $hash) - { - $value = null; - $algo = null; - if (isset($hash['data'])) - { - $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($hash['attribs']['']['algo'])) - { - $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $algo = 'md5'; - } - $hashes_parent[] = $algo.':'.$value; - } - } - elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) - { - foreach ($hashes_iterator as $hash) - { - $value = null; - $algo = null; - if (isset($hash['data'])) - { - $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($hash['attribs']['']['algo'])) - { - $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $algo = 'md5'; - } - $hashes_parent[] = $algo.':'.$value; - } - } - if (is_array($hashes_parent)) - { - $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent)); - } - - // KEYWORDS - if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) - { - if (isset($keywords[0]['data'])) - { - $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords_parent[] = trim($word); - } - } - unset($temp); - } - elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) - { - if (isset($keywords[0]['data'])) - { - $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords_parent[] = trim($word); - } - } - unset($temp); - } - elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) - { - if (isset($keywords[0]['data'])) - { - $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords_parent[] = trim($word); - } - } - unset($temp); - } - elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) - { - if (isset($keywords[0]['data'])) - { - $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords_parent[] = trim($word); - } - } - unset($temp); - } - if (is_array($keywords_parent)) - { - $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent)); - } - - // PLAYER - if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) - { - if (isset($player_parent[0]['attribs']['']['url'])) - { - $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - } - elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) - { - if (isset($player_parent[0]['attribs']['']['url'])) - { - $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - } - - // RATINGS - if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) - { - foreach ($ratings as $rating) - { - $rating_scheme = null; - $rating_value = null; - if (isset($rating['attribs']['']['scheme'])) - { - $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $rating_scheme = 'urn:simple'; - } - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - } - elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) - { - foreach ($ratings as $rating) - { - $rating_scheme = 'urn:itunes'; - $rating_value = null; - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - } - elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) - { - foreach ($ratings as $rating) - { - $rating_scheme = null; - $rating_value = null; - if (isset($rating['attribs']['']['scheme'])) - { - $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $rating_scheme = 'urn:simple'; - } - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - } - elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) - { - foreach ($ratings as $rating) - { - $rating_scheme = 'urn:itunes'; - $rating_value = null; - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - } - if (is_array($ratings_parent)) - { - $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent)); - } - - // RESTRICTIONS - if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) - { - foreach ($restrictions as $restriction) - { - $restriction_relationship = null; - $restriction_type = null; - $restriction_value = null; - if (isset($restriction['attribs']['']['relationship'])) - { - $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['attribs']['']['type'])) - { - $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['data'])) - { - $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - } - elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) - { - foreach ($restrictions as $restriction) - { - $restriction_relationship = 'allow'; - $restriction_type = null; - $restriction_value = 'itunes'; - if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') - { - $restriction_relationship = 'deny'; - } - $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - } - elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) - { - foreach ($restrictions as $restriction) - { - $restriction_relationship = null; - $restriction_type = null; - $restriction_value = null; - if (isset($restriction['attribs']['']['relationship'])) - { - $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['attribs']['']['type'])) - { - $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['data'])) - { - $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - } - elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) - { - foreach ($restrictions as $restriction) - { - $restriction_relationship = 'allow'; - $restriction_type = null; - $restriction_value = 'itunes'; - if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') - { - $restriction_relationship = 'deny'; - } - $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - } - if (is_array($restrictions_parent)) - { - $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent)); - } - - // THUMBNAILS - if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) - { - foreach ($thumbnails as $thumbnail) - { - if (isset($thumbnail['attribs']['']['url'])) - { - $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - } - } - elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) - { - foreach ($thumbnails as $thumbnail) - { - if (isset($thumbnail['attribs']['']['url'])) - { - $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - } - } - - // TITLES - if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) - { - if (isset($title_parent[0]['data'])) - { - $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - } - elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) - { - if (isset($title_parent[0]['data'])) - { - $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - } - - // Clear the memory - unset($parent); - - // Attributes - $bitrate = null; - $channels = null; - $duration = null; - $expression = null; - $framerate = null; - $height = null; - $javascript = null; - $lang = null; - $length = null; - $medium = null; - $samplingrate = null; - $type = null; - $url = null; - $width = null; - - // Elements - $captions = null; - $categories = null; - $copyrights = null; - $credits = null; - $description = null; - $hashes = null; - $keywords = null; - $player = null; - $ratings = null; - $restrictions = null; - $thumbnails = null; - $title = null; - - // If we have media:group tags, loop through them. - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group) - { - if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) - { - // If we have media:content tags, loop through them. - foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) - { - if (isset($content['attribs']['']['url'])) - { - // Attributes - $bitrate = null; - $channels = null; - $duration = null; - $expression = null; - $framerate = null; - $height = null; - $javascript = null; - $lang = null; - $length = null; - $medium = null; - $samplingrate = null; - $type = null; - $url = null; - $width = null; - - // Elements - $captions = null; - $categories = null; - $copyrights = null; - $credits = null; - $description = null; - $hashes = null; - $keywords = null; - $player = null; - $ratings = null; - $restrictions = null; - $thumbnails = null; - $title = null; - - // Start checking the attributes of media:content - if (isset($content['attribs']['']['bitrate'])) - { - $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['channels'])) - { - $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['duration'])) - { - $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $duration = $duration_parent; - } - if (isset($content['attribs']['']['expression'])) - { - $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['framerate'])) - { - $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['height'])) - { - $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['lang'])) - { - $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['fileSize'])) - { - $length = ceil($content['attribs']['']['fileSize']); - } - if (isset($content['attribs']['']['medium'])) - { - $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['samplingrate'])) - { - $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['type'])) - { - $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['width'])) - { - $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - - // Checking the other optional media: elements. Priority: media:content, media:group, item, channel - - // CAPTIONS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) - { - $caption_type = null; - $caption_lang = null; - $caption_startTime = null; - $caption_endTime = null; - $caption_text = null; - if (isset($caption['attribs']['']['type'])) - { - $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['lang'])) - { - $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['start'])) - { - $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['end'])) - { - $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['data'])) - { - $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); - } - if (is_array($captions)) - { - $captions = array_values(SimplePie_Misc::array_unique($captions)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) - { - foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) - { - $caption_type = null; - $caption_lang = null; - $caption_startTime = null; - $caption_endTime = null; - $caption_text = null; - if (isset($caption['attribs']['']['type'])) - { - $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['lang'])) - { - $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['start'])) - { - $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['end'])) - { - $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['data'])) - { - $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); - } - if (is_array($captions)) - { - $captions = array_values(SimplePie_Misc::array_unique($captions)); - } - } - else - { - $captions = $captions_parent; - } - - // CATEGORIES - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) - { - foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['data'])) - { - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = 'http://search.yahoo.com/mrss/category_schema'; - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories[] = new $this->feed->category_class($term, $scheme, $label); - } - } - if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) - { - foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['data'])) - { - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = 'http://search.yahoo.com/mrss/category_schema'; - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories[] = new $this->feed->category_class($term, $scheme, $label); - } - } - if (is_array($categories) && is_array($categories_parent)) - { - $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent))); - } - elseif (is_array($categories)) - { - $categories = array_values(SimplePie_Misc::array_unique($categories)); - } - elseif (is_array($categories_parent)) - { - $categories = array_values(SimplePie_Misc::array_unique($categories_parent)); - } - - // COPYRIGHTS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) - { - $copyright_url = null; - $copyright_label = null; - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) - { - $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) - { - $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label); - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) - { - $copyright_url = null; - $copyright_label = null; - if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) - { - $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) - { - $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label); - } - else - { - $copyrights = $copyrights_parent; - } - - // CREDITS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) - { - $credit_role = null; - $credit_scheme = null; - $credit_name = null; - if (isset($credit['attribs']['']['role'])) - { - $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($credit['attribs']['']['scheme'])) - { - $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $credit_scheme = 'urn:ebu'; - } - if (isset($credit['data'])) - { - $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); - } - if (is_array($credits)) - { - $credits = array_values(SimplePie_Misc::array_unique($credits)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) - { - foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) - { - $credit_role = null; - $credit_scheme = null; - $credit_name = null; - if (isset($credit['attribs']['']['role'])) - { - $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($credit['attribs']['']['scheme'])) - { - $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $credit_scheme = 'urn:ebu'; - } - if (isset($credit['data'])) - { - $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); - } - if (is_array($credits)) - { - $credits = array_values(SimplePie_Misc::array_unique($credits)); - } - } - else - { - $credits = $credits_parent; - } - - // DESCRIPTION - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) - { - $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) - { - $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $description = $description_parent; - } - - // HASHES - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) - { - $value = null; - $algo = null; - if (isset($hash['data'])) - { - $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($hash['attribs']['']['algo'])) - { - $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $algo = 'md5'; - } - $hashes[] = $algo.':'.$value; - } - if (is_array($hashes)) - { - $hashes = array_values(SimplePie_Misc::array_unique($hashes)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) - { - foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) - { - $value = null; - $algo = null; - if (isset($hash['data'])) - { - $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($hash['attribs']['']['algo'])) - { - $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $algo = 'md5'; - } - $hashes[] = $algo.':'.$value; - } - if (is_array($hashes)) - { - $hashes = array_values(SimplePie_Misc::array_unique($hashes)); - } - } - else - { - $hashes = $hashes_parent; - } - - // KEYWORDS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) - { - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) - { - $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords[] = trim($word); - } - unset($temp); - } - if (is_array($keywords)) - { - $keywords = array_values(SimplePie_Misc::array_unique($keywords)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) - { - if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) - { - $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords[] = trim($word); - } - unset($temp); - } - if (is_array($keywords)) - { - $keywords = array_values(SimplePie_Misc::array_unique($keywords)); - } - } - else - { - $keywords = $keywords_parent; - } - - // PLAYER - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) - { - $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) - { - $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - else - { - $player = $player_parent; - } - - // RATINGS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) - { - $rating_scheme = null; - $rating_value = null; - if (isset($rating['attribs']['']['scheme'])) - { - $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $rating_scheme = 'urn:simple'; - } - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - if (is_array($ratings)) - { - $ratings = array_values(SimplePie_Misc::array_unique($ratings)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) - { - foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) - { - $rating_scheme = null; - $rating_value = null; - if (isset($rating['attribs']['']['scheme'])) - { - $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $rating_scheme = 'urn:simple'; - } - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - if (is_array($ratings)) - { - $ratings = array_values(SimplePie_Misc::array_unique($ratings)); - } - } - else - { - $ratings = $ratings_parent; - } - - // RESTRICTIONS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) - { - $restriction_relationship = null; - $restriction_type = null; - $restriction_value = null; - if (isset($restriction['attribs']['']['relationship'])) - { - $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['attribs']['']['type'])) - { - $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['data'])) - { - $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - if (is_array($restrictions)) - { - $restrictions = array_values(SimplePie_Misc::array_unique($restrictions)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) - { - foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) - { - $restriction_relationship = null; - $restriction_type = null; - $restriction_value = null; - if (isset($restriction['attribs']['']['relationship'])) - { - $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['attribs']['']['type'])) - { - $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['data'])) - { - $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - if (is_array($restrictions)) - { - $restrictions = array_values(SimplePie_Misc::array_unique($restrictions)); - } - } - else - { - $restrictions = $restrictions_parent; - } - - // THUMBNAILS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) - { - $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - if (is_array($thumbnails)) - { - $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails)); - } - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) - { - foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) - { - $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - if (is_array($thumbnails)) - { - $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails)); - } - } - else - { - $thumbnails = $thumbnails_parent; - } - - // TITLES - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) - { - $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) - { - $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $title = $title_parent; - } - - $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); - } - } - } - } - - // If we have standalone media:content tags, loop through them. - if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) - { - foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) - { - if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) - { - // Attributes - $bitrate = null; - $channels = null; - $duration = null; - $expression = null; - $framerate = null; - $height = null; - $javascript = null; - $lang = null; - $length = null; - $medium = null; - $samplingrate = null; - $type = null; - $url = null; - $width = null; - - // Elements - $captions = null; - $categories = null; - $copyrights = null; - $credits = null; - $description = null; - $hashes = null; - $keywords = null; - $player = null; - $ratings = null; - $restrictions = null; - $thumbnails = null; - $title = null; - - // Start checking the attributes of media:content - if (isset($content['attribs']['']['bitrate'])) - { - $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['channels'])) - { - $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['duration'])) - { - $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $duration = $duration_parent; - } - if (isset($content['attribs']['']['expression'])) - { - $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['framerate'])) - { - $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['height'])) - { - $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['lang'])) - { - $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['fileSize'])) - { - $length = ceil($content['attribs']['']['fileSize']); - } - if (isset($content['attribs']['']['medium'])) - { - $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['samplingrate'])) - { - $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['type'])) - { - $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['width'])) - { - $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['attribs']['']['url'])) - { - $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - // Checking the other optional media: elements. Priority: media:content, media:group, item, channel - - // CAPTIONS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) - { - $caption_type = null; - $caption_lang = null; - $caption_startTime = null; - $caption_endTime = null; - $caption_text = null; - if (isset($caption['attribs']['']['type'])) - { - $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['lang'])) - { - $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['start'])) - { - $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['attribs']['']['end'])) - { - $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($caption['data'])) - { - $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); - } - if (is_array($captions)) - { - $captions = array_values(SimplePie_Misc::array_unique($captions)); - } - } - else - { - $captions = $captions_parent; - } - - // CATEGORIES - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) - { - foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['data'])) - { - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = 'http://search.yahoo.com/mrss/category_schema'; - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories[] = new $this->feed->category_class($term, $scheme, $label); - } - } - if (is_array($categories) && is_array($categories_parent)) - { - $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent))); - } - elseif (is_array($categories)) - { - $categories = array_values(SimplePie_Misc::array_unique($categories)); - } - elseif (is_array($categories_parent)) - { - $categories = array_values(SimplePie_Misc::array_unique($categories_parent)); - } - else - { - $categories = null; - } - - // COPYRIGHTS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) - { - $copyright_url = null; - $copyright_label = null; - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) - { - $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) - { - $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label); - } - else - { - $copyrights = $copyrights_parent; - } - - // CREDITS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) - { - $credit_role = null; - $credit_scheme = null; - $credit_name = null; - if (isset($credit['attribs']['']['role'])) - { - $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($credit['attribs']['']['scheme'])) - { - $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $credit_scheme = 'urn:ebu'; - } - if (isset($credit['data'])) - { - $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); - } - if (is_array($credits)) - { - $credits = array_values(SimplePie_Misc::array_unique($credits)); - } - } - else - { - $credits = $credits_parent; - } - - // DESCRIPTION - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) - { - $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $description = $description_parent; - } - - // HASHES - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) - { - $value = null; - $algo = null; - if (isset($hash['data'])) - { - $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($hash['attribs']['']['algo'])) - { - $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $algo = 'md5'; - } - $hashes[] = $algo.':'.$value; - } - if (is_array($hashes)) - { - $hashes = array_values(SimplePie_Misc::array_unique($hashes)); - } - } - else - { - $hashes = $hashes_parent; - } - - // KEYWORDS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) - { - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) - { - $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); - foreach ($temp as $word) - { - $keywords[] = trim($word); - } - unset($temp); - } - if (is_array($keywords)) - { - $keywords = array_values(SimplePie_Misc::array_unique($keywords)); - } - } - else - { - $keywords = $keywords_parent; - } - - // PLAYER - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) - { - $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - else - { - $player = $player_parent; - } - - // RATINGS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) - { - $rating_scheme = null; - $rating_value = null; - if (isset($rating['attribs']['']['scheme'])) - { - $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $rating_scheme = 'urn:simple'; - } - if (isset($rating['data'])) - { - $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value); - } - if (is_array($ratings)) - { - $ratings = array_values(SimplePie_Misc::array_unique($ratings)); - } - } - else - { - $ratings = $ratings_parent; - } - - // RESTRICTIONS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) - { - $restriction_relationship = null; - $restriction_type = null; - $restriction_value = null; - if (isset($restriction['attribs']['']['relationship'])) - { - $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['attribs']['']['type'])) - { - $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($restriction['data'])) - { - $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); - } - if (is_array($restrictions)) - { - $restrictions = array_values(SimplePie_Misc::array_unique($restrictions)); - } - } - else - { - $restrictions = $restrictions_parent; - } - - // THUMBNAILS - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) - { - foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) - { - $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); - } - if (is_array($thumbnails)) - { - $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails)); - } - } - else - { - $thumbnails = $thumbnails_parent; - } - - // TITLES - if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) - { - $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $title = $title_parent; - } - - $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); - } - } - } - - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) - { - if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') - { - // Attributes - $bitrate = null; - $channels = null; - $duration = null; - $expression = null; - $framerate = null; - $height = null; - $javascript = null; - $lang = null; - $length = null; - $medium = null; - $samplingrate = null; - $type = null; - $url = null; - $width = null; - - $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - if (isset($link['attribs']['']['type'])) - { - $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($link['attribs']['']['length'])) - { - $length = ceil($link['attribs']['']['length']); - } - - // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor - $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); - } - } - - foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) - { - if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') - { - // Attributes - $bitrate = null; - $channels = null; - $duration = null; - $expression = null; - $framerate = null; - $height = null; - $javascript = null; - $lang = null; - $length = null; - $medium = null; - $samplingrate = null; - $type = null; - $url = null; - $width = null; - - $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - if (isset($link['attribs']['']['type'])) - { - $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($link['attribs']['']['length'])) - { - $length = ceil($link['attribs']['']['length']); - } - - // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor - $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); - } - } - - if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure')) - { - if (isset($enclosure[0]['attribs']['']['url'])) - { - // Attributes - $bitrate = null; - $channels = null; - $duration = null; - $expression = null; - $framerate = null; - $height = null; - $javascript = null; - $lang = null; - $length = null; - $medium = null; - $samplingrate = null; - $type = null; - $url = null; - $width = null; - - $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0])); - if (isset($enclosure[0]['attribs']['']['type'])) - { - $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($enclosure[0]['attribs']['']['length'])) - { - $length = ceil($enclosure[0]['attribs']['']['length']); - } - - // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor - $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); - } - } - - 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)) - { - // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor - $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); - } - - $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures'])); - } - if (!empty($this->data['enclosures'])) - { - return $this->data['enclosures']; - } - else - { - return null; - } - } - - public function get_latitude() - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) - { - return (float) $return[0]['data']; - } - 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)) - { - return (float) $match[1]; - } - else - { - return null; - } - } - - public function get_longitude() - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) - { - return (float) $return[0]['data']; - } - elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) - { - return (float) $return[0]['data']; - } - 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)) - { - return (float) $match[2]; - } - else - { - return null; - } - } - - public function get_source() - { - if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source')) - { - return new $this->feed->source_class($this, $return[0]); - } - else - { - return null; - } - } -} - -class SimplePie_Source -{ - var $item; - var $data = array(); - - public function __construct($item, $data) - { - $this->item = $item; - $this->data = $data; - } - - public function __toString() - { - return md5(serialize($this->data)); - } - - public function get_source_tags($namespace, $tag) - { - if (isset($this->data['child'][$namespace][$tag])) - { - return $this->data['child'][$namespace][$tag]; - } - else - { - return null; - } - } - - public function get_base($element = array()) - { - return $this->item->get_base($element); - } - - public function sanitize($data, $type, $base = '') - { - return $this->item->sanitize($data, $type, $base); - } - - public function get_item() - { - return $this->item; - } - - public function get_title() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - return null; - } - } - - public function get_category($key = 0) - { - $categories = $this->get_categories(); - if (isset($categories[$key])) - { - return $categories[$key]; - } - else - { - return null; - } - } - - public function get_categories() - { - $categories = array(); - - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) - { - $term = null; - $scheme = null; - $label = null; - if (isset($category['attribs']['']['term'])) - { - $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['scheme'])) - { - $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($category['attribs']['']['label'])) - { - $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); - } - $categories[] = new $this->item->feed->category_class($term, $scheme, $label); - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) - { - // This is really the label, but keep this as the term also for BC. - // Label will also work on retrieving because that falls back to term. - $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); - if (isset($category['attribs']['']['domain'])) - { - $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - $scheme = null; - } - $categories[] = new $this->item->feed->category_class($term, $scheme, null); - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) - { - $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) - { - $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - - if (!empty($categories)) - { - return SimplePie_Misc::array_unique($categories); - } - else - { - return null; - } - } - - public function get_author($key = 0) - { - $authors = $this->get_authors(); - if (isset($authors[$key])) - { - return $authors[$key]; - } - else - { - return null; - } - } - - public function get_authors() - { - $authors = array(); - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) - { - $name = null; - $uri = null; - $email = null; - if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) - { - $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) - { - $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])); - } - if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) - { - $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $uri !== null) - { - $authors[] = new $this->item->feed->author_class($name, $uri, $email); - } - } - if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) - { - $name = null; - $url = null; - $email = null; - if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) - { - $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) - { - $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])); - } - if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) - { - $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $url !== null) - { - $authors[] = new $this->item->feed->author_class($name, $url, $email); - } - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) - { - $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) - { - $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) - { - $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); - } - - if (!empty($authors)) - { - return SimplePie_Misc::array_unique($authors); - } - else - { - return null; - } - } - - public function get_contributor($key = 0) - { - $contributors = $this->get_contributors(); - if (isset($contributors[$key])) - { - return $contributors[$key]; - } - else - { - return null; - } - } - - public function get_contributors() - { - $contributors = array(); - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) - { - $name = null; - $uri = null; - $email = null; - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) - { - $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) - { - $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])); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) - { - $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $uri !== null) - { - $contributors[] = new $this->item->feed->author_class($name, $uri, $email); - } - } - foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) - { - $name = null; - $url = null; - $email = null; - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) - { - $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) - { - $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])); - } - if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) - { - $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - if ($name !== null || $email !== null || $url !== null) - { - $contributors[] = new $this->item->feed->author_class($name, $url, $email); - } - } - - if (!empty($contributors)) - { - return SimplePie_Misc::array_unique($contributors); - } - else - { - return null; - } - } - - public function get_link($key = 0, $rel = 'alternate') - { - $links = $this->get_links($rel); - if (isset($links[$key])) - { - return $links[$key]; - } - else - { - return null; - } - } - - /** - * Added for parity between the parent-level and the item/entry-level. - */ - public function get_permalink() - { - return $this->get_link(0); - } - - public function get_links($rel = 'alternate') - { - if (!isset($this->data['links'])) - { - $this->data['links'] = array(); - if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link')) - { - foreach ($links as $link) - { - if (isset($link['attribs']['']['href'])) - { - $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; - $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - } - } - } - if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link')) - { - foreach ($links as $link) - { - if (isset($link['attribs']['']['href'])) - { - $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; - $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); - - } - } - } - if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) - { - $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); - } - - $keys = array_keys($this->data['links']); - foreach ($keys as $key) - { - if (SimplePie_Misc::is_isegment_nz_nc($key)) - { - if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) - { - $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); - $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; - } - else - { - $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; - } - } - elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) - { - $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; - } - $this->data['links'][$key] = array_unique($this->data['links'][$key]); - } - } - - if (isset($this->data['links'][$rel])) - { - return $this->data['links'][$rel]; - } - else - { - return null; - } - } - - public function get_description() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); - } - else - { - return null; - } - } - - public function get_copyright() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright')) - { - return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - return null; - } - } - - public function get_language() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); - } - elseif (isset($this->data['xml_lang'])) - { - return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); - } - else - { - return null; - } - } - - public function get_latitude() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) - { - return (float) $return[0]['data']; - } - 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)) - { - return (float) $match[1]; - } - else - { - return null; - } - } - - public function get_longitude() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) - { - return (float) $return[0]['data']; - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) - { - return (float) $return[0]['data']; - } - 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)) - { - return (float) $match[2]; - } - else - { - return null; - } - } - - public function get_image_url() - { - if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image')) - { - return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); - } - elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) - { - return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); - } - else - { - return null; - } - } -} - -class SimplePie_Author -{ - var $name; - var $link; - var $email; - - // Constructor, used to input the data - public function __construct($name = null, $link = null, $email = null) - { - $this->name = $name; - $this->link = $link; - $this->email = $email; - } - - public function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } - - public function get_name() - { - if ($this->name !== null) - { - return $this->name; - } - else - { - return null; - } - } - - public function get_link() - { - if ($this->link !== null) - { - return $this->link; - } - else - { - return null; - } - } - - public function get_email() - { - if ($this->email !== null) - { - return $this->email; - } - else - { - return null; - } - } -} - -class SimplePie_Category -{ - var $term; + var $role; var $scheme; - var $label; + var $name; - // Constructor, used to input the data - public function __construct($term = null, $scheme = null, $label = null) + public function __construct($role = null, $scheme = null, $name = null) { - $this->term = $term; + $this->role = $role; $this->scheme = $scheme; - $this->label = $label; + $this->name = $name; } public function __toString() { - // There is no $this->data here - return md5(serialize($this)); + return md5(serialize($this)); } - public function get_term() + public function get_role() { - if ($this->term !== null) + if ($this->role !== null) { - return $this->term; + return $this->role; } else { @@ -6023,19 +3178,181 @@ class SimplePie_Category } } - public function get_label() + public function get_name() { - if ($this->label !== null) + if ($this->name !== null) { - return $this->label; + return $this->name; } else { - return $this->get_term(); + return null; } } } + + + + + +class SimplePie_Decode_HTML_Entities +{ + + var $data = ''; + + + var $consumed = ''; + + + var $position = 0; + + + public function __construct($data) + { + $this->data = $data; + } + + + public function parse() + { + while (($this->position = strpos($this->data, '&', $this->position)) !== false) + { + $this->consume(); + $this->entity(); + $this->consumed = ''; + } + return $this->data; + } + + + public function consume() + { + if (isset($this->data[$this->position])) + { + $this->consumed .= $this->data[$this->position]; + return $this->data[$this->position++]; + } + else + { + return false; + } + } + + + public function consume_range($chars) + { + if ($len = strspn($this->data, $chars, $this->position)) + { + $data = substr($this->data, $this->position, $len); + $this->consumed .= $data; + $this->position += $len; + return $data; + } + else + { + return false; + } + } + + + public function unconsume() + { + $this->consumed = substr($this->consumed, 0, -1); + $this->position--; + } + + + public function entity() + { + switch ($this->consume()) + { + case "\x09": + case "\x0A": + case "\x0B": + case "\x0B": + case "\x0C": + case "\x20": + case "\x3C": + case "\x26": + case false: + break; + + case "\x23": + switch ($this->consume()) + { + case "\x78": + case "\x58": + $range = '0123456789ABCDEFabcdef'; + $hex = true; + break; + + default: + $range = '0123456789'; + $hex = false; + $this->unconsume(); + break; + } + + if ($codepoint = $this->consume_range($range)) + { + 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"); + + if ($hex) + { + $codepoint = hexdec($codepoint); + } + else + { + $codepoint = intval($codepoint); + } + + if (isset($windows_1252_specials[$codepoint])) + { + $replacement = $windows_1252_specials[$codepoint]; + } + else + { + $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint); + } + + if (!in_array($this->consume(), array(';', false), true)) + { + $this->unconsume(); + } + + $consumed_length = strlen($this->consumed); + $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length); + $this->position += strlen($replacement) - $consumed_length; + } + break; + + default: + 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"); + + for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++) + { + $consumed = substr($this->consumed, 1); + if (isset($entities[$consumed])) + { + $match = $consumed; + } + } + + if ($match !== null) + { + $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1); + $this->position += strlen($entities[$match]) - strlen($consumed) - 1; + } + break; + } + } +} + + + + + class SimplePie_Enclosure { var $bitrate; @@ -6066,8 +3383,7 @@ class SimplePie_Enclosure var $type; var $width; - // Constructor, used to input the data - 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) + 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) { $this->bitrate = $bitrate; $this->captions = $captions; @@ -6102,13 +3418,11 @@ class SimplePie_Enclosure $parsed = SimplePie_Misc::parse_url($link); $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); } - $this->handler = $this->get_handler(); // Needs to load last - } + $this->handler = $this->get_handler(); } public function __toString() { - // There is no $this->data here - return md5(serialize($this)); + return md5(serialize($this)); } public function get_bitrate() @@ -6559,13 +3873,10 @@ class SimplePie_Enclosure return $this->embed($options, true); } - /** - * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'. - */ + public function embed($options = '', $native = false) { - // Set up defaults - $audio = ''; + $audio = ''; $video = ''; $alt = ''; $altclass = ''; @@ -6578,8 +3889,7 @@ class SimplePie_Enclosure $handler = $this->get_handler(); $type = $this->get_real_type(); - // Process options and reassign values as necessary - if (is_array($options)) + if (is_array($options)) { extract($options); } @@ -6642,8 +3952,7 @@ class SimplePie_Enclosure $mime = explode('/', $type, 2); $mime = $mime[0]; - // Process values for 'auto' - if ($width === 'auto') + if ($width === 'auto') { if ($mime === 'video') { @@ -6704,8 +4013,7 @@ class SimplePie_Enclosure $height = 0; } - // Set proper placeholder value - if ($mime === 'audio') + if ($mime === 'audio') { $placeholder = $audio; } @@ -6716,8 +4024,7 @@ class SimplePie_Enclosure $embed = ''; - // Make sure the JS library is included - if (!$native) + if (!$native) { static $javascript_outputted = null; if (!$javascript_outputted && $this->javascript) @@ -6727,8 +4034,7 @@ class SimplePie_Enclosure } } - // Odeo Feed MP3's - if ($handler === 'odeo') + if ($handler === 'odeo') { if ($native) { @@ -6740,8 +4046,7 @@ class SimplePie_Enclosure } } - // Flash - elseif ($handler === 'flash') + elseif ($handler === 'flash') { if ($native) { @@ -6753,9 +4058,7 @@ class SimplePie_Enclosure } } - // Flash Media Player file types. - // Preferred handler for MP3 file types. - elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) + elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) { $height += 20; if ($native) @@ -6768,9 +4071,7 @@ class SimplePie_Enclosure } } - // QuickTime 7 file types. Need to test with QuickTime 6. - // Only handle MP3's if the Flash Media Player is not present. - elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) + elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) { $height += 16; if ($native) @@ -6790,8 +4091,7 @@ class SimplePie_Enclosure } } - // Windows Media - elseif ($handler === 'wmedia') + elseif ($handler === 'wmedia') { $height += 45; if ($native) @@ -6804,27 +4104,19 @@ class SimplePie_Enclosure } } - // Everything else - else $embed .= '' . $alt . ''; + else $embed .= '' . $alt . ''; return $embed; } public function get_real_type($find_handler = false) { - // If it's Odeo, let's get it out of the way. - if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com') + if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com') { return 'odeo'; } - // Mime-types by handler. - $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash - $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player - $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 - $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 - $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3 - + $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); $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'); $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'); $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); if ($this->get_type() !== null) { $type = strtolower($this->type); @@ -6834,13 +4126,11 @@ class SimplePie_Enclosure $type = null; } - // If we encounter an unsupported mime-type, check the file extension and guess intelligently. - if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) + if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) { switch (strtolower($this->get_extension())) { - // Audio mime-types - case 'aac': + case 'aac': case 'adts': $type = 'audio/acc'; break; @@ -6884,8 +4174,7 @@ class SimplePie_Enclosure $type = 'audio/x-ms-wma'; break; - // Video mime-types - case '3gp': + case '3gp': case '3gpp': $type = 'video/3gpp'; break; @@ -6947,8 +4236,7 @@ class SimplePie_Enclosure $type = 'video/x-ms-wvx'; break; - // Flash mime-types - case 'spl': + case 'spl': $type = 'application/futuresplash'; break; @@ -6992,294 +4280,11 @@ class SimplePie_Enclosure } } -class SimplePie_Caption -{ - var $type; - var $lang; - var $startTime; - var $endTime; - var $text; - // Constructor, used to input the data - public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null) - { - $this->type = $type; - $this->lang = $lang; - $this->startTime = $startTime; - $this->endTime = $endTime; - $this->text = $text; - } - public function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } - public function get_endtime() - { - if ($this->endTime !== null) - { - return $this->endTime; - } - else - { - return null; - } - } - public function get_language() - { - if ($this->lang !== null) - { - return $this->lang; - } - else - { - return null; - } - } - public function get_starttime() - { - if ($this->startTime !== null) - { - return $this->startTime; - } - else - { - return null; - } - } - - public function get_text() - { - if ($this->text !== null) - { - return $this->text; - } - else - { - return null; - } - } - - public function get_type() - { - if ($this->type !== null) - { - return $this->type; - } - else - { - return null; - } - } -} - -class SimplePie_Credit -{ - var $role; - var $scheme; - var $name; - - // Constructor, used to input the data - public function __construct($role = null, $scheme = null, $name = null) - { - $this->role = $role; - $this->scheme = $scheme; - $this->name = $name; - } - - public function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } - - public function get_role() - { - if ($this->role !== null) - { - return $this->role; - } - else - { - return null; - } - } - - public function get_scheme() - { - if ($this->scheme !== null) - { - return $this->scheme; - } - else - { - return null; - } - } - - public function get_name() - { - if ($this->name !== null) - { - return $this->name; - } - else - { - return null; - } - } -} - -class SimplePie_Copyright -{ - var $url; - var $label; - - // Constructor, used to input the data - public function __construct($url = null, $label = null) - { - $this->url = $url; - $this->label = $label; - } - - public function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } - - public function get_url() - { - if ($this->url !== null) - { - return $this->url; - } - else - { - return null; - } - } - - public function get_attribution() - { - if ($this->label !== null) - { - return $this->label; - } - else - { - return null; - } - } -} - -class SimplePie_Rating -{ - var $scheme; - var $value; - - // Constructor, used to input the data - public function __construct($scheme = null, $value = null) - { - $this->scheme = $scheme; - $this->value = $value; - } - - public function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } - - public function get_scheme() - { - if ($this->scheme !== null) - { - return $this->scheme; - } - else - { - return null; - } - } - - public function get_value() - { - if ($this->value !== null) - { - return $this->value; - } - else - { - return null; - } - } -} - -class SimplePie_Restriction -{ - var $relationship; - var $type; - var $value; - - // Constructor, used to input the data - public function __construct($relationship = null, $type = null, $value = null) - { - $this->relationship = $relationship; - $this->type = $type; - $this->value = $value; - } - - public function __toString() - { - // There is no $this->data here - return md5(serialize($this)); - } - - public function get_relationship() - { - if ($this->relationship !== null) - { - return $this->relationship; - } - else - { - return null; - } - } - - public function get_type() - { - if ($this->type !== null) - { - return $this->type; - } - else - { - return null; - } - } - - public function get_value() - { - if ($this->value !== null) - { - return $this->value; - } - else - { - return null; - } - } -} - -/** - * @todo Move to properly supporting RFC2616 (HTTP/1.1) - */ class SimplePie_File { var $url; @@ -7452,8 +4457,7 @@ class SimplePie_File } if (isset($this->headers['content-encoding'])) { - // Hey, we act dumb elsewhere, so let's do that here too - switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) + switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) { case 'gzip': case 'x-gzip': @@ -7509,119 +4513,253 @@ class SimplePie_File } } -/** - * HTTP Response Parser - * - * @package SimplePie - */ -class SimplePie_HTTP_Parser + + + + +class SimplePie_gzdecode { - /** - * HTTP Version - * - * @access public - * @var float - */ - var $http_version = 0.0; + + var $compressed_data; - /** - * Status code - * - * @access public - * @var int - */ - var $status_code = 0; + + var $compressed_size; - /** - * Reason phrase - * - * @access public - * @var string - */ - var $reason = ''; + + var $min_compressed_size = 18; - /** - * Key/value pairs of the headers - * - * @access public - * @var array - */ - var $headers = array(); - - /** - * Body of the response - * - * @access public - * @var string - */ - var $body = ''; - - /** - * Current state of the state machine - * - * @access private - * @var string - */ - var $state = 'http_version'; - - /** - * Input data - * - * @access private - * @var string - */ - var $data = ''; - - /** - * Input data length (to avoid calling strlen() everytime this is needed) - * - * @access private - * @var int - */ - var $data_length = 0; - - /** - * Current position of the pointer - * - * @var int - * @access private - */ + var $position = 0; - /** - * Name of the hedaer currently being parsed - * - * @access private - * @var string - */ + + var $flags; + + + var $data; + + + var $MTIME; + + + var $XFL; + + + var $OS; + + + var $SI1; + + + var $SI2; + + + var $extra_field; + + + var $filename; + + + var $comment; + + + public function __set($name, $value) + { + trigger_error("Cannot write property $name", E_USER_ERROR); + } + + + public function __construct($data) + { + $this->compressed_data = $data; + $this->compressed_size = strlen($data); + } + + + public function parse() + { + if ($this->compressed_size >= $this->min_compressed_size) + { + if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08") + { + return false; + } + + $this->flags = ord($this->compressed_data[3]); + + if ($this->flags > 0x1F) + { + return false; + } + + $this->position += 4; + + $mtime = substr($this->compressed_data, $this->position, 4); + if (current(unpack('S', "\x00\x01")) === 1) + { + $mtime = strrev($mtime); + } + $this->MTIME = current(unpack('l', $mtime)); + $this->position += 4; + + $this->XFL = ord($this->compressed_data[$this->position++]); + + $this->OS = ord($this->compressed_data[$this->position++]); + + if ($this->flags & 4) + { + $this->SI1 = $this->compressed_data[$this->position++]; + $this->SI2 = $this->compressed_data[$this->position++]; + + if ($this->SI2 === "\x00") + { + return false; + } + + $len = current(unpack('v', substr($this->compressed_data, $this->position, 2))); + $position += 2; + + $this->min_compressed_size += $len + 4; + if ($this->compressed_size >= $this->min_compressed_size) + { + $this->extra_field = substr($this->compressed_data, $this->position, $len); + $this->position += $len; + } + else + { + return false; + } + } + + if ($this->flags & 8) + { + $len = strcspn($this->compressed_data, "\x00", $this->position); + + $this->min_compressed_size += $len + 1; + if ($this->compressed_size >= $this->min_compressed_size) + { + $this->filename = substr($this->compressed_data, $this->position, $len); + $this->position += $len + 1; + } + else + { + return false; + } + } + + if ($this->flags & 16) + { + $len = strcspn($this->compressed_data, "\x00", $this->position); + + $this->min_compressed_size += $len + 1; + if ($this->compressed_size >= $this->min_compressed_size) + { + $this->comment = substr($this->compressed_data, $this->position, $len); + $this->position += $len + 1; + } + else + { + return false; + } + } + + if ($this->flags & 2) + { + $this->min_compressed_size += $len + 2; + if ($this->compressed_size >= $this->min_compressed_size) + { + $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2))); + + if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc) + { + $this->position += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + + if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false) + { + return false; + } + else + { + $this->position = $this->compressed_size - 8; + } + + $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4))); + $this->position += 4; + + + $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4))); + $this->position += 4; + if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize)) + { + return false; + } + + return true; + } + else + { + return false; + } + } +} + + + + + +class SimplePie_HTTP_Parser +{ + + var $http_version = 0.0; + + + var $status_code = 0; + + + var $reason = ''; + + + var $headers = array(); + + + var $body = ''; + + + var $state = 'http_version'; + + + var $data = ''; + + + var $data_length = 0; + + + var $position = 0; + + var $name = ''; - /** - * Value of the hedaer currently being parsed - * - * @access private - * @var string - */ + var $value = ''; - /** - * Create an instance of the class with the input data - * - * @access public - * @param string $data Input data - */ + public function __construct($data) { $this->data = $data; $this->data_length = strlen($this->data); } - /** - * Parse the input data - * - * @access public - * @return bool true on success, false on failure - */ + public function parse() { while ($this->state && $this->state !== 'emit' && $this->has_data()) @@ -7645,23 +4783,13 @@ class SimplePie_HTTP_Parser } } - /** - * Check whether there is data beyond the pointer - * - * @access private - * @return bool true if there is further data, false if not - */ + public function has_data() { return (bool) ($this->position < $this->data_length); } - /** - * See if the next character is LWS - * - * @access private - * @return bool true if the next character is LWS, false if not - */ + public function is_linear_whitespace() { return (bool) ($this->data[$this->position] === "\x09" @@ -7671,11 +4799,7 @@ class SimplePie_HTTP_Parser && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20"))); } - /** - * Parse the HTTP version - * - * @access private - */ + public function http_version() { if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/') @@ -7700,11 +4824,7 @@ class SimplePie_HTTP_Parser } } - /** - * Parse the status code - * - * @access private - */ + public function status() { if ($len = strspn($this->data, '0123456789', $this->position)) @@ -7719,11 +4839,7 @@ class SimplePie_HTTP_Parser } } - /** - * Parse the reason phrase - * - * @access private - */ + public function reason() { $len = strcspn($this->data, "\x0A", $this->position); @@ -7732,11 +4848,7 @@ class SimplePie_HTTP_Parser $this->state = 'new_line'; } - /** - * Deal with a new line, shifting data around as needed - * - * @access private - */ + public function new_line() { $this->value = trim($this->value, "\x0D\x20"); @@ -7770,11 +4882,7 @@ class SimplePie_HTTP_Parser } } - /** - * Parse a header name - * - * @access private - */ + public function name() { $len = strcspn($this->data, "\x0A:", $this->position); @@ -7798,11 +4906,7 @@ class SimplePie_HTTP_Parser } } - /** - * Parse LWS, replacing consecutive LWS characters with a single space - * - * @access private - */ + public function linear_whitespace() { do @@ -7820,11 +4924,7 @@ class SimplePie_HTTP_Parser $this->value .= "\x20"; } - /** - * See what state to move to while within non-quoted header values - * - * @access private - */ + public function value() { if ($this->is_linear_whitespace()) @@ -7852,11 +4952,7 @@ class SimplePie_HTTP_Parser } } - /** - * Parse a header value while outside quotes - * - * @access private - */ + public function value_char() { $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position); @@ -7865,11 +4961,7 @@ class SimplePie_HTTP_Parser $this->state = 'value'; } - /** - * See what state to move to while within quoted header values - * - * @access private - */ + public function quote() { if ($this->is_linear_whitespace()) @@ -7902,11 +4994,7 @@ class SimplePie_HTTP_Parser } } - /** - * Parse a header value while within quotes - * - * @access private - */ + public function quote_char() { $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position); @@ -7915,11 +5003,7 @@ class SimplePie_HTTP_Parser $this->state = 'value'; } - /** - * Parse an escaped character within quotes - * - * @access private - */ + public function quote_escaped() { $this->value .= $this->data[$this->position]; @@ -7927,11 +5011,7 @@ class SimplePie_HTTP_Parser $this->state = 'quote'; } - /** - * Parse the body - * - * @access private - */ + public function body() { $this->body = substr($this->data, $this->position); @@ -7939,767 +5019,3268 @@ class SimplePie_HTTP_Parser } } -/** - * gzdecode - * - * @package SimplePie - */ -class SimplePie_gzdecode + + + + +class SimplePie_IRI { - /** - * Compressed data - * - * @access private - * @see gzdecode::$data - */ - var $compressed_data; + + var $scheme; - /** - * Size of compressed data - * - * @access private - */ - var $compressed_size; + + var $userinfo; - /** - * Minimum size of a valid gzip string - * - * @access private - */ - var $min_compressed_size = 18; + + var $host; - /** - * Current position of pointer - * - * @access private - */ - var $position = 0; + + var $port; - /** - * Flags (FLG) - * - * @access private - */ - var $flags; + + var $path; - /** - * Uncompressed data - * - * @access public - * @see gzdecode::$compressed_data - */ - var $data; + + var $query; - /** - * Modified time - * - * @access public - */ - var $MTIME; + + var $fragment; - /** - * Extra Flags - * - * @access public - */ - var $XFL; + + var $valid = array(); - /** - * Operating System - * - * @access public - */ - var $OS; - - /** - * Subfield ID 1 - * - * @access public - * @see gzdecode::$extra_field - * @see gzdecode::$SI2 - */ - var $SI1; - - /** - * Subfield ID 2 - * - * @access public - * @see gzdecode::$extra_field - * @see gzdecode::$SI1 - */ - var $SI2; - - /** - * Extra field content - * - * @access public - * @see gzdecode::$SI1 - * @see gzdecode::$SI2 - */ - var $extra_field; - - /** - * Original filename - * - * @access public - */ - var $filename; - - /** - * Human readable comment - * - * @access public - */ - var $comment; - - /** - * Don't allow anything to be set - * - * @access public - */ - public function __set($name, $value) + + public function __toString() { - trigger_error("Cannot write property $name", E_USER_ERROR); + return $this->get_iri(); } - /** - * Set the compressed string and related properties - * - * @access public - */ - public function __construct($data) + + public function __construct($iri) { - $this->compressed_data = $data; - $this->compressed_size = strlen($data); - } - - /** - * Decode the GZIP stream - * - * @access public - */ - public function parse() - { - if ($this->compressed_size >= $this->min_compressed_size) + $iri = (string) $iri; + if ($iri !== '') { - // Check ID1, ID2, and CM - if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08") + $parsed = $this->parse_iri($iri); + $this->set_scheme($parsed['scheme']); + $this->set_authority($parsed['authority']); + $this->set_path($parsed['path']); + $this->set_query($parsed['query']); + $this->set_fragment($parsed['fragment']); + } + } + + + public static function absolutize($base, $relative) + { + $relative = (string) $relative; + if ($relative !== '') + { + $relative = new SimplePie_IRI($relative); + if ($relative->get_scheme() !== null) { - return false; + $target = $relative; } - - // Get the FLG (FLaGs) - $this->flags = ord($this->compressed_data[3]); - - // FLG bits above (1 << 4) are reserved - if ($this->flags > 0x1F) + elseif ($base->get_iri() !== null) { - return false; - } - - // Advance the pointer after the above - $this->position += 4; - - // MTIME - $mtime = substr($this->compressed_data, $this->position, 4); - // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness - if (current(unpack('S', "\x00\x01")) === 1) - { - $mtime = strrev($mtime); - } - $this->MTIME = current(unpack('l', $mtime)); - $this->position += 4; - - // Get the XFL (eXtra FLags) - $this->XFL = ord($this->compressed_data[$this->position++]); - - // Get the OS (Operating System) - $this->OS = ord($this->compressed_data[$this->position++]); - - // Parse the FEXTRA - if ($this->flags & 4) - { - // Read subfield IDs - $this->SI1 = $this->compressed_data[$this->position++]; - $this->SI2 = $this->compressed_data[$this->position++]; - - // SI2 set to zero is reserved for future use - if ($this->SI2 === "\x00") + if ($relative->get_authority() !== null) { - return false; - } - - // Get the length of the extra field - $len = current(unpack('v', substr($this->compressed_data, $this->position, 2))); - $position += 2; - - // Check the length of the string is still valid - $this->min_compressed_size += $len + 4; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Set the extra field to the given data - $this->extra_field = substr($this->compressed_data, $this->position, $len); - $this->position += $len; + $target = $relative; + $target->set_scheme($base->get_scheme()); } else { - return false; - } - } - - // Parse the FNAME - if ($this->flags & 8) - { - // Get the length of the filename - $len = strcspn($this->compressed_data, "\x00", $this->position); - - // Check the length of the string is still valid - $this->min_compressed_size += $len + 1; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Set the original filename to the given string - $this->filename = substr($this->compressed_data, $this->position, $len); - $this->position += $len + 1; - } - else - { - return false; - } - } - - // Parse the FCOMMENT - if ($this->flags & 16) - { - // Get the length of the comment - $len = strcspn($this->compressed_data, "\x00", $this->position); - - // Check the length of the string is still valid - $this->min_compressed_size += $len + 1; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Set the original comment to the given string - $this->comment = substr($this->compressed_data, $this->position, $len); - $this->position += $len + 1; - } - else - { - return false; - } - } - - // Parse the FHCRC - if ($this->flags & 2) - { - // Check the length of the string is still valid - $this->min_compressed_size += $len + 2; - if ($this->compressed_size >= $this->min_compressed_size) - { - // Read the CRC - $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2))); - - // Check the CRC matches - if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc) + $target = new SimplePie_IRI(''); + $target->set_scheme($base->get_scheme()); + $target->set_userinfo($base->get_userinfo()); + $target->set_host($base->get_host()); + $target->set_port($base->get_port()); + if ($relative->get_path() !== null) { - $this->position += 2; - } - else - { - return false; - } - } - else - { - return false; - } - } - - // Decompress the actual data - if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false) - { - return false; - } - else - { - $this->position = $this->compressed_size - 8; - } - - // Check CRC of data - $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4))); - $this->position += 4; - /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc)) - { - return false; - }*/ - - // Check ISIZE of data - $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4))); - $this->position += 4; - if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize)) - { - return false; - } - - // Wow, against all odds, we've actually got a valid gzip string - return true; - } - else - { - return false; - } - } -} - -class SimplePie_Cache -{ - /** - * Don't call the constructor. Please. - * - * @access private - */ - private function __construct() - { - trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR); - } - - /** - * Create a new SimplePie_Cache object - * - * @static - * @access public - */ - public static function create($location, $filename, $extension) - { - $location_iri = new SimplePie_IRI($location); - switch ($location_iri->get_scheme()) - { - case 'mysql': - if (extension_loaded('mysql')) - { - return new SimplePie_Cache_MySQL($location_iri, $filename, $extension); - } - break; - - default: - return new SimplePie_Cache_File($location, $filename, $extension); - } - } -} - -class SimplePie_Cache_File -{ - var $location; - var $filename; - var $extension; - var $name; - - public function __construct($location, $filename, $extension) - { - $this->location = $location; - $this->filename = $filename; - $this->extension = $extension; - $this->name = "$this->location/$this->filename.$this->extension"; - } - - public function save($data) - { - if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location)) - { - if (is_a($data, 'SimplePie')) - { - $data = $data->data; - } - - $data = serialize($data); - return (bool) file_put_contents($this->name, $data); - } - return false; - } - - public function load() - { - if (file_exists($this->name) && is_readable($this->name)) - { - return unserialize(file_get_contents($this->name)); - } - return false; - } - - public function mtime() - { - if (file_exists($this->name)) - { - return filemtime($this->name); - } - return false; - } - - public function touch() - { - if (file_exists($this->name)) - { - return touch($this->name); - } - return false; - } - - public function unlink() - { - if (file_exists($this->name)) - { - return unlink($this->name); - } - return false; - } -} - -class SimplePie_Cache_DB -{ - public function prepare_simplepie_object_for_cache($data) - { - $items = $data->get_items(); - $items_by_id = array(); - - if (!empty($items)) - { - foreach ($items as $item) - { - $items_by_id[$item->get_id()] = $item; - } - - if (count($items_by_id) !== count($items)) - { - $items_by_id = array(); - foreach ($items as $item) - { - $items_by_id[$item->get_id(true)] = $item; - } - } - - if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; - } - elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; - } - elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; - } - elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0])) - { - $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]; - } - else - { - $channel = null; - } - - if ($channel !== null) - { - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'])) - { - unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']); - } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry'])) - { - unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']); - } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])) - { - unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']); - } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])) - { - unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']); - } - if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item'])) - { - unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']); - } - } - if (isset($data->data['items'])) - { - unset($data->data['items']); - } - if (isset($data->data['ordered_items'])) - { - unset($data->data['ordered_items']); - } - } - return array(serialize($data->data), $items_by_id); - } -} - -class SimplePie_Cache_MySQL extends SimplePie_Cache_DB -{ - var $mysql; - var $options; - var $id; - - public function __construct($mysql_location, $name, $extension) - { - $host = $mysql_location->get_host(); - if (stripos($host, 'unix(') === 0 && substr($host, -1) === ')') - { - $server = ':' . substr($host, 5, -1); - } - else - { - $server = $host; - if ($mysql_location->get_port() !== null) - { - $server .= ':' . $mysql_location->get_port(); - } - } - - if (strpos($mysql_location->get_userinfo(), ':') !== false) - { - list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2); - } - else - { - $username = $mysql_location->get_userinfo(); - $password = null; - } - - if ($this->mysql = mysql_connect($server, $username, $password)) - { - $this->id = $name . $extension; - $this->options = SimplePie_Misc::parse_str($mysql_location->get_query()); - if (!isset($this->options['prefix'][0])) - { - $this->options['prefix'][0] = ''; - } - - if (mysql_select_db(ltrim($mysql_location->get_path(), '/')) - && mysql_query('SET NAMES utf8') - && ($query = mysql_unbuffered_query('SHOW TABLES'))) - { - $db = array(); - while ($row = mysql_fetch_row($query)) - { - $db[] = $row[0]; - } - - if (!in_array($this->options['prefix'][0] . 'cache_data', $db)) - { - 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)))')) - { - $this->mysql = null; - } - } - - if (!in_array($this->options['prefix'][0] . 'items', $db)) - { - 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)))')) - { - $this->mysql = null; - } - } - } - else - { - $this->mysql = null; - } - } - } - - public function save($data) - { - if ($this->mysql) - { - $feed_id = "'" . mysql_real_escape_string($this->id) . "'"; - - if (is_a($data, 'SimplePie')) - { - $data = clone $data; - - $prepared = $this->prepare_simplepie_object_for_cache($data); - - if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql)) - { - if (mysql_num_rows($query)) - { - $items = count($prepared[1]); - if ($items) + if (strpos($relative->get_path(), '/') === 0) { - $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id; + $target->set_path($relative->get_path()); + } + elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null) + { + $target->set_path('/' . $relative->get_path()); + } + elseif (($last_segment = strrpos($base->get_path(), '/')) !== false) + { + $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path()); } else { - $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id; - } - - if (!mysql_query($sql, $this->mysql)) - { - return false; - } - } - 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)) - { - return false; - } - - $ids = array_keys($prepared[1]); - if (!empty($ids)) - { - foreach ($ids as $id) - { - $database_ids[] = mysql_real_escape_string($id); - } - - 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)) - { - $existing_ids = array(); - while ($row = mysql_fetch_row($query)) - { - $existing_ids[] = $row[0]; - } - - $new_ids = array_diff($ids, $existing_ids); - - foreach ($new_ids as $new_id) - { - if (!($date = $prepared[1][$new_id]->get_date('U'))) - { - $date = time(); - } - - 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)) - { - return false; - } - } - return true; + $target->set_path($relative->get_path()); } + $target->set_query($relative->get_query()); } else { - return true; + $target->set_path($base->get_path()); + if ($relative->get_query() !== null) + { + $target->set_query($relative->get_query()); + } + elseif ($base->get_query() !== null) + { + $target->set_query($base->get_query()); + } } } - } - elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql)) - { - if (mysql_num_rows($query)) - { - 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)) - { - return true; - } - } - 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)) - { - return true; - } - } - } - return false; - } - - public function load() - { - 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))) - { - $data = unserialize($row[1]); - - if (isset($this->options['items'][0])) - { - $items = (int) $this->options['items'][0]; + $target->set_fragment($relative->get_fragment()); } else { - $items = (int) $row[0]; + $target = $relative; } + } + else + { + $target = $base; + } + return $target; + } - if ($items !== 0) + + public function parse_iri($iri) + { + preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match); + for ($i = count($match); $i <= 9; $i++) + { + $match[$i] = ''; + } + return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]); + } + + + public function remove_dot_segments($input) + { + $output = ''; + while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') + { + if (strpos($input, '../') === 0) { - if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) - { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; - } - elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) - { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; - } - elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) - { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; - } - elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0])) - { - $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]; - } - else - { - $feed = null; - } + $input = substr($input, 3); + } + elseif (strpos($input, './') === 0) + { + $input = substr($input, 2); + } + elseif (strpos($input, '/./') === 0) + { + $input = substr_replace($input, '/', 0, 3); + } + elseif ($input === '/.') + { + $input = '/'; + } + elseif (strpos($input, '/../') === 0) + { + $input = substr_replace($input, '/', 0, 4); + $output = substr_replace($output, '', strrpos($output, '/')); + } + elseif ($input === '/..') + { + $input = '/'; + $output = substr_replace($output, '', strrpos($output, '/')); + } + elseif ($input === '.' || $input === '..') + { + $input = ''; + } + elseif (($pos = strpos($input, '/', 1)) !== false) + { + $output .= substr($input, 0, $pos); + $input = substr_replace($input, '', 0, $pos); + } + else + { + $output .= $input; + $input = ''; + } + } + return $output . $input; + } - if ($feed !== null) + + public function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE) + { + if ($case & SIMPLEPIE_LOWERCASE) + { + $string = strtolower($string); + } + elseif ($case & SIMPLEPIE_UPPERCASE) + { + $string = strtoupper($string); + } + + $position = 0; + $strlen = strlen($string); + + while (($position += strspn($string, $valid_chars, $position)) < $strlen) + { + if ($string[$position] === '%') + { + if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2) { - $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC'; - if ($items > 0) + $chr = chr(hexdec(substr($string, $position + 1, 2))); + + if (strpos($valid_chars, $chr) !== false) { - $sql .= ' LIMIT ' . $items; + if ($case & SIMPLEPIE_LOWERCASE) + { + $chr = strtolower($chr); + } + elseif ($case & SIMPLEPIE_UPPERCASE) + { + $chr = strtoupper($chr); + } + $string = substr_replace($string, $chr, $position, 3); + $strlen -= 2; + $position++; } - if ($query = mysql_unbuffered_query($sql, $this->mysql)) + else { - while ($row = mysql_fetch_row($query)) - { - $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]); - } + $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2); + $position += 3; + } + } + else + { + $string = substr_replace($string, '%25', $position, 1); + $strlen += 2; + $position += 3; + } + } + else + { + $replacement = sprintf("%%%02X", ord($string[$position])); + $string = str_replace($string[$position], $replacement, $string); + $strlen = strlen($string); + } + } + return $string; + } + + + public function is_valid() + { + return array_sum($this->valid) === count($this->valid); + } + + + public function set_scheme($scheme) + { + if ($scheme === null || $scheme === '') + { + $this->scheme = null; + } + else + { + $len = strlen($scheme); + switch (true) + { + case $len > 1: + if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1)) + { + $this->scheme = null; + $this->valid[__FUNCTION__] = false; + return false; + } + + case $len > 0: + if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1)) + { + $this->scheme = null; + $this->valid[__FUNCTION__] = false; + return false; + } + } + $this->scheme = strtolower($scheme); + } + $this->valid[__FUNCTION__] = true; + return true; + } + + + public function set_authority($authority) + { + if (($userinfo_end = strrpos($authority, '@')) !== false) + { + $userinfo = substr($authority, 0, $userinfo_end); + $authority = substr($authority, $userinfo_end + 1); + } + else + { + $userinfo = null; + } + + if (($port_start = strpos($authority, ':')) !== false) + { + $port = substr($authority, $port_start + 1); + $authority = substr($authority, 0, $port_start); + } + else + { + $port = null; + } + + return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port); + } + + + public function set_userinfo($userinfo) + { + if ($userinfo === null || $userinfo === '') + { + $this->userinfo = null; + } + else + { + $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:'); + } + $this->valid[__FUNCTION__] = true; + return true; + } + + + public function set_host($host) + { + if ($host === null || $host === '') + { + $this->host = null; + $this->valid[__FUNCTION__] = true; + return true; + } + elseif ($host[0] === '[' && substr($host, -1) === ']') + { + if (Net_IPv6::checkIPv6(substr($host, 1, -1))) + { + $this->host = $host; + $this->valid[__FUNCTION__] = true; + return true; + } + else + { + $this->host = null; + $this->valid[__FUNCTION__] = false; + return false; + } + } + else + { + $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE); + $this->valid[__FUNCTION__] = true; + return true; + } + } + + + public function set_port($port) + { + if ($port === null || $port === '') + { + $this->port = null; + $this->valid[__FUNCTION__] = true; + return true; + } + elseif (strspn($port, '0123456789') === strlen($port)) + { + $this->port = (int) $port; + $this->valid[__FUNCTION__] = true; + return true; + } + else + { + $this->port = null; + $this->valid[__FUNCTION__] = false; + return false; + } + } + + + public function set_path($path) + { + if ($path === null || $path === '') + { + $this->path = null; + $this->valid[__FUNCTION__] = true; + return true; + } + elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null) + { + $this->path = null; + $this->valid[__FUNCTION__] = false; + return false; + } + else + { + $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/'); + if ($this->scheme !== null) + { + $this->path = $this->remove_dot_segments($this->path); + } + $this->valid[__FUNCTION__] = true; + return true; + } + } + + + public function set_query($query) + { + if ($query === null || $query === '') + { + $this->query = null; + } + else + { + $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&='); + } + $this->valid[__FUNCTION__] = true; + return true; + } + + + public function set_fragment($fragment) + { + if ($fragment === null || $fragment === '') + { + $this->fragment = null; + } + else + { + $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?'); + } + $this->valid[__FUNCTION__] = true; + return true; + } + + + public function get_iri() + { + $iri = ''; + if ($this->scheme !== null) + { + $iri .= $this->scheme . ':'; + } + if (($authority = $this->get_authority()) !== null) + { + $iri .= '//' . $authority; + } + if ($this->path !== null) + { + $iri .= $this->path; + } + if ($this->query !== null) + { + $iri .= '?' . $this->query; + } + if ($this->fragment !== null) + { + $iri .= '#' . $this->fragment; + } + + if ($iri !== '') + { + return $iri; + } + else + { + return null; + } + } + + + public function get_scheme() + { + return $this->scheme; + } + + + public function get_authority() + { + $authority = ''; + if ($this->userinfo !== null) + { + $authority .= $this->userinfo . '@'; + } + if ($this->host !== null) + { + $authority .= $this->host; + } + if ($this->port !== null) + { + $authority .= ':' . $this->port; + } + + if ($authority !== '') + { + return $authority; + } + else + { + return null; + } + } + + + public function get_userinfo() + { + return $this->userinfo; + } + + + public function get_host() + { + return $this->host; + } + + + public function get_port() + { + return $this->port; + } + + + public function get_path() + { + return $this->path; + } + + + public function get_query() + { + return $this->query; + } + + + public function get_fragment() + { + return $this->fragment; + } +} + + + + +class SimplePie_Item +{ + var $feed; + var $data = array(); + + public function __construct($feed, $data) + { + $this->feed = $feed; + $this->data = $data; + } + + public function __toString() + { + return md5(serialize($this->data)); + } + + + public function __destruct() + { + if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) + { + unset($this->feed); + } + } + + public function get_item_tags($namespace, $tag) + { + if (isset($this->data['child'][$namespace][$tag])) + { + return $this->data['child'][$namespace][$tag]; + } + else + { + return null; + } + } + + public function get_base($element = array()) + { + return $this->feed->get_base($element); + } + + public function sanitize($data, $type, $base = '') + { + return $this->feed->sanitize($data, $type, $base); + } + + public function get_feed() + { + return $this->feed; + } + + public function get_id($hash = false) + { + if (!$hash) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (($return = $this->get_permalink()) !== null) + { + return $return; + } + elseif (($return = $this->get_title()) !== null) + { + return $return; + } + } + if ($this->get_permalink() !== null || $this->get_title() !== null) + { + return md5($this->get_permalink() . $this->get_title()); + } + else + { + return md5(serialize($this->data)); + } + } + + public function get_title() + { + if (!isset($this->data['title'])) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $this->data['title'] = null; + } + } + return $this->data['title']; + } + + public function get_description($description_only = false) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML); + } + + elseif (!$description_only) + { + return $this->get_content(true); + } + else + { + return null; + } + } + + public function get_content($content_only = false) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif (!$content_only) + { + return $this->get_description(true); + } + else + { + return null; + } + } + + public function get_category($key = 0) + { + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } + } + + public function get_categories() + { + $categories = array(); + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) + { + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = new $this->feed->category_class($term, $scheme, $label); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = null; + } + $categories[] = new $this->feed->category_class($term, $scheme, null); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + { + $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + + if (!empty($categories)) + { + return SimplePie_Misc::array_unique($categories); + } + else + { + return null; + } + } + + public function get_author($key = 0) + { + $authors = $this->get_authors(); + if (isset($authors[$key])) + { + return $authors[$key]; + } + else + { + return null; + } + } + + public function get_contributor($key = 0) + { + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) + { + return $contributors[$key]; + } + else + { + return null; + } + } + + public function get_contributors() + { + $contributors = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) + { + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $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])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = new $this->feed->author_class($name, $uri, $email); + } + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) + { + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $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])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = new $this->feed->author_class($name, $url, $email); + } + } + + if (!empty($contributors)) + { + return SimplePie_Misc::array_unique($contributors); + } + else + { + return null; + } + } + + public function get_authors() + { + $authors = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) + { + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $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])); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $authors[] = new $this->feed->author_class($name, $uri, $email); + } + } + if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) + { + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $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])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = new $this->feed->author_class($name, $url, $email); + } + } + if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author')) + { + $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) + { + $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + + if (!empty($authors)) + { + return SimplePie_Misc::array_unique($authors); + } + elseif (($source = $this->get_source()) && ($authors = $source->get_authors())) + { + return $authors; + } + elseif ($authors = $this->feed->get_authors()) + { + return $authors; + } + else + { + return null; + } + } + + public function get_copyright() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_date($date_format = 'j F Y, g:i a') + { + if (!isset($this->data['date'])) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + + if (!empty($this->data['date']['raw'])) + { + $parser = SimplePie_Parse_Date::get(); + $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']); + } + else + { + $this->data['date'] = null; + } + } + if ($this->data['date']) + { + $date_format = (string) $date_format; + switch ($date_format) + { + case '': + return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT); + + case 'U': + return $this->data['date']['parsed']; + + default: + return date($date_format, $this->data['date']['parsed']); + } + } + else + { + return null; + } + } + + public function get_local_date($date_format = '%c') + { + if (!$date_format) + { + return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (($date = $this->get_date('U')) !== null && $date !== false) + { + return strftime($date_format, $date); + } + else + { + return null; + } + } + + public function get_permalink() + { + $link = $this->get_link(); + $enclosure = $this->get_enclosure(0); + if ($link !== null) + { + return $link; + } + elseif ($enclosure !== null) + { + return $enclosure->get_link(); + } + else + { + return null; + } + } + + public function get_link($key = 0, $rel = 'alternate') + { + $links = $this->get_links($rel); + if ($links[$key] !== null) + { + return $links[$key]; + } + else + { + return null; + } + } + + public function get_links($rel = 'alternate') + { + if (!isset($this->data['links'])) + { + $this->data['links'] = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + + } + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) + { + if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true') + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + } + + $keys = array_keys($this->data['links']); + foreach ($keys as $key) + { + if (SimplePie_Misc::is_isegment_nz_nc($key)) + { + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; } else { - return false; + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } + } + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) + { + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; + } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); + } + } + if (isset($this->data['links'][$rel])) + { + return $this->data['links'][$rel]; + } + else + { + return null; + } + } + + + public function get_enclosure($key = 0, $prefer = null) + { + $enclosures = $this->get_enclosures(); + if (isset($enclosures[$key])) + { + return $enclosures[$key]; + } + else + { + return null; + } + } + + + public function get_enclosures() + { + if (!isset($this->data['enclosures'])) + { + $this->data['enclosures'] = array(); + + $captions_parent = null; + $categories_parent = null; + $copyrights_parent = null; + $credits_parent = null; + $description_parent = null; + $duration_parent = null; + $hashes_parent = null; + $keywords_parent = null; + $player_parent = null; + $ratings_parent = null; + $restrictions_parent = null; + $thumbnails_parent = null; + $title_parent = null; + + $parent = $this->get_feed(); + + if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) + { + foreach ($captions as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); + } + } + elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) + { + foreach ($captions as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); + } + } + if (is_array($captions_parent)) + { + $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent)); + } + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); + } + foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); + } + foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category) + { + $term = null; + $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; + $label = null; + if (isset($category['attribs']['']['text'])) + { + $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); + + if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'])) + { + foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory) + { + if (isset($subcategory['attribs']['']['text'])) + { + $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = new $this->feed->category_class($term, $scheme, $label); } } } - return $data; - } - return false; - } + if (is_array($categories_parent)) + { + $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent)); + } - public function mtime() - { - 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))) + if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) + { + $copyright_url = null; + $copyright_label = null; + if (isset($copyright[0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($copyright[0]['data'])) + { + $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label); + } + elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) + { + $copyright_url = null; + $copyright_label = null; + if (isset($copyright[0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($copyright[0]['data'])) + { + $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label); + } + + if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) + { + foreach ($credits as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); + } + } + elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) + { + foreach ($credits as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); + } + } + if (is_array($credits_parent)) + { + $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent)); + } + + if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) + { + if (isset($description_parent[0]['data'])) + { + $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) + { + if (isset($description_parent[0]['data'])) + { + $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + + if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration')) + { + $seconds = null; + $minutes = null; + $hours = null; + if (isset($duration_parent[0]['data'])) + { + $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + if (sizeof($temp) > 0) + { + $seconds = (int) array_pop($temp); + } + if (sizeof($temp) > 0) + { + $minutes = (int) array_pop($temp); + $seconds += $minutes * 60; + } + if (sizeof($temp) > 0) + { + $hours = (int) array_pop($temp); + $seconds += $hours * 3600; + } + unset($temp); + $duration_parent = $seconds; + } + } + + if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) + { + foreach ($hashes_iterator as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes_parent[] = $algo.':'.$value; + } + } + elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) + { + foreach ($hashes_iterator as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes_parent[] = $algo.':'.$value; + } + } + if (is_array($hashes_parent)) + { + $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent)); + } + + if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + if (is_array($keywords_parent)) + { + $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent)); + } + + if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) + { + if (isset($player_parent[0]['attribs']['']['url'])) + { + $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) + { + if (isset($player_parent[0]['attribs']['']['url'])) + { + $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + + if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) + { + foreach ($ratings as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + } + elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) + { + foreach ($ratings as $rating) + { + $rating_scheme = 'urn:itunes'; + $rating_value = null; + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + } + elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) + { + foreach ($ratings as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + } + elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) + { + foreach ($ratings as $rating) + { + $rating_scheme = 'urn:itunes'; + $rating_value = null; + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + } + if (is_array($ratings_parent)) + { + $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent)); + } + + if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + } + elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = 'allow'; + $restriction_type = null; + $restriction_value = 'itunes'; + if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') + { + $restriction_relationship = 'deny'; + } + $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + } + elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + } + elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = 'allow'; + $restriction_type = null; + $restriction_value = 'itunes'; + if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') + { + $restriction_relationship = 'deny'; + } + $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + } + if (is_array($restrictions_parent)) + { + $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent)); + } + + if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + foreach ($thumbnails as $thumbnail) + { + if (isset($thumbnail['attribs']['']['url'])) + { + $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + } + elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + foreach ($thumbnails as $thumbnail) + { + if (isset($thumbnail['attribs']['']['url'])) + { + $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + } + + if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) + { + if (isset($title_parent[0]['data'])) + { + $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) + { + if (isset($title_parent[0]['data'])) + { + $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + + unset($parent); + + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group) + { + if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) + { + foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) + { + if (isset($content['attribs']['']['url'])) + { + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; + + if (isset($content['attribs']['']['bitrate'])) + { + $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['channels'])) + { + $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['duration'])) + { + $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $duration = $duration_parent; + } + if (isset($content['attribs']['']['expression'])) + { + $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['framerate'])) + { + $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['height'])) + { + $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['lang'])) + { + $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['fileSize'])) + { + $length = ceil($content['attribs']['']['fileSize']); + } + if (isset($content['attribs']['']['medium'])) + { + $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['samplingrate'])) + { + $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['type'])) + { + $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['width'])) + { + $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); + } + if (is_array($captions)) + { + $captions = array_values(SimplePie_Misc::array_unique($captions)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); + } + if (is_array($captions)) + { + $captions = array_values(SimplePie_Misc::array_unique($captions)); + } + } + else + { + $captions = $captions_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = new $this->feed->category_class($term, $scheme, $label); + } + } + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = new $this->feed->category_class($term, $scheme, $label); + } + } + if (is_array($categories) && is_array($categories_parent)) + { + $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent))); + } + elseif (is_array($categories)) + { + $categories = array_values(SimplePie_Misc::array_unique($categories)); + } + elseif (is_array($categories_parent)) + { + $categories = array_values(SimplePie_Misc::array_unique($categories_parent)); + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label); + } + else + { + $copyrights = $copyrights_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); + } + if (is_array($credits)) + { + $credits = array_values(SimplePie_Misc::array_unique($credits)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); + } + if (is_array($credits)) + { + $credits = array_values(SimplePie_Misc::array_unique($credits)); + } + } + else + { + $credits = $credits_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $description = $description_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(SimplePie_Misc::array_unique($hashes)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(SimplePie_Misc::array_unique($hashes)); + } + } + else + { + $hashes = $hashes_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(SimplePie_Misc::array_unique($keywords)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(SimplePie_Misc::array_unique($keywords)); + } + } + else + { + $keywords = $keywords_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + $player = $player_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + if (is_array($ratings)) + { + $ratings = array_values(SimplePie_Misc::array_unique($ratings)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + if (is_array($ratings)) + { + $ratings = array_values(SimplePie_Misc::array_unique($ratings)); + } + } + else + { + $ratings = $ratings_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + if (is_array($restrictions)) + { + $restrictions = array_values(SimplePie_Misc::array_unique($restrictions)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + if (is_array($restrictions)) + { + $restrictions = array_values(SimplePie_Misc::array_unique($restrictions)); + } + } + else + { + $restrictions = $restrictions_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails)); + } + } + else + { + $thumbnails = $thumbnails_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } + + $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); + } + } + } + } + + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) + { + foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) + { + if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; + + if (isset($content['attribs']['']['bitrate'])) + { + $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['channels'])) + { + $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['duration'])) + { + $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $duration = $duration_parent; + } + if (isset($content['attribs']['']['expression'])) + { + $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['framerate'])) + { + $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['height'])) + { + $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['lang'])) + { + $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['fileSize'])) + { + $length = ceil($content['attribs']['']['fileSize']); + } + if (isset($content['attribs']['']['medium'])) + { + $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['samplingrate'])) + { + $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['type'])) + { + $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['width'])) + { + $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['url'])) + { + $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text); + } + if (is_array($captions)) + { + $captions = array_values(SimplePie_Misc::array_unique($captions)); + } + } + else + { + $captions = $captions_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = new $this->feed->category_class($term, $scheme, $label); + } + } + if (is_array($categories) && is_array($categories_parent)) + { + $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent))); + } + elseif (is_array($categories)) + { + $categories = array_values(SimplePie_Misc::array_unique($categories)); + } + elseif (is_array($categories_parent)) + { + $categories = array_values(SimplePie_Misc::array_unique($categories_parent)); + } + else + { + $categories = null; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label); + } + else + { + $copyrights = $copyrights_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name); + } + if (is_array($credits)) + { + $credits = array_values(SimplePie_Misc::array_unique($credits)); + } + } + else + { + $credits = $credits_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $description = $description_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(SimplePie_Misc::array_unique($hashes)); + } + } + else + { + $hashes = $hashes_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(SimplePie_Misc::array_unique($keywords)); + } + } + else + { + $keywords = $keywords_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + $player = $player_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value); + } + if (is_array($ratings)) + { + $ratings = array_values(SimplePie_Misc::array_unique($ratings)); + } + } + else + { + $ratings = $ratings_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value); + } + if (is_array($restrictions)) + { + $restrictions = array_values(SimplePie_Misc::array_unique($restrictions)); + } + } + else + { + $restrictions = $restrictions_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails)); + } + } + else + { + $thumbnails = $thumbnails_parent; + } + + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } + + $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); + } + } + } + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) + { + if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') + { + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + if (isset($link['attribs']['']['type'])) + { + $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($link['attribs']['']['length'])) + { + $length = ceil($link['attribs']['']['length']); + } + + $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); + } + } + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) + { + if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') + { + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + if (isset($link['attribs']['']['type'])) + { + $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($link['attribs']['']['length'])) + { + $length = ceil($link['attribs']['']['length']); + } + + $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); + } + } + + if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure')) + { + if (isset($enclosure[0]['attribs']['']['url'])) + { + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0])); + if (isset($enclosure[0]['attribs']['']['type'])) + { + $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($enclosure[0]['attribs']['']['length'])) + { + $length = ceil($enclosure[0]['attribs']['']['length']); + } + + $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); + } + } + + 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)) + { + $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); + } + + $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures'])); + } + if (!empty($this->data['enclosures'])) { - return $row[0]; + return $this->data['enclosures']; } else { - return false; + return null; } } - public function touch() + public function get_latitude() { - 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)) + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) { - return true; + return (float) $return[0]['data']; + } + 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)) + { + return (float) $match[1]; } else { - return false; + return null; } } - public function unlink() + public function get_longitude() { - 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))) + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) { - return true; + return (float) $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + 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)) + { + return (float) $match[2]; } else { - return false; + return null; + } + } + + public function get_source() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source')) + { + return new $this->feed->source_class($this, $return[0]); + } + else + { + return null; } } } + + + + +class SimplePie_Locator +{ + var $useragent; + var $timeout; + var $file; + var $local = array(); + var $elsewhere = array(); + var $file_class = 'SimplePie_File'; + var $cached_entities = array(); + var $http_base; + var $base; + var $base_location = 0; + var $checked_feeds = 0; + var $max_checked_feeds = 10; + var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer'; + + public function __construct(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer') + { + $this->file =& $file; + $this->file_class = $file_class; + $this->useragent = $useragent; + $this->timeout = $timeout; + $this->max_checked_feeds = $max_checked_feeds; + $this->content_type_sniffer_class = $content_type_sniffer_class; + } + + public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working) + { + if ($this->is_feed($this->file)) + { + return $this->file; + } + + if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + { + $sniffer = new $this->content_type_sniffer_class($this->file); + if ($sniffer->get_type() !== 'text/html') + { + return null; + } + } + + if ($type & ~SIMPLEPIE_LOCATOR_NONE) + { + $this->get_base(); + } + + if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery()) + { + return $working[0]; + } + + if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) + { + if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) + { + return $working; + } + + if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) + { + return $working; + } + + if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) + { + return $working; + } + + if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) + { + return $working; + } + } + return null; + } + + public function is_feed(&$file) + { + if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + { + $sniffer = new $this->content_type_sniffer_class($file); + $sniffed = $sniffer->get_type(); + if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml'))) + { + return true; + } + else + { + return false; + } + } + elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) + { + return true; + } + else + { + return false; + } + } + + public function get_base() + { + $this->http_base = $this->file->url; + $this->base = $this->http_base; + $elements = SimplePie_Misc::get_element('base', $this->file->body); + foreach ($elements as $element) + { + if ($element['attribs']['href']['data'] !== '') + { + $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base); + $this->base_location = $element['offset']; + break; + } + } + } + + public function autodiscovery() + { + $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)); + $done = array(); + $feeds = array(); + foreach ($links as $link) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data'])) + { + $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data']))); + + if ($this->base_location < $link['offset']) + { + $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base); + } + else + { + $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base); + } + + 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])) + { + $this->checked_feeds++; + $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent); + 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)) + { + $feeds[$href] = $feed; + } + } + $done[] = $href; + } + } + + if (!empty($feeds)) + { + return array_values($feeds); + } + else { + return null; + } + } + + public function get_links() + { + $links = SimplePie_Misc::get_element('a', $this->file->body); + foreach ($links as $link) + { + if (isset($link['attribs']['href']['data'])) + { + $href = trim($link['attribs']['href']['data']); + $parsed = SimplePie_Misc::parse_url($href); + if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) + { + if ($this->base_location < $link['offset']) + { + $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base); + } + else + { + $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base); + } + + $current = SimplePie_Misc::parse_url($this->file->url); + + if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority']) + { + $this->local[] = $href; + } + else + { + $this->elsewhere[] = $href; + } + } + } + } + $this->local = array_unique($this->local); + $this->elsewhere = array_unique($this->elsewhere); + if (!empty($this->local) || !empty($this->elsewhere)) + { + return true; + } + return null; + } + + public function extension(&$array) + { + foreach ($array as $key => $value) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml'))) + { + $this->checked_feeds++; + $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent); + 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)) + { + return $feed; + } + else + { + unset($array[$key]); + } + } + } + return null; + } + + public function body(&$array) + { + foreach ($array as $key => $value) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (preg_match('/(rss|rdf|atom|xml)/i', $value)) + { + $this->checked_feeds++; + $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent); + 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)) + { + return $feed; + } + else + { + unset($array[$key]); + } + } + } + return null; + } +} + + + + + class SimplePie_Misc { public static function time_hms($seconds) @@ -8741,8 +8322,7 @@ class SimplePie_Misc $output = ''; while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') { - // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, - if (strpos($input, '../') === 0) + if (strpos($input, '../') === 0) { $input = substr($input, 3); } @@ -8750,8 +8330,7 @@ class SimplePie_Misc { $input = substr($input, 2); } - // 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, - elseif (strpos($input, '/./') === 0) + elseif (strpos($input, '/./') === 0) { $input = substr_replace($input, '/', 0, 3); } @@ -8759,8 +8338,7 @@ class SimplePie_Misc { $input = '/'; } - // 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, - elseif (strpos($input, '/../') === 0) + elseif (strpos($input, '/../') === 0) { $input = substr_replace($input, '/', 0, 4); $output = substr_replace($output, '', strrpos($output, '/')); @@ -8770,13 +8348,11 @@ class SimplePie_Misc $input = '/'; $output = substr_replace($output, '', strrpos($output, '/')); } - // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, - elseif ($input === '.' || $input === '..') + elseif ($input === '.' || $input === '..') { $input = ''; } - // 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 - elseif (($pos = strpos($input, '/', 1)) !== false) + elseif (($pos = strpos($input, '/', 1)) !== false) { $output .= substr($input, 0, $pos); $input = substr_replace($input, '', 0, $pos); @@ -8961,14 +8537,7 @@ class SimplePie_Misc } } - /** - * Converts a Windows-1252 encoded string to a UTF-8 encoded string - * - * @static - * @access public - * @param string $string Windows-1252 encoded string - * @return string UTF-8 encoded string - */ + public static function windows_1252_to_utf8($string) { 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"); @@ -8981,8 +8550,7 @@ class SimplePie_Misc $input = SimplePie_Misc::encoding($input); $output = SimplePie_Misc::encoding($output); - // We fail to fail on non US-ASCII bytes - if ($input === 'US-ASCII') + if ($input === 'US-ASCII') { static $non_ascii_octects = ''; if (!$non_ascii_octects) @@ -8995,43 +8563,28 @@ class SimplePie_Misc $data = substr($data, 0, strcspn($data, $non_ascii_octects)); } - // This is first, as behaviour of this is completely predictable - if ($input === 'windows-1252' && $output === 'UTF-8') + if ($input === 'windows-1252' && $output === 'UTF-8') { return SimplePie_Misc::windows_1252_to_utf8($data); } - // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported). - elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input))) + elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input))) { return $return; } - // This is last, as behaviour of this varies with OS userland and PHP version - elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data))) + elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data))) { return $return; } - // If we can't do anything, just fail - else + else { return false; } } - /** - * Normalize an encoding name - * - * This is automatically generated by create.php - * - * To generate it, run `php create.php` on the command line, and copy the - * output to replace this function. - * - * @param string $charset Character set to standardise - * @return string Standardised name - */ + public static function encoding($charset) { - // Normalization from UTS #22 - switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset))) + switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset))) { case 'adobestandardencoding': case 'csadobestandardencoding': @@ -10293,8 +9846,7 @@ class SimplePie_Misc case 'ksc56011987': case 'ksc56011989': case 'windows949': - //return 'windows-949'; - return 'EUC-KR'; + return 'windows-949'; case 'windows1250': return 'windows-1250'; @@ -10397,13 +9949,7 @@ class SimplePie_Misc return false; } - /** - * Strip HTML comments - * - * @access public - * @param string $data Data to strip comments from - * @return string Comment stripped string - */ + public static function strip_comments($data) { $output = ''; @@ -10428,27 +9974,14 @@ class SimplePie_Misc return $parser->parse($dt); } - /** - * Decode HTML entities - * - * @static - * @access public - * @param string $data Input data - * @return string Output data - */ + public static function entities_decode($data) { $decoder = new SimplePie_Decode_HTML_Entities($data); return $decoder->parse(); } - /** - * Remove RFC822 comments - * - * @access public - * @param string $data Data to strip comments from - * @return string Comment stripped string - */ + public static function uncomment_rfc822($string) { $string = (string) $string; @@ -10682,14 +10215,7 @@ class SimplePie_Misc } } - /** - * Converts a unicode codepoint to a UTF-8 character - * - * @static - * @access public - * @param int $codepoint Unicode codepoint - * @return string UTF-8 character - */ + public static function codepoint_to_utf8($codepoint) { $codepoint = (int) $codepoint; @@ -10715,22 +10241,11 @@ class SimplePie_Misc } else { - // U+FFFD REPLACEMENT CHARACTER - return "\xEF\xBF\xBD"; + return "\xEF\xBF\xBD"; } } - /** - * Similar to parse_str() - * - * Returns an associative array of name/value pairs, where the value is an - * array of values that have used the same name - * - * @static - * @access string - * @param string $str The input string. - * @return array - */ + public static function parse_str($str) { $return = array(); @@ -10752,42 +10267,30 @@ class SimplePie_Misc return $return; } - /** - * Detect XML encoding, as per XML 1.0 Appendix F.1 - * - * @todo Add support for EBCDIC - * @param string $data XML data - * @return array Possible encodings - */ + public static function xml_encoding($data) { - // UTF-32 Big Endian BOM - if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") { $encoding[] = 'UTF-32BE'; } - // UTF-32 Little Endian BOM - elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") { $encoding[] = 'UTF-32LE'; } - // UTF-16 Big Endian BOM - elseif (substr($data, 0, 2) === "\xFE\xFF") + elseif (substr($data, 0, 2) === "\xFE\xFF") { $encoding[] = 'UTF-16BE'; } - // UTF-16 Little Endian BOM - elseif (substr($data, 0, 2) === "\xFF\xFE") + elseif (substr($data, 0, 2) === "\xFF\xFE") { $encoding[] = 'UTF-16LE'; } - // UTF-8 BOM - elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") { $encoding[] = 'UTF-8'; } - // UTF-32 Big Endian Without BOM - 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") + 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") { if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E")) { @@ -10799,8 +10302,7 @@ class SimplePie_Misc } $encoding[] = 'UTF-32BE'; } - // UTF-32 Little Endian Without BOM - 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") + 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") { if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00")) { @@ -10812,8 +10314,7 @@ class SimplePie_Misc } $encoding[] = 'UTF-32LE'; } - // UTF-16 Big Endian Without BOM - elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C") + elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C") { if ($pos = strpos($data, "\x00\x3F\x00\x3E")) { @@ -10825,8 +10326,7 @@ class SimplePie_Misc } $encoding[] = 'UTF-16BE'; } - // UTF-16 Little Endian Without BOM - elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00") + elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00") { if ($pos = strpos($data, "\x3F\x00\x3E\x00")) { @@ -10838,8 +10338,7 @@ class SimplePie_Misc } $encoding[] = 'UTF-16LE'; } - // US-ASCII (or superset) - elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C") + elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C") { if ($pos = strpos($data, "\x3F\x3E")) { @@ -10851,8 +10350,7 @@ class SimplePie_Misc } $encoding[] = 'UTF-8'; } - // Fallback to UTF-8 - else + else { $encoding[] = 'UTF-8'; } @@ -10867,8 +10365,7 @@ class SimplePie_Misc } header('Content-type: text/javascript; charset: UTF-8'); header('Cache-Control: must-revalidate'); - header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days - ?> + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); ?> function embed_odeo(link) { document.writeln(''); } @@ -10897,974 +10394,14 @@ function embed_wmedia(width, height, link) { } } -/** - * Decode HTML Entities - * - * This implements HTML5 as of revision 967 (2007-06-28) - * - * @package SimplePie - */ -class SimplePie_Decode_HTML_Entities -{ - /** - * Data to be parsed - * - * @access private - * @var string - */ - var $data = ''; - /** - * Currently consumed bytes - * - * @access private - * @var string - */ - var $consumed = ''; - /** - * Position of the current byte being parsed - * - * @access private - * @var int - */ - var $position = 0; - /** - * Create an instance of the class with the input data - * - * @access public - * @param string $data Input data - */ - public function __construct($data) - { - $this->data = $data; - } - /** - * Parse the input data - * - * @access public - * @return string Output data - */ - public function parse() - { - while (($this->position = strpos($this->data, '&', $this->position)) !== false) - { - $this->consume(); - $this->entity(); - $this->consumed = ''; - } - return $this->data; - } - /** - * Consume the next byte - * - * @access private - * @return mixed The next byte, or false, if there is no more data - */ - public function consume() - { - if (isset($this->data[$this->position])) - { - $this->consumed .= $this->data[$this->position]; - return $this->data[$this->position++]; - } - else - { - return false; - } - } - - /** - * Consume a range of characters - * - * @access private - * @param string $chars Characters to consume - * @return mixed A series of characters that match the range, or false - */ - public function consume_range($chars) - { - if ($len = strspn($this->data, $chars, $this->position)) - { - $data = substr($this->data, $this->position, $len); - $this->consumed .= $data; - $this->position += $len; - return $data; - } - else - { - return false; - } - } - - /** - * Unconsume one byte - * - * @access private - */ - public function unconsume() - { - $this->consumed = substr($this->consumed, 0, -1); - $this->position--; - } - - /** - * Decode an entity - * - * @access private - */ - public function entity() - { - switch ($this->consume()) - { - case "\x09": - case "\x0A": - case "\x0B": - case "\x0B": - case "\x0C": - case "\x20": - case "\x3C": - case "\x26": - case false: - break; - - case "\x23": - switch ($this->consume()) - { - case "\x78": - case "\x58": - $range = '0123456789ABCDEFabcdef'; - $hex = true; - break; - - default: - $range = '0123456789'; - $hex = false; - $this->unconsume(); - break; - } - - if ($codepoint = $this->consume_range($range)) - { - 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"); - - if ($hex) - { - $codepoint = hexdec($codepoint); - } - else - { - $codepoint = intval($codepoint); - } - - if (isset($windows_1252_specials[$codepoint])) - { - $replacement = $windows_1252_specials[$codepoint]; - } - else - { - $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint); - } - - if (!in_array($this->consume(), array(';', false), true)) - { - $this->unconsume(); - } - - $consumed_length = strlen($this->consumed); - $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length); - $this->position += strlen($replacement) - $consumed_length; - } - break; - - default: - 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"); - - for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++) - { - $consumed = substr($this->consumed, 1); - if (isset($entities[$consumed])) - { - $match = $consumed; - } - } - - if ($match !== null) - { - $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1); - $this->position += strlen($entities[$match]) - strlen($consumed) - 1; - } - break; - } - } -} - -/** - * IRI parser/serialiser - * - * @package SimplePie - */ -class SimplePie_IRI -{ - /** - * Scheme - * - * @access private - * @var string - */ - var $scheme; - - /** - * User Information - * - * @access private - * @var string - */ - var $userinfo; - - /** - * Host - * - * @access private - * @var string - */ - var $host; - - /** - * Port - * - * @access private - * @var string - */ - var $port; - - /** - * Path - * - * @access private - * @var string - */ - var $path; - - /** - * Query - * - * @access private - * @var string - */ - var $query; - - /** - * Fragment - * - * @access private - * @var string - */ - var $fragment; - - /** - * Whether the object represents a valid IRI - * - * @access private - * @var array - */ - var $valid = array(); - - /** - * Return the entire IRI when you try and read the object as a string - * - * @access public - * @return string - */ - public function __toString() - { - return $this->get_iri(); - } - - /** - * Create a new IRI object, from a specified string - * - * @access public - * @param string $iri - * @return SimplePie_IRI - */ - public function __construct($iri) - { - $iri = (string) $iri; - if ($iri !== '') - { - $parsed = $this->parse_iri($iri); - $this->set_scheme($parsed['scheme']); - $this->set_authority($parsed['authority']); - $this->set_path($parsed['path']); - $this->set_query($parsed['query']); - $this->set_fragment($parsed['fragment']); - } - } - - /** - * Create a new IRI object by resolving a relative IRI - * - * @static - * @access public - * @param SimplePie_IRI $base Base IRI - * @param string $relative Relative IRI - * @return SimplePie_IRI - */ - public static function absolutize($base, $relative) - { - $relative = (string) $relative; - if ($relative !== '') - { - $relative = new SimplePie_IRI($relative); - if ($relative->get_scheme() !== null) - { - $target = $relative; - } - elseif ($base->get_iri() !== null) - { - if ($relative->get_authority() !== null) - { - $target = $relative; - $target->set_scheme($base->get_scheme()); - } - else - { - $target = new SimplePie_IRI(''); - $target->set_scheme($base->get_scheme()); - $target->set_userinfo($base->get_userinfo()); - $target->set_host($base->get_host()); - $target->set_port($base->get_port()); - if ($relative->get_path() !== null) - { - if (strpos($relative->get_path(), '/') === 0) - { - $target->set_path($relative->get_path()); - } - elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null) - { - $target->set_path('/' . $relative->get_path()); - } - elseif (($last_segment = strrpos($base->get_path(), '/')) !== false) - { - $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path()); - } - else - { - $target->set_path($relative->get_path()); - } - $target->set_query($relative->get_query()); - } - else - { - $target->set_path($base->get_path()); - if ($relative->get_query() !== null) - { - $target->set_query($relative->get_query()); - } - elseif ($base->get_query() !== null) - { - $target->set_query($base->get_query()); - } - } - } - $target->set_fragment($relative->get_fragment()); - } - else - { - // No base URL, just return the relative URL - $target = $relative; - } - } - else - { - $target = $base; - } - return $target; - } - - /** - * Parse an IRI into scheme/authority/path/query/fragment segments - * - * @access private - * @param string $iri - * @return array - */ - public function parse_iri($iri) - { - preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match); - for ($i = count($match); $i <= 9; $i++) - { - $match[$i] = ''; - } - return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]); - } - - /** - * Remove dot segments from a path - * - * @access private - * @param string $input - * @return string - */ - public function remove_dot_segments($input) - { - $output = ''; - while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') - { - // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, - if (strpos($input, '../') === 0) - { - $input = substr($input, 3); - } - elseif (strpos($input, './') === 0) - { - $input = substr($input, 2); - } - // 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, - elseif (strpos($input, '/./') === 0) - { - $input = substr_replace($input, '/', 0, 3); - } - elseif ($input === '/.') - { - $input = '/'; - } - // 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, - elseif (strpos($input, '/../') === 0) - { - $input = substr_replace($input, '/', 0, 4); - $output = substr_replace($output, '', strrpos($output, '/')); - } - elseif ($input === '/..') - { - $input = '/'; - $output = substr_replace($output, '', strrpos($output, '/')); - } - // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, - elseif ($input === '.' || $input === '..') - { - $input = ''; - } - // 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 - elseif (($pos = strpos($input, '/', 1)) !== false) - { - $output .= substr($input, 0, $pos); - $input = substr_replace($input, '', 0, $pos); - } - else - { - $output .= $input; - $input = ''; - } - } - return $output . $input; - } - - /** - * Replace invalid character with percent encoding - * - * @access private - * @param string $string Input string - * @param string $valid_chars Valid characters - * @param int $case Normalise case - * @return string - */ - public function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE) - { - // Normalise case - if ($case & SIMPLEPIE_LOWERCASE) - { - $string = strtolower($string); - } - elseif ($case & SIMPLEPIE_UPPERCASE) - { - $string = strtoupper($string); - } - - // Store position and string length (to avoid constantly recalculating this) - $position = 0; - $strlen = strlen($string); - - // Loop as long as we have invalid characters, advancing the position to the next invalid character - while (($position += strspn($string, $valid_chars, $position)) < $strlen) - { - // If we have a % character - if ($string[$position] === '%') - { - // If we have a pct-encoded section - if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2) - { - // Get the the represented character - $chr = chr(hexdec(substr($string, $position + 1, 2))); - - // If the character is valid, replace the pct-encoded with the actual character while normalising case - if (strpos($valid_chars, $chr) !== false) - { - if ($case & SIMPLEPIE_LOWERCASE) - { - $chr = strtolower($chr); - } - elseif ($case & SIMPLEPIE_UPPERCASE) - { - $chr = strtoupper($chr); - } - $string = substr_replace($string, $chr, $position, 3); - $strlen -= 2; - $position++; - } - - // Otherwise just normalise the pct-encoded to uppercase - else - { - $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2); - $position += 3; - } - } - // If we don't have a pct-encoded section, just replace the % with its own esccaped form - else - { - $string = substr_replace($string, '%25', $position, 1); - $strlen += 2; - $position += 3; - } - } - // If we have an invalid character, change into its pct-encoded form - else - { - $replacement = sprintf("%%%02X", ord($string[$position])); - $string = str_replace($string[$position], $replacement, $string); - $strlen = strlen($string); - } - } - return $string; - } - - /** - * Check if the object represents a valid IRI - * - * @access public - * @return bool - */ - public function is_valid() - { - return array_sum($this->valid) === count($this->valid); - } - - /** - * Set the scheme. Returns true on success, false on failure (if there are - * any invalid characters). - * - * @access public - * @param string $scheme - * @return bool - */ - public function set_scheme($scheme) - { - if ($scheme === null || $scheme === '') - { - $this->scheme = null; - } - else - { - $len = strlen($scheme); - switch (true) - { - case $len > 1: - if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1)) - { - $this->scheme = null; - $this->valid[__FUNCTION__] = false; - return false; - } - - case $len > 0: - if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1)) - { - $this->scheme = null; - $this->valid[__FUNCTION__] = false; - return false; - } - } - $this->scheme = strtolower($scheme); - } - $this->valid[__FUNCTION__] = true; - return true; - } - - /** - * Set the authority. Returns true on success, false on failure (if there are - * any invalid characters). - * - * @access public - * @param string $authority - * @return bool - */ - public function set_authority($authority) - { - if (($userinfo_end = strrpos($authority, '@')) !== false) - { - $userinfo = substr($authority, 0, $userinfo_end); - $authority = substr($authority, $userinfo_end + 1); - } - else - { - $userinfo = null; - } - - if (($port_start = strpos($authority, ':')) !== false) - { - $port = substr($authority, $port_start + 1); - $authority = substr($authority, 0, $port_start); - } - else - { - $port = null; - } - - return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port); - } - - /** - * Set the userinfo. - * - * @access public - * @param string $userinfo - * @return bool - */ - public function set_userinfo($userinfo) - { - if ($userinfo === null || $userinfo === '') - { - $this->userinfo = null; - } - else - { - $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:'); - } - $this->valid[__FUNCTION__] = true; - return true; - } - - /** - * Set the host. Returns true on success, false on failure (if there are - * any invalid characters). - * - * @access public - * @param string $host - * @return bool - */ - public function set_host($host) - { - if ($host === null || $host === '') - { - $this->host = null; - $this->valid[__FUNCTION__] = true; - return true; - } - elseif ($host[0] === '[' && substr($host, -1) === ']') - { - if (Net_IPv6::checkIPv6(substr($host, 1, -1))) - { - $this->host = $host; - $this->valid[__FUNCTION__] = true; - return true; - } - else - { - $this->host = null; - $this->valid[__FUNCTION__] = false; - return false; - } - } - else - { - $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE); - $this->valid[__FUNCTION__] = true; - return true; - } - } - - /** - * Set the port. Returns true on success, false on failure (if there are - * any invalid characters). - * - * @access public - * @param string $port - * @return bool - */ - public function set_port($port) - { - if ($port === null || $port === '') - { - $this->port = null; - $this->valid[__FUNCTION__] = true; - return true; - } - elseif (strspn($port, '0123456789') === strlen($port)) - { - $this->port = (int) $port; - $this->valid[__FUNCTION__] = true; - return true; - } - else - { - $this->port = null; - $this->valid[__FUNCTION__] = false; - return false; - } - } - - /** - * Set the path. - * - * @access public - * @param string $path - * @return bool - */ - public function set_path($path) - { - if ($path === null || $path === '') - { - $this->path = null; - $this->valid[__FUNCTION__] = true; - return true; - } - elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null) - { - $this->path = null; - $this->valid[__FUNCTION__] = false; - return false; - } - else - { - $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/'); - if ($this->scheme !== null) - { - $this->path = $this->remove_dot_segments($this->path); - } - $this->valid[__FUNCTION__] = true; - return true; - } - } - - /** - * Set the query. - * - * @access public - * @param string $query - * @return bool - */ - public function set_query($query) - { - if ($query === null || $query === '') - { - $this->query = null; - } - else - { - $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&='); - } - $this->valid[__FUNCTION__] = true; - return true; - } - - /** - * Set the fragment. - * - * @access public - * @param string $fragment - * @return bool - */ - public function set_fragment($fragment) - { - if ($fragment === null || $fragment === '') - { - $this->fragment = null; - } - else - { - $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?'); - } - $this->valid[__FUNCTION__] = true; - return true; - } - - /** - * Get the complete IRI - * - * @access public - * @return string - */ - public function get_iri() - { - $iri = ''; - if ($this->scheme !== null) - { - $iri .= $this->scheme . ':'; - } - if (($authority = $this->get_authority()) !== null) - { - $iri .= '//' . $authority; - } - if ($this->path !== null) - { - $iri .= $this->path; - } - if ($this->query !== null) - { - $iri .= '?' . $this->query; - } - if ($this->fragment !== null) - { - $iri .= '#' . $this->fragment; - } - - if ($iri !== '') - { - return $iri; - } - else - { - return null; - } - } - - /** - * Get the scheme - * - * @access public - * @return string - */ - public function get_scheme() - { - return $this->scheme; - } - - /** - * Get the complete authority - * - * @access public - * @return string - */ - public function get_authority() - { - $authority = ''; - if ($this->userinfo !== null) - { - $authority .= $this->userinfo . '@'; - } - if ($this->host !== null) - { - $authority .= $this->host; - } - if ($this->port !== null) - { - $authority .= ':' . $this->port; - } - - if ($authority !== '') - { - return $authority; - } - else - { - return null; - } - } - - /** - * Get the user information - * - * @access public - * @return string - */ - public function get_userinfo() - { - return $this->userinfo; - } - - /** - * Get the host - * - * @access public - * @return string - */ - public function get_host() - { - return $this->host; - } - - /** - * Get the port - * - * @access public - * @return string - */ - public function get_port() - { - return $this->port; - } - - /** - * Get the path - * - * @access public - * @return string - */ - public function get_path() - { - return $this->path; - } - - /** - * Get the query - * - * @access public - * @return string - */ - public function get_query() - { - return $this->query; - } - - /** - * Get the fragment - * - * @access public - * @return string - */ - public function get_fragment() - { - return $this->fragment; - } -} - -/** - * Class to validate and to work with IPv6 addresses. - * - * @package SimplePie - * @copyright 2003-2005 The PHP Group - * @license http://www.opensource.org/licenses/bsd-license.php - * @link http://pear.php.net/package/Net_IPv6 - * @author Alexander Merz - * @author elfrink at introweb dot nl - * @author Josh Peck - * @author Geoffrey Sneddon - */ class SimplePie_Net_IPv6 { - /** - * Removes a possible existing netmask specification of an IP address. - * - * @param string $ip the (compressed) IP as Hex representation - * @return string the IP the without netmask - * @since 1.1.0 - * @access public - * @static - */ + public static function removeNetmaskSpec($ip) { if (strpos($ip, '/') !== false) @@ -11878,21 +10415,7 @@ class SimplePie_Net_IPv6 return $addr; } - /** - * Uncompresses an IPv6 address - * - * RFC 2373 allows you to compress zeros in an address to '::'. This - * function expects an valid IPv6 address and expands the '::' to - * the required zeros. - * - * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 - * ::1 -> 0:0:0:0:0:0:0:1 - * - * @access public - * @static - * @param string $ip a valid IPv6-address (hex format) - * @return string the uncompressed IPv6-address (hex format) - */ + public static function Uncompress($ip) { $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip); @@ -11937,25 +10460,21 @@ class SimplePie_Net_IPv6 { $c2++; } - // :: - if ($c1 === -1 && $c2 === -1) + if ($c1 === -1 && $c2 === -1) { $uip = '0:0:0:0:0:0:0:0'; } - // ::xxx - else if ($c1 === -1) + else if ($c1 === -1) { $fill = str_repeat('0:', 7 - $c2); $uip = str_replace('::', $fill, $uip); } - // xxx:: - else if ($c2 === -1) + else if ($c2 === -1) { $fill = str_repeat(':0', 7 - $c1); $uip = str_replace('::', $fill, $uip); } - // xxx::xxx - else + else { $fill = str_repeat(':0:', 6 - $c2 - $c1); $uip = str_replace('::', $fill, $uip); @@ -11965,20 +10484,7 @@ class SimplePie_Net_IPv6 return $uip; } - /** - * Splits an IPv6 address into the IPv6 and a possible IPv4 part - * - * RFC 2373 allows you to note the last two parts of an IPv6 address as - * an IPv4 compatible address - * - * Example: 0:0:0:0:0:0:13.1.68.3 - * 0:0:0:0:0:FFFF:129.144.52.38 - * - * @access public - * @static - * @param string $ip a valid IPv6-address (hex format) - * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format) - */ + public static function SplitV64($ip) { $ip = SimplePie_Net_IPv6::Uncompress($ip); @@ -11995,16 +10501,7 @@ class SimplePie_Net_IPv6 } } - /** - * Checks an IPv6 address - * - * Checks if the given IP is IPv6-compatible - * - * @access public - * @static - * @param string $ip a valid IPv6-address - * @return bool true if $ip is an IPv6 address - */ + public static function checkIPv6($ip) { $ipPart = SimplePie_Net_IPv6::SplitV64($ip); @@ -12054,30 +10551,19 @@ class SimplePie_Net_IPv6 } } -/** - * Date Parser - * - * @package SimplePie - */ + + + + + class SimplePie_Parse_Date { - /** - * Input data - * - * @access protected - * @var string - */ + var $date; - /** - * List of days, calendar day name => ordinal day number in the week - * - * @access protected - * @var array - */ + var $day = array( - // English - 'mon' => 1, + 'mon' => 1, 'monday' => 1, 'tue' => 2, 'tuesday' => 2, @@ -12091,24 +10577,21 @@ class SimplePie_Parse_Date 'saturday' => 6, 'sun' => 7, 'sunday' => 7, - // Dutch - 'maandag' => 1, + 'maandag' => 1, 'dinsdag' => 2, 'woensdag' => 3, 'donderdag' => 4, 'vrijdag' => 5, 'zaterdag' => 6, 'zondag' => 7, - // French - 'lundi' => 1, + 'lundi' => 1, 'mardi' => 2, 'mercredi' => 3, 'jeudi' => 4, 'vendredi' => 5, 'samedi' => 6, 'dimanche' => 7, - // German - 'montag' => 1, + 'montag' => 1, 'dienstag' => 2, 'mittwoch' => 3, 'donnerstag' => 4, @@ -12116,40 +10599,35 @@ class SimplePie_Parse_Date 'samstag' => 6, 'sonnabend' => 6, 'sonntag' => 7, - // Italian - 'lunedì' => 1, + 'lunedì' => 1, 'martedì' => 2, 'mercoledì' => 3, 'giovedì' => 4, 'venerdì' => 5, 'sabato' => 6, 'domenica' => 7, - // Spanish - 'lunes' => 1, + 'lunes' => 1, 'martes' => 2, 'miércoles' => 3, 'jueves' => 4, 'viernes' => 5, 'sábado' => 6, 'domingo' => 7, - // Finnish - 'maanantai' => 1, + 'maanantai' => 1, 'tiistai' => 2, 'keskiviikko' => 3, 'torstai' => 4, 'perjantai' => 5, 'lauantai' => 6, 'sunnuntai' => 7, - // Hungarian - 'hétfő' => 1, + 'hétfő' => 1, 'kedd' => 2, 'szerda' => 3, 'csütörtok' => 4, 'péntek' => 5, 'szombat' => 6, 'vasárnap' => 7, - // Greek - 'Δευ' => 1, + 'Δευ' => 1, 'Τρι' => 2, 'Τετ' => 3, 'Πεμ' => 4, @@ -12158,15 +10636,9 @@ class SimplePie_Parse_Date 'Κυρ' => 7, ); - /** - * List of months, calendar month name => calendar month number - * - * @access protected - * @var array - */ + var $month = array( - // English - 'jan' => 1, + 'jan' => 1, 'january' => 1, 'feb' => 2, 'february' => 2, @@ -12175,8 +10647,7 @@ class SimplePie_Parse_Date 'apr' => 4, 'april' => 4, 'may' => 5, - // No long form of May - 'jun' => 6, + 'jun' => 6, 'june' => 6, 'jul' => 7, 'july' => 7, @@ -12190,8 +10661,7 @@ class SimplePie_Parse_Date 'november' => 11, 'dec' => 12, 'december' => 12, - // Dutch - 'januari' => 1, + 'januari' => 1, 'februari' => 2, 'maart' => 3, 'april' => 4, @@ -12203,8 +10673,7 @@ class SimplePie_Parse_Date 'oktober' => 10, 'november' => 11, 'december' => 12, - // French - 'janvier' => 1, + 'janvier' => 1, 'février' => 2, 'mars' => 3, 'avril' => 4, @@ -12216,8 +10685,7 @@ class SimplePie_Parse_Date 'octobre' => 10, 'novembre' => 11, 'décembre' => 12, - // German - 'januar' => 1, + 'januar' => 1, 'februar' => 2, 'märz' => 3, 'april' => 4, @@ -12229,8 +10697,7 @@ class SimplePie_Parse_Date 'oktober' => 10, 'november' => 11, 'dezember' => 12, - // Italian - 'gennaio' => 1, + 'gennaio' => 1, 'febbraio' => 2, 'marzo' => 3, 'aprile' => 4, @@ -12242,8 +10709,7 @@ class SimplePie_Parse_Date 'ottobre' => 10, 'novembre' => 11, 'dicembre' => 12, - // Spanish - 'enero' => 1, + 'enero' => 1, 'febrero' => 2, 'marzo' => 3, 'abril' => 4, @@ -12256,8 +10722,7 @@ class SimplePie_Parse_Date 'octubre' => 10, 'noviembre' => 11, 'diciembre' => 12, - // Finnish - 'tammikuu' => 1, + 'tammikuu' => 1, 'helmikuu' => 2, 'maaliskuu' => 3, 'huhtikuu' => 4, @@ -12269,8 +10734,7 @@ class SimplePie_Parse_Date 'lokakuu' => 10, 'marras' => 11, 'joulukuu' => 12, - // Hungarian - 'január' => 1, + 'január' => 1, 'február' => 2, 'március' => 3, 'április' => 4, @@ -12282,8 +10746,7 @@ class SimplePie_Parse_Date 'október' => 10, 'november' => 11, 'december' => 12, - // Greek - 'Ιαν' => 1, + 'Ιαν' => 1, 'Φεβ' => 2, 'Μάώ' => 3, 'Μαώ' => 3, @@ -12303,12 +10766,7 @@ class SimplePie_Parse_Date 'Δεκ' => 12, ); - /** - * List of timezones, abbreviation => offset from UTC - * - * @access protected - * @var array - */ + var $timezone = array( 'ACDT' => 37800, 'ACIT' => 28800, @@ -12511,44 +10969,19 @@ class SimplePie_Parse_Date 'YEKT' => 18000, ); - /** - * Cached PCRE for SimplePie_Parse_Date::$day - * - * @access protected - * @var string - */ + var $day_pcre; - /** - * Cached PCRE for SimplePie_Parse_Date::$month - * - * @access protected - * @var string - */ + var $month_pcre; - /** - * Array of user-added callback methods - * - * @access private - * @var array - */ + var $built_in = array(); - /** - * Array of user-added callback methods - * - * @access private - * @var array - */ + var $user = array(); - /** - * Create new SimplePie_Parse_Date object, and set self::day_pcre, - * self::month_pcre, and self::built_in - * - * @access private - */ + public function __construct() { $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')'; @@ -12574,11 +11007,7 @@ class SimplePie_Parse_Date } } - /** - * Get the object - * - * @access public - */ + public static function get() { static $object; @@ -12589,14 +11018,7 @@ class SimplePie_Parse_Date return $object; } - /** - * Parse a date - * - * @final - * @access public - * @param string $date Date to parse - * @return int Timestamp corresponding to date string, or false on failure - */ + public function parse($date) { foreach ($this->user as $method) @@ -12618,13 +11040,7 @@ class SimplePie_Parse_Date return false; } - /** - * Add a callback method to parse a date - * - * @final - * @access public - * @param callback $callback - */ + public function add_callback($callback) { if (is_callable($callback)) @@ -12637,14 +11053,7 @@ class SimplePie_Parse_Date } } - /** - * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as - * well as allowing any of upper or lower case "T", horizontal tabs, or - * spaces to be used as the time seperator (including more than one)) - * - * @access protected - * @return int Timestamp - */ + public function date_w3cdtf($date) { static $pcre; @@ -12658,23 +11067,9 @@ class SimplePie_Parse_Date } if (preg_match($pcre, $date, $match)) { - /* - Capturing subpatterns: - 1: Year - 2: Month - 3: Day - 4: Hour - 5: Minute - 6: Second - 7: Decimal fraction of a second - 8: Zulu - 9: Timezone ± - 10: Timezone hours - 11: Timezone minutes - */ + - // Fill in empty matches - for ($i = count($match); $i <= 3; $i++) + for ($i = count($match); $i <= 3; $i++) { $match[$i] = '1'; } @@ -12684,8 +11079,7 @@ class SimplePie_Parse_Date $match[$i] = '0'; } - // Numeric timezone - if (isset($match[9]) && $match[9] !== '') + if (isset($match[9]) && $match[9] !== '') { $timezone = $match[10] * 3600; $timezone += $match[11] * 60; @@ -12699,8 +11093,7 @@ class SimplePie_Parse_Date $timezone = 0; } - // Convert the number of seconds to an integer, taking decimals into account - $second = round($match[6] + $match[7] / pow(10, strlen($match[7]))); + $second = round($match[6] + $match[7] / pow(10, strlen($match[7]))); return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone; } @@ -12710,13 +11103,7 @@ class SimplePie_Parse_Date } } - /** - * Remove RFC822 comments - * - * @access protected - * @param string $data Data to strip comments from - * @return string Comment stripped string - */ + public function remove_rfc2822_comments($string) { $string = (string) $string; @@ -12771,12 +11158,7 @@ class SimplePie_Parse_Date return $output; } - /** - * Parse RFC2822's date format - * - * @access protected - * @return int Timestamp - */ + public function date_rfc2822($date) { static $pcre; @@ -12797,26 +11179,11 @@ class SimplePie_Parse_Date } if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) { - /* - Capturing subpatterns: - 1: Day name - 2: Day - 3: Month - 4: Year - 5: Hour - 6: Minute - 7: Second - 8: Timezone ± - 9: Timezone hours - 10: Timezone minutes - 11: Alphabetic timezone - */ + - // Find the month number - $month = $this->month[strtolower($match[3])]; + $month = $this->month[strtolower($match[3])]; - // Numeric timezone - if ($match[8] !== '') + if ($match[8] !== '') { $timezone = $match[9] * 3600; $timezone += $match[10] * 60; @@ -12825,19 +11192,16 @@ class SimplePie_Parse_Date $timezone = 0 - $timezone; } } - // Character timezone - elseif (isset($this->timezone[strtoupper($match[11])])) + elseif (isset($this->timezone[strtoupper($match[11])])) { $timezone = $this->timezone[strtoupper($match[11])]; } - // Assume everything else to be -0000 - else + else { $timezone = 0; } - // Deal with 2/3 digit years - if ($match[4] < 50) + if ($match[4] < 50) { $match[4] += 2000; } @@ -12846,8 +11210,7 @@ class SimplePie_Parse_Date $match[4] += 1900; } - // Second is optional, if it is empty set it to zero - if ($match[7] !== '') + if ($match[7] !== '') { $second = $match[7]; } @@ -12864,12 +11227,7 @@ class SimplePie_Parse_Date } } - /** - * Parse RFC850's date format - * - * @access protected - * @return int Timestamp - */ + public function date_rfc850($date) { static $pcre; @@ -12885,34 +11243,20 @@ class SimplePie_Parse_Date } if (preg_match($pcre, $date, $match)) { - /* - Capturing subpatterns: - 1: Day name - 2: Day - 3: Month - 4: Year - 5: Hour - 6: Minute - 7: Second - 8: Timezone - */ + - // Month - $month = $this->month[strtolower($match[3])]; + $month = $this->month[strtolower($match[3])]; - // Character timezone - if (isset($this->timezone[strtoupper($match[8])])) + if (isset($this->timezone[strtoupper($match[8])])) { $timezone = $this->timezone[strtoupper($match[8])]; } - // Assume everything else to be -0000 - else + else { $timezone = 0; } - // Deal with 2 digit year - if ($match[4] < 50) + if ($match[4] < 50) { $match[4] += 2000; } @@ -12929,12 +11273,7 @@ class SimplePie_Parse_Date } } - /** - * Parse C99's asctime()'s date format - * - * @access protected - * @return int Timestamp - */ + public function date_asctime($date) { static $pcre; @@ -12951,16 +11290,7 @@ class SimplePie_Parse_Date } if (preg_match($pcre, $date, $match)) { - /* - Capturing subpatterns: - 1: Day name - 2: Month - 3: Day - 4: Hour - 5: Minute - 6: Second - 7: Year - */ + $month = $this->month[strtolower($match[2])]; return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]); @@ -12971,12 +11301,7 @@ class SimplePie_Parse_Date } } - /** - * Parse dates using strtotime() - * - * @access protected - * @return int Timestamp - */ + public function date_strtotime($date) { $strtotime = strtotime($date); @@ -12991,855 +11316,9 @@ class SimplePie_Parse_Date } } -/** - * Content-type sniffing - * - * @package SimplePie - */ -class SimplePie_Content_Type_Sniffer -{ - /** - * File object - * - * @var SimplePie_File - * @access private - */ - var $file; - /** - * Create an instance of the class with the input file - * - * @access public - * @param SimplePie_Content_Type_Sniffer $file Input file - */ - public function __construct($file) - { - $this->file = $file; - } - /** - * Get the Content-Type of the specified file - * - * @access public - * @return string Actual Content-Type - */ - public function get_type() - { - if (isset($this->file->headers['content-type'])) - { - if (!isset($this->file->headers['content-encoding']) - && ($this->file->headers['content-type'] === 'text/plain' - || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' - || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1')) - { - return $this->text_or_binary(); - } - if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) - { - $official = substr($this->file->headers['content-type'], 0, $pos); - } - else - { - $official = $this->file->headers['content-type']; - } - $official = strtolower($official); - - if ($official === 'unknown/unknown' - || $official === 'application/unknown') - { - return $this->unknown(); - } - elseif (substr($official, -4) === '+xml' - || $official === 'text/xml' - || $official === 'application/xml') - { - return $official; - } - elseif (substr($official, 0, 6) === 'image/') - { - if ($return = $this->image()) - { - return $return; - } - else - { - return $official; - } - } - elseif ($official === 'text/html') - { - return $this->feed_or_html(); - } - else - { - return $official; - } - } - else - { - return $this->unknown(); - } - } - - /** - * Sniff text or binary - * - * @access private - * @return string Actual Content-Type - */ - public function text_or_binary() - { - if (substr($this->file->body, 0, 2) === "\xFE\xFF" - || substr($this->file->body, 0, 2) === "\xFF\xFE" - || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" - || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") - { - return 'text/plain'; - } - elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) - { - return 'application/octect-stream'; - } - else - { - return 'text/plain'; - } - } - - /** - * Sniff unknown - * - * @access private - * @return string Actual Content-Type - */ - public function unknown() - { - $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); - if (strtolower(substr($this->file->body, $ws, 14)) === 'file->body, $ws, 5)) === 'file->body, $ws, 7)) === 'file->body, 0, 5) === '%PDF-') - { - return 'application/pdf'; - } - elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') - { - return 'application/postscript'; - } - elseif (substr($this->file->body, 0, 6) === 'GIF87a' - || substr($this->file->body, 0, 6) === 'GIF89a') - { - return 'image/gif'; - } - elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") - { - return 'image/png'; - } - elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") - { - return 'image/jpeg'; - } - elseif (substr($this->file->body, 0, 2) === "\x42\x4D") - { - return 'image/bmp'; - } - else - { - return $this->text_or_binary(); - } - } - - /** - * Sniff images - * - * @access private - * @return string Actual Content-Type - */ - public function image() - { - if (substr($this->file->body, 0, 6) === 'GIF87a' - || substr($this->file->body, 0, 6) === 'GIF89a') - { - return 'image/gif'; - } - elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") - { - return 'image/png'; - } - elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") - { - return 'image/jpeg'; - } - elseif (substr($this->file->body, 0, 2) === "\x42\x4D") - { - return 'image/bmp'; - } - else - { - return false; - } - } - - /** - * Sniff HTML - * - * @access private - * @return string Actual Content-Type - */ - public function feed_or_html() - { - $len = strlen($this->file->body); - $pos = strspn($this->file->body, "\x09\x0A\x0D\x20"); - - while ($pos < $len) - { - switch ($this->file->body[$pos]) - { - case "\x09": - case "\x0A": - case "\x0D": - case "\x20": - $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); - continue 2; - - case '<': - $pos++; - break; - - default: - return 'text/html'; - } - - if (substr($this->file->body, $pos, 3) === '!--') - { - $pos += 3; - if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) - { - $pos += 3; - } - else - { - return 'text/html'; - } - } - elseif (substr($this->file->body, $pos, 1) === '!') - { - if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) - { - $pos++; - } - else - { - return 'text/html'; - } - } - elseif (substr($this->file->body, $pos, 1) === '?') - { - if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) - { - $pos += 2; - } - else - { - return 'text/html'; - } - } - elseif (substr($this->file->body, $pos, 3) === 'rss' - || substr($this->file->body, $pos, 7) === 'rdf:RDF') - { - return 'application/rss+xml'; - } - elseif (substr($this->file->body, $pos, 4) === 'feed') - { - return 'application/atom+xml'; - } - else - { - return 'text/html'; - } - } - - return 'text/html'; - } -} - -/** - * Parses the XML Declaration - * - * @package SimplePie - */ -class SimplePie_XML_Declaration_Parser -{ - /** - * XML Version - * - * @access public - * @var string - */ - var $version = '1.0'; - - /** - * Encoding - * - * @access public - * @var string - */ - var $encoding = 'UTF-8'; - - /** - * Standalone - * - * @access public - * @var bool - */ - var $standalone = false; - - /** - * Current state of the state machine - * - * @access private - * @var string - */ - var $state = 'before_version_name'; - - /** - * Input data - * - * @access private - * @var string - */ - var $data = ''; - - /** - * Input data length (to avoid calling strlen() everytime this is needed) - * - * @access private - * @var int - */ - var $data_length = 0; - - /** - * Current position of the pointer - * - * @var int - * @access private - */ - var $position = 0; - - /** - * Create an instance of the class with the input data - * - * @access public - * @param string $data Input data - */ - public function __construct($data) - { - $this->data = $data; - $this->data_length = strlen($this->data); - } - - /** - * Parse the input data - * - * @access public - * @return bool true on success, false on failure - */ - public function parse() - { - while ($this->state && $this->state !== 'emit' && $this->has_data()) - { - $state = $this->state; - $this->$state(); - } - $this->data = ''; - if ($this->state === 'emit') - { - return true; - } - else - { - $this->version = ''; - $this->encoding = ''; - $this->standalone = ''; - return false; - } - } - - /** - * Check whether there is data beyond the pointer - * - * @access private - * @return bool true if there is further data, false if not - */ - public function has_data() - { - return (bool) ($this->position < $this->data_length); - } - - /** - * Advance past any whitespace - * - * @return int Number of whitespace characters passed - */ - public function skip_whitespace() - { - $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position); - $this->position += $whitespace; - return $whitespace; - } - - /** - * Read value - */ - public function get_value() - { - $quote = substr($this->data, $this->position, 1); - if ($quote === '"' || $quote === "'") - { - $this->position++; - $len = strcspn($this->data, $quote, $this->position); - if ($this->has_data()) - { - $value = substr($this->data, $this->position, $len); - $this->position += $len + 1; - return $value; - } - } - return false; - } - - public function before_version_name() - { - if ($this->skip_whitespace()) - { - $this->state = 'version_name'; - } - else - { - $this->state = false; - } - } - - public function version_name() - { - if (substr($this->data, $this->position, 7) === 'version') - { - $this->position += 7; - $this->skip_whitespace(); - $this->state = 'version_equals'; - } - else - { - $this->state = false; - } - } - - public function version_equals() - { - if (substr($this->data, $this->position, 1) === '=') - { - $this->position++; - $this->skip_whitespace(); - $this->state = 'version_value'; - } - else - { - $this->state = false; - } - } - - public function version_value() - { - if ($this->version = $this->get_value()) - { - $this->skip_whitespace(); - if ($this->has_data()) - { - $this->state = 'encoding_name'; - } - else - { - $this->state = 'emit'; - } - } - else - { - $this->state = false; - } - } - - public function encoding_name() - { - if (substr($this->data, $this->position, 8) === 'encoding') - { - $this->position += 8; - $this->skip_whitespace(); - $this->state = 'encoding_equals'; - } - else - { - $this->state = 'standalone_name'; - } - } - - public function encoding_equals() - { - if (substr($this->data, $this->position, 1) === '=') - { - $this->position++; - $this->skip_whitespace(); - $this->state = 'encoding_value'; - } - else - { - $this->state = false; - } - } - - public function encoding_value() - { - if ($this->encoding = $this->get_value()) - { - $this->skip_whitespace(); - if ($this->has_data()) - { - $this->state = 'standalone_name'; - } - else - { - $this->state = 'emit'; - } - } - else - { - $this->state = false; - } - } - - public function standalone_name() - { - if (substr($this->data, $this->position, 10) === 'standalone') - { - $this->position += 10; - $this->skip_whitespace(); - $this->state = 'standalone_equals'; - } - else - { - $this->state = false; - } - } - - public function standalone_equals() - { - if (substr($this->data, $this->position, 1) === '=') - { - $this->position++; - $this->skip_whitespace(); - $this->state = 'standalone_value'; - } - else - { - $this->state = false; - } - } - - public function standalone_value() - { - if ($standalone = $this->get_value()) - { - switch ($standalone) - { - case 'yes': - $this->standalone = true; - break; - - case 'no': - $this->standalone = false; - break; - - default: - $this->state = false; - return; - } - - $this->skip_whitespace(); - if ($this->has_data()) - { - $this->state = false; - } - else - { - $this->state = 'emit'; - } - } - else - { - $this->state = false; - } - } -} - -class SimplePie_Locator -{ - var $useragent; - var $timeout; - var $file; - var $local = array(); - var $elsewhere = array(); - var $file_class = 'SimplePie_File'; - var $cached_entities = array(); - var $http_base; - var $base; - var $base_location = 0; - var $checked_feeds = 0; - var $max_checked_feeds = 10; - var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer'; - - public function __construct(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer') - { - $this->file =& $file; - $this->file_class = $file_class; - $this->useragent = $useragent; - $this->timeout = $timeout; - $this->max_checked_feeds = $max_checked_feeds; - $this->content_type_sniffer_class = $content_type_sniffer_class; - } - - public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working) - { - if ($this->is_feed($this->file)) - { - return $this->file; - } - - if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) - { - $sniffer = new $this->content_type_sniffer_class($this->file); - if ($sniffer->get_type() !== 'text/html') - { - return null; - } - } - - if ($type & ~SIMPLEPIE_LOCATOR_NONE) - { - $this->get_base(); - } - - if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery()) - { - return $working[0]; - } - - if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) - { - if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) - { - return $working; - } - - if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) - { - return $working; - } - - if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) - { - return $working; - } - - if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) - { - return $working; - } - } - return null; - } - - public function is_feed(&$file) - { - if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) - { - $sniffer = new $this->content_type_sniffer_class($file); - $sniffed = $sniffer->get_type(); - if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml'))) - { - return true; - } - else - { - return false; - } - } - elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) - { - return true; - } - else - { - return false; - } - } - - public function get_base() - { - $this->http_base = $this->file->url; - $this->base = $this->http_base; - $elements = SimplePie_Misc::get_element('base', $this->file->body); - foreach ($elements as $element) - { - if ($element['attribs']['href']['data'] !== '') - { - $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base); - $this->base_location = $element['offset']; - break; - } - } - } - - public function autodiscovery() - { - $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)); - $done = array(); - $feeds = array(); - foreach ($links as $link) - { - if ($this->checked_feeds === $this->max_checked_feeds) - { - break; - } - if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data'])) - { - $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data']))); - - if ($this->base_location < $link['offset']) - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base); - } - else - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base); - } - - 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])) - { - $this->checked_feeds++; - $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent); - 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)) - { - $feeds[$href] = $feed; - } - } - $done[] = $href; - } - } - - if (!empty($feeds)) - { - return array_values($feeds); - } - else { - return null; - } - } - - public function get_links() - { - $links = SimplePie_Misc::get_element('a', $this->file->body); - foreach ($links as $link) - { - if (isset($link['attribs']['href']['data'])) - { - $href = trim($link['attribs']['href']['data']); - $parsed = SimplePie_Misc::parse_url($href); - if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) - { - if ($this->base_location < $link['offset']) - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base); - } - else - { - $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base); - } - - $current = SimplePie_Misc::parse_url($this->file->url); - - if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority']) - { - $this->local[] = $href; - } - else - { - $this->elsewhere[] = $href; - } - } - } - } - $this->local = array_unique($this->local); - $this->elsewhere = array_unique($this->elsewhere); - if (!empty($this->local) || !empty($this->elsewhere)) - { - return true; - } - return null; - } - - public function extension(&$array) - { - foreach ($array as $key => $value) - { - if ($this->checked_feeds === $this->max_checked_feeds) - { - break; - } - if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml'))) - { - $this->checked_feeds++; - $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent); - 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)) - { - return $feed; - } - else - { - unset($array[$key]); - } - } - } - return null; - } - - public function body(&$array) - { - foreach ($array as $key => $value) - { - if ($this->checked_feeds === $this->max_checked_feeds) - { - break; - } - if (preg_match('/(rss|rdf|atom|xml)/i', $value)) - { - $this->checked_feeds++; - $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent); - 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)) - { - return $feed; - } - else - { - unset($array[$key]); - } - } - } - return null; - } -} class SimplePie_Parser { @@ -13861,8 +11340,7 @@ class SimplePie_Parser public function parse(&$data, $encoding) { - // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character - if (strtoupper($encoding) === 'US-ASCII') + if (strtoupper($encoding) === 'US-ASCII') { $this->encoding = 'UTF-8'; } @@ -13871,29 +11349,23 @@ class SimplePie_Parser $this->encoding = $encoding; } - // Strip BOM: - // UTF-32 Big Endian BOM - if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") { $data = substr($data, 4); } - // UTF-32 Little Endian BOM - elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") { $data = substr($data, 4); } - // UTF-16 Big Endian BOM - elseif (substr($data, 0, 2) === "\xFE\xFF") + elseif (substr($data, 0, 2) === "\xFE\xFF") { $data = substr($data, 2); } - // UTF-16 Little Endian BOM - elseif (substr($data, 0, 2) === "\xFF\xFE") + elseif (substr($data, 0, 2) === "\xFF\xFE") { $data = substr($data, 2); } - // UTF-8 BOM - elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") { $data = substr($data, 3); } @@ -13924,8 +11396,7 @@ class SimplePie_Parser $xml_is_sane = isset($values[0]['value']); } - // Create the parser - if ($xml_is_sane) + if ($xml_is_sane) { $xml = xml_parser_create_ns($this->encoding, $this->separator); xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1); @@ -13934,8 +11405,7 @@ class SimplePie_Parser xml_set_character_data_handler($xml, 'cdata'); xml_set_element_handler($xml, 'tag_open', 'tag_close'); - // Parse! - if (!xml_parse($xml, $data, true)) + if (!xml_parse($xml, $data, true)) { $this->error_code = xml_get_error_code($xml); $this->error_string = xml_error_string($this->error_code); @@ -14163,8 +11633,7 @@ class SimplePie_Parser $namespace = SIMPLEPIE_NAMESPACE_ITUNES; } - // Normalize the Media RSS namespaces - if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG || + if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG || $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 || $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 || $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 || @@ -14183,16 +11652,117 @@ class SimplePie_Parser } } -/** - * @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 - */ + + + +class SimplePie_Rating +{ + var $scheme; + var $value; + + public function __construct($scheme = null, $value = null) + { + $this->scheme = $scheme; + $this->value = $value; + } + + public function __toString() + { + return md5(serialize($this)); + } + + public function get_scheme() + { + if ($this->scheme !== null) + { + return $this->scheme; + } + else + { + return null; + } + } + + public function get_value() + { + if ($this->value !== null) + { + return $this->value; + } + else + { + return null; + } + } +} + + + + +class SimplePie_Restriction +{ + var $relationship; + var $type; + var $value; + + public function __construct($relationship = null, $type = null, $value = null) + { + $this->relationship = $relationship; + $this->type = $type; + $this->value = $value; + } + + public function __toString() + { + return md5(serialize($this)); + } + + public function get_relationship() + { + if ($this->relationship !== null) + { + return $this->relationship; + } + else + { + return null; + } + } + + public function get_type() + { + if ($this->type !== null) + { + return $this->type; + } + else + { + return null; + } + } + + public function get_value() + { + if ($this->value !== null) + { + return $this->value; + } + else + { + return null; + } + } +} + + + + + class SimplePie_Sanitize { - // Private vars - var $base; + var $base; - // Options - var $remove_div = true; + var $remove_div = true; var $image_handler = ''; var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); var $encode_instead_of_strip = false; @@ -14336,14 +11906,7 @@ class SimplePie_Sanitize $this->output_encoding = (string) $encoding; } - /** - * Set element/attribute key/value pairs of HTML attributes - * containing URLs that need to be resolved relative to the feed - * - * @access public - * @since 1.0 - * @param array $element_attribute Element/attribute key/value pairs - */ + 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')) { $this->replace_url_attributes = (array) $element_attribute; @@ -14386,16 +11949,12 @@ class SimplePie_Sanitize if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML)) { - // Strip comments - if ($this->strip_comments) + if ($this->strip_comments) { $data = SimplePie_Misc::strip_comments($data); } - // Strip out HTML tags and attributes that might cause various security problems. - // Based on recommendations by Mark Pilgrim at: - // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely - if ($this->strip_htmltags) + if ($this->strip_htmltags) { foreach ($this->strip_htmltags as $tag) { @@ -14415,15 +11974,13 @@ class SimplePie_Sanitize } } - // Replace relative URLs - $this->base = $base; + $this->base = $base; foreach ($this->replace_url_attributes as $element => $attributes) { $data = $this->replace_urls($data, $element, $attributes); } - // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags. - if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache) + if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache) { $images = SimplePie_Misc::get_element('img', $data); foreach ($images as $img) @@ -14460,8 +12017,7 @@ class SimplePie_Sanitize } } - // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data - $data = trim($data); + $data = trim($data); } if ($type & SIMPLEPIE_CONSTRUCT_IRI) @@ -14536,4 +12092,815 @@ class SimplePie_Sanitize return ''; } } +} + + + + +class SimplePie_Source +{ + var $item; + var $data = array(); + + public function __construct($item, $data) + { + $this->item = $item; + $this->data = $data; + } + + public function __toString() + { + return md5(serialize($this->data)); + } + + public function get_source_tags($namespace, $tag) + { + if (isset($this->data['child'][$namespace][$tag])) + { + return $this->data['child'][$namespace][$tag]; + } + else + { + return null; + } + } + + public function get_base($element = array()) + { + return $this->item->get_base($element); + } + + public function sanitize($data, $type, $base = '') + { + return $this->item->sanitize($data, $type, $base); + } + + public function get_item() + { + return $this->item; + } + + public function get_title() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_category($key = 0) + { + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } + } + + public function get_categories() + { + $categories = array(); + + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) + { + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = new $this->item->feed->category_class($term, $scheme, $label); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = null; + } + $categories[] = new $this->item->feed->category_class($term, $scheme, null); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + { + $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + + if (!empty($categories)) + { + return SimplePie_Misc::array_unique($categories); + } + else + { + return null; + } + } + + public function get_author($key = 0) + { + $authors = $this->get_authors(); + if (isset($authors[$key])) + { + return $authors[$key]; + } + else + { + return null; + } + } + + public function get_authors() + { + $authors = array(); + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) + { + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $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])); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $authors[] = new $this->item->feed->author_class($name, $uri, $email); + } + } + if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) + { + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $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])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = new $this->item->feed->author_class($name, $url, $email); + } + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) + { + $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null); + } + + if (!empty($authors)) + { + return SimplePie_Misc::array_unique($authors); + } + else + { + return null; + } + } + + public function get_contributor($key = 0) + { + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) + { + return $contributors[$key]; + } + else + { + return null; + } + } + + public function get_contributors() + { + $contributors = array(); + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) + { + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $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])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = new $this->item->feed->author_class($name, $uri, $email); + } + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) + { + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $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])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = new $this->item->feed->author_class($name, $url, $email); + } + } + + if (!empty($contributors)) + { + return SimplePie_Misc::array_unique($contributors); + } + else + { + return null; + } + } + + public function get_link($key = 0, $rel = 'alternate') + { + $links = $this->get_links($rel); + if (isset($links[$key])) + { + return $links[$key]; + } + else + { + return null; + } + } + + + public function get_permalink() + { + return $this->get_link(0); + } + + public function get_links($rel = 'alternate') + { + if (!isset($this->data['links'])) + { + $this->data['links'] = array(); + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link')) + { + foreach ($links as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } + } + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link')) + { + foreach ($links as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + + } + } + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + + $keys = array_keys($this->data['links']); + foreach ($keys as $key) + { + if (SimplePie_Misc::is_isegment_nz_nc($key)) + { + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; + } + else + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } + } + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) + { + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; + } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); + } + } + + if (isset($this->data['links'][$rel])) + { + return $this->data['links'][$rel]; + } + else + { + return null; + } + } + + public function get_description() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + else + { + return null; + } + } + + public function get_copyright() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright')) + { + return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_language() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['xml_lang'])) + { + return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_latitude() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) + { + return (float) $return[0]['data']; + } + 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)) + { + return (float) $match[1]; + } + else + { + return null; + } + } + + public function get_longitude() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) + { + return (float) $return[0]['data']; + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + 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)) + { + return (float) $match[2]; + } + else + { + return null; + } + } + + public function get_image_url() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image')) + { + return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + else + { + return null; + } + } +} + + + + + + +class SimplePie_XML_Declaration_Parser +{ + + var $version = '1.0'; + + + var $encoding = 'UTF-8'; + + + var $standalone = false; + + + var $state = 'before_version_name'; + + + var $data = ''; + + + var $data_length = 0; + + + var $position = 0; + + + public function __construct($data) + { + $this->data = $data; + $this->data_length = strlen($this->data); + } + + + public function parse() + { + while ($this->state && $this->state !== 'emit' && $this->has_data()) + { + $state = $this->state; + $this->$state(); + } + $this->data = ''; + if ($this->state === 'emit') + { + return true; + } + else + { + $this->version = ''; + $this->encoding = ''; + $this->standalone = ''; + return false; + } + } + + + public function has_data() + { + return (bool) ($this->position < $this->data_length); + } + + + public function skip_whitespace() + { + $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position); + $this->position += $whitespace; + return $whitespace; + } + + + public function get_value() + { + $quote = substr($this->data, $this->position, 1); + if ($quote === '"' || $quote === "'") + { + $this->position++; + $len = strcspn($this->data, $quote, $this->position); + if ($this->has_data()) + { + $value = substr($this->data, $this->position, $len); + $this->position += $len + 1; + return $value; + } + } + return false; + } + + public function before_version_name() + { + if ($this->skip_whitespace()) + { + $this->state = 'version_name'; + } + else + { + $this->state = false; + } + } + + public function version_name() + { + if (substr($this->data, $this->position, 7) === 'version') + { + $this->position += 7; + $this->skip_whitespace(); + $this->state = 'version_equals'; + } + else + { + $this->state = false; + } + } + + public function version_equals() + { + if (substr($this->data, $this->position, 1) === '=') + { + $this->position++; + $this->skip_whitespace(); + $this->state = 'version_value'; + } + else + { + $this->state = false; + } + } + + public function version_value() + { + if ($this->version = $this->get_value()) + { + $this->skip_whitespace(); + if ($this->has_data()) + { + $this->state = 'encoding_name'; + } + else + { + $this->state = 'emit'; + } + } + else + { + $this->state = false; + } + } + + public function encoding_name() + { + if (substr($this->data, $this->position, 8) === 'encoding') + { + $this->position += 8; + $this->skip_whitespace(); + $this->state = 'encoding_equals'; + } + else + { + $this->state = 'standalone_name'; + } + } + + public function encoding_equals() + { + if (substr($this->data, $this->position, 1) === '=') + { + $this->position++; + $this->skip_whitespace(); + $this->state = 'encoding_value'; + } + else + { + $this->state = false; + } + } + + public function encoding_value() + { + if ($this->encoding = $this->get_value()) + { + $this->skip_whitespace(); + if ($this->has_data()) + { + $this->state = 'standalone_name'; + } + else + { + $this->state = 'emit'; + } + } + else + { + $this->state = false; + } + } + + public function standalone_name() + { + if (substr($this->data, $this->position, 10) === 'standalone') + { + $this->position += 10; + $this->skip_whitespace(); + $this->state = 'standalone_equals'; + } + else + { + $this->state = false; + } + } + + public function standalone_equals() + { + if (substr($this->data, $this->position, 1) === '=') + { + $this->position++; + $this->skip_whitespace(); + $this->state = 'standalone_value'; + } + else + { + $this->state = false; + } + } + + public function standalone_value() + { + if ($standalone = $this->get_value()) + { + switch ($standalone) + { + case 'yes': + $this->standalone = true; + break; + + case 'no': + $this->standalone = false; + break; + + default: + $this->state = false; + return; + } + + $this->skip_whitespace(); + if ($this->has_data()) + { + $this->state = false; + } + else + { + $this->state = 'emit'; + } + } + else + { + $this->state = false; + } + } } \ No newline at end of file diff --git a/makefulltextfeed.php b/makefulltextfeed.php index 62a88a2..de73862 100644 --- a/makefulltextfeed.php +++ b/makefulltextfeed.php @@ -1,10 +1,10 @@ 'iri/iri.php', // Include Zend Cache to improve performance (cache results) - 'Zend_Cache' => 'Zend/Cache.php' + 'Zend_Cache' => 'Zend/Cache.php', + // Include Zend CSS to XPath for dealing with custom patterns + 'Zend_Dom_Query_Css2Xpath' => 'Zend/Dom/Query/Css2Xpath.php' ); if (isset($mapping[$class_name])) { //echo "Loading $class_name\n
"; @@ -68,29 +70,9 @@ function __autoload($class_name) { //////////////////////////////// // Load config file if it exists //////////////////////////////// -// the config values below should be set in config.php (rename config-sample.php if config.php doesn't exist). -// the values below will only be used if config.php doesn't exist. -$options->enabled = true; -$options->restrict = false; -$options->default_entries = 5; -$options->max_entries = 10; -$options->rewrite_relative_urls = true; -$options->caching = false; -$options->cache_dir = dirname(__FILE__).'/cache'; -$options->message_to_prepend = ''; -$options->message_to_append = ''; -$options->blocked_urls = array(); -$options->alternative_url = ''; -$options->error_message = '[unable to retrieve full-text content]'; -$options->api_keys = array(); -$options->default_entries_with_key = 5; -$options->max_entries_with_key = 10; -$options->message_to_prepend_with_key = ''; -$options->message_to_append_with_key = ''; -$options->error_message_with_key = '[unable to retrieve full-text content]'; -$options->cache_directory_level = 0; -if (file_exists(dirname(__FILE__).'/config.php')) { - require_once(dirname(__FILE__).'/config.php'); +require_once(dirname(__FILE__).'/config.php'); +if (file_exists(dirname(__FILE__).'/custom_config.php')) { + require_once(dirname(__FILE__).'/custom_config.php'); } ////////////////////////////////////////////// @@ -100,10 +82,6 @@ if (file_exists(dirname(__FILE__).'/config.php')) { ////////////////////////////////////////////// function convert_to_utf8($html, $header=null) { - $accept = array( - 'type' => array('application/rss+xml', 'application/xml', 'application/rdf+xml', 'text/xml', 'text/html'), - 'charset' => array_diff(mb_list_encodings(), array('pass', 'auto', 'wchar', 'byte2be', 'byte2le', 'byte4be', 'byte4le', 'BASE64', 'UUENCODE', 'HTML-ENTITIES', 'Quoted-Printable', '7bit', '8bit')) - ); $encoding = null; if ($html || $header) { if (is_array($header)) $header = implode("\n", $header); @@ -111,10 +89,6 @@ function convert_to_utf8($html, $header=null) // error parsing the response } else { $match = end($match); // get last matched element (in case of redirects) - if (!in_array(strtolower($match[1]), $accept['type'])) { - // type not accepted - // TODO: avoid conversion - } if (isset($match[2])) $encoding = trim($match[2], '"\''); } if (!$encoding) { @@ -127,10 +101,6 @@ function convert_to_utf8($html, $header=null) if (!$encoding) { $encoding = 'utf-8'; } else { - if (!in_array($encoding, array_map('strtolower', $accept['charset']))) { - // encoding not accepted - // TODO: avoid conversion - } if (strtolower($encoding) != 'utf-8') { if (strtolower($encoding) == 'iso-8859-1') { // replace MS Word smart qutoes @@ -184,17 +154,21 @@ function makeAbsolute($base, $elem) { for ($i = $elems->length-1; $i >= 0; $i--) { $e = $elems->item($i); //$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e); - if ($e->hasAttribute($attr)) { - // Trim leading and trailing white space. I don't really like this but - // unfortunately it does appear on some sites. e.g. - $url = trim(str_replace('%20', ' ', $e->getAttribute($attr))); - $url = str_replace(' ', '%20', $url); - if (!preg_match('!https?://!i', $url)) { - $absolute = IRI::absolutize($base, $url); - if ($absolute) { - $e->setAttribute($attr, $absolute); - } - } + makeAbsoluteAttr($base, $e, $attr); + } + if (strtolower($elem->tagName) == $tag) makeAbsoluteAttr($base, $elem, $attr); + } +} +function makeAbsoluteAttr($base, $e, $attr) { + if ($e->hasAttribute($attr)) { + // Trim leading and trailing white space. I don't really like this but + // unfortunately it does appear on some sites. e.g. + $url = trim(str_replace('%20', ' ', $e->getAttribute($attr))); + $url = str_replace(' ', '%20', $url); + if (!preg_match('!https?://!i', $url)) { + $absolute = IRI::absolutize($base, $url); + if ($absolute) { + $e->setAttribute($attr, $absolute); } } } @@ -233,6 +207,26 @@ if ($options->alternative_url != '' && !isset($_GET['redir']) && mt_rand(0, 100) if (isset($_GET['key'])) $redirect .= '&key='.urlencode($_GET['key']); if (isset($_GET['max'])) $redirect .= '&max='.(int)$_GET['max']; if (isset($_GET['links'])) $redirect .= '&links='.$_GET['links']; + if (isset($_GET['exc'])) $redirect .= '&exc='.$_GET['exc']; + if (isset($_GET['what'])) $redirect .= '&what='.$_GET['what']; + header("Location: $redirect"); + exit; +} + +///////////////////////////////// +// Redirect to hide API key +///////////////////////////////// +if (isset($_GET['key']) && ($key_index = array_search($_GET['key'], $options->api_keys)) !== false) { + $host = $_SERVER['HTTP_HOST']; + $path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\'); + $redirect = 'http://'.htmlspecialchars($host.$path).'/makefulltextfeed.php?url='.urlencode($url); + $redirect .= '&key='.$key_index; + $redirect .= '&hash='.urlencode(sha1($_GET['key'].$url)); + if (isset($_GET['html'])) $redirect .= '&html='.urlencode($_GET['html']); + if (isset($_GET['max'])) $redirect .= '&max='.(int)$_GET['max']; + if (isset($_GET['links'])) $redirect .= '&links='.urlencode($_GET['links']); + if (isset($_GET['exc'])) $redirect .= '&exc='.urlencode($_GET['exc']); + if (isset($_GET['what'])) $redirect .= '&what='.urlencode($_GET['what']); header("Location: $redirect"); exit; } @@ -240,20 +234,35 @@ if ($options->alternative_url != '' && !isset($_GET['redir']) && mt_rand(0, 100) /////////////////////////////////////////////// // Check if the request is explicitly for an HTML page /////////////////////////////////////////////// -$html_only = (isset($_GET['html']) && $_GET['html'] == 'true'); +$html_only = (isset($_GET['html']) && ($_GET['html'] == '1' || $_GET['html'] == 'true')); /////////////////////////////////////////////// // Check if valid key supplied /////////////////////////////////////////////// -$valid_key = (isset($_GET['key']) && in_array($_GET['key'], $options->api_keys)); +$valid_key = false; +if (isset($_GET['key']) && isset($_GET['hash']) && isset($options->api_keys[(int)$_GET['key']])) { + $valid_key = ($_GET['hash'] == sha1($options->api_keys[(int)$_GET['key']].$url)); +} /////////////////////////////////////////////// // Check URL against list of blacklisted URLs // TODO: set up better system for this /////////////////////////////////////////////// -foreach ($options->blocked_urls as $blockurl) { - if (strstr($url, $blockurl) !== false) { - die('URL blocked'); + +if (!empty($options->allowed_urls)) { + $allowed = false; + foreach ($options->allowed_urls as $allowurl) { + if (strstr($url, $allowurl) !== false) { + $allowed = true; + break; + } + } + if (!$allowed) die('URL not allowed'); +} else { + foreach ($options->blocked_urls as $blockurl) { + if (strstr($url, $blockurl) !== false) { + die('URL blocked'); + } } } @@ -285,6 +294,50 @@ if (($valid_key || !$options->restrict) && isset($_GET['links']) && in_array($_G $links = 'preserve'; } +/////////////////////////////////////////////// +// Exclude items if extraction fails +/////////////////////////////////////////////// +if ($options->exclude_items_on_fail == 'user') { + $exclude_on_fail = (isset($_GET['exc']) && ($_GET['exc'] == '1')); +} else { + $exclude_on_fail = $options->exclude_items_on_fail; +} + +/////////////////////////////////////////////// +// Extraction pattern +/////////////////////////////////////////////// +$auto_extract = true; +if ($options->extraction_pattern == 'user') { + $extract_pattern = (isset($_GET['what']) ? trim($_GET['what']) : 'auto'); +} else { + $extract_pattern = trim($options->extraction_pattern); +} +if (($extract_pattern != '') && ($extract_pattern != 'auto')) { + // split pattern by space (currently only descendants of 'auto' are recognised) + $extract_pattern = preg_split('/\s+/', $extract_pattern, 2); + if ($extract_pattern[0] == 'auto') { // parent selector is 'auto' + $extract_pattern = $extract_pattern[1]; + } else { + $extract_pattern = implode(' ', $extract_pattern); + $auto_extract = false; + } + // Convert CSS to XPath + // Borrowed from Symfony's cssToXpath() function: https://github.com/fabpot/symfony/blob/master/src/Symfony/Component/CssSelector/Parser.php + // (Itself based on Python's lxml library) + if (preg_match('#^\w+\s*$#u', $extract_pattern, $match)) { + $extract_pattern = '//'.trim($match[0]); + } elseif (preg_match('~^(\w*)#(\w+)\s*$~u', $extract_pattern, $match)) { + $extract_pattern = sprintf("%s%s[@id = '%s']", '//', $match[1] ? $match[1] : '*', $match[2]); + } elseif (preg_match('#^(\w*)\.(\w+)\s*$#u', $extract_pattern, $match)) { + $extract_pattern = sprintf("%s%s[contains(concat(' ', normalize-space(@class), ' '), ' %s ')]", '//', $match[1] ? $match[1] : '*', $match[2]); + } else { + // if the patterns above do not match, invoke Zend's CSS to Xpath function + $extract_pattern = Zend_Dom_Query_Css2Xpath::transform($extract_pattern); + } +} else { + $extract_pattern = false; +} + ///////////////////////////////////// // Check for valid format // (stick to RSS for the time being) @@ -299,7 +352,7 @@ if ($options->caching) { 'lifetime' => ($valid_key || !$options->restrict) ? 10*60 : 20*60, // cache lifetime of 10 or 20 minutes 'automatic_serialization' => false, 'write_control' => false, - 'automatic_cleaning_factor' => 100, + 'automatic_cleaning_factor' => $options->cache_cleanup, 'ignore_user_abort' => false ); $backendOptions = array( @@ -315,8 +368,8 @@ if ($options->caching) { // getting a Zend_Cache_Core object $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); - $cache_id = md5($max.$url.$valid_key.$links); - + $cache_id = md5($max.$url.$valid_key.$links.$exclude_on_fail.$auto_extract.$extract_pattern.(int)isset($_GET['pubsub'])); + if ($data = $cache->load($cache_id)) { header("Content-type: text/xml; charset=UTF-8"); if (headers_sent()) die('Some data has already been output, can\'t send RSS file'); @@ -339,12 +392,13 @@ if ($valid_key) { ////////////////////////////////// $http = new HumbleHttpAgent(); +/* if ($options->caching) { $frontendOptions = array( 'lifetime' => 30*60, // cache lifetime of 30 minutes 'automatic_serialization' => true, 'write_control' => false, - 'automatic_cleaning_factor' => 100, + 'automatic_cleaning_factor' => $options->cache_cleanup, 'ignore_user_abort' => false ); $backendOptions = array( @@ -360,6 +414,7 @@ if ($options->caching) { $httpCache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); $http->useCache($httpCache); } +*/ //////////////////////////////// // Tidy config @@ -416,22 +471,50 @@ if ($html_only || !$result) { } else { die('Error retrieving '.$url); } - // Run through Tidy (if it exists). - // This fixes problems with some sites which would otherwise - // trouble DOMDocument's HTML parsing. - if (function_exists('tidy_parse_string')) { - $tidy = tidy_parse_string($html, $tidy_config, 'UTF8'); - if (tidy_clean_repair($tidy)) { - $html = $tidy->value; + if ($auto_extract) { + // Run through Tidy (if it exists). + // This fixes problems with some sites which would otherwise + // trouble DOMDocument's HTML parsing. + if (function_exists('tidy_parse_string')) { + $tidy = tidy_parse_string($html, $tidy_config, 'UTF8'); + if (tidy_clean_repair($tidy)) { + $html = $tidy->value; + } + } + $readability = new Readability($html, $effective_url); + if ($links == 'footnotes') $readability->convertLinksToFootnotes = true; + if (!$readability->init() && $exclude_on_fail) die('Sorry, could not extract content'); + // content block is detected element + $content_block = $readability->getContent(); + } else { + $readability = new Readability($html, $effective_url); + // content block is entire document + $content_block = $readability->dom; + } + if ($extract_pattern) { + $xpath = new DOMXPath($readability->dom); + $elems = @$xpath->query($extract_pattern, $content_block); + // check if our custom extraction pattern matched + if ($elems && $elems->length > 0) { + // get the first matched element + $content_block = $elems->item(0); + // clean it up + $readability->removeScripts($content_block); + $readability->prepArticle($content_block); + } else { + if ($exclude_on_fail) die('Sorry, could not extract content'); + $content_block = $readability->dom->createElement('p', 'Sorry, could not extract content'); } } - $readability = new Readability($html, $effective_url); - if ($links == 'footnotes') $readability->convertLinksToFootnotes = true; - $readability->init(); - $readability->clean($readability->getContent(), 'select'); - if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $readability->getContent()); + $readability->clean($content_block, 'select'); + if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $content_block); $title = $readability->getTitle()->textContent; - $content = $readability->getContent()->innerHTML; + if ($extract_pattern) { + // get outerHTML + $content = $content_block->ownerDocument->saveXML($content_block); + } else { + $content = $content_block->innerHTML; + } if ($links == 'remove') { $content = preg_replace('!]*>!', '', $content); } @@ -446,6 +529,7 @@ if ($html_only || !$result) { $output = new FeedWriter(); //ATOM an option $output->setTitle($title); $output->setDescription("Content extracted from $url"); + $output->setXsl('css/feed.xsl'); // Chrome uses this, most browsers ignore it if ($format == 'atom') { $output->setChannelElement('updated', date(DATE_ATOM)); $output->setChannelElement('author', array('name'=>'Five Filters', 'uri'=>'http://fivefilters.org')); @@ -471,7 +555,13 @@ if ($html_only || !$result) { $output = new FeedWriter(); $output->setTitle($feed->get_title()); $output->setDescription($feed->get_description()); -$output->setLink($feed->get_link()); +$output->setXsl('css/feed.xsl'); // Chrome uses this, most browsers ignore it +if ($valid_key && isset($_GET['pubsub'])) { // used only on fivefilters.org at the moment + $output->addHub('http://fivefilters.superfeedr.com/'); + $output->addHub('http://pubsubhubbub.appspot.com/'); + $output->setSelf('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); +} +$output->setLink($feed->get_link()); // Google Reader uses this for pulling in favicons if ($img_url = $feed->get_image_url()) { $output->setImage($feed->get_title(), $feed->get_link(), $img_url); } @@ -499,33 +589,82 @@ $http->fetchAll($urls_sanitized); $http->cacheAll(); foreach ($items as $key => $item) { + $extract_result = false; $permalink = $urls[$key]; $newitem = $output->createNewItem(); $newitem->setTitle(htmlspecialchars_decode($item->get_title())); - if ($permalink !== false) { - $newitem->setLink($permalink); + if ($valid_key && isset($_GET['pubsub'])) { // used only on fivefilters.org at the moment + if ($permalink !== false) { + $newitem->setLink('http://fivefilters.org/content-only/redirect.php?url='.urlencode($permalink)); + } else { + $newitem->setLink('http://fivefilters.org/content-only/redirect.php?url='.urlencode($item->get_permalink())); + } } else { - $newitem->setLink($item->get_permalink()); + if ($permalink !== false) { + $newitem->setLink($permalink); + } else { + $newitem->setLink($item->get_permalink()); + } } if ($permalink && $response = $http->get($permalink)) { $effective_url = $response['effective_url']; $html = $response['body']; $html = convert_to_utf8($html, $response['headers']); - // Run through Tidy (if it exists). - // This fixes problems with some sites which would otherwise - // trouble DOMDocument's HTML parsing. (Although sometimes it fails - // to return anything, so it's a bit of tradeoff.) - if (function_exists('tidy_parse_string')) { - $tidy = tidy_parse_string($html, $tidy_config, 'UTF8'); - $tidy->cleanRepair(); - $html = $tidy->value; - } - $readability = new Readability($html, $effective_url); - if ($links == 'footnotes') $readability->convertLinksToFootnotes = true; - $readability->init(); - $readability->clean($readability->getContent(), 'select'); - if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $readability->getContent()); - $html = $readability->getContent()->innerHTML; + if ($auto_extract) { + // Run through Tidy (if it exists). + // This fixes problems with some sites which would otherwise + // trouble DOMDocument's HTML parsing. (Although sometimes it fails + // to return anything, so it's a bit of tradeoff.) + if (function_exists('tidy_parse_string')) { + $tidy = tidy_parse_string($html, $tidy_config, 'UTF8'); + $tidy->cleanRepair(); + $html = $tidy->value; + } + $readability = new Readability($html, $effective_url); + if ($links == 'footnotes') $readability->convertLinksToFootnotes = true; + $extract_result = $readability->init(); + // content block is detected element + $content_block = $readability->getContent(); + } else { + $readability = new Readability($html, $effective_url); + // content block is entire document (for now...) + $content_block = $readability->dom; + } + if ($extract_pattern) { + $xpath = new DOMXPath($readability->dom); + $elems = @$xpath->query($extract_pattern, $content_block); + // check if our custom extraction pattern matched + if ($elems && $elems->length > 0) { + $extract_result = true; + // get the first matched element + $content_block = $elems->item(0); + // clean it up + $readability->removeScripts($content_block); + $readability->prepArticle($content_block); + } + } + } + // if we failed to extract content... + if (!$extract_result) { + if ($exclude_on_fail) continue; // skip this and move to next item + if (!$valid_key) { + $html = $options->error_message; + } else { + $html = $options->error_message_with_key; + } + // keep the original item description + $html .= $item->get_description(); + } else { + $readability->clean($content_block, 'select'); + if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $content_block); + if ($extract_pattern) { + // get outerHTML + $html = $content_block->ownerDocument->saveXML($content_block); + } else { + $html = $content_block->innerHTML; + } + // post-processing cleanup + $html = preg_replace('!

[\s\h\v]*

!u', '', $html); if ($links == 'remove') { $html = preg_replace('!]*>!', '', $html); } @@ -535,14 +674,7 @@ foreach ($items as $key => $item) { } else { $html = $options->message_to_prepend_with_key.$html; $html .= $options->message_to_append_with_key; - } - } else { - if (!$valid_key) { - $html = $options->error_message; - } else { - $html = $options->error_message_with_key; - } - $html .= $item->get_description(); + } } if ($format == 'atom') { $newitem->addElement('content', $html); @@ -551,7 +683,11 @@ foreach ($items as $key => $item) { $newitem->addElement('author', array('name'=>$author->get_name())); } } else { - $newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true')); + if ($valid_key && isset($_GET['pubsub'])) { // used only on fivefilters.org at the moment + $newitem->addElement('guid', 'http://fivefilters.org/content-only/redirect.php?url='.urlencode($item->get_permalink()), array('isPermaLink'=>'false')); + } else { + $newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true')); + } $newitem->setDescription($html); if ((int)$item->get_date('U') > 0) { $newitem->setDate((int)$item->get_date('U'));
-

Create Full-Text Feeds — from FiveFilters.org

-
-
- Create full-text feed from webpage or feed URL -
-
-
-
-
-
- Options - - -
-
-
-
-
-
-
-
-
-
- -
-
- -

For the site owner

- -

Thanks for downloading and setting this up. If you haven't done so already, check server compatibility - to see if your environment will support this application.

-

If everything's okay, feel free to edit this file (index.html) and make any changes you like. If you plan - to offer this service to others, please keep a download link so users can grab a copy of the code if they - want it (you can either offer the download yourself, or link to the download page on fivefilters.org). - That's one requirement of the license.

-

Thanks! :)

- -

For everyone else

- -

About

-

This is a free software project to help people extract content from web pages. It can extract content from a standard HTML page and return a 1-item feed or it can transform an existing feed into a full-text feed. It is being developed as part of the Five Filters project to promote independent, non-corporate media.

- -

Bookmarklet

-

To easily transform partial-feeds you encounter (or convert any content on a page into a 1-item feed), drag the link below to your browser's bookmarks toolbar. - Then whenever you'd like a full-text feed, click the bookmarklet.

-

Drag this: - - -

API

-

To extract content from a web page or to transform an existing partial feed to full text, pass the URL (encoded) in the querystring to the following URL:

-
    -
  • /makefulltextfeed.php?url=[url]
  • -
-

If you have an API key, add that to the querystring:

-
    -
  • /makefulltextfeed.php?key=[key]&url=[url]
  • -
  • /makefulltextfeed.php?key=[key]&max=[number of feed items]&url=[url]
  • -
- -

If you're not hosting this yourself, you do not have to rely on an external API if you don't want to — this is a free software (open source) - project licensed under the AGPL. You're free to download your own copy.

- -

Source Code and Technologies

-

Source code available on launchpad.net.

The application uses PHP, PHP Readability, SimplePie, FeedWriter, Humble HTTP Agent, Zend Cache and IRI. Readability is the magic piece of code that tries to identify and extract the content block from any given web page.

- -

System Requirements

- -

PHP 5.2 or above is required. - The code has been tested on Windows and Linux using the Apache web server. If you're a Windows user, you can try it on your own machine using WampServer.

- -

Download and Installation

-

The software can be downloaded free of charge through launchpad.net using a Bazaar client (see below). - However, for those who'd like a simpler solution, you can also buy a zip package with the - source code.

- -

Installation with the Bazaar client

- -
    -
  1. Log in to your host using SSH
  2. -
  3. Change to the directory where you want Full-Text RSS installed
  4. -
  5. Enter bzr export full-text-rss http://bazaar.launchpad.net/~keyvan/fivefilters/content-only/
  6. -
  7. Now enter chmod -R 0777 full-text-rss/cache/
  8. -
  9. That's it! Try accessing the full-text-rss folder through your web browser, you should see the form asking for a URL.
  10. -
  11. (Optional) If you'd like to customise the software, rename config-sample.php to config.php and edit the file.
  12. -
- -

If you'd like to create a feed without going through the form first, you can simply pass the URL in the query string to makefulltextfeed.php (see the API section above).

- -

License

-

AGPL logo
This web application is licensed under the AGPL version 3 — which basically means if you use the code to offer the same or similar service for your users, you are also required to share the code with your users so they can do the same themselves. (More on why this is important.)

-

The libraries used by the application are licensed as follows...

- - - -

To support the development of the Full-Text RSS project, please donate. All donations greatly appreciated.

- -