Source code for file /simplepie/simplepie.inc
Documentation is available at simplepie.inc
/**************************************************
A PHP-Based RSS and Atom Feed Framework
Takes the hard work out of managing a complete RSS/Atom solution.
Version: "Lemon Meringue"
Updated: 24 November 2006
Copyright: 2004-2006 Ryan Parman, Geoffrey Sneddon
****************************************************
GNU Lesser General Public License 2.1 (LGPL)
http://creativecommons.org/licenses/LGPL/2.1/
****************************************************
Please submit all bug reports and feature requests to the SimplePie forums.
http://simplepie.org/support/
****************************************************/
var $url =
'http://simplepie.org/';
// Other objects, instances created here so we can set options on them
function SimplePie($feed_url =
null, $cache_location =
null, $cache_max_minutes =
null)
// Couple of variables built up from other variables
// Other objects, instances created here so we can set options on them
// Set options if they're passed to the constructor
// If we've passed an xmldump variable in the URL, snap into XMLdump mode
if (isset
($_GET['xmldump']))
// Only init the script if we're passed a feed URL
if (is_a($file, 'SimplePie_File'))
$this->raw_data =
trim((string)
$data);
$this->sanitize->bypass_image_hotlink($get);
$this->sanitize->bypass_image_hotlink_page($page);
$this->sanitize->replace_headers($enable);
function strip_htmltags($tags =
array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'), $encode =
null)
$this->sanitize->encode_instead_of_strip($tags);
$this->sanitize->encode_instead_of_strip($enable);
function strip_attributes($attribs =
array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
$this->sanitize->strip_attributes($attribs);
$this->sanitize->output_encoding($encoding);
return $this->sanitize->set_item_class($class);
return $this->sanitize->set_author_class($class);
return $this->sanitize->set_enclosure_class($class);
if ($this->sanitize->bypass_image_hotlink &&
!empty($_GET[$this->sanitize->bypass_image_hotlink]))
function embed_odeo(
link)
{
document.
writeln('<
embed src="
http://
odeo.
com/
flash/
audio_player_fullsize.
swf"
pluginspage="
http://
www.
macromedia.
com/
go/
getflashplayer"
type="
application/
x-
shockwave-
flash"
quality="
high"
width="440"
height="80"
wmode="
transparent"
allowScriptAccess="
any"
flashvars="
valid_sample_rate=
true&
external_url='+
link+'"></
embed>');
function embed_quicktime(
type,
bgcolor,
width,
height,
link,
placeholder,
loop)
{
document.
writeln('<
embed type="'+
type+'"
style="
cursor:
hand;
cursor:
pointer;"
href="'+
link+'"
src="'+
placeholder+'"
width="'+
width+'"
height="'+
height+'"
autoplay="
false"
target="
myself"
controller="
false"
loop="'+
loop+'"
scale="
aspect"
bgcolor="'+
bgcolor+'"
pluginspage="
http://
www.
apple.
com/
quicktime/
download/"></
embed>');
document.
writeln('<
embed type="'+
type+'"
style="
cursor:
hand;
cursor:
pointer;"
src="'+
link+'"
width="'+
width+'"
height="'+
height+'"
autoplay="
false"
target="
myself"
controller="
true"
loop="'+
loop+'"
scale="
aspect"
bgcolor="'+
bgcolor+'"
pluginspage="
http://
www.
apple.
com/
quicktime/
download/"></
embed>');
function embed_flash(
bgcolor,
width,
height,
link,
loop,
type)
{
document.
writeln('<
embed src="'+
link+'"
pluginspage="
http://
www.
macromedia.
com/
shockwave/
download/
index.
cgi?
P1_Prod_Version=
ShockwaveFlash"
type="'+
type+'"
quality="
high"
width="'+
width+'"
height="'+
height+'"
bgcolor="'+
bgcolor+'"
loop="'+
loop+'"></
embed>');
function embed_wmedia(
width,
height,
link)
{
document.
writeln('<
embed type="
application/
x-
mplayer2"
src="'+
link+'"
autosize="1"
width="'+
width+'"
height="'+
height+'"
showcontrols="1"
showstatusbar="0"
showdisplay="0"
autostart="0"></
embed>');
header('Content-type: text/javascript; charset: UTF-8');
header('Cache-Control: must-revalidate');
if (!empty($this->rss_url) ||
!empty($this->raw_data))
// Decide whether to enable caching
// If it's enabled and we don't want an XML dump, use the cache
$this->data =
$cache->load();
// If we've hit a collision just rerun it with caching disabled
// If we've got a feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL
else if (!empty($this->data['feed_url']))
if ($this->data['feed_url'] ==
$this->data['url'])
// If the cache is new enough
// If we have last-modified and/or etag set
if (!empty($this->data['last-modified']) ||
!empty($this->data['etag']))
if (!empty($this->data['last-modified']))
$headers['if-modified-since'] =
$this->data['last-modified'];
if (!empty($this->data['etag']))
$headers['if-none-match'] =
$this->data['etag'];
$headers =
$file->headers();
if ($headers['status']['code'] ==
304)
// If we don't have last-modified or etag set, just clear the cache
// If the cache is still valid, just return true
// If the cache is empty, delete it
// If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
// If the file connection has an error, set SimplePie::error to that and quit
$this->error =
$file->error;
// Check if the supplied URL is a feed, if it isn't, look for it.
if (!$locate->is_feed($file))
if ($cache &&
!$cache->save(array('url' =>
$this->rss_url, 'feed_url' =>
$feed)))
$this->error =
"$cache->name is not writeable";
$this->error =
"A feed could not be found at $this->rss_url";
$headers =
$file->headers();
$data =
trim($file->body());
// First check to see if input has been overridden.
// Second try HTTP headers
else if (!empty($headers['content-type']) &&
preg_match('/charset\s*=\s*([^;]*)/i', $headers['content-type'], $charset))
// Then prolog, if at the very start of the document
else if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog) &&
preg_match('/encoding\s*=\s*("([^"]*)"|\'([^\']*)\')/Ui', $prolog[1], $encoding))
$encoding =
substr($encoding[1], 1, -
1);
else if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) ===
0)
// UTF-32 Little Endian BOM
else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) ===
0)
// UTF-16 Little Endian BOM
else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) ===
0)
// Fallback to the default
// Change the encoding to UTF-8 (as we always use UTF-8 internally)
// Strip illegal characters (if on less than PHP5, as on PHP5 expat can manage fine)
$data =
iconv('UTF-8', 'UTF-8//IGNORE', $data);
$data =
mb_convert_encoding($data, 'UTF-8', 'UTF-8');
$data =
new $this->parser_class($data, 'UTF-8', $this->xml_dump);
// If we want the XML, just output that and quit
header('Content-type: text/xml; charset=UTF-8');
else if (!$data->error_code)
// Parse the data, and make it sane
$this->data['feedinfo']['encoding'] =
$this->sanitize->output_encoding;
// Store the headers that we need
if (!empty($headers['last-modified']))
$this->data['last-modified'] =
$headers['last-modified'];
if (!empty($headers['etag']))
$this->data['etag'] =
$headers['etag'];
// If we want to order it by date, check if all items have a date, and then sort it
foreach ($this->data['items'] as $item)
if (!$item->get_date('U'))
usort($this->data['items'], create_function('$a, $b', 'if ($a->get_date(\'U\') == $b->get_date(\'U\')) return 1; return ($a->get_date(\'U\') < $b->get_date(\'U\')) ? 1 : -1;'));
// Cache the file if caching is enabled
if ($cache &&
!$cache->save($this->data))
$this->error =
"$cache->name is not writeable";
// If we have an error, just set SimplePie::error to it and quit
$this->error =
"XML error: $data->error_string at line $data->current_line, column $data->current_column";
if (!empty($this->data['feedinfo']['encoding']))
return $this->data['feedinfo']['encoding'];
$header =
"Content-type: $mime;";
$header .=
' charset=UTF-8';
if (!empty($this->data['feedinfo']['type']))
return $this->data['feedinfo']['type'];
if (!empty($this->data['feedinfo']['version']))
return $this->data['feedinfo']['version'];
function get_favicon($check =
false, $alternate =
null)
if (!empty($this->data['info']['link']['alternate'][0]))
$headers =
$file->headers();
if ($headers['status']['code'] ==
200)
return 'http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=' .
rawurlencode($this->subscribe_url());
if (!empty($this->data['info']['title']))
return $this->data['info']['title'];
if (!empty($this->data['info']['link']['alternate'][0]))
return $this->data['info']['link']['alternate'][0];
if (!empty($this->data['info']['link']))
return $this->data['info']['link'];
if (!empty($this->data['info']['description']))
return $this->data['info']['description'];
else if (!empty($this->data['info']['dc:description']))
return $this->data['info']['dc:description'];
else if (!empty($this->data['info']['tagline']))
return $this->data['info']['tagline'];
else if (!empty($this->data['info']['subtitle']))
return $this->data['info']['subtitle'];
if (!empty($this->data['info']['copyright']))
return $this->data['info']['copyright'];
if (!empty($this->data['info']['language']))
return $this->data['info']['language'];
else if (!empty($this->data['info']['xml:lang']))
return $this->data['info']['xml:lang'];
if (!empty($this->data['info']['image']['url']) ||
!empty($this->data['info']['image']['logo']))
if (!empty($this->data['info']['image']['title']))
return $this->data['info']['image']['title'];
if (!empty($this->data['info']['image']['url']))
return $this->data['info']['image']['url'];
else if (!empty($this->data['info']['image']['logo']))
return $this->data['info']['image']['logo'];
if (!empty($this->data['info']['image']['link']))
return $this->data['info']['image']['link'];
if (!empty($this->data['info']['image']['width']))
return $this->data['info']['image']['width'];
if (!empty($this->data['info']['image']['height']))
return $this->data['info']['image']['height'];
if (!empty($this->data['items']))
return ($qty >
$max) ?
$max :
$qty;
if (!empty($this->data['items'][$key]))
return $this->data['items'][$key];
if (!empty($this->data['guid']['data']))
return $this->data['guid']['data'];
else if (!empty($this->data['id']))
return $this->data['id'];
if (!empty($this->data['title']))
return $this->data['title'];
else if (!empty($this->data['dc:title']))
return $this->data['dc:title'];
if (!empty($this->data['content']))
return $this->data['content'];
else if (!empty($this->data['encoded']))
return $this->data['encoded'];
else if (!empty($this->data['summary']))
return $this->data['summary'];
else if (!empty($this->data['description']))
return $this->data['description'];
else if (!empty($this->data['dc:description']))
return $this->data['dc:description'];
else if (!empty($this->data['longdesc']))
return $this->data['longdesc'];
if (!empty($categories[$key]))
return $categories[$key];
if (!empty($this->data['category']))
if (!empty($this->data['subject']))
if (!empty($this->data['term']))
if (!empty($authors[$key]))
if (!empty($this->data['author']))
if (!empty($this->data['creator']))
function get_date($date_format =
'j F Y, g:i a')
if (!empty($this->data['pubdate']))
return date($date_format, $this->data['pubdate']);
else if (!empty($this->data['dc:date']))
return date($date_format, $this->data['dc:date']);
else if (!empty($this->data['issued']))
return date($date_format, $this->data['issued']);
else if (!empty($this->data['published']))
return date($date_format, $this->data['published']);
else if (!empty($this->data['modified']))
return date($date_format, $this->data['modified']);
else if (!empty($this->data['updated']))
return date($date_format, $this->data['updated']);
else if (!empty($enclosure))
return $enclosure->get_link();
function get_link($key =
0, $rel =
'alternate')
if (!empty($links[$key]))
if (!empty($this->data['link'][$rel]))
$links =
$this->data['link'][$rel];
if (!empty($this->data['guid']['data']) &&
$this->data['guid']['permalink'] ==
true)
$links[] =
$this->data['guid']['data'];
else if (!empty($this->data['link'][$rel]))
return $this->data['link'][$rel];
if (!empty($enclosures[$key]))
return $enclosures[$key];
if (!empty($this->data['enclosures']))
$url =
'http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=' .
rawurlencode($this->get_permalink());
// Constructor, used to input the data
if (!empty($this->email))
// Constructor, used to input the data
$this->link =
$idn->encode($this->link);
return round($length/
1048576, 2);
return $this->embed($options, true);
function embed($options =
'', $native =
false)
// Process options and reassign values as necessary
foreach($options as $option)
if (isset
($opt[0], $opt[1]))
// If we encounter an unsupported mime-type, check the file extension and guess intelligently.
if (!in_array($type, array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'x-audio/mp3', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video', 'application/x-shockwave-flash', 'application/futuresplash', 'application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx')))
$type =
'audio/x-ms-wax';
$type =
'audio/x-ms-wma';
$type =
'video/x-ms-asf';
$type =
'video/quicktime';
$type =
'video/sd-video';
$type =
'video/x-ms-wmv';
$type =
'video/x-ms-wvx';
$type =
'application/futuresplash';
$type =
'application/x-shockwave-flash';
// Process values for 'auto'
else if ($mime ==
'video')
// Set proper placeholder value
else if ($mime ==
'video')
// Make sure the JS library is included
// (I know it'll be included multiple times, but I can't think of a better way to do this automatically)
$embed .=
'<script type="text/javascript" src="?js"></script>';
$embed .=
'<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' .
$this->get_link() .
'"></embed>';
$embed .=
'<script type="text/javascript">embed_odeo("' .
$this->get_link() .
'");</script>';
// QuickTime 7 file types. Need to test with QuickTime 6.
else if (in_array($type, array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'x-audio/mp3', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video')))
if ($placeholder !=
"") {
$embed .=
"<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" .
$this->get_link() .
"\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>";
$embed .=
"<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" .
$this->get_link() .
"\" width=\"$width+\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>";
$embed .=
"<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" .
$this->get_link() .
"', '$placeholder', '$loop');</script>";
else if (in_array($type, array('application/x-shockwave-flash', 'application/futuresplash')))
$embed .=
"<embed src=\"" .
$this->get_link() .
"\" pluginspage=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
$embed .=
"<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" .
$this->get_link() .
"', '$loop', '$type');</script>";
else if (in_array($type, array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx')))
$embed .=
"<embed type=\"application/x-mplayer2\" src=\"" .
$this->get_link() .
"\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
$embed .=
"<script type='text/javascript'>embed_wmedia('$width', '$height', '" .
$this->get_link() .
"');</script>";
else $embed .=
'<a href="' .
$this->get_link() .
'" class="' .
$altclass .
'">' .
$alt .
'</a>';
function SimplePie_File($url, $timeout =
10, $redirects =
5, $headers =
null, $useragent =
null, $force_fsockopen =
false)
$url =
$idn->encode($url);
$useragent =
ini_get('user_agent');
foreach ($headers as $key =>
$value)
$headers2[] =
"$key: $value";
if (($this->headers['status']['code'] ==
301 ||
$this->headers['status']['code'] ==
302 ||
$this->headers['status']['code'] ==
303 ||
$this->headers['status']['code'] ==
307) &&
!empty($this->headers['location']) &&
$this->redirects <
$redirects)
return $this->SimplePie_File($this->headers['location'], $timeout, $redirects, $headers, $useragent, $force_fsockopen);
if (isset
($url_parts['scheme']) &&
strtolower($url_parts['scheme']) ==
'https')
$url_parts['host'] =
"ssl://$url_parts[host]";
$url_parts['port'] =
443;
if (!isset
($url_parts['port']))
$this->fp =
fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
$this->error =
'fsockopen error: ' .
$errstr;
$get =
(isset
($url_parts['query'])) ?
"$url_parts[path]?$url_parts[query]" :
$url_parts['path'];
$out =
"GET $get HTTP/1.0\r\n";
$out .=
"Host: $url_parts[host]\r\n";
$out .=
"User-Agent: $useragent\r\n";
$out .=
"Accept-Encoding: gzip,deflate\r\n";
if (!empty($url_parts['user']) &&
!empty($url_parts['pass']))
$out .=
"Authorization: Basic " .
base64_encode("$url_parts[user]:$url_parts[pass]") .
"\r\n";
foreach ($headers as $key =>
$value)
$out .=
"$key: $value\r\n";
$out .=
"Connection: Close\r\n\r\n";
while (strpos($data, "\r\n\r\n") ===
false &&
!$info['timed_out'])
if (($this->headers['status']['code'] ==
301 ||
$this->headers['status']['code'] ==
302 ||
$this->headers['status']['code'] ==
303 ||
$this->headers['status']['code'] ==
307) &&
!empty($this->headers['location']) &&
$this->redirects <
$redirects)
return $this->SimplePie_File($this->headers['location'], $timeout, $redirects, $headers, $useragent, $force_fsockopen);
$this->error =
'fsocket timed out';
return $this->headers['status']['code'];
$this->error =
'fopen could not open the file';
while (!$info['eof'] &&
!$info['timed_out'])
if ($this->method ==
'fsockopen' &&
!empty($this->headers['content-encoding']) &&
($this->headers['content-encoding'] ==
'gzip' ||
$this->headers['content-encoding'] ==
'deflate'))
if (substr($this->body, 0, 8) ==
"\x1f\x8b\x08\x00\x00\x00\x00\x00")
foreach ($headers as $header)
if (preg_match('/HTTP\/[0-9\.]+ ([0-9]+)(.*)$/i', $status, $matches))
if (isset
($head['status']))
$head['status']['code'] =
$matches[1];
$head['status']['name'] =
trim($matches[2]);
$relative =
trim($relative);
$relative =
array('scheme' =>
$relative[2], 'authority' =>
$relative[3], 'path' =>
$relative[5], 'query' =>
$relative[7], 'fragment' =>
$relative[9]);
if (!empty($relative['scheme']))
$base =
array('scheme' =>
$base[2], 'authority' =>
$base[3], 'path' =>
$base[5], 'query' =>
$base[7], 'fragment' =>
$base[9]);
$target['scheme'] =
$base['scheme'];
if (!empty($relative['authority']))
$target['authority'] =
$base['authority'];
if (!empty($relative['path']))
if (strpos($relative['path'], '/') ===
0)
$target['path'] =
$relative['path'];
if (!empty($base['path']))
$target['path'] =
dirname("$base[path].") .
'/' .
$relative['path'];
$target['path'] =
'/' .
$relative['path'];
if (!empty($relative['query']))
$target['query'] =
$relative['query'];
$input =
$target['path'];
if (strpos($input, '../') ===
0)
else if (strpos($input, './') ===
0)
else if (strpos($input, '/./') ===
0)
else if (strpos($input, '/../') ===
0)
$target['path'] =
preg_replace('/(\/)?([^\/]+)$/msiU', '', $target['path']);
$target['path'] =
preg_replace('/(\/)?([^\/]+)$/msiU', '', $target['path']);
else if ($input ==
'.' ||
$input ==
'..')
if (preg_match('/^(.+)(\/|$)/msiU', $input, $match))
$target['path'] .=
$match[1];
if (!empty($base['path']))
$target['path'] =
$base['path'];
if (!empty($relative['query']))
$target['query'] =
$relative['query'];
else if (!empty($base['query']))
$target['query'] =
$base['query'];
if (!empty($relative['fragment']))
$target['fragment'] =
$relative['fragment'];
if (!empty($target['scheme']))
$return .=
"$target[scheme]:";
if (!empty($target['authority']))
$return .=
$target['authority'];
if (!empty($target['path']))
$return .=
$target['path'];
if (!empty($target['query']))
$return .=
"?$target[query]";
if (!empty($target['fragment']))
$return .=
"#$target[fragment]";
preg_match_all("/<($name)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))*)\s*((\/)?>|>(.*)<\/$name>)/msiU", $string, $matches, PREG_SET_ORDER);
for ($i =
0; $i <
count($matches); $i++
)
$return[$i]['tag'] =
$realname;
$return[$i]['full'] =
$matches[$i][0];
if (strlen($matches[$i][10]) <=
2)
$return[$i]['self_closing'] =
true;
$return[$i]['self_closing'] =
false;
$return[$i]['content'] =
$matches[$i][12];
$return[$i]['attribs'] =
array();
if (!empty($matches[$i][2]))
preg_match_all('/((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(\S+))\s/msiU', ' ' .
$matches[$i][2] .
' ', $attribs, PREG_SET_ORDER);
for ($j =
0; $j <
count($attribs); $j++
)
$return[$i]['attribs'][strtoupper($attribs[$j][1])]['data'] =
$attribs[$j][count($attribs[$j])-
1];
$first =
substr($attribs[$j][2], 0, 1);
$return[$i]['attribs'][strtoupper($attribs[$j][1])]['split'] =
($first ==
'"' ||
$first ==
"'") ?
$first :
'"';
$full =
"<$element[tag]";
foreach ($element['attribs'] as $key =>
$value)
$full .=
" $key=$value[split]$value[data]$value[split]";
if ($element['self_closing'])
$full .=
">$element[content]</$element[tag]>";
function error($message, $level, $file, $line)
error_log("$note: $message in $file on line $line", 0);
function display_file($url, $timeout =
10, $useragent =
null)
$file =
new SimplePie_File($url, $timeout, 5, array('X-FORWARDED-FOR' =>
$_SERVER['REMOTE_ADDR']), $useragent);
$headers =
$file->headers();
if ($file->body() !==
false)
header('Content-type: ' .
$headers['content-type']);
if (!empty($parsed['scheme']) &&
strtolower($parsed['scheme']) !=
'http' &&
strtolower($parsed['scheme']) !=
'https')
if ($http ==
2 &&
!empty($parsed['scheme']))
else if ($http ==
3 &&
strtolower($parsed['scheme']) ==
'http')
function parse_url($url, $parse_match =
true)
preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/i', $url, $match);
for ($i =
6; $i <
10; $i++
)
$match =
array('scheme' =>
$match[2], 'authority' =>
$match[4], 'path' =>
$match[5], 'query' =>
$match[6], 'fragment' =>
$match[8]);
* PCRE Pattern to locate bad bytes in a UTF-8 string
* Comes from W3 FAQ: Multilingual Forms
* Note: modified to include full ASCII range including control chars
* Modified by Geoffrey Sneddon 2006-11-19 to remove functionality
* to choose what the replace string is, and to use a variable for
* the output instead of PHP's output buffer
'([\x00-\x7F]' .
# ASCII (including control chars)
'|[\xC2-\xDF][\x80-\xBF]' .
# non-overlong 2-byte
'|\xE0[\xA0-\xBF][\x80-\xBF]' .
# excluding overlongs
'|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}' .
# straight 3-byte
'|\xED[\x80-\x9F][\x80-\xBF]' .
# excluding surrogates
'|\xF0[\x90-\xBF][\x80-\xBF]{2}' .
# planes 1-3
'|[\xF1-\xF3][\x80-\xBF]{3}' .
# planes 4-15
'|\xF4[\x80-\x8F][\x80-\xBF]{2}' .
# plane 16
'|(.{1}))'; # invalid byte
while (preg_match('/' .
$UTF8_BAD .
'/S', $str, $matches))
if (function_exists('iconv') &&
$input['use_iconv'] &&
$output['use_iconv'] &&
iconv($input['encoding'], "$output[encoding]//TRANSLIT", $data))
return iconv($input['encoding'], "$output[encoding]//TRANSLIT", $data);
else if (function_exists('iconv') &&
$input['use_iconv'] &&
$output['use_iconv'] &&
iconv($input['encoding'], $output['encoding'], $data))
return iconv($input['encoding'], $output['encoding'], $data);
else if (function_exists('mb_convert_encoding') &&
$input['use_mbstring'] &&
$output['use_mbstring'])
return mb_convert_encoding($data, $output['encoding'], $input['encoding']);
else if ($input['encoding'] ==
'ISO-8859-1' &&
$output['encoding'] ==
'UTF-8')
else if ($input['encoding'] ==
'UTF-8' &&
$output['encoding'] ==
'ISO-8859-1')
$return['use_mbstring'] =
false;
$return['use_iconv'] =
false;
$return['encoding'] =
'7bit';
$return['use_mbstring'] =
true;
$return['encoding'] =
'8bit';
$return['use_mbstring'] =
true;
$return['encoding'] =
'ARMSCII-8';
$return['use_iconv'] =
true;
$return['encoding'] =
'US-ASCII';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'BASE64';
$return['use_mbstring'] =
true;
// Big5 - Traditional Chinese, mainly used in Taiwan
$return['encoding'] =
'BIG5';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
// Big5 with Hong Kong extensions, Traditional Chinese
$return['encoding'] =
'BIG5-HKSCS';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'byte2be';
$return['use_mbstring'] =
true;
$return['encoding'] =
'byte2le';
$return['use_mbstring'] =
true;
$return['encoding'] =
'byte4be';
$return['use_mbstring'] =
true;
$return['encoding'] =
'byte4le';
$return['use_mbstring'] =
true;
$return['encoding'] =
'EUC-CN';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'EUC-JISX0213';
$return['use_iconv'] =
true;
$return['encoding'] =
'EUC-JP';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'EUCJP-win';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'EUC-KR';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'EUC-TW';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
// GB18030 - Simplified Chinese, national standard character set
$return['encoding'] =
'GB18030';
$return['use_iconv'] =
true;
// GB2312 - Simplified Chinese, national standard character set
$return['encoding'] =
'GB2312';
$return['use_mbstring'] =
true;
$return['encoding'] =
'GBK';
$return['use_iconv'] =
true;
$return['encoding'] =
'Georgian-Academy';
$return['use_iconv'] =
true;
$return['encoding'] =
'Georgian-PS';
$return['use_iconv'] =
true;
$return['encoding'] =
'HTML-ENTITIES';
$return['use_mbstring'] =
true;
$return['encoding'] =
'HZ';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-2022-CN';
$return['use_iconv'] =
true;
$return['encoding'] =
'ISO-2022-CN';
$return['use_iconv'] =
true;
$return['encoding'] =
'ISO-2022-JP';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-2022-JP-1';
$return['use_iconv'] =
true;
$return['encoding'] =
'ISO-2022-JP-2';
$return['use_iconv'] =
true;
$return['encoding'] =
'ISO-2022-JP-3';
$return['use_iconv'] =
true;
$return['encoding'] =
'ISO-2022-KR';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-1';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-2';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-3';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-4';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-5';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-6';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-7';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-8';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-9';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-10';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
// mbstring/iconv functions don't appear to support 11 & 12
$return['encoding'] =
'ISO-8859-13';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-14';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-15';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'ISO-8859-16';
$return['use_iconv'] =
true;
$return['encoding'] =
'JIS';
$return['use_mbstring'] =
true;
$return['encoding'] =
'JOHAB';
$return['use_iconv'] =
true;
$return['encoding'] =
'KOI8-R';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'KOI8-T';
$return['use_iconv'] =
true;
$return['encoding'] =
'KOI8-U';
$return['use_iconv'] =
true;
$return['encoding'] =
'KOI8-RU';
$return['use_iconv'] =
true;
// Macintosh (Mac OS Classic)
$return['encoding'] =
'Macintosh';
$return['use_iconv'] =
true;
// MacArabic (Mac OS Classic)
$return['encoding'] =
'MacArabic';
$return['use_iconv'] =
true;
// MacCentralEurope (Mac OS Classic)
$return['encoding'] =
'MacCentralEurope';
$return['use_iconv'] =
true;
// MacCroatian (Mac OS Classic)
$return['encoding'] =
'MacCroatian';
$return['use_iconv'] =
true;
// MacCyrillic (Mac OS Classic)
$return['encoding'] =
'MacCyrillic';
$return['use_iconv'] =
true;
// MacGreek (Mac OS Classic)
$return['encoding'] =
'MacGreek';
$return['use_iconv'] =
true;
// MacHebrew (Mac OS Classic)
$return['encoding'] =
'MacHebrew';
$return['use_iconv'] =
true;
// MacIceland (Mac OS Classic)
$return['encoding'] =
'MacIceland';
$return['use_iconv'] =
true;
// MacRoman (Mac OS Classic)
$return['encoding'] =
'MacRoman';
$return['use_iconv'] =
true;
// MacRomania (Mac OS Classic)
$return['encoding'] =
'MacRomania';
$return['use_iconv'] =
true;
// MacThai (Mac OS Classic)
$return['encoding'] =
'MacThai';
$return['use_iconv'] =
true;
// MacTurkish (Mac OS Classic)
$return['encoding'] =
'MacTurkish';
$return['use_iconv'] =
true;
// MacUkraine (Mac OS Classic)
$return['encoding'] =
'MacUkraine';
$return['use_iconv'] =
true;
$return['encoding'] =
'MuleLao-1';
$return['use_iconv'] =
true;
$return['encoding'] =
'Shift_JIS';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'Shift_JISX0213';
$return['use_iconv'] =
true;
$return['encoding'] =
'SJIS-win';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'TCVN';
$return['use_iconv'] =
true;
$return['encoding'] =
'TDS565';
$return['use_iconv'] =
true;
$return['encoding'] =
'TIS-620';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-2';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-2BE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-2LE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-2-INTERNAL';
$return['use_iconv'] =
true;
$return['encoding'] =
'UCS-4';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-4BE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-4LE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-4-INTERNAL';
$return['use_iconv'] =
true;
$return['encoding'] =
'UCS-16';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-16BE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-16LE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-32';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-32BE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UCS-32LE';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UTF-7';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$return['encoding'] =
'UTF7-IMAP';
$return['use_mbstring'] =
true;
// VISCII - Vietnamese ASCII
$return['encoding'] =
'VISCII';
$return['use_iconv'] =
true;
// Windows-specific Central & Eastern Europe
$return['encoding'] =
'Windows-1250';
$return['use_iconv'] =
true;
// Windows-specific Cyrillic
$return['encoding'] =
'Windows-1251';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
// Windows-specific Western Europe
$return['encoding'] =
'Windows-1252';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
// Windows-specific Greek
$return['encoding'] =
'Windows-1253';
$return['use_iconv'] =
true;
// Windows-specific Turkish
$return['encoding'] =
'Windows-1254';
$return['use_iconv'] =
true;
// Windows-specific Hebrew
$return['encoding'] =
'Windows-1255';
$return['use_iconv'] =
true;
// Windows-specific Arabic
$return['encoding'] =
'Windows-1256';
$return['use_iconv'] =
true;
// Windows-specific Baltic
$return['encoding'] =
'Windows-1257';
$return['use_iconv'] =
true;
// Windows-specific Vietnamese
$return['encoding'] =
'Windows-1258';
$return['use_iconv'] =
true;
$return['encoding'] =
'UTF-8';
$return['use_iconv'] =
true;
$return['use_mbstring'] =
true;
$curl =
$curl['version'];
function SimplePie_Locator(&$file, $timeout =
10, $useragent =
null, $file_class =
'SimplePie_File')
if (!is_a($file, 'SimplePie_File'))
$this->file =
new $this->file_class($file, $timeout, $useragent);
if (!empty($this->local))
if ($extension_elsewhere)
return $extension_elsewhere;
if (!is_a($file, 'SimplePie_File'))
$file2 =
new $this->file_class($file, $this->timeout, 5, null, $this->useragent);
$file2 =
new $this->file_class($file);
$body =
preg_replace('/<\!-(.*)-\>/msiU', '', $file2->body());
foreach ($links as $link)
if (!empty($link['attribs']['TYPE']['data']) &&
!empty($link['attribs']['HREF']['data']) &&
!empty($link['attribs']['REL']['data']))
$type =
preg_match('/^(application\/rss\+xml|application\/atom\+xml|application\/rdf\+xml|application\/xml\+rss|application\/xml\+atom|application\/xml\+rdf|application\/xml|application\/x\.atom\+xml|text\/xml)(;|$)/msiU', trim($link['attribs']['TYPE']['data']));
foreach ($links as $link)
if (!empty($link['attribs']['HREF']['data']))
$href =
trim($link['attribs']['HREF']['data']);
if (empty($parsed['scheme']) ||
$parsed['scheme'] !=
'javascript')
if (empty($parsed['authority']) ||
$parsed['authority'] ==
$current['authority'])
if (!empty($this->local))
foreach ($array as $key =>
$value)
if (in_array(strrchr($value, '.'), array('.rss', '.rdf', '.atom', '.xml')))
foreach ($array as $key =>
$value)
var $namespaces =
array('xml' =>
'HTTP://WWW.W3.ORG/XML/1998/NAMESPACE', 'atom' =>
'ATOM', 'rss2' =>
'RSS', 'rdf' =>
'RDF', 'rss1' =>
'RSS', 'dc' =>
'DC', 'xhtml' =>
'XHTML', 'content' =>
'CONTENT');
if (strpos($data, sprintf('%c%c%c%c', 0x00, 0x00, 0xFE, 0xFF)) ===
0)
// UTF-32 Little Endian BOM
else if (strpos($data, sprintf('%c%c%c%c', 0xFF, 0xFE, 0x00, 0x00)) ===
0)
// UTF-16 Little Endian BOM
else if (strpos($data, sprintf('%c%c%c', 0xEF, 0xBB, 0xBF)) ===
0)
// Make sure the XML prolog is sane and has the correct encoding
if (preg_match('/^<\?xml(.*)?>/msiU', $data, $prolog))
$data =
"<?xml version='1.0' encoding='$encoding'?>\n" .
$data;
// Put some data into CDATA blocks
foreach ($sp_elements as $full)
$data =
preg_replace_callback("/<($full)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'))*)\s*(\/>|>(.*)<\/$full>)/msiU", array(&$this, 'add_cdata'), $data);
foreach ($sp_elements as $full)
// Deal with CDATA within CDATA (this can be caused by us inserting CDATA above)
$data =
preg_replace_callback("/<($full)((\s*((\w+:)?\w+)\s*=\s*(\"([^\"]*)\"|'([^']*)'))*)\s*(\/>|><!\[CDATA\[(.*)\]\]><\/$full>)/msiU", array(&$this, 'cdata_in_cdata'), $data);
// Return the XML, if so desired
return "<$match[1]$match[2]><![CDATA[$match[10]]]></$match[1]>";
$match[10] =
preg_replace_callback('/<!\[CDATA\[(.*)\]\]>/msiU', array(&$this, 'real_cdata_in_cdata'), $match[10]);
return "<$match[1]$match[2]><![CDATA[$match[10]]]></$match[1]>";
$array['attribs'] =
$this->attribs;
$this->data['feedinfo']['type'] =
'RSS';
if (!empty($attribs['VERSION']))
$this->data['feedinfo']['version'] =
trim($attribs['VERSION']);
$this->data['feedinfo']['type'] =
'RSS';
$this->data['feedinfo']['version'] =
1;
$this->data['feedinfo']['type'] =
'Atom';
if (!empty($attribs['VERSION']))
$this->data['feedinfo']['version'] =
trim($attribs['VERSION']);
if (!empty($this->data['feedinfo']['type']) &&
$this->data['feedinfo']['type'] ==
'Atom' &&
($this->tag_name ==
'AUTHOR' ||
$this->tag_name ==
$this->namespaces['atom'] .
':AUTHOR'))
if ($prefix ==
'ATOM' ||
$uri ==
'HTTP://WWW.W3.ORG/2005/ATOM' ||
$uri ==
'HTTP://PURL.ORG/ATOM/NS#')
else if ($prefix ==
'RSS2' ||
$uri ==
'HTTP://BACKEND.USERLAND.COM/RSS2')
else if ($prefix ==
'RDF' ||
$uri ==
'HTTP://WWW.W3.ORG/1999/02/22-RDF-SYNTAX-NS#')
else if ($prefix ==
'RSS' ||
$uri ==
'HTTP://PURL.ORG/RSS/1.0/' ||
$uri ==
'HTTP://MY.NETSCAPE.COM/RDF/SIMPLE/0.9/')
else if ($prefix ==
'DC' ||
$uri ==
'HTTP://PURL.ORG/DC/ELEMENTS/1.1/')
else if ($prefix ==
'XHTML' ||
$uri ==
'HTTP://WWW.W3.ORG/1999/XHTML')
$this->xhtml_prefix =
$prefix;
else if ($prefix ==
'CONTENT' ||
$uri ==
'HTTP://PURL.ORG/RSS/1.0/MODULES/CONTENT/')
else if ($key ==
'xhtml')
$this->xhtml_prefix =
'XHTML';
else if ($key ==
'content')
var $strip_htmltags =
array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
var $strip_attributes =
array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur');
$this->enable_headers = (bool)
$enable;
function strip_htmltags($tags =
array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
function strip_attributes($attribs =
array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur'))
// Feed Info (Type and Version)
if (!empty($data['feedinfo']['type']))
if (!empty($data['feeddata']['attribs']['XML:BASE']))
$this->feed_xmlbase =
$data['feeddata']['attribs']['XML:BASE'];
else if (!empty($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
$this->feed_xmlbase =
$data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'];
// FeedBurner feeds use alternate link
else if (strpos($url, 'http://feeds.feedburner.com/') !==
0)
if (!empty($data['info']['link']))
foreach ($data['info']['link'] as $link)
if (empty($link['attribs']['REL']))
if (!empty($link['data']))
$href =
$this->sanitize($link['data'], $link['attribs'], true);
else if (!empty($link['attribs']['HREF']))
$href =
$this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
if (!empty($link['attribs']['TYPE'])) {
$type =
$this->sanitize($link['attribs']['TYPE'], $link['attribs']);
if (!empty($link['attribs']['LENGTH'])) {
$length =
$this->sanitize($link['attribs']['LENGTH'], $link['attribs']);
$this->info['link']['enclosure'][] =
new $this->enclosure_class($href, $type, $length);
if (!empty($link['data']))
$this->info['link'][$rel][] =
$this->sanitize($link['data'], $link['attribs'], true);
else if (!empty($link['attribs']['HREF']))
$this->info['link'][$rel][] =
$this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
// Use the first alternate link if we don't have any feed xml:base
if (!empty($data['info']['title']['data']))
$this->info['title'] =
$this->sanitize($data['info']['title']['data'], $data['info']['title']['attribs']);
if (!empty($data['info']['description']['data']))
$this->info['description'] =
$this->sanitize($data['info']['description']['data'], $data['info']['description']['attribs'], false, true);
if (!empty($data['info']['dc:description']['data']))
$this->info['dc:description'] =
$this->sanitize($data['info']['dc:description']['data'], $data['info']['dc:description']['attribs']);
if (!empty($data['info']['tagline']['data']))
$this->info['tagline'] =
$this->sanitize($data['info']['tagline']['data'], $data['info']['tagline']['attribs']);
if (!empty($data['info']['subtitle']['data']))
$this->info['subtitle'] =
$this->sanitize($data['info']['subtitle']['data'], $data['info']['subtitle']['attribs']);
if (!empty($data['info']['language']['data']))
$this->info['language'] =
$this->sanitize($data['info']['language']['data'], $data['info']['language']['attribs']);
if (!empty($data['feeddata']['attribs']['XML:LANG']))
$this->info['xml:lang'] =
$this->sanitize($data['feeddata']['attribs']['XML:LANG'], null);
else if (!empty($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:LANG']))
$this->info['xml:lang'] =
$this->sanitize($data['feeddata']['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:LANG'], null);
if (!empty($data['info']['copyright']['data']))
$this->info['copyright'] =
$this->sanitize($data['info']['copyright']['data'], $data['info']['copyright']['attribs']);
if (!empty($data['info']['image']['title']['data']))
$this->info['image']['title'] =
$this->sanitize($data['info']['image']['title']['data'], $data['info']['image']['title']['attribs']);
if (!empty($data['info']['image']['url']['data']))
$this->info['image']['url'] =
$this->sanitize($data['info']['image']['url']['data'], $data['info']['image']['url']['attribs'], true);
if (!empty($data['info']['logo']['data']))
$this->info['image']['logo'] =
$this->sanitize($data['info']['logo']['data'], $data['info']['logo']['attribs'], true);
if (!empty($data['info']['image']['link']['data']))
$this->info['image']['link'] =
$this->sanitize($data['info']['image']['link']['data'], $data['info']['image']['link']['attribs'], true);
if (!empty($data['info']['image']['width']['data']))
$this->info['image']['width'] =
$this->sanitize($data['info']['image']['width']['data'], $data['info']['image']['width']['attribs']);
if (!empty($data['info']['image']['height']['data']))
$this->info['image']['height'] =
$this->sanitize($data['info']['image']['height']['data'], $data['info']['image']['height']['attribs']);
if (!empty($data['items']))
foreach ($data['items'] as $key =>
$item)
if (!empty($item['attribs']['XML:BASE']))
else if (!empty($item['attribs']['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
if (!empty($item['title']['data'])) {
$newitem['title'] =
$this->sanitize($item['title']['data'], $item['title']['attribs']);
if (!empty($item['dc:title']['data']))
$newitem['dc:title'] =
$this->sanitize($item['dc:title']['data'], $item['dc:title']['attribs']);
if (!empty($item['content']['data']))
$newitem['content'] =
$this->sanitize($item['content']['data'], $item['content']['attribs']);
if (!empty($item['encoded']['data']))
$newitem['encoded'] =
$this->sanitize($item['encoded']['data'], $item['encoded']['attribs']);
if (!empty($item['summary']['data']))
$newitem['summary'] =
$this->sanitize($item['summary']['data'], $item['summary']['attribs']);
if (!empty($item['description']['data']))
$newitem['description'] =
$this->sanitize($item['description']['data'], $item['description']['attribs'], false, true);
if (!empty($item['dc:description']['data']))
$newitem['dc:description'] =
$this->sanitize($item['dc:description']['data'], $item['dc:description']['attribs']);
if (!empty($item['longdesc']['data']))
$newitem['longdesc'] =
$this->sanitize($item['longdesc']['data'], $item['longdesc']['attribs']);
if (!empty($item['link']))
foreach ($item['link'] as $link)
if (empty($link['attribs']['REL']))
if (!empty($link['data']))
$href =
$this->sanitize($link['data'], $link['attribs'], true);
else if (!empty($link['attribs']['HREF']))
$href =
$this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
if (!empty($link['attribs']['TYPE'])) {
$type =
$this->sanitize($link['attribs']['TYPE'], $link['attribs']);
if (!empty($link['attribs']['LENGTH'])) {
$length =
$this->sanitize($link['attribs']['LENGTH'], $link['attribs']);
$newitem['link'][$rel][] =
new $this->enclosure_class($href, $type, $length);
if (!empty($link['data']))
$newitem['link'][$rel][] =
$this->sanitize($link['data'], $link['attribs'], true);
else if (!empty($link['attribs']['HREF']))
$newitem['link'][$rel][] =
$this->sanitize($link['attribs']['HREF'], $link['attribs'], true);
if (!empty($item['enclosure']))
foreach ($item['enclosure'] as $enclosure)
if (!empty($enclosure['attribs']['URL']))
$href =
$this->sanitize($enclosure['attribs']['URL'], $enclosure['attribs'], true);
if (!empty($enclosure['attribs']['TYPE']))
$type =
$this->sanitize($enclosure['attribs']['TYPE'], $enclosure['attribs']);
if (!empty($enclosure['attribs']['LENGTH']))
$length =
$this->sanitize($enclosure['attribs']['LENGTH'], $enclosure['attribs']);
$newitem['enclosures'][] =
new $this->enclosure_class($href, $type, $length);
if (!empty($item['guid']['data']))
if (!empty($item['guid']['attribs']['ISPERMALINK']) &&
strtolower($item['guid']['attribs']['ISPERMALINK']) ==
'false')
$newitem['guid']['permalink'] =
false;
$newitem['guid']['permalink'] =
true;
$newitem['guid']['data'] =
$this->sanitize($item['guid']['data'], $item['guid']['attribs']);
if (!empty($item['id']['data']))
$newitem['id'] =
$this->sanitize($item['id']['data'], $item['id']['attribs']);
if (!empty($item['pubdate']['data']))
$newitem['pubdate'] =
$this->parse_date($this->sanitize($item['pubdate']['data'], $item['pubdate']['attribs']));
if (!empty($item['dc:date']['data']))
$newitem['dc:date'] =
$this->parse_date($this->sanitize($item['dc:date']['data'], $item['dc:date']['attribs']));
if (!empty($item['issued']['data']))
$newitem['issued'] =
$this->parse_date($this->sanitize($item['issued']['data'], $item['issued']['attribs']));
if (!empty($item['published']['data']))
$newitem['published'] =
$this->parse_date($this->sanitize($item['published']['data'], $item['published']['attribs']));
if (!empty($item['modified']['data']))
$newitem['modified'] =
$this->parse_date($this->sanitize($item['modified']['data'], $item['modified']['attribs']));
if (!empty($item['updated']['data']))
$newitem['updated'] =
$this->parse_date($this->sanitize($item['updated']['data'], $item['updated']['attribs']));
if (!empty($item['category']))
foreach ($item['category'] as $category)
if (!empty($category['data']))
$newitem['category'][] =
$this->sanitize($category['data'], $category['attribs']);
else if (!empty($category['attribs']['TERM']))
$newitem['term'][] =
$this->sanitize($category['attribs']['TERM'], $category['attribs']);
if (!empty($item['subject']))
foreach ($item['subject'] as $category)
if (!empty($category['data']))
$newitem['subject'][] =
$this->sanitize($category['data'], $category['attribs']);
if (!empty($item['creator']))
foreach ($item['creator'] as $creator)
if (!empty($creator['data']))
$newitem['creator'][] =
new $this->author_class($this->sanitize($creator['data'], $creator['attribs']), null, null);
if (!empty($item['author']))
foreach ($item['author'] as $author)
if (!empty($author['rss']))
$sane =
$this->sanitize($author['rss']['data'], $author['rss']['attribs']);
if (preg_match('/(.*)@(.*) \((.*)\)/msiU', $sane, $matches)) {
$name =
trim($matches[3]);
$email =
trim("$matches[1]@$matches[2]");
if (!empty($author['name']))
$name =
$this->sanitize($author['name']['data'], $author['name']['attribs']);
if (!empty($author['url']))
$link =
$this->sanitize($author['url']['data'], $author['url']['attribs'], true);
else if (!empty($author['uri']))
$link =
$this->sanitize($author['uri']['data'], $author['uri']['attribs'], true);
else if (!empty($author['homepage']))
$link =
$this->sanitize($author['homepage']['data'], $author['homepage']['attribs'], true);
if (!empty($author['email'])) {
$email =
$this->sanitize($author['email']['data'], $author['email']['attribs']);
$newitem['author'][] =
new $this->author_class($name, $link, $email);
unset
($data['items'][$key]);
$this->items[] =
new $this->item_class($newitem);
function sanitize($data, $attribs, $is_url =
false, $force_decode =
false)
if ((!empty($attribs['MODE']) &&
$attribs['MODE'] ==
'base64') ||
(!empty($attribs['TYPE']) &&
$attribs['TYPE'] ==
'application/octet-stream'))
else if ((!empty($attribs['MODE']) &&
$attribs['MODE'] ==
'escaped' ||
!empty($attribs['TYPE']) &&
($attribs['TYPE'] ==
'html' ||
$attribs['TYPE'] ==
'text/html')))
if (!empty($attribs['TYPE']) &&
($attribs['TYPE'] ==
'xhtml' ||
$attribs['TYPE'] ==
'application/xhtml+xml'))
$data =
preg_replace('/<div( .*)?>/msiU', '<div>', $data, 1);
$data =
preg_replace('/<\!--([^-]|-[^-])*-->/msiU', '', $data);
// If Strip Ads is enabled, strip them.
$data =
preg_replace('/<a (.*)href=(.*)click\.phdo\?s=(.*)<\/a>/msiU', '', $data); // Pheedo links (tested with Dooce.com)
$data =
preg_replace('/<p(.*)>(.*)<a href="http:\/\/ad.doubleclick.net\/jump\/(.*)<\/p>/msiU', '', $data); // Doubleclick links (tested with InfoWorld.com)
$data =
preg_replace('/<p><map (.*)name=(.*)google_ad_map(.*)<\/p>/msiU', '', $data); // Google AdSense for Feeds (tested with tuaw.com).
// Feedflare, from Feedburner
// Replace H1, H2, and H3 tags with the less important H4 tags.
// This is because on a site, the more important headers might make sense,
// but it most likely doesn't fit in the context of RSS-in-a-webpage.
$data =
preg_replace('/<h[1-3]((\s*((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(.*)))*)\s*>/msiU', '<h4\\1>', $data);
$data =
preg_replace_callback('/<(\S+)((\s*((\w+:)?\w+)\s*=\s*("([^"]*)"|\'([^\']*)\'|(.*)))*)\s*(\/>|>(.*)<\/\S+>)/msiU', array(&$this, 'replace_urls'), $data);
// If Bypass Image Hotlink is enabled, rewrite all the image tags.
foreach ($images as $img)
if (!empty($img['attribs']['SRC']['data']))
// Strip out HTML tags and attributes that might cause various security problems.
// Based on recommendations by Mark Pilgrim at:
// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
$data =
preg_replace_callback("/<($tag)((\s*((\w+:)?\w+)(\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))?)*)\s*(\/>|>(.*)<\/($tag)((\s*((\w+:)?\w+)(\s*=\s*(\"([^\"]*)\"|'([^']*)'|(.*)))?)*)\s*>)/msiU", array(&$this, 'do_strip_htmltags'), $data);
$data =
preg_replace('/ '.
trim($attrib) .
'=("|")(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\'|'|<|>|\+|{|})*("|")/i', '', $data);
$data =
preg_replace('/ '.
trim($attrib) .
'=(\'|')(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|"|"|<|>|\+|{|})*(\'|')/i', '', $data);
$data =
preg_replace('/ '.
trim($attrib) .
'=(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\+|{|})*/i', '', $data);
return "<$match[1]$match[2]>$match[12]</$match[1]>";
else if (isset
($match[12]))
return "<$match[1]$match[2]></$match[1]>";
return "<$match[1]$match[2]/>";
if (!empty($this->attribs['XML:BASE']))
$xmlbase =
$attribs['XML:BASE'];
else if (!empty($this->attribs['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE']))
$xmlbase =
$this->attribs['HTTP://WWW.W3.ORG/XML/1998/NAMESPACE:BASE'];
foreach ($attributes as $attribute)
if (preg_match("/$attribute='(.*)'/siU", $data[0], $attrib) ||
preg_match("/$attribute=\"(.*)\"/siU", $data[0], $attrib) ||
preg_match("/$attribute=(.*)[ |\/|>]/siU", $data[0], $attrib))
$data[0] =
str_replace($attrib[0], $new_tag, $data[0]);
* Escape numeric entities
* From a PHP Manual note (on html_entity_decode())
* Copyright (c) 2005 by "php dot net at c dash ovidiu dot tk",
* "emilianomartinezluque at yahoo dot com" and "hurricane at cyberworldz dot org".
* This material may be distributed only subject to the terms and conditions set forth in
* the Open Publication License, v1.0 or later (the latest version is presently available at
* http://www.opencontent.org/openpub/).
if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match))
$prefix =
array(31, 192);
$prefix =
array(15, 224);
for ($i =
0; $i <
$no_bytes; $i++
)
$byte[$no_bytes-
$i-
1] =
(($ord & (63 *
pow(2,6*
$i))) /
pow(2,6*
$i)) & 63 |
128;
$byte[0] =
($byte[0] & $prefix[0]) |
$prefix[1];
for ($i =
0; $i <
$no_bytes; $i++
)
$military_timezone =
array('A' =>
'-0100', 'B' =>
'-0200', 'C' =>
'-0300', 'D' =>
'-0400', 'E' =>
'-0500', 'F' =>
'-0600', 'G' =>
'-0700', 'H' =>
'-0800', 'I' =>
'-0900', 'K' =>
'-1000', 'L' =>
'-1100', 'M' =>
'-1200', 'N' =>
'+0100', 'O' =>
'+0200', 'P' =>
'+0300', 'Q' =>
'+0400', 'R' =>
'+0500', 'S' =>
'+0600', 'T' =>
'+0700', 'U' =>
'+0800', 'V' =>
'+0900', 'W' =>
'+1000', 'X' =>
'+1100', 'Y' =>
'+1200', 'Z' =>
'-0000');
$north_american_timezone =
array('GMT' =>
'-0000', 'EST' =>
'-0500', 'EDT' =>
'-0400', 'CST' =>
'-0600', 'CDT' =>
'-0500', 'MST' =>
'-0700', 'MDT' =>
'-0600', 'PST' =>
'-0800', 'PDT' =>
'-0700');
if (preg_match('/([0-9]{2,4})-?([0-9]{2})-?([0-9]{2})T([0-9]{2}):?([0-9]{2})(:?([0-9]{2}(\.[0-9]*)?))?(UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[a-z]|(\\+|-)[0-9]{4}|(\\+|-)[0-9]{2}:[0-9]{2})?/i', $date, $matches))
$matches[7] =
str_pad(round($matches[7]), 2, '0', STR_PAD_LEFT);
$timezone =
$military_timezone[strtoupper($matches[9])];
$timezone =
$north_american_timezone[strtoupper($matches[9])];
$date =
strtotime("$matches[1]-$matches[2]-$matches[3] $matches[4]:$matches[5]:$matches[7] $timezone");
else if (preg_match('/([0-9]{1,2})\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s*([0-9]{2}|[0-9]{4})\s*([0-9]{2}):([0-9]{2})(:([0-9]{2}(\.[0-9]*)?))?\s*(UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[a-z]|(\\+|-)[0-9]{4}|(\\+|-)[0-9]{2}:[0-9]{2})?/i', $date, $matches))
$three_month =
array('Jan' =>
1, 'Feb' =>
2, 'Mar' =>
3, 'Apr' =>
4, 'May' =>
5, 'Jun' =>
6, 'Jul' =>
7, 'Aug' =>
8, 'Sep' =>
9, 'Oct' =>
10, 'Nov' =>
11, 'Dec' =>
12);
$month =
$three_month[$matches[2]];
$year =
($matches[3] <
70) ?
"20$matches[3]" :
"19$matches[3]";
$second =
str_pad(round($matches[7]), 2, '0', STR_PAD_LEFT);
$timezone =
$military_timezone[strtoupper($matches[9])];
$timezone =
$north_american_timezone[strtoupper($matches[9])];
$date =
strtotime("$year-$month-$matches[1] $matches[4]:$matches[5]:$second $timezone");
if ($date !==
false &&
$date !== -
1)