2
/****************************************************
4
A PHP-Based RSS and Atom Feed Framework
5
Takes the hard work out of managing a complete RSS/Atom solution.
9
Copyright: 2004-2006 Ryan Parman, Geoffrey Sneddon
12
*****************************************************
15
GNU Lesser General Public License 2.1 (LGPL)
16
http://creativecommons.org/licenses/LGPL/2.1/
18
*****************************************************
19
Please submit all bug reports and feature requests to the SimplePie forums.
20
http://simplepie.org/support/
22
****************************************************/
26
// SimplePie Information
27
var $name = 'SimplePie';
28
var $version = '1.0 Beta 2';
29
var $build = '20060530';
30
var $url = 'http://simplepie.org/';
37
var $xml_dump = false;
39
var $max_minutes = 60;
40
var $cache_location = './cache';
41
var $bypass_image_hotlink = 'i';
42
var $bypass_image_hotlink_page = false;
43
var $replace_headers = false;
44
var $remove_div = true;
45
var $order_by_date = true;
46
var $strip_ads = false;
47
var $strip_htmltags = 'blink,body,doctype,embed,font,form,frame,frameset,html,iframe,input,marquee,meta,noscript,object,param,script,style';
48
var $strip_attributes = 'class,id,style,onclick,onmouseover,onmouseout,onfocus,onblur';
49
var $encode_instead_of_strip = false;
51
// RSS Auto-Discovery Variables
54
var $elsewhere = array();
56
// XML Parsing Variables
64
var $authorNumber = 0;
65
var $categoryNumber = 0;
66
var $enclosureNumber = 0;
68
var $itemLinkNumber = 0;
79
/****************************************************
81
Initiates a couple of variables. Accepts feed_url, cache_location,
82
and cache_max_minutes.
83
****************************************************/
84
function SimplePie($feed_url = null, $cache_location = null, $cache_max_minutes = null) {
85
$this->useragent = $this->name . '/' . $this->version . ' (Feed Parser; ' . $this->url . '; Allow like Gecko) Build/' . $this->build;
86
$this->linkback = '<a href="' . $this->url . '" title="' . $this->name . ' ' . $this->version . '">' . $this->name . '</a>';
88
if (!is_null($feed_url)) {
89
$this->feed_url($feed_url);
92
if (!is_null($cache_location)) {
93
$this->cache_location($cache_location);
96
if (!is_null($cache_max_minutes)) {
97
$this->cache_max_minutes($cache_max_minutes);
100
if (!is_null($feed_url)) {
101
return $this->init();
104
// If we've passed an xmldump variable in the URL, snap into XMLdump mode
105
if (isset($_GET['xmldump'])) {
106
$this->enable_xmldump($_GET['xmldump']);
113
/****************************************************
115
Set various options (feed URL, XML dump, caching, etc.)
116
****************************************************/
118
function feed_url($url) {
119
$url = $this->fix_protocol($url, 1);
120
$this->rss_url = $url;
125
function enable_xmldump($enable) {
126
$this->xml_dump = (bool) $enable;
130
// Bypass Image Hotlink
131
function bypass_image_hotlink($getvar='i') {
132
$this->bypass_image_hotlink = (string) $getvar;
136
// Bypass Image Hotlink Page
137
function bypass_image_hotlink_page($page = false) {
138
$this->bypass_image_hotlink_page = (string) $page;
143
function enable_caching($enable) {
144
$this->caching = (bool) $enable;
149
function cache_max_minutes($minutes) {
150
$this->max_minutes = (int) $minutes;
155
function cache_location($location) {
156
$this->cache_location = (string) $location;
160
// Replace H1, H2, and H3 tags with the less important H4 tags.
161
function replace_headers($enable) {
162
$this->replace_headers = (bool) $enable;
166
// Remove outer div in XHTML content within Atom
167
function remove_div($enable) {
168
$this->remove_div = (bool) $enable;
172
// Order the items by date
173
function order_by_date($enable) {
174
$this->order_by_date = (bool) $enable;
178
// Strip out certain well-known ads
179
function strip_ads($enable) {
180
$this->strip_ads = (bool) $enable;
184
// Strip out potentially dangerous tags
185
function strip_htmltags($tags, $encode=false) {
186
$this->strip_htmltags = (string) $tags;
187
$this->encode_instead_of_strip = (bool) $encode;
191
// Encode dangerous tags instead of stripping them
192
function encode_instead_of_strip($encode=true) {
193
$this->encode_instead_of_strip = (bool) $encode;
197
// Strip out potentially dangerous attributes
198
function strip_attributes($attrib) {
199
$this->strip_attributes = (string) $attrib;
206
/****************************************************
207
MAIN INITIALIZATION FUNCTION
208
Rewrites the feed so that it actually resembles XML, processes the XML,
209
and builds an array from the feed.
210
****************************************************/
212
// If Bypass Image Hotlink is enabled, send image to the page and quit.
213
if ($this->bypass_image_hotlink) {
214
if (isset($_GET[$this->bypass_image_hotlink]) && !empty($_GET[$this->bypass_image_hotlink])) {
215
$this->display_image($_GET[$this->bypass_image_hotlink]);
220
// If Bypass Image Hotlink is enabled, send image to the page and quit.
221
if (isset($_GET['js'])) {
223
// JavaScript for the Odeo Player
225
$embed.='function embed_odeo(link) {';
226
$embed.='document.writeln(\'';
227
$embed.='<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
228
$embed.=' codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" ';
229
$embed.=' width="440" ';
230
$embed.=' height="80" ';
231
$embed.=' align="middle">';
232
$embed.='<param name="movie" value="http://odeo.com/flash/audio_player_fullsize.swf" />';
233
$embed.='<param name="allowScriptAccess" value="any" />';
234
$embed.='<param name="quality" value="high">';
235
$embed.='<param name="wmode" value="transparent">';
236
$embed.='<param name="flashvars" value="valid_sample_rate=true&external_url=\'+link+\'" />';
237
$embed.='<embed src="http://odeo.com/flash/audio_player_fullsize.swf" ';
238
$embed.=' pluginspage="http://www.macromedia.com/go/getflashplayer" ';
239
$embed.=' type="application/x-shockwave-flash" ';
240
$embed.=' quality="high" ';
241
$embed.=' width="440" ';
242
$embed.=' height="80" ';
243
$embed.=' wmode="transparent" ';
244
$embed.=' allowScriptAccess="any" ';
245
$embed.=' flashvars="valid_sample_rate=true&external_url=\'+link+\'">';
253
$embed.='function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {';
254
$embed.='document.writeln(\'';
255
$embed.='<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" ';
256
$embed.=' style="cursor:hand; cursor:pointer;" ';
257
$embed.=' type="\'+type+\'" ';
258
$embed.=' codebase="http://www.apple.com/qtactivex/qtplugin.cab" ';
259
$embed.=' bgcolor="\'+bgcolor+\'" ';
260
$embed.=' width="\'+width+\'" ';
261
$embed.=' height="\'+height+\'">';
262
$embed.='<param name="href" value="\'+link+\'" />';
263
$embed.='<param name="src" value="\'+placeholder+\'" />';
264
$embed.='<param name="autoplay" value="false" />';
265
$embed.='<param name="target" value="myself" />';
266
$embed.='<param name="controller" value="false" />';
267
$embed.='<param name="loop" value="\'+loop+\'" />';
268
$embed.='<param name="scale" value="aspect" />';
269
$embed.='<param name="bgcolor" value="\'+bgcolor+\'">';
270
$embed.='<embed type="\'+type+\'" ';
271
$embed.=' style="cursor:hand; cursor:pointer;" ';
272
$embed.=' href="\'+link+\'" ';
273
$embed.=' src="\'+placeholder+\'"';
274
$embed.=' width="\'+width+\'" ';
275
$embed.=' height="\'+height+\'" ';
276
$embed.=' autoplay="false" ';
277
$embed.=' target="myself" ';
278
$embed.=' controller="false" ';
279
$embed.=' loop="\'+loop+\'" ';
280
$embed.=' scale="aspect" ';
281
$embed.=' bgcolor="\'+bgcolor+\'" ';
282
$embed.=' pluginspage="http://www.apple.com/quicktime/download/">';
290
$embed.='function embed_flash(bgcolor, width, height, link, loop, type) {';
291
$embed.='document.writeln(\'';
292
$embed.='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
293
$embed.=' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" ';
294
$embed.=' bgcolor="\'+bgcolor+\'" ';
295
$embed.=' width="\'+width+\'" ';
296
$embed.=' height="\'+height+\'">';
297
$embed.='<param name="movie" value="\'+link+\'">';
298
$embed.='<param name="quality" value="high">';
299
$embed.='<param name="loop" value="\'+loop+\'">';
300
$embed.='<param name="bgcolor" value="\'+bgcolor+\'">';
301
$embed.='<embed src="\'+link+\'" ';
302
$embed.=' pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" ';
303
$embed.=' type="\'+type+\'" ';
304
$embed.=' quality="high" ';
305
$embed.=' width="\'+width+\'" ';
306
$embed.=' height="\'+height+\'" ';
307
$embed.=' bgcolor="\'+bgcolor+\'" ';
308
$embed.=' loop="\'+loop+\'">';
316
$embed.='function embed_wmedia(width, height, link) {';
317
$embed.='document.writeln(\'';
318
$embed.='<object classid="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"';
319
$embed.=' type="application/x-oleobject"';
320
$embed.=' width="\'+width+\'"';
321
$embed.=' height="\'+height+\'"';
322
$embed.=' standby="Loading Windows Media Player...">';
323
$embed.='<param name="FileName" value="\'+link+\'">';
324
$embed.='<param name="autosize" value="true">';
325
$embed.='<param name="ShowControls" value="true">';
326
$embed.='<param name="ShowStatusBar" value="false">';
327
$embed.='<param name="ShowDisplay" value="false">';
328
$embed.='<param name="autostart" value="false">';
329
$embed.='<embed type="application/x-mplayer2" ';
330
$embed.=' src="\'+link+\'" ';
331
$embed.=' autosize="1" ';
332
$embed.=' width="\'+width+\'" ';
333
$embed.=' height="\'+height+\'" ';
334
$embed.=' showcontrols="1" ';
335
$embed.=' showstatusbar="0" ';
336
$embed.=' showdisplay="0" ';
337
$embed.=' autostart="0">';
345
// enable gzip compression
346
ob_start ("ob_gzhandler");
347
header("Content-type: text/javascript; charset: UTF-8");
348
header("Cache-Control: must-revalidate");
349
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 60*60*24) . " GMT");
354
// If this is a .Mac Photocast, change it to the real URL.
355
if (stristr($this->rss_url, 'http://photocast.mac.com')) {
356
$this->rss_url = preg_replace('%http://photocast.mac.com%i', 'http://web.mac.com', $this->rss_url);
359
// Clear all outdated cache from the server's cache folder
360
$this->clear_cache($this->cache_location, $this->max_minutes);
362
if (!empty($this->rss_url)) {
363
// Read the XML file for processing.
364
$cache_filename = $this->cache_location . '/' . urlencode($this->rss_url) . '.spc';
365
if ($this->caching && !$this->xml_dump && substr($this->rss_url, 0, 7) == 'http://' && file_exists($cache_filename)) {
366
if ($fp = fopen($cache_filename, 'r')) {
369
$data .= fread($fp, 2048);
372
$mp_rss = unserialize($data);
373
if (empty($mp_rss)) {
374
$this->caching = false;
375
return $this->init();
376
} else if (isset($mp_rss['feed_url'])) {
377
$this->rss_url = $mp_rss['feed_url'];
378
return $this->init();
380
$this->data = $mp_rss;
384
$this->caching = false;
385
return $this->init();
389
$mp_rss = $this->get_file($this->rss_url);
391
// Check if file is a feed or a webpage
392
// If it's a webpage, auto-discover the feed and re-pass it to init()
393
$discovery = $this->rss_locator($mp_rss, $this->rss_url);
395
if ($discovery != $this->rss_url) {
396
$this->rss_url = $discovery;
397
if ($this->caching && substr($this->rss_url, 0, 7) == 'http://') {
398
if ($this->is_writeable_createable($cache_filename)) {
399
$fp = fopen($cache_filename, 'w');
400
fwrite($fp, serialize(array('feed_url' => $discovery)));
403
else trigger_error("$cache_filename is not writeable", E_USER_WARNING);
405
return $this->init();
408
$this->sp_error("A feed could not be found at $this->rss_url", E_USER_WARNING, __FILE__, __LINE__);
412
// Trim out any whitespace at the beginning or the end of the file
413
$mp_rss = trim($mp_rss);
416
// Attempt to support everything from libiconv (http://www.gnu.org/software/libiconv/)
417
// Support everything from mbstring (http://www.php.net/manual/en/ref.mbstring.php#mbstring.supported-encodings)
419
$use_mbstring = false;
421
if (preg_match('/encoding=["|\'](.*)["|\']/Ui', $mp_rss, $encoding)) {
423
switch (strtolower($encoding[1])) {
429
$use_mbstring = true;
436
$use_mbstring = true;
442
$encoding = 'ARMSCII-8';
449
$encoding = 'US-ASCII';
451
$use_mbstring = true;
458
$encoding = 'BASE64';
459
$use_mbstring = true;
462
// Big5 - Traditional Chinese, mainly used in Taiwan
467
$use_mbstring = true;
470
// Big5 with Hong Kong extensions, Traditional Chinese
472
$encoding = 'BIG5-HKSCS';
474
$use_mbstring = true;
479
$encoding = 'byte2be';
480
$use_mbstring = true;
485
$encoding = 'byte2le';
486
$use_mbstring = true;
491
$encoding = 'byte4be';
492
$use_mbstring = true;
497
$encoding = 'byte4le';
498
$use_mbstring = true;
504
$encoding = 'EUC-CN';
506
$use_mbstring = true;
512
$encoding = 'EUC-JISX0213';
519
$encoding = 'EUC-JP';
521
$use_mbstring = true;
528
$encoding = 'EUCJP-win';
530
$use_mbstring = true;
536
$encoding = 'EUC-KR';
538
$use_mbstring = true;
544
$encoding = 'EUC-TW';
546
$use_mbstring = true;
549
// GB18030 - Simplified Chinese, national standard character set
552
$encoding = 'GB18030';
556
// GB2312 - Simplified Chinese, national standard character set
559
$encoding = 'GB2312';
560
$use_mbstring = true;
570
case 'georgian-academy':
571
$encoding = 'Georgian-Academy';
577
$encoding = 'Georgian-PS';
582
case 'html-entities':
584
$encoding = 'HTML-ENTITIES';
585
$use_mbstring = true;
592
$use_mbstring = true;
599
$encoding = 'ISO-2022-CN';
604
case 'iso-2022-cn-ext':
605
case 'iso2022-cn-ext':
606
case 'iso2022cn-ext':
608
$encoding = 'ISO-2022-CN';
616
$encoding = 'ISO-2022-JP';
618
$use_mbstring = true;
622
case 'iso-2022-jp-1':
626
$encoding = 'ISO-2022-JP-1';
631
case 'iso-2022-jp-2':
635
$encoding = 'ISO-2022-JP-2';
640
case 'iso-2022-jp-3':
644
$encoding = 'ISO-2022-JP-3';
652
$encoding = 'ISO-2022-KR';
654
$use_mbstring = true;
660
$encoding = 'ISO-8859-1';
662
$use_mbstring = true;
669
$encoding = 'ISO-8859-2';
671
$use_mbstring = true;
677
$encoding = 'ISO-8859-3';
679
$use_mbstring = true;
685
$encoding = 'ISO-8859-4';
687
$use_mbstring = true;
693
$encoding = 'ISO-8859-5';
695
$use_mbstring = true;
701
$encoding = 'ISO-8859-6';
703
$use_mbstring = true;
709
$encoding = 'ISO-8859-7';
711
$use_mbstring = true;
717
$encoding = 'ISO-8859-8';
719
$use_mbstring = true;
725
$encoding = 'ISO-8859-9';
727
$use_mbstring = true;
733
$encoding = 'ISO-8859-10';
735
$use_mbstring = true;
738
// mbstring/iconv functions don't appear to support 11 & 12
743
$encoding = 'ISO-8859-13';
745
$use_mbstring = true;
751
$encoding = 'ISO-8859-14';
753
$use_mbstring = true;
759
$encoding = 'ISO-8859-15';
761
$use_mbstring = true;
767
$encoding = 'ISO-8859-16';
774
$use_mbstring = true;
786
$encoding = 'KOI8-R';
788
$use_mbstring = true;
794
$encoding = 'KOI8-T';
801
$encoding = 'KOI8-U';
808
$encoding = 'KOI8-RU';
812
// Macintosh (Mac OS Classic)
814
$encoding = 'Macintosh';
818
// MacArabic (Mac OS Classic)
820
$encoding = 'MacArabic';
824
// MacCentralEurope (Mac OS Classic)
825
case 'maccentraleurope':
826
$encoding = 'MacCentralEurope';
830
// MacCroatian (Mac OS Classic)
832
$encoding = 'MacCroatian';
836
// MacCyrillic (Mac OS Classic)
838
$encoding = 'MacCyrillic';
842
// MacGreek (Mac OS Classic)
844
$encoding = 'MacGreek';
848
// MacHebrew (Mac OS Classic)
850
$encoding = 'MacHebrew';
854
// MacIceland (Mac OS Classic)
856
$encoding = 'MacIceland';
860
// MacRoman (Mac OS Classic)
862
$encoding = 'MacRoman';
866
// MacRomania (Mac OS Classic)
868
$encoding = 'MacRomania';
872
// MacThai (Mac OS Classic)
874
$encoding = 'MacThai';
878
// MacTurkish (Mac OS Classic)
880
$encoding = 'MacTurkish';
884
// MacUkraine (Mac OS Classic)
886
$encoding = 'MacUkraine';
893
$encoding = 'MuleLao-1';
901
$encoding = 'Shift_JIS';
903
$use_mbstring = true;
907
case 'shift-jisx0213':
908
case 'shiftjisx0213':
909
$encoding = 'Shift_JISX0213';
916
case 'shift_jis-win':
917
$encoding = 'SJIS-win';
919
$use_mbstring = true;
930
$encoding = 'TDS565';
937
$encoding = 'TIS-620';
939
$use_mbstring = true;
949
$use_mbstring = true;
957
$encoding = 'UCS-2BE';
959
$use_mbstring = true;
967
$encoding = 'UCS-2LE';
969
$use_mbstring = true;
973
case 'ucs-2-internal':
975
$encoding = 'UCS-2-INTERNAL';
986
$use_mbstring = true;
994
$encoding = 'UCS-4BE';
996
$use_mbstring = true;
1004
$encoding = 'UCS-4LE';
1006
$use_mbstring = true;
1010
case 'ucs-4-internal':
1011
case 'ucs4internal':
1012
$encoding = 'UCS-4-INTERNAL';
1019
$encoding = 'UCS-16';
1021
$use_mbstring = true;
1027
$encoding = 'UCS-16BE';
1029
$use_mbstring = true;
1035
$encoding = 'UCS-16LE';
1037
$use_mbstring = true;
1043
$encoding = 'UCS-32';
1045
$use_mbstring = true;
1051
$encoding = 'UCS-32BE';
1053
$use_mbstring = true;
1059
$encoding = 'UCS-32LE';
1061
$use_mbstring = true;
1067
$encoding = 'UTF-7';
1069
$use_mbstring = true;
1076
$encoding = 'UTF7-IMAP';
1077
$use_mbstring = true;
1080
// VISCII - Vietnamese ASCII
1082
$encoding = 'VISCII';
1086
// Windows-specific Central & Eastern Europe
1088
case 'windows-1250':
1091
$encoding = 'Windows-1250';
1095
// Windows-specific Cyrillic
1097
case 'windows-1251':
1100
$encoding = 'Windows-1251';
1102
$use_mbstring = true;
1105
// Windows-specific Western Europe
1107
case 'windows-1252':
1109
$encoding = 'Windows-1252';
1111
$use_mbstring = true;
1114
// Windows-specific Greek
1116
case 'windows-1253':
1118
$encoding = 'Windows-1253';
1122
// Windows-specific Turkish
1124
case 'windows-1254':
1126
$encoding = 'Windows-1254';
1130
// Windows-specific Hebrew
1132
case 'windows-1255':
1134
$encoding = 'Windows-1255';
1138
// Windows-specific Arabic
1140
case 'windows-1256':
1142
$encoding = 'Windows-1256';
1146
// Windows-specific Baltic
1148
case 'windows-1257':
1150
$encoding = 'Windows-1257';
1154
// Windows-specific Vietnamese
1156
case 'windows-1258':
1158
$encoding = 'Windows-1258';
1164
$encoding = 'UTF-8';
1168
$mp_rss = preg_replace ('/<\?xml(.*)( standalone="no")(.*)\?>/msiU', '<?xml\\1\\3?>', $mp_rss, 1);
1169
$mp_rss = preg_replace ('/<\?xml(.*)\?>/msiU', '<?xml\\1 encoding="UTF-8"?>', $mp_rss, 1);
1170
preg_match('/encoding=["|\'](.*)["|\']/Ui', $mp_rss, $match);
1172
$use_mbstring = true;
1174
$encoding = 'UTF-8';
1176
$this->encoding = $encoding;
1178
// If function is available and able, convert characters to UTF-8, and overwrite $this->encoding
1179
if (function_exists('iconv') && $use_iconv && iconv($encoding, 'UTF-8', $mp_rss)) {
1180
$mp_rss = iconv($encoding, 'UTF-8//TRANSLIT', $mp_rss);
1181
$mp_rss = str_replace ($match[0], 'encoding="UTF-8"', $mp_rss);
1182
$this->encoding = 'UTF-8';
1184
else if (function_exists('mb_convert_encoding') && $use_mbstring) {
1185
$mp_rss = mb_convert_encoding($mp_rss, 'UTF-8', $encoding);
1186
$mp_rss = str_replace ($match[0], 'encoding="UTF-8"', $mp_rss);
1187
$this->encoding = 'UTF-8';
1189
else if (($use_mbstring || $use_iconv) && $utf8_fail) {
1190
$this->encoding = 'UTF-8';
1191
$mp_rss = str_replace ($match[0], 'encoding="UTF-8"', $mp_rss);
1193
$mp_rss = preg_replace('/<(.*)>[\s]*<\!\[CDATA\[/msiU', '<\\1 spencoded="false"><![CDATA[', $mp_rss); // Add an internal attribute to CDATA sections
1194
$mp_rss = str_replace(']] spencoded="false">', ']]>', $mp_rss); // Remove it when we're on the end of a CDATA block (therefore making it ill-formed)
1197
if (preg_match('/<rdf:rdf/i', $mp_rss) || preg_match('/<rss/i', $mp_rss)) {
1198
$sp_elements = array(
1204
$sp_elements = array(
1214
foreach ($sp_elements as $full) {
1215
// The (<\!\[CDATA\[)? never matches any CDATA block, therefore the CDATA gets added, but never replaced
1216
$mp_rss = preg_replace("/<$full(.*)>[\s]*(<\!\[CDATA\[)?(.*)(]]>)?[\s]*<\/$full>/msiU", "<$full\\1><![CDATA[\\3]]></$full>", $mp_rss);
1217
// The following line is a work-around for the above bug
1218
$mp_rss = preg_replace("/<$full(.*)><\!\[CDATA\[[\s]*<\!\[CDATA\[/msiU", "<$full\\1><![CDATA[", $mp_rss);
1219
// Deal with CDATA within CDATA (this can be caused by us inserting CDATA above)
1220
$mp_rss = preg_replace_callback("/<($full)(.*)><!\[CDATA\[(.*)\]\]><\/$full>/msiU", array(&$this, 'cdata_in_cdata'), $mp_rss);
1223
// If XML Dump is enabled, send feed to the page and quit.
1224
if ($this->xml_dump) {
1225
header("Content-type: text/xml; charset=" . $this->encoding);
1230
$this->xml = xml_parser_create_ns($this->encoding);
1231
$this->namespaces = array('xml' => 'HTTP://WWW.W3.ORG/XML/1998/NAMESPACE', 'atom' => 'ATOM', 'rss2' => 'RSS', 'rdf' => 'RDF', 'rss1' => 'RSS', 'dc' => 'DC', 'xhtml' => 'XHTML', 'content' => 'CONTENT');
1232
xml_parser_set_option($this->xml, XML_OPTION_SKIP_WHITE, 1);
1233
xml_set_object($this->xml, $this);
1234
xml_set_character_data_handler($this->xml, 'dataHandler');
1235
xml_set_element_handler($this->xml, 'startHandler', 'endHandler');
1236
xml_set_start_namespace_decl_handler($this->xml, 'startNameSpace');
1237
xml_set_end_namespace_decl_handler($this->xml, 'endNameSpace');
1238
if (xml_parse($this->xml, $mp_rss))
1240
xml_parser_free($this->xml);
1241
$this->parse_xml_data_array();
1242
$this->data['feedinfo']['encoding'] = $this->encoding;
1243
if ($this->order_by_date && !empty($this->data['items'])) {
1244
usort($this->data['items'], create_function('$a,$b', 'if ($a->date == $b->date) return 0; return ($a->date < $b->date) ? 1 : -1;'));
1246
if ($this->caching && substr($this->rss_url, 0, 7) == 'http://') {
1247
if ($this->is_writeable_createable($cache_filename)) {
1248
$fp = fopen($cache_filename, 'w');
1249
fwrite($fp, serialize($this->data));
1252
else trigger_error("$cache_filename is not writeable", E_USER_WARNING);
1258
$this->sp_error(sprintf('XML error: %s at line %d, column %d', xml_error_string(xml_get_error_code($this->xml)), xml_get_current_line_number($this->xml), xml_get_current_column_number($this->xml)), E_USER_WARNING, __FILE__, __LINE__);
1259
xml_parser_free($this->xml);
1260
$this->data = array();
1273
/****************************************************
1274
SIMPLEPIE ERROR (internal function)
1275
****************************************************/
1276
function sp_error($message, $level, $file, $line) {
1277
$this->error = $message;
1280
$note = 'PHP Error';
1282
case E_USER_WARNING:
1283
$note = 'PHP Warning';
1286
$note = 'PHP Notice';
1289
$note = 'Unknown Error';
1292
error_log("$note: $message in $file on line $line", 0);
1298
/****************************************************
1300
****************************************************/
1301
function get_encoding() {
1302
if (isset($this->encoding)) {
1303
return $this->encoding;
1304
} else if (isset($this->data['feedinfo']['encoding'])) {
1305
return $this->data['feedinfo']['encoding'];
1306
} else return false;
1309
function handle_content_type($mime='text/html') {
1310
if (!headers_sent() && $this->get_encoding()) header('Content-type: ' . $mime . '; charset=' . $this->get_encoding());
1316
/****************************************************
1317
GET FEED VERSION NUMBER
1318
****************************************************/
1319
function get_version() {
1320
if (isset($this->data['feedinfo'])) {
1321
return (isset($this->data['feedinfo']['version'])) ? $this->data[feedinfo][type] . ' ' . $this->data[feedinfo][version] : $this->data['feedinfo']['type'];
1329
/****************************************************
1331
This allows people to subscribe to the feed in various services.
1332
****************************************************/
1333
function subscribe_url() {
1334
return (empty($this->rss_url)) ? false : $this->fix_protocol($this->rss_url, 1);
1337
function subscribe_feed() {
1338
return (empty($this->rss_url)) ? false : $this->fix_protocol($this->rss_url, 2);
1341
function subscribe_podcast() {
1342
return (empty($this->rss_url)) ? false : $this->fix_protocol($this->rss_url, 3);
1345
function subscribe_aol() {
1346
return (empty($this->rss_url)) ? false : 'http://feeds.my.aol.com/add.jsp?url=' . rawurlencode($this->subscribe_url());
1349
function subscribe_bloglines() {
1350
return (empty($this->rss_url)) ? false : 'http://www.bloglines.com/sub/' . rawurlencode($this->subscribe_url());
1353
function subscribe_google() {
1354
return (empty($this->rss_url)) ? false : 'http://fusion.google.com/add?feedurl=' . rawurlencode($this->subscribe_url());
1357
function subscribe_msn() {
1358
return (empty($this->rss_url)) ? false : 'http://my.msn.com/addtomymsn.armx?id=rss&ut=' . rawurlencode($this->subscribe_url()) . '&ru=' . rawurlencode($this->get_feed_link());
1361
function subscribe_netvibes() {
1362
return (empty($this->rss_url)) ? false : 'http://www.netvibes.com/subscribe.php?url=' . rawurlencode($this->subscribe_url());
1365
function subscribe_newsburst() {
1366
return (empty($this->rss_url)) ? false : 'http://www.newsburst.com/Source/?add=' . rawurlencode($this->subscribe_url());
1369
function subscribe_newsgator() {
1370
return (empty($this->rss_url)) ? false : 'http://www.newsgator.com/ngs/subscriber/subext.aspx?url=' . rawurlencode($this->subscribe_url());
1373
function subscribe_odeo() {
1374
return (empty($this->rss_url)) ? false : 'http://www.odeo.com/listen/subscribe?feed=' . rawurlencode($this->subscribe_url());
1377
function subscribe_pluck() {
1378
return (empty($this->rss_url)) ? false : 'http://client.pluck.com/pluckit/prompt.aspx?GCID=C12286x053&a=' . rawurlencode($this->subscribe_url());
1381
function subscribe_podnova() {
1382
return (empty($this->rss_url)) ? false : 'http://www.podnova.com/index_your_podcasts.srf?action=add&url=' . rawurlencode($this->subscribe_url());
1385
function subscribe_rojo() {
1386
return (empty($this->rss_url)) ? false : 'http://www.rojo.com/add-subscription?resource=' . rawurlencode($this->subscribe_url());
1389
function subscribe_yahoo() {
1390
return (empty($this->rss_url)) ? false : 'http://add.my.yahoo.com/rss?url=' . rawurlencode($this->subscribe_url());
1396
/****************************************************
1397
PARSE OUT GENERAL FEED-RELATED DATA
1398
****************************************************/
1399
// Reads the feed's title
1400
function get_feed_title() {
1401
return (isset($this->data['info']['title'])) ? $this->data['info']['title'] : false;
1404
// Reads the feed's link (URL)
1405
function get_feed_link() {
1406
return (isset($this->data['info']['link'][0])) ? $this->data['info']['link'][0] : false;
1409
// Reads the feed's link (URL)
1410
function get_feed_links($key) {
1411
return (isset($this->data['info']['link'][$key])) ? $this->data['info']['link'][$key] : false;
1414
// Reads the feed's description
1415
function get_feed_description() {
1416
return (isset($this->data['info']['description'])) ? $this->data['info']['description'] : false;
1419
// Reads the feed's copyright information.
1420
function get_feed_copyright() {
1421
return (isset($this->data['info']['copyright'])) ? $this->data['info']['copyright'] : false;
1424
// Reads the feed's language
1425
function get_feed_language() {
1426
return (isset($this->data['info']['language'])) ? $this->data['info']['language'] : false;
1432
/****************************************************
1433
PARSE OUT IMAGE-RELATED DATA
1434
Apparently Atom doesn't have feed images.
1435
****************************************************/
1436
// Check if an image element exists (returns true/false)
1437
function get_image_exist() {
1438
return (isset($this->data['info']['image']['url'])) ? true : false;
1441
// Get the image title (to be used in alt and/or title)
1442
function get_image_title() {
1443
return (isset($this->data['info']['image']['title'])) ? $this->data['info']['image']['title'] : false;
1446
// The path to the actual image
1447
function get_image_url() {
1448
return (isset($this->data['info']['image']['url'])) ? $this->data['info']['image']['url'] : false;
1451
// The URL that the image is supposed to link to.
1452
function get_image_link() {
1453
return (isset($this->data['info']['image']['link'])) ? $this->data['info']['image']['link'] : false;
1456
// Get the image width
1457
function get_image_width() {
1458
return (isset($this->data['info']['image']['width'])) ? $this->data['info']['image']['width'] : false;
1461
// Get the image height
1462
function get_image_height() {
1463
return (isset($this->data['info']['image']['height'])) ? $this->data['info']['image']['height'] : false;
1469
/****************************************************
1470
PARSE OUT ITEM-RELATED DATA
1471
****************************************************/
1472
// Get the size of the array of items (for use in a for-loop)
1473
function get_item_quantity($max=0) {
1474
$qty = (isset($this->data['items'])) ? sizeof($this->data['items']) : 0;
1475
if ($max != 0) return ($qty > $max) ? $max : $qty;
1479
function get_item($key) {
1480
return $this->data['items'][$key];
1483
function get_items($start = 0, $end = 0) {
1484
return ($end == 0) ? array_slice($this->data['items'], $start) : array_slice($this->data['items'], $start, $end);
1490
/****************************************************
1492
Convert feed:// and no-protocol URL's to http://
1493
Feed is allowed to have no protocol. Local files are toggled in init().
1494
This is an internal function and is not intended to be used publically.
1496
$http=1, http://www.domain.com/feed.xml (absolute)
1497
$http=2, feed://www.domain.com/feed.xml (absolute)
1498
$http=3, podcast://www.domain.com/feed.xml (absolute)
1499
****************************************************/
1500
function fix_protocol($mp_feed_proto, $http = 1) {
1501
$url = $mp_feed_proto;
1503
$url = preg_replace('/feed:(\/\/)?(http:\/\/)?/i', 'http://', $url);
1504
$url = preg_replace('/(feed:)?(\/\/)?https:\/\//i', 'https://', $url);
1505
$url = preg_replace('/p(od)?cast:(\/\/)?(http:\/\/)?/i', 'http://', $url);
1506
$url = preg_replace('/(p(od)?cast:)?(\/\/)?https:\/\//i', 'https://', $url);
1507
if (!stristr($url, 'http://') && !stristr($url, 'https://') && !file_exists($url)) $url = "http://$url";
1509
if ($http == 1) return $url;
1510
else if ($http == 2) {
1511
if (strstr($url, 'http://')) {
1512
$url = substr_replace($url, 'feed', 0, 4);
1517
else if ($http == 3) {
1518
if (strstr($url, 'http://')) {
1519
$url = substr_replace($url, 'podcast', 0, 4);
1529
/****************************************************
1530
ULTRA-LIBERAL FEED LOCATOR
1531
Based upon http://diveintomark.org/archives/2002/08/15/ultraliberal_rss_locator
1532
This function enables support for RSS auto-discovery-on-crack.
1533
****************************************************/
1534
function rss_locator($data, $url) {
1537
$this->parsed_url = parse_url($url);
1538
if (!isset($this->parsed_url['path'])) {
1539
$this->parsed_url['path'] = '/';
1542
// Check is the URL we're given is a feed
1543
if ($this->is_feed($data, false)) {
1547
// Feeds pointed to by LINK tags in the header of the page (autodiscovery)
1548
$stage1 = $this->check_link_elements($data);
1553
// Grab all the links in the page, and put them into two arrays (local, and external)
1554
if ($this->get_links($data)) {
1556
// <A> links to feeds on the same server ending in ".rss", ".rdf", ".xml", or ".atom"
1557
$stage2 = $this->check_link_extension($this->local);
1562
// <A> links to feeds on the same server containing "rss", "rdf", "xml", or "atom"
1563
$stage3 = $this->check_link_body($this->local);
1568
// <A> links to feeds on external servers ending in ".rss", ".rdf", ".xml", or ".atom"
1569
$stage4 = $this->check_link_extension($this->elsewhere);
1574
// <A> links to feeds on external servers containing "rss", "rdf", "xml", or "atom"
1575
$stage5 = $this->check_link_body($this->elsewhere);
1584
function check_link_elements($data) {
1585
if (preg_match_all('/<link (.*)>/siU', $data, $matches)) {
1586
foreach($matches[1] as $match) {
1587
if (preg_match('/type=[\'|"]?(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)[\'|"]?/iU', $match, $type)) {
1588
$href = $this->get_attribute($match, 'href');
1589
if (!empty($href[1])) {
1590
$href = $this->absolutize_url($href[1], $this->parsed_url);
1591
if ($this->is_feed($href)) {
1597
} else return false;
1600
function check_link_extension($array) {
1601
foreach ($array as $value) {
1602
$parsed = @parse_url($value);
1603
if (isset($parsed['path'])) {
1604
$ext = strtolower(pathinfo($parsed['path'], PATHINFO_EXTENSION));
1605
if (($ext == 'rss' || $ext == 'rdf' || $ext == 'xml' || $ext == 'atom') && $this->is_feed($value)) {
1606
return $this->absolutize_url($value, $this->parsed_url);
1613
function check_link_body($array) {
1614
foreach ($array as $value) {
1615
$value2 = @parse_url($value);
1616
if (!empty($value2['path'])) {
1617
if (strlen(pathinfo($value2['path'], PATHINFO_EXTENSION)) > 0) {
1618
$value3 = substr_replace($value, '', strpos($value, $value2['path'])+strpos($value2['path'], pathinfo($value2['path'], PATHINFO_EXTENSION))-1, strlen(pathinfo($value2['path'], PATHINFO_EXTENSION))+1);
1622
if ((stristr($value3, 'rss') || stristr($value3, 'rdf') || stristr($value3, 'xml') || stristr($value3, 'atom') || stristr($value3, 'feed')) && $this->is_feed($value)) {
1623
return $this->absolutize_url($value, $this->parsed_url);
1630
function get_links($data) {
1631
if (preg_match_all('/href="(.*)"/iU', $data, $matches)) {
1632
$this->parse_links($matches);
1634
if (preg_match_all('/href=\'(.*)\'/iU', $data, $matches)) {
1635
$this->parse_links($matches);
1637
if (preg_match_all('/href=(.*)[ |\/|>]/iU', $data, $matches)) {
1638
foreach ($matches[1] as $key => $value) {
1639
if (substr($value, 0, 1) == '"' || substr($value, 0, 1) == "'") {
1640
unset($matches[1][$key]);
1643
$this->parse_links($matches);
1645
if (!empty($this->local) || !empty($this->elsewhere)) {
1646
$this->local = array_unique($this->local);
1647
$this->elsewhere = array_unique($this->elsewhere);
1649
} else return false;
1652
function parse_links($matches) {
1653
foreach ($matches[1] as $match) {
1654
if (strtolower(substr($match, 0, 11)) != 'javascript:') {
1655
$parsed = @parse_url($match);
1656
if (!isset($parsed['host']) || $parsed['host'] == $this->parsed_url['host']) {
1657
$this->local[] = $this->absolutize_url($match, $this->parsed_url);
1659
$this->elsewhere[] = $this->absolutize_url($match, $this->parsed_url);
1665
function is_feed($data, $is_url = true) {
1667
$data = $this->get_file($data);
1669
if (stristr($data, '<!DOCTYPE HTML')) {
1672
else if (stristr($data, '<rss') || stristr($data, '<rdf:RDF') || preg_match('/<([a-z0-9]+\:)?feed/mi', $data)) {
1679
function absolutize_url($href, $location) {
1680
@$href_parts = parse_url($href);
1681
if (!empty($href_parts['scheme'])) {
1684
if (isset($location['host'])) {
1685
$full_url = $location['scheme'] . '://' . $location['host'];
1689
if (isset($location['port'])) {
1690
$full_url .= ':' . $location['port'];
1692
if (!empty($href_parts['path'])) {
1693
if (substr($href_parts['path'], 0, 1) == '/') {
1694
$full_url .= $href_parts['path'];
1695
} else if (!empty($location['path'])) {
1696
$full_url .= dirname($location['path'] . 'a') . '/' . $href_parts['path'];
1698
$full_url .= $href_parts['path'];
1700
} else if (!empty($location['path'])) {
1701
$full_url .= $location['path'];
1705
if (!empty($href_parts['query'])) {
1706
$full_url .= '?' . $href_parts['query'];
1707
} else if (!empty($location['query'])) {
1708
$full_url .= '?' . $location['query'];
1710
if (!empty($href_parts['fragment'])) {
1711
$full_url .= '#' . $href_parts['fragment'];
1712
} else if (!empty($location['fragment'])) {
1713
$full_url .= '#' . $location['fragment'];
1722
/****************************************************
1724
Some websites have a setting that blocks images from being loaded
1725
into other pages. This gets around those blocks by spoofing the referrer.
1726
****************************************************/
1727
function display_image($image_url) {
1728
$image = $this->get_file(urldecode($image_url));
1729
$suffix = pathinfo($image_url, PATHINFO_EXTENSION);
1747
$mime='image/pipeg';
1760
header('Content-type: ' . $mime);
1769
/****************************************************
1770
DELETE OUTDATED CACHE FILES
1771
Copyright 2004 by "adam at roomvoter dot com". This material
1772
may be distributed only subject to the terms and conditions set
1773
forth in the Open Publication License, v1.0 or later (the latest
1774
version is presently available at http://www.opencontent.org/openpub/).
1775
This function deletes cache files that have not been used in a hour.
1776
****************************************************/
1777
function clear_cache($path, $max_minutes=60) {
1778
if (is_dir($path) ) {
1779
$handle = opendir($path);
1780
while (false !== ($file = readdir($handle))) {
1781
if ($file != '.' && $file != '..' && pathinfo($file, PATHINFO_EXTENSION) == 'spc') {
1782
$diff = (time() - filemtime("$path/$file"))/60;
1783
if ($diff > $max_minutes) unlink("$path/$file");
1793
/****************************************************
1794
OPENS A FILE, WITH EITHER FOPEN OR CURL
1795
****************************************************/
1796
function get_file($url) {
1797
if (substr($url, 0, 7) == 'http://' && extension_loaded('curl')) {
1799
curl_setopt ($gch, CURLOPT_URL, $url);
1800
curl_setopt ($gch, CURLOPT_HEADER, 0);
1801
curl_setopt ($gch, CURLOPT_FOLLOWLOCATION, 1);
1802
curl_setopt ($gch, CURLOPT_TIMEOUT, 10);
1803
curl_setopt ($gch, CURLOPT_RETURNTRANSFER, 1);
1804
curl_setopt ($gch, CURLOPT_REFERER, $url);
1805
curl_setopt ($gch, CURLOPT_USERAGENT, $this->useragent);
1806
$data = curl_exec ($gch);
1809
$old_ua = ini_get('user_agent');
1810
ini_set('user_agent', $this->useragent);
1811
if ($fp = fopen($url, 'r')) {
1812
stream_set_blocking($fp, false);
1813
stream_set_timeout($fp, 10);
1814
$status = socket_get_status($fp);
1816
while (!feof($fp) && !$status['timed_out']) {
1817
$data .= fread($fp, 2048);
1818
$status = socket_get_status($fp);
1820
if ($status['timed_out'])
1823
} else return false;
1824
ini_set('user_agent', $old_ua);
1832
/****************************************************
1833
CHECKS IF A FILE IS WRITEABLE, OR CREATEABLE
1834
****************************************************/
1835
function is_writeable_createable($file) {
1836
if (file_exists($file))
1837
return is_writeable($file);
1839
return is_writeable(dirname($file));
1845
/****************************************************
1847
****************************************************/
1848
function get_attribute($data, $attribute_name) {
1849
if (preg_match("/$attribute_name='(.*)'/iU", $data, $match)) {
1851
} else if (preg_match("/$attribute_name=\"(.*)\"/iU", $data, $match)) {
1853
} else if (preg_match("/$attribute_name=(.*)[ |\/|>]/iU", $data, $match)) {
1861
/****************************************************
1862
CALLBACK FUNCTION TO DEAL WITH CDATA WITHIN CDATA
1863
****************************************************/
1864
function cdata_in_cdata($match) {
1865
$match[3] = preg_replace_callback('/<!\[CDATA\[(.*)\]\]>/msiU', array(&$this, 'real_cdata_in_cdata'), $match[3]);
1866
return "<$match[1]$match[2]><![CDATA[$match[3]]]></$match[1]>";
1872
/****************************************************
1873
CALLBACK FUNCTION TO REALLY DEAL WITH CDATA WITHIN CDATA
1874
****************************************************/
1875
function real_cdata_in_cdata($match) {
1876
return htmlentities($match[1], ENT_NOQUOTES, $this->encoding);
1882
/****************************************************
1884
****************************************************/
1885
function do_add_content(&$array, $data) {
1886
if ($this->is_first) {
1887
$array['data'] = $data;
1888
$array['attribs'] = $this->attribs;
1889
} else $array['data'] .= $data;
1895
/****************************************************
1897
****************************************************/
1898
function parse_xml_data_array() {
1899
// Feed level xml:base
1900
if (!empty($this->xmldata['feeddata']['attribs']['XML:BASE'])) {
1901
$this->feed_xmlbase = parse_url($this->xmldata['feeddata']['attribs']['XML:BASE']);
1903
else if (!empty($this->xmldata['feeddata']['attribs'][$this->namespaces['xml'] . ':BASE'])) {
1904
$this->feed_xmlbase = parse_url($this->xmldata['feeddata']['attribs'][$this->namespaces['xml'] . ':BASE']);
1906
else if (substr($this->rss_url, 0, 28) == 'http://feeds.feedburner.com/' && !empty($this->xmldata['info']['link'][0]['data'])) {
1907
$this->feed_xmlbase = parse_url($this->xmldata['info']['link'][0]['data']);
1909
$this->feed_xmlbase = $this->parsed_url;
1913
if (isset($this->xmldata['feedinfo']['type'])) {
1914
$this->data['feedinfo'] = $this->xmldata['feedinfo'];
1918
if (!empty($this->xmldata['info']['title']['data'])) {
1919
$this->data['info']['title'] = $this->sanitise($this->xmldata['info']['title']['data'], $this->xmldata['info']['title']['attribs']);
1923
if (!empty($this->xmldata['info']['link'])) {
1924
foreach ($this->xmldata['info']['link'] as $num => $link) {
1925
if (empty($link['attribs']['REL']) || $link['attribs']['REL'] == 'alternate') {
1926
if (empty($link['data'])) {
1927
$this->data['info']['link'][$num] = $this->sanitise($link['attribs']['HREF'], $link['attribs'], true);
1929
$this->data['info']['link'][$num] = $this->sanitise($link['data'], $link['attribs'], true);
1936
if (!empty($this->xmldata['info']['description']['data'])) {
1937
$this->data['info']['description'] = $this->sanitise($this->xmldata['info']['description']['data'], $this->xmldata['info']['description']['attribs']);
1939
else if (!empty($this->xmldata['info']['dc:description']['data'])) {
1940
$this->data['info']['description'] = $this->sanitise($this->xmldata['info']['dc:description']['data'], $this->xmldata['info']['dc:description']['attribs']);
1942
else if (!empty($this->xmldata['info']['tagline']['data'])) {
1943
$this->data['info']['description'] = $this->sanitise($this->xmldata['info']['tagline']['data'], $this->xmldata['info']['tagline']['attribs']);
1945
else if (!empty($this->xmldata['info']['subtitle']['data'])) {
1946
$this->data['info']['description'] = $this->sanitise($this->xmldata['info']['subtitle']['data'], $this->xmldata['info']['subtitle']['attribs']);
1950
if (!empty($this->xmldata['info']['language']['data'])) {
1951
$this->data['info']['language'] = $this->sanitise($this->xmldata['info']['language']['data'], $this->xmldata['info']['language']['attribs']);
1955
if (!empty($this->xmldata['info']['copyright']['data'])) {
1956
$this->data['info']['copyright'] = $this->sanitise($this->xmldata['info']['copyright']['data'], $this->xmldata['info']['copyright']['attribs']);
1960
if (!empty($this->xmldata['info']['image']['title']['data'])) {
1961
$this->data['info']['image']['title'] = $this->sanitise($this->xmldata['info']['image']['title']['data'], $this->xmldata['info']['image']['title']['attribs']);
1963
if (!empty($this->xmldata['info']['image']['url']['data'])) {
1964
$this->data['info']['image']['url'] = $this->sanitise($this->xmldata['info']['image']['url']['data'], $this->xmldata['info']['image']['url']['attribs'], true);
1966
else if (!empty($this->xmldata['info']['logo']['data'])) {
1967
$this->data['info']['image']['url'] = $this->sanitise($this->xmldata['info']['logo']['data'], $this->xmldata['info']['logo']['attribs'], true);
1969
if (!empty($this->xmldata['info']['image']['link']['data'])) {
1970
$this->data['info']['image']['link'] = $this->sanitise($this->xmldata['info']['image']['link']['data'], $this->xmldata['info']['image']['link']['attribs'], true);
1972
if (!empty($this->xmldata['info']['image']['width']['data'])) {
1973
$this->data['info']['image']['width'] = $this->sanitise($this->xmldata['info']['image']['width']['data'], $this->xmldata['info']['image']['width']['attribs']);
1975
if (!empty($this->xmldata['info']['image']['height']['data'])) {
1976
$this->data['info']['image']['height'] = $this->sanitise($this->xmldata['info']['image']['height']['data'], $this->xmldata['info']['image']['height']['attribs']);
1980
if (!empty($this->xmldata['items'])) {
1981
foreach ($this->xmldata['items'] as $num => $item) {
1982
// Item level xml:base
1983
if (!empty($item['attribs']['XML:BASE'])) {
1984
$this->item_xmlbase = parse_url($this->absolutize_url($item['attribs']['XML:BASE'], $this->feed_xmlbase));
1986
else if (!empty($item['attribs'][$this->namespaces['xml'] . ':BASE'])) {
1987
$this->item_xmlbase = parse_url($this->absolutize_url($item['attribs'][$this->namespaces['xml'] . ':BASE'], $this->feed_xmlbase));
1993
$description = null;
1994
$categories = array();
1998
$enclosures = array();
2001
if (!empty($item['title']['data'])) {
2002
$title = $this->sanitise($item['title']['data'], $item['title']['attribs']);
2004
else if (!empty($item['dc:title']['data'])) {
2005
$title = $this->sanitise($item['dc:title']['data'], $item['dc:title']['attribs']);
2009
if (!empty($item['content']['data'])) {
2010
$description = $this->sanitise($item['content']['data'], $item['content']['attribs']);
2012
else if (!empty($item['encoded']['data'])) {
2013
$description = $this->sanitise($item['encoded']['data'], $item['encoded']['attribs']);
2015
else if (!empty($item['summary']['data'])) {
2016
$description = $this->sanitise($item['summary']['data'], $item['summary']['attribs']);
2018
else if (!empty($item['description']['data'])) {
2019
$description = $this->sanitise($item['description']['data'], $item['description']['attribs']);
2021
else if (!empty($item['dc:description']['data'])) {
2022
$description = $this->sanitise($item['dc:description']['data'], $item['dc:description']['attribs']);
2024
else if (!empty($item['longdesc']['data'])) {
2025
$description = $this->sanitise($item['longdesc']['data'], $item['longdesc']['attribs']);
2029
if (!empty($item['link'])) {
2030
foreach ($item['link'] as $link) {
2031
if (empty($link['attribs']['REL']) || $link['attribs']['REL'] == 'alternate') {
2032
if (empty($link['data'])) {
2033
$links[sizeof($links)] = $this->sanitise($link['attribs']['HREF'], $link['attribs'], true);
2035
$links[sizeof($links)] = $this->sanitise($link['data'], $link['attribs'], true);
2037
} else if ($link['attribs']['REL'] == 'enclosure' && !empty($link['attribs']['HREF'])) {
2041
$href = $this->sanitise($link['attribs']['HREF'], $link['attribs'], true);
2042
if (!empty($link['attribs']['TYPE'])) {
2043
$type = $this->sanitise($link['attribs']['TYPE'], $link['attribs']);
2045
if (!empty($link['attribs']['LENGTH'])) {
2046
$length = $this->sanitise($link['attribs']['LENGTH'], $link['attribs']);
2048
$enclosures[] = new SimplePie_Enclosure($href, $type, $length);
2054
if (!empty($item['enclosure'])) {
2055
foreach ($item['enclosure'] as $enclosure) {
2056
if (!empty($enclosure['attribs']['URL'])) {
2060
$href = $this->sanitise($enclosure['attribs']['URL'], $enclosure['attribs'], true);
2061
if (!empty($enclosure['attribs']['TYPE'])) {
2062
$type = $this->sanitise($enclosure['attribs']['TYPE'], $enclosure['attribs']);
2064
if (!empty($enclosure['attribs']['LENGTH'])) {
2065
$length = $this->sanitise($enclosure['attribs']['LENGTH'], $enclosure['attribs']);
2067
$enclosures[] = new SimplePie_Enclosure($href, $type, $length);
2073
if (!empty($item['guid']['data'])) {
2074
if (empty($item['guid']['attribs']['ISPERMALINK']) || strtolower($item['guid']['attribs']['ISPERMALINK']) != 'false') {
2075
$links[sizeof($links)] = $this->sanitise($item['guid']['data'], $item['guid']['attribs']);
2077
$id = $this->sanitise($item['guid']['data'], $item['guid']['attribs']);
2079
else if (!empty($item['id']['data'])) {
2080
$id = $this->sanitise($item['id']['data'], $item['id']['attribs']);
2084
if (!empty($item['pubdate']['data'])) {
2085
$date = $this->parse_date($this->sanitise($item['pubdate']['data'], $item['pubdate']['attribs']));
2087
else if (!empty($item['dc:date']['data'])) {
2088
$date = $this->parse_date($this->sanitise($item['dc:date']['data'], $item['dc:date']['attribs']));
2090
else if (!empty($item['issued']['data'])) {
2091
$date = $this->parse_date($this->sanitise($item['issued']['data'], $item['issued']['attribs']));
2093
else if (!empty($item['published']['data'])) {
2094
$date = $this->parse_date($this->sanitise($item['published']['data'], $item['published']['attribs']));
2096
else if (!empty($item['modified']['data'])) {
2097
$date = $this->parse_date($this->sanitise($item['modified']['data'], $item['modified']['attribs']));
2099
else if (!empty($item['updated']['data'])) {
2100
$date = $this->parse_date($this->sanitise($item['updated']['data'], $item['updated']['attribs']));
2104
if (!empty($item['category'])) {
2105
foreach ($item['category'] as $category) {
2106
$categories[sizeof($categories)] = $this->sanitise($category['data'], $category['attribs']);
2109
if (!empty($item['subject'])) {
2110
foreach ($item['subject'] as $category) {
2111
$categories[sizeof($categories)] = $this->sanitise($category['data'], $category['attribs']);
2117
if (!empty($item['creator'])) {
2118
foreach($item['creator'] as $creator) {
2119
$authors[] = new SimplePie_Author($this->sanitise($creator['data'], $creator['attribs']), null, null);
2122
if (!empty($item['author'])) {
2123
foreach($item['author'] as $author) {
2127
if (!empty($author['name'])) {
2128
$name = $this->sanitise($author['name']['data'], $author['name']['attribs']);
2130
if (!empty($author['url'])) {
2131
$link = $this->sanitise($author['url']['data'], $author['url']['attribs'], true);
2133
else if (!empty($author['uri'])) {
2134
$link = $this->sanitise($author['uri']['data'], $author['uri']['attribs'], true);
2136
else if (!empty($author['homepage'])) {
2137
$link = $this->sanitise($author['homepage']['data'], $author['homepage']['attribs'], true);
2139
if (!empty($author['email'])) {
2140
$email = $this->sanitise($author['email']['data'], $author['email']['attribs']);
2142
if (!empty($author['rss'])) {
2143
$sane = $this->sanitise($author['rss']['data'], $author['rss']['attribs']);
2144
if (preg_match('/(.*)@(.*) \((.*)\)/msiU', $sane, $matches)) {
2145
$name = trim($matches[3]);
2146
$email = trim("$matches[1]@$matches[2]");
2151
$authors[] = new SimplePie_Author($name, $link, $email);
2154
$this->data['items'][] = new SimplePie_Item($id, $title, $description, array_unique($categories), array_unique($authors), $date, array_unique($links), array_unique($enclosures));
2157
unset($this->xmldata);
2158
} // End parse_xml_data_array();
2160
function sanitise($data, $attribs, $is_url = false) {
2161
$this->attribs = $attribs;
2162
if (isset($this->data['feedinfo']['type']) && $this->data['feedinfo']['type'] == 'Atom') {
2163
if (!empty($attribs['MODE']) && $attribs['MODE'] == 'base64') {
2164
$data = base64_decode($data);
2165
} else if ((!empty($attribs['MODE']) && $attribs['MODE'] == 'escaped' || !empty($attribs['TYPE']) && ($attribs['TYPE'] == 'html' || $attribs['TYPE'] == 'text/html')) && (empty($attribs['SPENCODED']) || $attribs['SPENCODED'] != 'false')) {
2166
$data = $this->entities_decode($data);
2168
if (!empty($attribs['TYPE']) && ($attribs['TYPE'] == 'xhtml' || $attribs['TYPE'] == 'application/xhtml+xml')) {
2169
if ($this->remove_div) {
2170
$data = preg_replace('/<div( .*)?>/msiU', '', strrev(preg_replace('/>vid\/</i', '', strrev($data), 1)), 1);
2172
$data = preg_replace('/<div( .*)?>/msiU', '<div>', $data, 1);
2174
$data = preg_replace("/<(\/)?$this->xhtml_prefix:/msiU", '<\\1', $data);
2177
if (empty($attribs['SPENCODED']) || $attribs['SPENCODED'] != 'false') {
2178
$data = $this->entities_decode($data);
2181
$data = trim($data);
2182
$data = str_replace(' spencoded="false">', '>', $data);
2184
// Strip out HTML tags and attributes that might cause various security problems.
2185
// Based on recommendations by Mark Pilgrim at:
2186
// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
2187
if ($this->strip_htmltags) {
2188
$tags_to_strip = explode(',', $this->strip_htmltags);
2189
foreach ($tags_to_strip as $tag) {
2190
if ($this->encode_instead_of_strip) {
2191
// For encoded angled brackets (do these first)
2192
$data = preg_replace('/<(!)?(\/)?'. trim($tag) .'(\w|\s|=|-|"|\'|"|:|;|%|\/|\.|\?|&|,|#|!|\+|\(|\))*>/i', '&lt;\\0&gt;', $data);
2193
$data = str_replace('&lt;<', '&lt;', $data);
2194
$data = str_replace('>&gt;', '&gt;', $data);
2196
// For angled brackets
2197
$data = preg_replace('/<(!)?(\/)?'. trim($tag) .'(\w|\s|=|-|"|\'|"|:|;|%|\/|\.|\?|&|,|#|!|\+|\(|\))*>/i', '<\\0>', $data);
2198
$data = str_replace('<<', '<', $data);
2199
$data = str_replace('>>', '>', $data);
2202
$data = preg_replace('/(<|<)(!)?(\/)?'. trim($tag) .'(\w|\s|=|-|"|\'|"|:|;|%|\/|\.|\?|&|,|#|!|\+|\(|\))*(>|>)/i', '', $data);
2207
if ($this->strip_attributes) {
2208
$attribs_to_strip = explode(',', $this->strip_attributes);
2209
foreach ($attribs_to_strip as $attrib) {
2210
$data = preg_replace('/ '. trim($attrib) .'=(\'|'|"|")?(\w|\s|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\'|'|<|>|\+|{|})*(\'|'|"|")?/i', '', $data);
2214
// Replace H1, H2, and H3 tags with the less important H4 tags.
2215
// This is because on a site, the more important headers might make sense,
2216
// but it most likely doesn't fit in the context of RSS-in-a-webpage.
2217
if ($this->replace_headers) {
2218
$data = preg_replace('/<h[1-3]( .*)?>/msiU', '<h4>', $data);
2219
$data = preg_replace('/<\/h[1-3]>/i', '</h4>', $data);
2222
// If Strip Ads is enabled, strip them.
2223
if ($this->strip_ads) {
2224
$data = preg_replace('/(<|<)a(.*)href=("|")(.*)\\/\/(www\.)?pheedo.com\/(.*).phdo\?s=(.*)(>|>)(\s*|.*)((<|<).*(>|>)|.*)(\s*|.*)(<|<)\/a(>|>)/i', '', $data); // Pheedo links (tested with Dooce.com)
2225
$data = preg_replace('/(<|<)a(\w|\s|\=|"|")*href=("|")http:\/\/ad.doubleclick.net\/(.*)(>|>)(\s*|.*)((<|<).*(>|>)|.*)(\s*|.*)(<|<)\/a(>|>)/i', '', $data); // Doubleclick links (tested with InfoWorld.com)
2226
$data = preg_replace('/(<|<)map(\w|\s|=|-|"|\'|")*name=("|\'|")google_ad_map(\w|\s|=|-)*("|\'|")(\w|\s|=|-|"|\'|")*(^gt;|>)(.*)(<|<)\/map(>|>)(<|<)img(\w|\s|=|-|"|\'|")*usemap=("|\'|")#google_ad_map(\w|\s|=|-)*("|\'|")(\w|\s|=|-|"|\'|"|:|;|\/|\.|\?|&)*(>|>)/i', '', $data); // Google AdSense for Feeds (tested with tuaw.com).
2227
// Feedflare, from Feedburner
2231
$data = $this->replace_urls($data, true);
2233
$data = preg_replace_callback('/<(.+)>/msiU', array(&$this, 'replace_urls'), $data);
2236
// If Bypass Image Hotlink is enabled, rewrite all the image tags.
2237
if ($this->bypass_image_hotlink != false) {
2238
$data = preg_replace_callback('/src=("|"|\'|')?(\w|=|-|:|;|\/|\.|\?|&|,|#|!|\(|\)|\'|')*("|"|\'|')?/', create_function('$m', 'return "src=\"".rawurlencode(str_replace("\"", "", str_replace("src=", "", html_entity_decode($m[0]))))."\"";'), $data);
2240
if ($this->bypass_image_hotlink_page != false) {
2241
$data = preg_replace('/<img(\w|\s|=|-|"|\'|"|:|;|\/|\.|\?|&|,|#|!)*src=("|"|\')?/i', '\\0'.$this->bypass_image_hotlink_page.'?i=', $data);
2243
else $data = preg_replace('/<img(\w|\s|=|-|"|\'|"|:|;|\/|\.|\?|&|,|#|!)*src=("|"|\')?/i', '\\0?i=', $data);
2249
function replace_urls($data, $raw_url = false) {
2250
if (!empty($this->attribs['XML:BASE'])) {
2251
if (!empty($this->item_xmlbase)) {
2252
$attrib_xmlbase = parse_url($this->absolutize_url($this->attribs['XML:BASE'], $this->item_xmlbase));
2254
$attrib_xmlbase = parse_url($this->absolutize_url($this->attribs['XML:BASE'], $this->feed_xmlbase));
2257
else if (!empty($this->attribs[$this->namespaces['xml'] . ':BASE'])) {
2258
if (!empty($this->item_xmlbase)) {
2259
$attrib_xmlbase = parse_url($this->absolutize_url($this->attribs[$this->namespaces['xml'] . ':BASE'], $this->item_xmlbase));
2261
$attrib_xmlbase = parse_url($this->absolutize_url($this->attribs[$this->namespaces['xml'] . ':BASE'], $this->feed_xmlbase));
2264
if (!empty($attrib_xmlbase)) {
2265
$xmlbase = $attrib_xmlbase;
2266
} else if (!empty($this->item_xmlbase)) {
2267
$xmlbase = $this->item_xmlbase;
2269
$xmlbase = $this->feed_xmlbase;
2272
return $this->absolutize_url($data, $xmlbase);
2274
$attributes = array(
2288
foreach ($attributes as $attribute) {
2289
$attrib = $this->get_attribute($data[0], $attribute);
2290
$new_tag = str_replace($attrib[1], $this->absolutize_url($attrib[1], $xmlbase), $attrib[0]);
2291
$data[0] = str_replace($attrib[0], $new_tag, $data[0]);
2297
function entities_decode($data) {
2298
return preg_replace_callback('/&(#)?(x)?([0-9a-z]+);/mi', array(&$this, 'do_entites_decode'), $data);
2301
function do_entites_decode($data)
2303
$entity = "&$data[1]$data[2]$data[3];";
2304
$entity_html = html_entity_decode($entity, ENT_QUOTES);
2305
if ($entity == $entity_html) {
2306
return preg_replace_callback('/&#([0-9a-fx]+);/mi', array(&$this, 'replace_num_entity'), $entity);
2308
return $entity_html;
2313
* Escape numeric entities
2314
* From a PHP Manual note (on html_entity_decode())
2315
* Copyright (c) 2005 by "php dot net at c dash ovidiu dot tk",
2316
* "emilianomartinezluque at yahoo dot com" and "hurricane at cyberworldz dot org".
2318
* This material may be distributed only subject to the terms and conditions set forth in
2319
* the Open Publication License, v1.0 or later (the latest version is presently available at
2320
* http://www.opencontent.org/openpub/).
2322
function replace_num_entity($ord) {
2324
if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match))
2325
$ord = hexdec($match[1]);
2327
$ord = intval($ord);
2334
else if ($ord < 65536)
2336
else if ($ord < 1114112)
2339
switch ($no_bytes) {
2341
$prefix = array(31, 192);
2345
$prefix = array(15, 224);
2349
$prefix = array(7, 240);
2352
for ($i=0; $i < $no_bytes; ++$i)
2353
$byte[$no_bytes-$i-1] = (($ord & (63 * pow(2,6*$i))) / pow(2,6*$i)) & 63 | 128;
2354
$byte[0] = ($byte[0] & $prefix[0]) | $prefix[1];
2356
for ($i=0; $i < $no_bytes; ++$i)
2357
$ret .= chr($byte[$i]);
2361
function parse_date($date) {
2362
if (preg_match('/([0-9]{2,4})-([0-9][0-9])-([0-9][0-9])T([0-9][0-9]):([0-9][0-9]):([0-9][0-9])(\.[0-9][0-9])?Z/i', $date, $matches)) {
2363
if (isset($matches[7]) && substr($matches[7], 1) >= 50)
2365
return strtotime("$matches[1]-$matches[2]-$matches[3] $matches[4]:$matches[5]:$matches[6] -0000");
2366
} else if (preg_match('/([0-9]{2,4})-([0-9][0-9])-([0-9][0-9])T([0-9][0-9]):([0-9][0-9]):([0-9][0-9])(\.[0-9][0-9])?(\+|-)([0-9][0-9]):([0-9][0-9])/i', $date, $matches)) {
2367
if (isset($matches[7]) && substr($matches[7], 1) >= 50)
2369
return strtotime("$matches[1]-$matches[2]-$matches[3] $matches[4]:$matches[5]:$matches[6] $matches[8]$matches[9]$matches[10]");
2371
return strtotime($date);
2378
/****************************************************
2379
FUNCTIONS FOR XML_PARSE
2380
****************************************************/
2381
function startHandler($parser, $name, $attribs) {
2382
$this->tagName = $name;
2383
$this->attribs = $attribs;
2384
$this->is_first = true;
2385
switch ($this->tagName) {
2387
case $this->namespaces['rss2'] . ':ITEM':
2388
case $this->namespaces['rss1'] . ':ITEM':
2390
case $this->namespaces['atom'] . ':ENTRY':
2391
$this->insideItem = true;
2392
$this->do_add_content($this->xmldata['items'][$this->itemNumber], '');
2396
case $this->namespaces['rss2'] . ':CHANNEL':
2397
case $this->namespaces['rss1'] . ':CHANNEL':
2398
$this->insideChannel = true;
2402
case $this->namespaces['rss2'] . ':RSS':
2403
$this->xmldata['feedinfo']['type'] = 'RSS';
2404
$this->do_add_content($this->xmldata['feeddata'], '');
2405
if (!empty($attribs['VERSION'])) {
2406
$this->xmldata['feedinfo']['version'] = trim($attribs['VERSION']);
2410
case $this->namespaces['rdf'] . ':RDF':
2411
$this->xmldata['feedinfo']['type'] = 'RSS';
2412
$this->do_add_content($this->xmldata['feeddata'], '');
2413
$this->xmldata['feedinfo']['version'] = 1;
2417
case $this->namespaces['atom'] . ':FEED':
2418
$this->xmldata['feedinfo']['type'] = 'Atom';
2419
$this->do_add_content($this->xmldata['feeddata'], '');
2420
if (!empty($attribs['VERSION'])) {
2421
$this->xmldata['feedinfo']['version'] = trim($attribs['VERSION']);
2426
case $this->namespaces['rss2'] . ':IMAGE':
2427
case $this->namespaces['rss1'] . ':IMAGE':
2428
if ($this->insideChannel) $this->insideImage = true;
2432
if (isset($this->xmldata['feedinfo']['type']) && $this->xmldata['feedinfo']['type'] == 'Atom') {
2433
switch ($this->tagName) {
2435
case $this->namespaces['atom'] . ':AUTHOR':
2436
$this->insideAuthor = true;
2440
$this->dataHandler($this->xml, '');
2443
function dataHandler($parser, $data) {
2444
if ($this->insideItem) {
2445
switch ($this->tagName) {
2447
case $this->namespaces['rss1'] . ':TITLE':
2448
case $this->namespaces['rss2'] . ':TITLE':
2449
case $this->namespaces['atom'] . ':TITLE':
2450
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['title'], $data);
2453
case $this->namespaces['dc'] . ':TITLE':
2454
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['dc:title'], $data);
2458
case $this->namespaces['atom'] . ':CONTENT':
2459
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['content'], $data);
2462
case $this->namespaces['content'] . ':ENCODED':
2463
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['encoded'], $data);
2467
case $this->namespaces['atom'] . ':SUMMARY':
2468
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['summary'], $data);
2472
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['longdesc'], $data);
2476
case $this->namespaces['rss1'] . ':DESCRIPTION':
2477
case $this->namespaces['rss2'] . ':DESCRIPTION':
2478
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['description'], $data);
2481
case $this->namespaces['dc'] . ':DESCRIPTION':
2482
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['dc:description'], $data);
2486
case $this->namespaces['rss1'] . ':LINK':
2487
case $this->namespaces['rss2'] . ':LINK':
2488
case $this->namespaces['atom'] . ':LINK':
2489
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['link'][$this->itemLinkNumber], $data);
2493
case $this->namespaces['rss1'] . ':ENCLOSURE':
2494
case $this->namespaces['rss2'] . ':ENCLOSURE':
2495
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['enclosure'][$this->enclosureNumber], $data);
2499
case $this->namespaces['rss1'] . ':GUID':
2500
case $this->namespaces['rss2'] . ':GUID':
2501
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['guid'], $data);
2505
case $this->namespaces['atom'] . ':ID':
2506
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['id'], $data);
2510
case $this->namespaces['rss1'] . ':PUBDATE':
2511
case $this->namespaces['rss2'] . ':PUBDATE':
2512
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['pubdate'], $data);
2515
case $this->namespaces['dc'] . ':DATE':
2516
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['dc:date'], $data);
2520
case $this->namespaces['atom'] . ':ISSUED':
2521
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['issued'], $data);
2525
case $this->namespaces['atom'] . ':PUBLISHED':
2526
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['published'], $data);
2530
case $this->namespaces['atom'] . ':MODIFIED':
2531
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['modified'], $data);
2535
case $this->namespaces['atom'] . ':UPDATED':
2536
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['updated'], $data);
2540
case $this->namespaces['rss1'] . ':CATEGORY':
2541
case $this->namespaces['rss2'] . ':CATEGORY':
2542
case $this->namespaces['atom'] . ':CATEGORY':
2543
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['category'][$this->categoryNumber], $data);
2546
case $this->namespaces['dc'] . ':SUBJECT':
2547
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['subject'][$this->categoryNumber], $data);
2550
case $this->namespaces['dc'] . ':CREATOR':
2551
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['creator'][$this->authorNumber], $data);
2555
case $this->namespaces['rss1'] . ':AUTHOR':
2556
case $this->namespaces['rss2'] . ':AUTHOR':
2557
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['rss'], $data);
2561
if ($this->insideAuthor) {
2562
switch ($this->tagName) {
2564
case $this->namespaces['atom'] . ':NAME':
2565
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['name'], $data);
2569
case $this->namespaces['atom'] . ':URL':
2570
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['url'], $data);
2574
case $this->namespaces['atom'] . ':URI':
2575
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['uri'], $data);
2579
case $this->namespaces['atom'] . ':HOMEPAGE':
2580
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['homepage'], $data);
2584
case $this->namespaces['atom'] . ':EMAIL':
2585
$this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['email'], $data);
2591
else if (($this->insideChannel && !$this->insideImage) || (isset($this->xmldata['feedinfo']['type']) && $this->xmldata['feedinfo']['type'] == 'Atom')) {
2592
switch ($this->tagName) {
2594
case $this->namespaces['rss1'] . ':TITLE':
2595
case $this->namespaces['rss2'] . ':TITLE':
2596
case $this->namespaces['atom'] . ':TITLE':
2597
$this->do_add_content($this->xmldata['info']['title'], $data);
2601
case $this->namespaces['rss1'] . ':LINK':
2602
case $this->namespaces['rss2'] . ':LINK':
2603
case $this->namespaces['atom'] . ':LINK':
2604
$this->do_add_content($this->xmldata['info']['link'][$this->linkNumber], $data);
2608
case $this->namespaces['rss1'] . ':DESCRIPTION':
2609
case $this->namespaces['rss2'] . ':DESCRIPTION':
2610
$this->do_add_content($this->xmldata['info']['description'], $data);
2613
case $this->namespaces['dc'] . ':DESCRIPTION':
2614
$this->do_add_content($this->xmldata['info']['dc:description'], $data);
2618
case $this->namespaces['atom'] . ':TAGLINE':
2619
$this->do_add_content($this->xmldata['info']['tagline'], $data);
2623
case $this->namespaces['atom'] . ':SUBTITLE':
2624
$this->do_add_content($this->xmldata['info']['subtitle'], $data);
2628
case $this->namespaces['rss1'] . ':COPYRIGHT':
2629
case $this->namespaces['rss2'] . ':COPYRIGHT':
2630
case $this->namespaces['atom'] . ':COPYRIGHT':
2631
$this->do_add_content($this->xmldata['info']['copyright'], $data);
2635
case $this->namespaces['rss1'] . ':LANGUAGE':
2636
case $this->namespaces['rss2'] . ':LANGUAGE':
2637
$this->do_add_content($this->xmldata['info']['language'], $data);
2641
case $this->namespaces['atom'] . ':LOGO':
2642
$this->do_add_content($this->xmldata['info']['logo'], $data);
2648
else if ($this->insideChannel && $this->insideImage) {
2649
switch ($this->tagName) {
2651
case $this->namespaces['rss1'] . ':TITLE':
2652
case $this->namespaces['rss2'] . ':TITLE':
2653
$this->do_add_content($this->xmldata['info']['image']['title'], $data);
2657
case $this->namespaces['rss1'] . ':URL':
2658
case $this->namespaces['rss2'] . ':URL':
2659
$this->do_add_content($this->xmldata['info']['image']['url'], $data);
2663
case $this->namespaces['rss1'] . ':LINK':
2664
case $this->namespaces['rss2'] . ':LINK':
2665
$this->do_add_content($this->xmldata['info']['image']['link'], $data);
2669
case $this->namespaces['rss1'] . ':WIDTH':
2670
case $this->namespaces['rss2'] . ':WIDTH':
2671
$this->do_add_content($this->xmldata['info']['image']['width'], $data);
2675
case $this->namespaces['rss1'] . ':HEIGHT':
2676
case $this->namespaces['rss2'] . ':HEIGHT':
2677
$this->do_add_content($this->xmldata['info']['image']['height'], $data);
2681
$this->is_first = false;
2684
function endHandler($parser, $name) {
2685
$this->tagName = '';
2688
case $this->namespaces['rss1'] . ':ITEM':
2689
case $this->namespaces['rss2'] . ':ITEM':
2691
case $this->namespaces['atom'] . ':ENTRY':
2692
$this->insideItem = false;
2693
$this->itemNumber++;
2694
$this->authorNumber = 0;
2695
$this->categoryNumber = 0;
2696
$this->enclosureNumber = 0;
2697
$this->itemLinkNumber = 0;
2701
case $this->namespaces['rss1'] . ':CHANNEL':
2702
case $this->namespaces['rss2'] . ':CHANNEL':
2703
$this->insideChannel = false;
2707
case $this->namespaces['rss1'] . ':IMAGE':
2708
case $this->namespaces['rss2'] . ':IMAGE':
2709
if ($this->insideChannel) $this->insideImage = false;
2713
case $this->namespaces['rss1'] . ':AUTHOR':
2714
case $this->namespaces['rss2'] . ':AUTHOR':
2715
case $this->namespaces['atom'] . ':AUTHOR':
2716
$this->authorNumber++;
2717
if ($this->xmldata['feedinfo']['type'] == 'Atom') $this->insideAuthor = false;
2721
case $this->namespaces['rss1'] . ':CATEGORY':
2722
case $this->namespaces['rss2'] . ':CATEGORY':
2723
case $this->namespaces['atom'] . ':CATEGORY':
2724
case $this->namespaces['dc'] . ':SUBJECT':
2725
$this->categoryNumber++;
2729
case $this->namespaces['rss1'] . ':ENCLOSURE':
2730
case $this->namespaces['rss2'] . ':ENCLOSURE':
2731
$this->enclosureNumber++;
2735
case $this->namespaces['rss1'] . ':LINK':
2736
case $this->namespaces['rss2'] . ':LINK':
2737
case $this->namespaces['atom'] . ':LINK':
2738
if ($this->insideItem)
2739
$this->itemLinkNumber++;
2741
$this->linkNumber++;
2746
function startNameSpace($parser, $prefix, $uri = null) {
2747
$prefix = strtoupper($prefix);
2748
$uri = strtoupper($uri);
2749
if ($prefix == 'ATOM' || $uri == 'HTTP://WWW.W3.ORG/2005/ATOM' || $uri == 'HTTP://PURL.ORG/ATOM/NS#') {
2750
$this->namespaces['atom'] = $uri;
2752
else if ($prefix == 'RSS2' || $uri == 'HTTP://BACKEND.USERLAND.COM/RSS2') {
2753
$this->namespaces['rss2'] = $uri;
2755
else if ($prefix == 'RDF' || $uri == 'HTTP://WWW.W3.ORG/1999/02/22-RDF-SYNTAX-NS#') {
2756
$this->namespaces['rdf'] = $uri;
2758
else if ($prefix == 'RSS' || $uri == 'HTTP://PURL.ORG/RSS/1.0/') {
2759
$this->namespaces['rss1'] = $uri;
2761
else if ($prefix == 'DC' || $uri == 'HTTP://PURL.ORG/DC/ELEMENTS/1.1/') {
2762
$this->namespaces['dc'] = $uri;
2764
else if ($prefix == 'XHTML' || $uri == 'HTTP://WWW.W3.ORG/1999/XHTML') {
2765
$this->namespaces['xhtml'] = $uri;
2766
$this->xhtml_prefix = $prefix;
2768
else if ($prefix == 'CONTENT' || $uri == 'HTTP://PURL.ORG/RSS/1.0/MODULES/CONTENT/') {
2769
$this->namespaces['content'] = $uri;
2773
function endNameSpace($parser, $prefix) {
2774
if ($key = array_search(strtoupper($prefix), $this->namespaces)) {
2775
if ($key == 'atom') {
2776
$this->namespaces['atom'] = 'ATOM';
2778
else if ($key == 'rss2') {
2779
$this->namespaces['rss2'] = 'RSS';
2781
else if ($key == 'rdf') {
2782
$this->namespaces['rdf'] = 'RDF';
2784
else if ($key == 'rss1') {
2785
$this->namespaces['rss1'] = 'RSS';
2787
else if ($key == 'dc') {
2788
$this->namespaces['dc'] = 'DC';
2790
else if ($key == 'xhtml') {
2791
$this->namespaces['xhtml'] = 'XHTML';
2792
$this->xhtml_prefix = 'XHTML';
2794
else if ($key == 'content') {
2795
$this->namespaces['content'] = 'CONTENT';
2801
class SimplePie_Item
2803
function SimplePie_Item($id, $title, $description, $category, $author, $date, $links, $enclosure) {
2805
$this->title = $title;
2806
$this->description = $description;
2807
$this->category = $category;
2808
$this->author = $author;
2809
$this->date = $date;
2810
$this->links = $links;
2811
$this->enclosure = $enclosure;
2814
/****************************************************
2815
PARSE OUT ITEM-RELATED DATA
2816
****************************************************/
2817
// Get the id of the item
2819
return (empty($this->id)) ? false : $this->id;
2821
// Get the title of the item
2822
function get_title() {
2823
return (empty($this->title)) ? false : $this->title;
2826
// Get the description of the item
2827
function get_description() {
2828
return (empty($this->description)) ? false : $this->description;
2831
// Get the category of the item
2832
function get_category() {
2833
return (empty($this->category)) ? false : $this->category;
2836
// Get the author of the item
2837
function get_author($key) {
2838
return (empty($this->author[$key])) ? false : $this->author[$key];
2841
// Get the author of the item
2842
function get_authors() {
2843
return (empty($this->author)) ? false : $this->author;
2846
// Get the date of the item
2847
// Also, allow users to set the format of how dates are displayed on a webpage.
2848
function get_date($date_format = 'j F Y, g:i a') {
2849
return (empty($this->date)) ? false : date($date_format, $this->date);
2852
// Get the Permalink of the item
2853
function get_permalink() {
2854
// If there is a link, take it. Fine.
2855
if (!empty($this->links[0])) {
2856
return $this->links[0];
2859
// If there isn't, check for an enclosure, if that exists, give that.
2860
else if ($this->get_enclosure(0)) {
2861
return $this->get_enclosure(0);
2867
function get_links() {
2868
return (empty($this->links)) ? false : $this->links;
2871
// Get the enclosure of the item
2872
function get_enclosure($key) {
2873
return (empty($this->enclosure[$key])) ? false : $this->enclosure[$key];
2876
// Get the enclosure of the item
2877
function get_enclosures() {
2878
return (empty($this->enclosure)) ? false : $this->enclosure;
2884
/****************************************************
2886
Allows people to easily add news postings to social bookmarking sites.
2887
****************************************************/
2888
function add_to_blinklist() {
2889
return "http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=" . rawurlencode($this->get_permalink()) . "&Title=" . rawurlencode($this->get_title());
2892
function add_to_delicious() {
2893
return "http://del.icio.us/post/?v=3&url=" . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title());
2896
function add_to_digg() {
2897
return "http://digg.com/submit?phase=2&URL=" . rawurlencode($this->get_permalink());
2900
function add_to_furl() {
2901
return "http://www.furl.net/storeIt.jsp?u=" . rawurlencode($this->get_permalink()) . "&t=" . rawurlencode($this->get_title());
2904
function add_to_magnolia() {
2905
return "http://ma.gnolia.com/bookmarklet/add?url=" . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title());
2908
function add_to_myweb20() {
2909
return "http://myweb2.search.yahoo.com/myresults/bookmarklet?u=" . rawurlencode($this->get_permalink()) . "&t=" . rawurlencode($this->get_title());
2912
function add_to_newsvine() {
2913
return "http://www.newsvine.com/_wine/save?u=" . rawurlencode($this->get_permalink()) . "&h=" . rawurlencode($this->get_title());
2916
function add_to_reddit() {
2917
return 'http://reddit.com/submit?url=' . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title());
2920
function add_to_spurl() {
2921
return "http://www.spurl.net/spurl.php?v=3&url=" . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title());
2927
/****************************************************
2930
****************************************************/
2931
function search_technorati() {
2932
return 'http://www.technorati.com/search/' . rawurlencode($this->get_permalink());
2936
class SimplePie_Author
2942
// Constructor, used to input the data
2943
function SimplePie_Author($name, $link, $email) {
2944
$this->name = $name;
2945
$this->link = $link;
2946
$this->email = $email;
2949
function get_name() {
2950
return (empty($this->name)) ? false : $this->name;
2953
function get_link() {
2954
return (empty($this->link)) ? false : $this->link;
2957
function get_email() {
2958
return (empty($this->email)) ? false : $this->email;
2962
class SimplePie_Enclosure
2968
// Constructor, used to input the data
2969
function SimplePie_Enclosure($link, $type, $length) {
2970
$this->link = $link;
2971
$this->type = $type;
2972
$this->length = $length;
2975
function get_link() {
2976
return (empty($this->link)) ? false : $this->link;
2979
function get_extension() {
2980
if (!empty($this->link)) {
2981
return pathinfo($this->link, PATHINFO_EXTENSION);
2987
function get_type() {
2988
return (empty($this->type)) ? false : $this->type;
2991
function get_length() {
2992
return (empty($this->length)) ? false : $this->length;
2995
function get_size() {
2996
return (empty($this->length)) ? false : round(($this->length/1048576), 2);
2999
function embed($options) {
3012
// Process options and reassign values as necessary
3013
$options = explode(',', $options);
3014
foreach($options as $option) {
3015
$opt = explode(':', trim($option));
3016
if ($opt[0] == 'audio') $audio=$opt[1];
3017
else if ($opt[0] == 'video') $video=$opt[1];
3018
else if ($opt[0] == 'alt') $alt=$opt[1];
3019
else if ($opt[0] == 'altclass') $altclass=$opt[1];
3020
else if ($opt[0] == 'loop') $loop=$opt[1];
3021
else if ($opt[0] == 'width') $width=$opt[1];
3022
else if ($opt[0] == 'height') $height=$opt[1];
3023
else if ($opt[0] == 'bgcolor') $bgcolor=$opt[1];
3026
// Process values for 'auto'
3027
if ($width == 'auto') {
3028
if (stristr($this->type, 'audio/')) $width='100%';
3029
else if (stristr($this->type, 'video/')) $width='320';
3032
if ($height == 'auto') {
3033
if (stristr($this->type, 'audio/')) $height=0;
3034
else if (stristr($this->type, 'video/')) $height=240;
3038
// Set proper placeholder value
3039
if (stristr($this->type, 'audio/')) $placeholder=$audio;
3040
else if (stristr($this->type, 'video/')) $placeholder=$video;
3042
// Make sure the JS library is included
3043
// (I know it'll be included multiple times, but I can't think of a better way to do this automatically)
3044
$embed.='<script type="text/javascript" src="?js"></script>';
3047
if (substr(strtolower($this->link), 0, 15) == 'http://odeo.com') {
3048
$embed.='<script type="text/javascript">embed_odeo("'.$this->link.'");</script>';
3051
// QuickTime 7 file types. Need to test with QuickTime 6.
3052
else if ($this->type == 'audio/3gpp' || $this->type == 'audio/3gpp2' || $this->type == 'audio/aac' || $this->type == 'audio/x-aac' || $this->type == 'audio/aiff' || $this->type == 'audio/x-aiff' || $this->type == 'audio/mid' || $this->type == 'audio/midi' || $this->type == 'audio/x-midi' || $this->type == 'audio/mpeg' || $this->type == 'audio/x-mpeg' || $this->type == 'audio/mp3' || $this->type == 'x-audio/mp3' || $this->type == 'audio/mp4' || $this->type == 'audio/m4a' || $this->type == 'audio/x-m4a' || $this->type == 'audio/wav' || $this->type == 'audio/x-wav' || $this->type == 'video/3gpp' || $this->type == 'video/3gpp2' || $this->type == 'video/m4v' || $this->type == 'video/x-m4v' || $this->type == 'video/mp4' || $this->type == 'video/mpeg' || $this->type == 'video/x-mpeg' || $this->type == 'video/quicktime' || $this->type == 'video/sd-video') {
3054
$embed.='<script type="text/javascript">embed_quicktime("'.$this->type.'", "'.$bgcolor.'", "'.$width.'", "'.$height.'", "'.$this->link.'", "'.$placeholder.'", "'.$loop.'");</script>';
3058
else if ($this->type == 'application/x-shockwave-flash' || $this->type == 'application/futuresplash') {
3059
$embed.='<script type="text/javascript">embed_flash("'.$bgcolor.'", "'.$width.'", "'.$height.'", "'.$this->link.'", "'.$loop.'", "'.$this->type.'");</script>';
3063
else if ($this->type == 'application/asx' || $this->type == 'application/x-mplayer2' || $this->type == 'audio/x-ms-wma' || $this->type == 'audio/x-ms-wax' || $this->type == 'video/x-ms-asf-plugin' || $this->type == 'video/x-ms-asf' || $this->type == 'video/x-ms-wm' || $this->type == 'video/x-ms-wmv' || $this->type == 'video/x-ms-wvx') {
3065
$embed.='<script type="text/javascript">embed_wmedia("'.$width.'", "'.$height.'", "'.$this->link.'");</script>';
3069
else $embed.='<a href="' . $this->link . '" class="' . $altclass . '">' . $alt . '</a>';