Full-Text RSS 2.5

This commit is contained in:
Keyvan 2011-03-23 23:39:01 +01:00
parent 415ec01264
commit 8f5d813459
21 changed files with 7144 additions and 8224 deletions

View File

@ -2,6 +2,16 @@ FiveFilters.org: Full-Text RSS
http://fivefilters.org/content-only/ http://fivefilters.org/content-only/
CHANGELOG 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) 2.2 (2010-10-30)
- Character-encoding detection improved (minor change) - Character-encoding detection improved (minor change)

119
cleancache.php Normal file
View File

@ -0,0 +1,119 @@
<?php
// Full-Text RSS: Clear Cache
// Author: Keyvan Minoukadeh
// Copyright (c) 2010 Keyvan Minoukadeh
// License: AGPLv3
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// 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<br />";
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);
?>

View File

@ -1,5 +1,10 @@
<?php <?php
/* Full-Text RSS options */ /* Full-Text RSS config */
// Please do not change this file (config.php) directly.
// Save a copy as custom_config.php and make your
// changes to that instead. It will automatically
// override anything in config.php.
// Enable service // Enable service
// ---------------------- // ----------------------
@ -8,15 +13,6 @@
// be told that the service is disabled. // be told that the service is disabled.
$options->enabled = true; $options->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) // Default entries (without API key)
// ---------------------- // ----------------------
// The number of feed items to process when no API key is supplied. // 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. // the extracted content block.
$options->rewrite_relative_urls = true; $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 caching
// ---------------------- // ----------------------
// Enable this if you'd like to cache results // 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. // HTML to insert at the end of each feed item when no API key is supplied.
$options->message_to_append = ''; $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 // 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(); $options->blocked_urls = array();
// Error message when content extraction fails (without API key) // Error message when content extraction fails (without API key)
@ -71,43 +98,6 @@ $options->error_message = '[unable to retrieve full-text content]';
/// ADVANCED OPTIONS //////////////////////////// /// 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 // Alternative Full-Text RSS service URL
// ---------------------- // ----------------------
// This option is to offer very simple load distribution for the service. // 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. // It's best not to change this if you're unsure.
$options->cache_directory_level = 0; $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');
?> ?>

30
css/feed.css Normal file
View File

@ -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; }

34
css/feed.xsl Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:variable name="title" select="/rss/channel/title"/>
<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="$title"/> (full-text feed)</title>
<style type="text/css">
@import url(css/feed.css);
</style>
</head>
<body>
<div id="explanation">
<h1><xsl:value-of select="$title"/> <span class="small"> (full-text feed)</span></h1>
<p>You are viewing an auto-generated full-text <acronym title="Really Simple Syndication">RSS</acronym> 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.</p>
<p>Below is the latest content available from this feed.</p>
</div>
<div id="content">
<ul>
<xsl:for-each select="rss/channel/item">
<div class="article">
<li><a href="{link}" rel="bookmark"><xsl:value-of disable-output-escaping="yes" select="title"/></a>
<div><xsl:value-of disable-output-escaping="yes" select="description" /></div>
</li>
</div>
</xsl:for-each>
</ul>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -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 {font-size:11px; font-weight:bold; color:#666;}
label.opt {font-weight:normal;} label.opt {font-weight:normal;}
dl {clear:both;} dl {clear:both;}
dt {float:left; text-align:right; width:90px; line-height:25px; margin:0 10px 10px 0;} dt {float:left; text-align:right; width:100px; line-height:25px; margin:0 10px 10px 0;}
dd {float:left; width:475px; line-height:25px; margin:0 0 10px 0;} dd {float:left; width:465px; line-height:25px; margin:0 0 10px 0;}
#footer {font-size:11px;} #footer {font-size:11px;}
#container {width:700px; margin:0 auto;} #container {width:700px; margin:0 auto;}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,144 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Full-Text RSS Feeds | from fivefilters.org</title>
<script type="text/javascript" src="niceforms.js"></script>
<link rel="stylesheet" href="css/niceforms-default.css" type="text/css" media="screen" />
<script type="text/javascript" src="js/niceforms.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var baseUrl = 'http://'+window.location.host+window.location.pathname.replace(/(\/index\.html|\/)$/, '');
</script>
</head>
<body style="background-color: #eee; margin: 0; line-height: 1.4em;">
<div id="container">
<h1 style="padding-bottom: 30px;">Create Full-Text Feeds <span style="font-size: .7em; font-weight: normal;">&mdash; from <a href="http://fivefilters.org">FiveFilters.org</a></span></h1>
<form method="get" action="makefulltextfeed.php" id="form" class="niceform">
<fieldset>
<legend>Create full-text feed from webpage or feed URL</legend>
<dl>
<dt><label for="url">Enter URL:</label></dt>
<dd><input type="text" id="url" name="url" style="width: 450px" /></dd>
</dl>
</fieldset>
<fieldset>
<legend>Options</legend>
<!-- Remove the comments below to include API key field -->
<!--
<dl>
<dt><label for="key">API key:</label></dt>
<dd><input type="text" id="key" name="key" /></dd>
</dl>
-->
<dl>
<dt><label for="max">Max items:</label></dt>
<dd><select name="max" id="max">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5" selected="selected">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select></dd>
</dl>
<dl>
<dt><label for="links">Links</label></dt>
<dd><select name="links">
<option value="preserve" selected="selected">preserve</option>
<option value="footnotes">add to footnotes</option>
<option value="remove">remove</option>
</select></label></dd>
</dl>
</fieldset>
<fieldset class="action" style="background: transparent; border: none; margin-bottom: 20px; padding: 0;">
<input type="submit" id="sudbmit" name="submit" value="Create Feed" />
</fieldset>
</form>
<h2>For the site owner</h2>
<p>Thanks for downloading and setting this up. If you haven't done so already, <a href="ftr_compatibility_test.php">check server compatibility</a>
to see if your environment will support this application.</p>
<p>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.</p>
<p>Thanks! :)</p>
<h2>For everyone else</h2>
<h3>About</h3>
<p>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 <a href="http://fivefilters.org">Five Filters</a> project to promote independent, non-corporate media.</p>
<h3>Bookmarklet</h3>
<p>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.</p>
<p>Drag this:
<script type="text/javascript">
document.write('<a style="cursor: move;" onclick="alert(\'drag to bookmarks toolbar\'); return false;" href="javascript:location.href=\''+baseUrl+'/makefulltextfeed.php?url=\'+escape(document.location.href);">Full-Text RSS</a>');
</script>
<h3 id="api">API</h3>
<p>To extract content from a web page or to transform an existing partial feed to full text, pass the URL (<a href="http://meyerweb.com/eric/tools/dencoder/">encoded</a>) in the querystring to the following URL:</p>
<ul>
<li style="font-family: monospace;"><script type="text/javascript">document.write(baseUrl);</script>/makefulltextfeed.php?url=<strong>[url]</strong></li>
</ul>
<p>If you have an API key, add that to the querystring:</p>
<ul>
<li style="font-family: monospace; white-space:nowrap;"><script type="text/javascript">document.write(baseUrl);</script>/makefulltextfeed.php?key=<strong>[key]</strong>&amp;url=<strong>[url]</strong></li>
<li style="font-family: monospace; white-space:nowrap;"><script type="text/javascript">document.write(baseUrl);</script>/makefulltextfeed.php?key=<strong>[key]</strong>&amp;max=<strong>[number of feed items]</strong>&amp;url=<strong>[url]</strong></li>
</ul>
<p>If you're not hosting this yourself, you do not have to rely on an external API if you don't want to &mdash; this is a free software (open source)
project licensed under the AGPL. You're free to <a href="http://fivefilters.org/content-only/#download">download your own copy</a>.</p>
<h3>Source Code and Technologies</h3>
<p><a href="https://code.launchpad.net/~keyvan/fivefilters/content-only">Source code available on launchpad.net</a>.</p><p>The application uses <a href="http://en.wikipedia.org/wiki/PHP">PHP</a>, <a href="http://www.keyvan.net/2010/08/php-readability/">PHP Readability</a>, <a href="http://simplepie.org/">SimplePie</a>, <a href="http://www.ajaxray.com/blog/2008/03/08/php-universal-feed-generator-supports-rss-10-rss-20-and-atom/">FeedWriter</a>, Humble HTTP Agent, <a href="http://framework.zend.com/manual/en/zend.cache.introduction.html">Zend Cache</a> and <a href="http://hg.gsnedders.com/iri/">IRI</a>. Readability is the magic piece of code that tries to identify and extract the content block from any given web page.</p>
<h3>System Requirements</h3>
<p>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 <a href="http://www.wampserver.com/en/index.php">WampServer</a>.</p>
<h3 id="download">Download and Installation</h3>
<p>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 <a href="http://fivefilters.org/content-only/#download">buy a zip package</a> with the
source code.</p>
<h3>Installation with the Bazaar client</h3>
<ol style="width: 800px">
<li>Log in to your host using SSH</li>
<li>Change to the directory where you want Full-Text RSS installed</li>
<li>Enter <kbd>bzr export full-text-rss http://bazaar.launchpad.net/~keyvan/fivefilters/content-only/</kbd></li>
<li>Now enter <kbd>chmod -R 0777 full-text-rss/cache/</kbd></li>
<li><strong>That's it!</strong> Try accessing the full-text-rss folder through your web browser, you should see the form asking for a URL.</li>
<li>(Optional) If you'd like to customise the software, rename config-sample.php to config.php and edit the file.</li>
</ol>
<p>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 <a href="#api">API section</a> above).</p>
<h3>License</h3>
<p><a href="http://en.wikipedia.org/wiki/Affero_General_Public_License" style="border-bottom: none;"><img src="images/agplv3.png" alt="AGPL logo" /></a><br />This web application is licensed under the <a href="http://en.wikipedia.org/wiki/Affero_General_Public_License">AGPL version 3</a> &mdash; 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. (<a href="http://www.clipperz.com/users/marco/blog/2008/05/30/freedom_and_privacy_cloud_call_action">More on why this is important.</a>)</p>
<p>The libraries used by the application are licensed as follows...</p>
<ul>
<li>Readability: <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License v2</a></li>
<li>SimplePie: <a href="http://en.wikipedia.org/wiki/BSD_license">BSD</a></li>
<li>FeedWriter: <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GPL v2</a></li>
<li>Humble HTTP Agent: <a href="http://en.wikipedia.org/wiki/Affero_General_Public_License">AGPL v3</a></li>
<li>Zend Cache: <a href="http://framework.zend.com/license/new-bsd">New BSD</a></li>
<li>IRI: <a href="http://en.wikipedia.org/wiki/BSD_license">BSD</a></li>
</ul>
<h3 id="donate">Donate</h3>
<p>To support the development of the Full-Text RSS project, please <a href="http://fivefilters.org/content-only/#donate">donate</a>. All donations greatly appreciated.</p>
</div>
</body>
</html>

182
index.php Normal file
View File

@ -0,0 +1,182 @@
<?php
require_once(dirname(__FILE__).'/config.php');
// check for custom config.php (custom_config.php)
if (file_exists(dirname(__FILE__).'/custom_config.php')) {
require_once(dirname(__FILE__).'/custom_config.php');
}
// check for custom index.php (custom_index.php)
if (!defined('_FF_FTR_INDEX')) {
define('_FF_FTR_INDEX', true);
if (file_exists(dirname(__FILE__).'/custom_index.php')) {
include(dirname(__FILE__).'/custom_index.php');
exit;
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Full-Text RSS Feeds | from fivefilters.org</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="robots" content="noindex, follow" />
<script type="text/javascript" src="niceforms.js"></script>
<link rel="stylesheet" href="css/niceforms-default.css" type="text/css" media="screen" />
<script type="text/javascript" src="js/niceforms.js"></script>
<!--<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>-->
<script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
var baseUrl = 'http://'+window.location.host+window.location.pathname.replace(/(\/index\.html|\/)$/, '');
$(document).ready(function() {
$('#form').submit(function() {
$('#url').val($('#url').val().replace(/^http:\/\//i, ''));
return true;
});
});
</script>
</head>
<body style="background-color: #eee; margin: 0; line-height: 1.4em;">
<div id="container">
<h1 style="padding-bottom: 30px;">Full-Text RSS <?php echo _FF_FTR_VERSION; ?> <span style="font-size: .7em; font-weight: normal;">&mdash; from <a href="http://fivefilters.org">FiveFilters.org</a></span></h1>
<form method="get" action="makefulltextfeed.php" id="form" class="niceform">
<fieldset>
<legend>Create full-text feed from feed or webpage URL</legend>
<dl>
<dt><label for="url">Enter URL:</label></dt>
<dd><input type="text" id="url" name="url" style="width: 450px;" /></dd>
</dl>
</fieldset>
<fieldset>
<legend>Options</legend>
<?php if ($options->extraction_pattern == 'user') { ?>
<dl>
<dt><label for="what">Extraction pattern:</label></dt>
<dd><input type="text" id="what" name="what" value="auto" style="width: 250px;" /></dd>
</dl>
<?php } ?>
<?php if (isset($options->api_keys) && !empty($options->api_keys)) { ?>
<dl>
<dt><label for="key">API key:</label></dt>
<dd><input type="text" id="key" name="key" style="width: 250px;" /></dd>
</dl>
<?php } ?>
<dl>
<dt><label for="max">Max items:</label></dt>
<dd><select name="max" id="max">
<?php for ($i = 1; $i <= $options->max_entries; $i++) {
printf("<option value=\"%s\"%s>%s</option>\n", $i, ($i==$options->default_entries) ? ' selected="selected"' : '', $i);
}
?>
</select>
</dd>
</dl>
<dl>
<dt><label for="links">Links:</label></dt>
<dd><select name="links">
<option value="preserve" selected="selected">preserve</option>
<option value="footnotes">add to footnotes</option>
<option value="remove">remove</option>
</select></label></dd>
</dl>
<?php if ($options->exclude_items_on_fail == 'user') { ?>
<dl>
<dt><label for="exc">If extraction fails:</label></dt>
<dd><select name="exc">
<option value="" selected="selected">keep item in feed</option>
<option value="1">remove item from feed</option>
</select></label></dd>
</dl>
<?php } ?>
</fieldset>
<fieldset class="action" style="background: transparent; border: none; margin-bottom: 20px; padding: 0;">
<input type="submit" id="sudbmit" name="submit" value="Create Feed" />
</fieldset>
</form>
<hr />
<h2>For the site owner</h2>
<p>Thanks for downloading and setting this up. If you haven't done so already, <a href="ftr_compatibility_test.php">check server compatibility</a>
to see if your environment will support this application. Full-Text RSS runs on most shared web hosting environments.</p>
<h3>Configure</h3>
<p>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:</p>
<ul>
<li>Restrict access to a pre-defined set of URLs or block certain URLs</li>
<li>Restrict the maximum number of feed items to be processed</li>
<li>Prepend or append an HTML fragment to each feed item processed</li>
<li>Caching</li>
</ul>
<p><?php if (!file_exists('custom_config.php')) { ?>To change the configuration, save a copy of <tt>config.php</tt> as <tt>custom_config.php</tt> and make any changes you like to it.<?php } else { ?>To change the configuration, edit <tt>custom_config.php</tt> and make any changes you like.<?php } ?></p>
<p>If everything works fine, feel free to modify this page by saving it as <tt>custom_index.php</tt> and change it to whatever you like.</p>
<h3>Sharing is caring</h3>
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 <a href="http://www.gnu.org/licenses/agpl-3.0.html" title="AGPLv3">license</a>.</p>
<p>Thanks! :)</p>
<h3 id="donate">Updates</h3>
<p>To see if you're running the latest version, <a href="http://fivefilters.org/content-only/latest_version.php?version=<?php echo urlencode(_FF_FTR_VERSION); ?>">check for updates</a>.</p>
<h3 id="donate">Support</h3>
<p>We have more information in the section below, but if you need help with anything, please email <a href="mailto:fivefilters@fivefilters.org">fivefilters@fivefilters.org</a>.</p>
<hr />
<h2>For everyone</h2>
<h3>About</h3>
<p>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 <a href="http://fivefilters.org">Five Filters</a> project to promote independent, non-corporate media.</p>
<h3>Bookmarklet</h3>
<p>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.</p>
<p>Drag this:
<script type="text/javascript">
document.write('<a style="cursor: move;" onclick="alert(\'drag to bookmarks toolbar\'); return false;" href="javascript:location.href=\''+baseUrl+'/makefulltextfeed.php?url=\'+escape(document.location.href);">Full-Text RSS</a>');
</script>
<h3 id="api">API</h3>
<p>To extract content from a web page or to transform an existing partial feed to full text, pass the URL (<a href="http://meyerweb.com/eric/tools/dencoder/">encoded</a>) in the querystring to the following URL:</p>
<ul>
<li style="font-family: monospace;"><script type="text/javascript">document.write(baseUrl);</script>/makefulltextfeed.php?url=<strong>[url]</strong></li>
</ul>
<p>If you have an API key, add that to the querystring:</p>
<ul>
<li style="font-family: monospace; white-space:nowrap;"><script type="text/javascript">document.write(baseUrl);</script>/makefulltextfeed.php?key=<strong>[key]</strong>&amp;url=<strong>[url]</strong></li>
<li style="font-family: monospace; white-space:nowrap;"><script type="text/javascript">document.write(baseUrl);</script>/makefulltextfeed.php?key=<strong>[key]</strong>&amp;max=<strong>[number of feed items]</strong>&amp;url=<strong>[url]</strong></li>
</ul>
<p>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.</p>
<p>Note: If you're not hosting this yourself, you do not have to rely on an external API if you don't want to &mdash; this is a free software (open source)
project licensed under the AGPL. You're free to <a href="http://fivefilters.org/content-only/#download">download your own copy</a>.</p>
<h3>Source Code and Technologies</h3>
<p><p>The application uses <a href="http://en.wikipedia.org/wiki/PHP">PHP</a>, <a href="http://www.keyvan.net/2010/08/php-readability/">PHP Readability</a>, <a href="http://simplepie.org/">SimplePie</a>, <a href="http://www.ajaxray.com/blog/2008/03/08/php-universal-feed-generator-supports-rss-10-rss-20-and-atom/">FeedWriter</a>, Humble HTTP Agent. Depending on configuration, these optional components may also be used: <a href="http://framework.zend.com/manual/en/zend.cache.introduction.html">Zend Cache</a>, <a href="http://framework.zend.com/manual/en/zend.dom.query.html">Zend DOM Query</a> and <a href="http://hg.gsnedders.com/iri/">IRI</a>. Readability is the magic piece of code that tries to identify and extract the content block from any given web page.</p>
<h3>System Requirements</h3>
<p>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 <a href="http://www.wampserver.com/en/index.php">WampServer</a>.</p>
<h3 id="download">Download</h3>
<p>Download from <a href="http://fivefilters.org/content-only/#download">fivefilters.org</a> - old versions are available in the code repository.</p>
<h3>License</h3>
<p><a href="http://en.wikipedia.org/wiki/Affero_General_Public_License" style="border-bottom: none;"><img src="images/agplv3.png" alt="AGPL logo" /></a><br />This web application is licensed under the <a href="http://en.wikipedia.org/wiki/Affero_General_Public_License">AGPL version 3</a> &mdash; 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. (<a href="http://www.clipperz.com/users/marco/blog/2008/05/30/freedom_and_privacy_cloud_call_action">More on why this is important.</a>)</p>
<p>The libraries used by the application are licensed as follows...</p>
<ul>
<li>Readability: <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License v2</a></li>
<li>SimplePie: <a href="http://en.wikipedia.org/wiki/BSD_license">BSD</a></li>
<li>FeedWriter: <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GPL v2</a></li>
<li>Humble HTTP Agent: <a href="http://en.wikipedia.org/wiki/Affero_General_Public_License">AGPL v3</a></li>
<li>Zend: <a href="http://framework.zend.com/license/new-bsd">New BSD</a></li>
<li>IRI: <a href="http://en.wikipedia.org/wiki/BSD_license">BSD</a></li>
</ul>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

167
js/jquery-1.4.4.min.js vendored Normal file
View File

@ -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;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"||
h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)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(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--;
if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))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<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z],
z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j,
s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v=
s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)||
[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u,
false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";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="<input type='radio' name='radiotest' checked='checked'/>";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="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";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<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this,
a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=
c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,
a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",
colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===
1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "),
l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,
"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-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<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r=
a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=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<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b=
w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=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<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this,
Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=
c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U};
var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!==
"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V,
xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-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;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d,
a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d=
1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d===
"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}});
c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?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;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i,
[y]).length>0){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;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*"));
return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!==
B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()===
i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=
i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g,
"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=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 i<n[3]-0},gt:function(g,i,n){return i>n[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<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n===
"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/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<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1;
for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"),
i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";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="<a href='#'></a>";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="<p class='TEST'></p>";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="<div class='test e'></div><div class='test'></div>";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;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML;
c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})},
not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},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<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-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<f;e++)for(h=this[e];h;)if(l?l.index(h)>-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=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1,
"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_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<div>","</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></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=
c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a,
b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")):
this[f]:this[f],f>0||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;f<h;f++){var l=(f>0?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></$2>");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]==="<table>"&&!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\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/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("<div>").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<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay",
d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b,
d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)===
"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L||
1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=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<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===
b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&&
h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle;
for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+=
parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",
height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells=
f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a,
"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-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);

View File

@ -0,0 +1,169 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Dom
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* Transform CSS selectors to XPath
*
* @package Zend_Dom
* @subpackage Query
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id: Css2Xpath.php 23484 2010-12-10 03:57:59Z mjh_ca $
*/
class Zend_Dom_Query_Css2Xpath
{
/**
* Transform CSS expression to XPath
*
* @param string $path
* @return string
*/
public static function transform($path)
{
$path = (string) $path;
if (strstr($path, ',')) {
$paths = explode(',', $path);
$expressions = array();
foreach ($paths as $path) {
$xpath = self::transform(trim($path));
if (is_string($xpath)) {
$expressions[] = $xpath;
} elseif (is_array($xpath)) {
$expressions = array_merge($expressions, $xpath);
}
}
return implode('|', $expressions);
}
$paths = array('//');
$path = preg_replace('|\s+>\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('|(?<![a-z0-9_-])(\[@id=)|i', '*$1', $expression);
// arbitrary attribute strict equality
$expression = preg_replace_callback(
'|\[([a-z0-9_-]+)=[\'"]([^\'"]+)[\'"]\]|i',
array(__CLASS__, '_createEqualityExpression'),
$expression
);
// arbitrary attribute contains full word
$expression = preg_replace_callback(
'|\[([a-z0-9_-]+)~=[\'"]([^\'"]+)[\'"]\]|i',
array(__CLASS__, '_normalizeSpaceAttribute'),
$expression
);
// arbitrary attribute contains specified content
$expression = preg_replace_callback(
'|\[([a-z0-9_-]+)\*=[\'"]([^\'"]+)[\'"]\]|i',
array(__CLASS__, '_createContainsExpression'),
$expression
);
// Classes
$expression = preg_replace(
'|\.([a-z][a-z0-9_-]*)|i',
"[contains(concat(' ', normalize-space(@class), ' '), ' \$1 ')]",
$expression
);
/** ZF-9764 -- remove double asterix */
$expression = str_replace('**', '*', $expression);
return $expression;
}
/**
* Callback for creating equality expressions
*
* @param array $matches
* @return string
*/
protected static function _createEqualityExpression($matches)
{
return '[@' . strtolower($matches[1]) . "='" . $matches[2] . "']";
}
/**
* Callback for creating expressions to match one or more attribute values
*
* @param array $matches
* @return string
*/
protected static function _normalizeSpaceAttribute($matches)
{
return "[contains(concat(' ', normalize-space(@" . strtolower($matches[1]) . "), ' '), ' "
. $matches[2] . " ')]";
}
/**
* Callback for creating a strict "contains" expression
*
* @param array $matches
* @return string
*/
protected static function _createContainsExpression($matches)
{
return "[contains(@" . strtolower($matches[1]) . ", '"
. $matches[2] . "')]";
}
}

View File

@ -10,7 +10,9 @@
/** /**
* Univarsel Feed Writer class * Univarsel Feed Writer class
* *
* Genarate RSS 1.0, RSS2.0 and ATOM Feed * Genarate RSS 1.0, RSS2.0 and ATOM Feed.
* Modified for FiveFilters.org's Full-Text RSS project
* to allow for inclusion of hubs
* *
* @package UnivarselFeedWriter * @package UnivarselFeedWriter
* @author Anis uddin Ahmad <anisniit@gmail.com> * @author Anis uddin Ahmad <anisniit@gmail.com>
@ -18,10 +20,13 @@
*/ */
class FeedWriter 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 $channels = array(); // Collection of channel elements
private $items = array(); // Collection of items as object of FeedItem class. private $items = array(); // Collection of items as object of FeedItem class.
private $data = array(); // Store some other version wise data private $data = array(); // Store some other version wise data
private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA 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; private $version = null;
@ -113,7 +118,6 @@
$this->items[] = $feedItem; $this->items[] = $feedItem;
} }
// Wrapper functions ------------------------------------------------------------------- // Wrapper functions -------------------------------------------------------------------
/** /**
@ -128,6 +132,42 @@
$this->setChannelElement('title', $title); $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 * Set the 'description' channel element
* *
@ -213,6 +253,7 @@
if($this->version == RSS2) if($this->version == RSS2)
{ {
if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL;
$out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">' . PHP_EOL; $out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">' . PHP_EOL;
} }
elseif($this->version == RSS1) elseif($this->version == RSS1)
@ -316,6 +357,16 @@
{ {
case RSS2: case RSS2:
echo '<channel>' . PHP_EOL; echo '<channel>' . 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 '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . 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 '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;
}
break; break;
case RSS1: case RSS1:
echo (isset($this->data['ChannelAbout']))? "<channel rdf:about=\"{$this->data['ChannelAbout']}\">" : "<channel rdf:about=\"{$this->channels['link']}\">"; echo (isset($this->data['ChannelAbout']))? "<channel rdf:about=\"{$this->data['ChannelAbout']}\">" : "<channel rdf:about=\"{$this->channels['link']}\">";

View File

@ -42,7 +42,9 @@ class HumbleHttpAgent
$this->httpContext = stream_context_create(array( $this->httpContext = stream_context_create(array(
'http' => array( 'http' => array(
'timeout' => $this->requestOptions['timeout'], '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) { public function validateUrl($url) {
$url = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED); //TODO: run sanitize filter first!
if ($url !== false && $url !== null && preg_match('!^https?://!', $url)) { $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); return filter_var($url, FILTER_SANITIZE_URL);
} else { } else {
return false; return false;

View File

@ -1,9 +1,8 @@
<?php <?php
/** /**
* IRI parser/serialiser/normaliser * IRI parser/serialiser/normaliser
* *
* Copyright (c) 2007-2009, Geoffrey Sneddon and Steve Minutillo. * Copyright (c) 2007-2010, Geoffrey Sneddon and Steve Minutillo.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -48,49 +47,49 @@ class IRI
* *
* @var string * @var string
*/ */
private $scheme; private $scheme = null;
/** /**
* User Information * User Information
* *
* @var string * @var string
*/ */
private $iuserinfo; private $iuserinfo = null;
/** /**
* ihost * ihost
* *
* @var string * @var string
*/ */
private $ihost; private $ihost = null;
/** /**
* Port * Port
* *
* @var string * @var string
*/ */
private $port; private $port = null;
/** /**
* ipath * ipath
* *
* @var string * @var string
*/ */
private $ipath; private $ipath = '';
/** /**
* iquery * iquery
* *
* @var string * @var string
*/ */
private $iquery; private $iquery = null;
/** /**
* ifragment * ifragment
* *
* @var string * @var string
*/ */
private $ifragment; private $ifragment = null;
/** /**
* Normalization database * Normalization database
@ -125,7 +124,7 @@ class IRI
*/ */
public function __toString() public function __toString()
{ {
return $this->iri; return $this->get_iri();
} }
/** /**
@ -162,13 +161,14 @@ class IRI
*/ */
public function __get($name) public function __get($name)
{ {
if (!$this->is_valid()) if (
$name === 'iri' ||
$name === 'uri' ||
$name === 'iauthority' ||
$name === 'authority'
)
{ {
return false; $return = $this->{"get_$name"}();
}
elseif (method_exists($this, 'get_' . $name))
{
$return = call_user_func(array($this, 'get_' . $name));
} }
elseif (isset($this->$name)) elseif (isset($this->$name))
{ {
@ -239,25 +239,35 @@ class IRI
* *
* Returns false if $base is not absolute, otherwise an 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 * @param IRI|string $relative Relative IRI
* @return IRI|false * @return IRI|false
*/ */
public static function absolutize(IRI $base, $relative) public static function absolutize($base, $relative)
{ {
if (!($relative instanceof IRI)) if (!($relative instanceof IRI))
{ {
$relative = new IRI($relative); $relative = new IRI($relative);
} }
if ($base->scheme !== null) if (!$relative->is_valid())
{ {
if ($relative->iri !== '' && $relative->iri !== null) return false;
{
if ($relative->scheme !== null)
{
$target = clone $relative;
} }
elseif ($relative->iauthority !== null) elseif ($relative->scheme !== null)
{
return clone $relative;
}
else
{
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 = clone $relative;
$target->scheme = $base->scheme; $target->scheme = $base->scheme;
@ -275,7 +285,7 @@ class IRI
{ {
$target->ipath = $relative->ipath; $target->ipath = $relative->ipath;
} }
elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === null) elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')
{ {
$target->ipath = '/' . $relative->ipath; $target->ipath = '/' . $relative->ipath;
} }
@ -318,6 +328,7 @@ class IRI
return false; return false;
} }
} }
}
/** /**
* Create a new IRI object by creating a relative IRI from two IRIs * Create a new IRI object by creating a relative IRI from two IRIs
@ -339,24 +350,9 @@ class IRI
private function parse_iri($iri) private function parse_iri($iri)
{ {
$iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
static $cache = array(); if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
if (isset($cache[$iri]))
{ {
return $cache[$iri]; if ($match[1] === '')
}
elseif ($iri === '')
{
return $cache[$iri] = array(
'scheme' => null,
'authority' => null,
'path' => '',
'query' => null,
'fragment' => null
);
}
elseif (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
{
if (!isset($match[1]) || $match[1] === '')
{ {
$match['scheme'] = null; $match['scheme'] = null;
} }
@ -364,7 +360,7 @@ class IRI
{ {
$match['authority'] = null; $match['authority'] = null;
} }
if (!isset($match[5]) || $match[5] === '') if (!isset($match[5]))
{ {
$match['path'] = ''; $match['path'] = '';
} }
@ -376,7 +372,12 @@ class IRI
{ {
$match['fragment'] = null; $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, // 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); $input = substr($input, 2);
} }
elseif ($input === '/.') 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, // 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); $input = substr($input, 3);
$output = substr_replace($output, '', strrpos($output, '/')); $output = substr_replace($output, '', strrpos($output, '/'));
} }
elseif ($input === '/..') elseif ($input === '/..')
@ -451,12 +452,12 @@ class IRI
*/ */
private function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) 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 // Normalize as many pct-encoded sections as possible
$string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string); $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 // Add unreserved and % to $extra_chars (the latter is safe because all
// pct-encoded sections are now valid). // pct-encoded sections are now valid).
$extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
@ -733,7 +734,7 @@ class IRI
} }
if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) 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']) if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])
{ {
@ -753,10 +754,19 @@ class IRI
*/ */
public function is_valid() public function is_valid()
{ {
if ($this->ipath !== null && ( $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;
substr($this->ipath, 0, 2) === '//' && $this->get_iauthority() === null if ($this->ipath !== '' &&
|| 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->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, '/'))
)
) )
) )
{ {
@ -775,15 +785,21 @@ class IRI
*/ */
private function set_iri($iri) private function set_iri($iri)
{ {
if ($iri !== null) if ($iri === null)
{
return true;
}
else
{ {
$parsed = $this->parse_iri((string) $iri); $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_authority($parsed['authority'])
&& $this->set_path($parsed['path']) && $this->set_path($parsed['path'])
&& $this->set_query($parsed['query']) && $this->set_query($parsed['query'])
&& $this->set_fragment($parsed['fragment']); && $this->set_fragment($parsed['fragment']);
return $return;
} }
} }
@ -800,14 +816,7 @@ class IRI
{ {
$this->scheme = null; $this->scheme = null;
} }
elseif ( elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))
!($scheme = (string) $scheme)
|| !isset($scheme[0])
|| $scheme[0] < 'A'
|| $scheme[0] > 'Z' && $scheme[0] < 'a'
|| $scheme[0] > 'z'
|| strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.') !== strlen($scheme)
)
{ {
$this->scheme = null; $this->scheme = null;
return false; return false;
@ -828,29 +837,44 @@ class IRI
*/ */
private function set_authority($authority) private function set_authority($authority)
{ {
if (($iuserinfo_end = strrpos($authority, '@')) !== false) if ($authority === null)
{ {
$iuserinfo = substr($authority, 0, $iuserinfo_end); $this->iuserinfo = null;
$authority = substr($authority, $iuserinfo_end + 1); $this->ihost = null;
$this->port = null;
return true;
}
else
{
$remaining = $authority;
if (($iuserinfo_end = strrpos($remaining, '@')) !== false)
{
$iuserinfo = substr($remaining, 0, $iuserinfo_end);
$remaining = substr($remaining, $iuserinfo_end + 1);
} }
else else
{ {
$iuserinfo = null; $iuserinfo = null;
} }
if (($port_start = strpos($authority, ':', strpos($authority, ']'))) !== false) if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)
{ {
if (($port = substr($authority, $port_start + 1)) === false) if (($port = substr($remaining, $port_start + 1)) === false)
{ {
$port = null; $port = null;
} }
$authority = substr($authority, 0, $port_start); $remaining = substr($remaining, 0, $port_start);
} }
else else
{ {
$port = null; $port = null;
} }
return $this->set_userinfo($iuserinfo) && $this->set_host($authority) && $this->set_port($port); $return = $this->set_userinfo($iuserinfo) &&
$this->set_host($remaining) &&
$this->set_port($port);
return $return;
}
} }
/** /**
@ -965,29 +989,16 @@ class IRI
*/ */
private function set_path($ipath) private function set_path($ipath)
{ {
if ($ipath === null) $ipath = (string) $ipath;
{
$this->ipath = null; $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
return true; $removed = $this->remove_dot_segments($valid);
}
else $this->ipath = ($this->scheme !== null) ? $removed : $valid;
{
$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(); $this->scheme_normalization();
return true; return true;
} }
}
/** /**
* Set the iquery. * Set the iquery.
@ -1036,7 +1047,11 @@ class IRI
*/ */
private function to_uri($string) 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; $position = 0;
$strlen = strlen($string); $strlen = strlen($string);
@ -1057,21 +1072,21 @@ class IRI
*/ */
private function get_iri() private function get_iri()
{ {
if (!$this->is_valid())
{
return false;
}
$iri = ''; $iri = '';
$defined = false;
if ($this->scheme !== null) if ($this->scheme !== null)
{ {
$iri .= $this->scheme . ':'; $iri .= $this->scheme . ':';
} }
if (($iauthority = $this->iauthority) !== null) if (($iauthority = $this->get_iauthority()) !== null)
{ {
$iri .= '//' . $iauthority; $iri .= '//' . $iauthority;
} }
if ($this->ipath !== null)
{
$iri .= $this->ipath; $iri .= $this->ipath;
$defined = true;
}
if ($this->iquery !== null) if ($this->iquery !== null)
{ {
$iri .= '?' . $this->iquery; $iri .= '?' . $this->iquery;
@ -1081,15 +1096,8 @@ class IRI
$iri .= '#' . $this->ifragment; $iri .= '#' . $this->ifragment;
} }
if ($iri !== '' || $defined)
{
return $iri; return $iri;
} }
else
{
return null;
}
}
/** /**
* Get the complete URI * Get the complete URI
@ -1098,11 +1106,7 @@ class IRI
*/ */
private function get_uri() private function get_uri()
{ {
$iri = $this->iri; return $this->to_uri($this->get_iri());
if (is_string($iri))
return $this->to_uri($iri);
else
return $iri;
} }
/** /**
@ -1111,6 +1115,8 @@ class IRI
* @return string * @return string
*/ */
private function get_iauthority() private function get_iauthority()
{
if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)
{ {
$iauthority = ''; $iauthority = '';
if ($this->iuserinfo !== null) if ($this->iuserinfo !== null)
@ -1125,9 +1131,6 @@ class IRI
{ {
$iauthority .= ':' . $this->port; $iauthority .= ':' . $this->port;
} }
if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)
{
return $iauthority; return $iauthority;
} }
else else
@ -1143,255 +1146,10 @@ class IRI
*/ */
private function get_authority() private function get_authority()
{ {
$iauthority = $this->iauthority; $iauthority = $this->get_iauthority();
if (is_string($iauthority)) if (is_string($iauthority))
return $this->to_uri($iauthority); return $this->to_uri($iauthority);
else else
return $iauthority; 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 <alexander.merz@web.de>
* @author elfrink at introweb dot nl
* @author Josh Peck <jmp at joshpeck dot org>
* @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;
}
}
}
?>

View File

@ -918,10 +918,6 @@ class Readability
* @return void * @return void
*/ */
public function killBreaks($node) { 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 = $node->innerHTML;
$html = preg_replace($this->regexps['killBreaks'], '<br />', $html); $html = preg_replace($this->regexps['killBreaks'], '<br />', $html);
$node->innerHTML = $html; $node->innerHTML = $html;

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,10 @@
<?php <?php
// Create Full-Text Feeds // Create Full-Text Feeds
// Author: Keyvan Minoukadeh // Author: Keyvan Minoukadeh
// Copyright (c) 2010 Keyvan Minoukadeh // Copyright (c) 2011 Keyvan Minoukadeh
// License: AGPLv3 // License: AGPLv3
// Version: 2.2 // Version: 2.5
// Date: 2010-10-30 // Date: 2011-01-08
/* /*
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -54,7 +54,9 @@ function __autoload($class_name) {
// Include IRI class for resolving relative URLs // Include IRI class for resolving relative URLs
'IRI' => 'iri/iri.php', 'IRI' => 'iri/iri.php',
// Include Zend Cache to improve performance (cache results) // 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])) { if (isset($mapping[$class_name])) {
//echo "Loading $class_name\n<br />"; //echo "Loading $class_name\n<br />";
@ -68,29 +70,9 @@ function __autoload($class_name) {
//////////////////////////////// ////////////////////////////////
// Load config file if it exists // 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) 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; $encoding = null;
if ($html || $header) { if ($html || $header) {
if (is_array($header)) $header = implode("\n", $header); if (is_array($header)) $header = implode("\n", $header);
@ -111,10 +89,6 @@ function convert_to_utf8($html, $header=null)
// error parsing the response // error parsing the response
} else { } else {
$match = end($match); // get last matched element (in case of redirects) $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 (isset($match[2])) $encoding = trim($match[2], '"\'');
} }
if (!$encoding) { if (!$encoding) {
@ -127,10 +101,6 @@ function convert_to_utf8($html, $header=null)
if (!$encoding) { if (!$encoding) {
$encoding = 'utf-8'; $encoding = 'utf-8';
} else { } else {
if (!in_array($encoding, array_map('strtolower', $accept['charset']))) {
// encoding not accepted
// TODO: avoid conversion
}
if (strtolower($encoding) != 'utf-8') { if (strtolower($encoding) != 'utf-8') {
if (strtolower($encoding) == 'iso-8859-1') { if (strtolower($encoding) == 'iso-8859-1') {
// replace MS Word smart qutoes // replace MS Word smart qutoes
@ -184,6 +154,12 @@ function makeAbsolute($base, $elem) {
for ($i = $elems->length-1; $i >= 0; $i--) { for ($i = $elems->length-1; $i >= 0; $i--) {
$e = $elems->item($i); $e = $elems->item($i);
//$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e); //$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e);
makeAbsoluteAttr($base, $e, $attr);
}
if (strtolower($elem->tagName) == $tag) makeAbsoluteAttr($base, $elem, $attr);
}
}
function makeAbsoluteAttr($base, $e, $attr) {
if ($e->hasAttribute($attr)) { if ($e->hasAttribute($attr)) {
// Trim leading and trailing white space. I don't really like this but // Trim leading and trailing white space. I don't really like this but
// unfortunately it does appear on some sites. e.g. <img src=" /path/to/image.jpg" /> // unfortunately it does appear on some sites. e.g. <img src=" /path/to/image.jpg" />
@ -197,8 +173,6 @@ function makeAbsolute($base, $elem) {
} }
} }
} }
}
}
//////////////////////////////// ////////////////////////////////
// Check if service is enabled // Check if service is enabled
@ -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['key'])) $redirect .= '&key='.urlencode($_GET['key']);
if (isset($_GET['max'])) $redirect .= '&max='.(int)$_GET['max']; if (isset($_GET['max'])) $redirect .= '&max='.(int)$_GET['max'];
if (isset($_GET['links'])) $redirect .= '&links='.$_GET['links']; 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"); header("Location: $redirect");
exit; exit;
} }
@ -240,22 +234,37 @@ if ($options->alternative_url != '' && !isset($_GET['redir']) && mt_rand(0, 100)
/////////////////////////////////////////////// ///////////////////////////////////////////////
// Check if the request is explicitly for an HTML page // 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 // 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 // Check URL against list of blacklisted URLs
// TODO: set up better system for this // TODO: set up better system for this
/////////////////////////////////////////////// ///////////////////////////////////////////////
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) { foreach ($options->blocked_urls as $blockurl) {
if (strstr($url, $blockurl) !== false) { if (strstr($url, $blockurl) !== false) {
die('URL blocked'); die('URL blocked');
} }
} }
}
/////////////////////////////////////////////// ///////////////////////////////////////////////
// Max entries // Max entries
@ -285,6 +294,50 @@ if (($valid_key || !$options->restrict) && isset($_GET['links']) && in_array($_G
$links = 'preserve'; $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 // Check for valid format
// (stick to RSS for the time being) // (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 'lifetime' => ($valid_key || !$options->restrict) ? 10*60 : 20*60, // cache lifetime of 10 or 20 minutes
'automatic_serialization' => false, 'automatic_serialization' => false,
'write_control' => false, 'write_control' => false,
'automatic_cleaning_factor' => 100, 'automatic_cleaning_factor' => $options->cache_cleanup,
'ignore_user_abort' => false 'ignore_user_abort' => false
); );
$backendOptions = array( $backendOptions = array(
@ -315,7 +368,7 @@ if ($options->caching) {
// getting a Zend_Cache_Core object // getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); $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)) { if ($data = $cache->load($cache_id)) {
header("Content-type: text/xml; charset=UTF-8"); header("Content-type: text/xml; charset=UTF-8");
@ -339,12 +392,13 @@ if ($valid_key) {
////////////////////////////////// //////////////////////////////////
$http = new HumbleHttpAgent(); $http = new HumbleHttpAgent();
/*
if ($options->caching) { if ($options->caching) {
$frontendOptions = array( $frontendOptions = array(
'lifetime' => 30*60, // cache lifetime of 30 minutes 'lifetime' => 30*60, // cache lifetime of 30 minutes
'automatic_serialization' => true, 'automatic_serialization' => true,
'write_control' => false, 'write_control' => false,
'automatic_cleaning_factor' => 100, 'automatic_cleaning_factor' => $options->cache_cleanup,
'ignore_user_abort' => false 'ignore_user_abort' => false
); );
$backendOptions = array( $backendOptions = array(
@ -360,6 +414,7 @@ if ($options->caching) {
$httpCache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); $httpCache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
$http->useCache($httpCache); $http->useCache($httpCache);
} }
*/
//////////////////////////////// ////////////////////////////////
// Tidy config // Tidy config
@ -416,6 +471,7 @@ if ($html_only || !$result) {
} else { } else {
die('Error retrieving '.$url); die('Error retrieving '.$url);
} }
if ($auto_extract) {
// Run through Tidy (if it exists). // Run through Tidy (if it exists).
// This fixes problems with some sites which would otherwise // This fixes problems with some sites which would otherwise
// trouble DOMDocument's HTML parsing. // trouble DOMDocument's HTML parsing.
@ -427,11 +483,38 @@ if ($html_only || !$result) {
} }
$readability = new Readability($html, $effective_url); $readability = new Readability($html, $effective_url);
if ($links == 'footnotes') $readability->convertLinksToFootnotes = true; if ($links == 'footnotes') $readability->convertLinksToFootnotes = true;
$readability->init(); if (!$readability->init() && $exclude_on_fail) die('Sorry, could not extract content');
$readability->clean($readability->getContent(), 'select'); // content block is detected element
if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $readability->getContent()); $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->clean($content_block, 'select');
if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $content_block);
$title = $readability->getTitle()->textContent; $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') { if ($links == 'remove') {
$content = preg_replace('!</?a[^>]*>!', '', $content); $content = preg_replace('!</?a[^>]*>!', '', $content);
} }
@ -446,6 +529,7 @@ if ($html_only || !$result) {
$output = new FeedWriter(); //ATOM an option $output = new FeedWriter(); //ATOM an option
$output->setTitle($title); $output->setTitle($title);
$output->setDescription("Content extracted from $url"); $output->setDescription("Content extracted from $url");
$output->setXsl('css/feed.xsl'); // Chrome uses this, most browsers ignore it
if ($format == 'atom') { if ($format == 'atom') {
$output->setChannelElement('updated', date(DATE_ATOM)); $output->setChannelElement('updated', date(DATE_ATOM));
$output->setChannelElement('author', array('name'=>'Five Filters', 'uri'=>'http://fivefilters.org')); $output->setChannelElement('author', array('name'=>'Five Filters', 'uri'=>'http://fivefilters.org'));
@ -471,7 +555,13 @@ if ($html_only || !$result) {
$output = new FeedWriter(); $output = new FeedWriter();
$output->setTitle($feed->get_title()); $output->setTitle($feed->get_title());
$output->setDescription($feed->get_description()); $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()) { if ($img_url = $feed->get_image_url()) {
$output->setImage($feed->get_title(), $feed->get_link(), $img_url); $output->setImage($feed->get_title(), $feed->get_link(), $img_url);
} }
@ -499,18 +589,28 @@ $http->fetchAll($urls_sanitized);
$http->cacheAll(); $http->cacheAll();
foreach ($items as $key => $item) { foreach ($items as $key => $item) {
$extract_result = false;
$permalink = $urls[$key]; $permalink = $urls[$key];
$newitem = $output->createNewItem(); $newitem = $output->createNewItem();
$newitem->setTitle(htmlspecialchars_decode($item->get_title())); $newitem->setTitle(htmlspecialchars_decode($item->get_title()));
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 {
if ($permalink !== false) { if ($permalink !== false) {
$newitem->setLink($permalink); $newitem->setLink($permalink);
} else { } else {
$newitem->setLink($item->get_permalink()); $newitem->setLink($item->get_permalink());
} }
}
if ($permalink && $response = $http->get($permalink)) { if ($permalink && $response = $http->get($permalink)) {
$effective_url = $response['effective_url']; $effective_url = $response['effective_url'];
$html = $response['body']; $html = $response['body'];
$html = convert_to_utf8($html, $response['headers']); $html = convert_to_utf8($html, $response['headers']);
if ($auto_extract) {
// Run through Tidy (if it exists). // Run through Tidy (if it exists).
// This fixes problems with some sites which would otherwise // This fixes problems with some sites which would otherwise
// trouble DOMDocument's HTML parsing. (Although sometimes it fails // trouble DOMDocument's HTML parsing. (Although sometimes it fails
@ -522,10 +622,49 @@ foreach ($items as $key => $item) {
} }
$readability = new Readability($html, $effective_url); $readability = new Readability($html, $effective_url);
if ($links == 'footnotes') $readability->convertLinksToFootnotes = true; if ($links == 'footnotes') $readability->convertLinksToFootnotes = true;
$readability->init(); $extract_result = $readability->init();
$readability->clean($readability->getContent(), 'select'); // content block is detected element
if ($options->rewrite_relative_urls) makeAbsolute($effective_url, $readability->getContent()); $content_block = $readability->getContent();
$html = $readability->getContent()->innerHTML; } 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('!<p>[\s\h\v]*</p>!u', '', $html);
if ($links == 'remove') { if ($links == 'remove') {
$html = preg_replace('!</?a[^>]*>!', '', $html); $html = preg_replace('!</?a[^>]*>!', '', $html);
} }
@ -536,13 +675,6 @@ foreach ($items as $key => $item) {
$html = $options->message_to_prepend_with_key.$html; $html = $options->message_to_prepend_with_key.$html;
$html .= $options->message_to_append_with_key; $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') { if ($format == 'atom') {
$newitem->addElement('content', $html); $newitem->addElement('content', $html);
@ -550,8 +682,12 @@ foreach ($items as $key => $item) {
if ($author = $item->get_author()) { if ($author = $item->get_author()) {
$newitem->addElement('author', array('name'=>$author->get_name())); $newitem->addElement('author', array('name'=>$author->get_name()));
} }
} else {
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 { } else {
$newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true')); $newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true'));
}
$newitem->setDescription($html); $newitem->setDescription($html);
if ((int)$item->get_date('U') > 0) { if ((int)$item->get_date('U') > 0) {
$newitem->setDate((int)$item->get_date('U')); $newitem->setDate((int)$item->get_date('U'));