| [ Index ] |
|
Code source de DokuWiki 2006-11-06 |
1 <?php 2 /**************************************************** 3 SIMPLEPIE 4 A PHP-Based RSS and Atom Feed Framework 5 Takes the hard work out of managing a complete RSS/Atom solution. 6 7 Version: 1.0 Beta 2 8 Updated: 30 May 2006 9 Copyright: 2004-2006 Ryan Parman, Geoffrey Sneddon 10 http://simplepie.org 11 12 ***************************************************** 13 LICENSE: 14 15 GNU Lesser General Public License 2.1 (LGPL) 16 http://creativecommons.org/licenses/LGPL/2.1/ 17 18 ***************************************************** 19 Please submit all bug reports and feature requests to the SimplePie forums. 20 http://simplepie.org/support/ 21 22 ****************************************************/ 23 24 class SimplePie { 25 26 // SimplePie Information 27 var $name = 'SimplePie'; 28 var $version = '1.0 Beta 2'; 29 var $build = '20060530'; 30 var $url = 'http://simplepie.org/'; 31 var $useragent; 32 var $linkback; 33 34 // Run-time Variables 35 var $rss_url; 36 var $encoding; 37 var $xml_dump = false; 38 var $caching = true; 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; 50 51 // RSS Auto-Discovery Variables 52 var $parsed_url; 53 var $local = array(); 54 var $elsewhere = array(); 55 56 // XML Parsing Variables 57 var $xml; 58 var $tagName; 59 var $insideItem; 60 var $insideChannel; 61 var $insideImage; 62 var $insideAuthor; 63 var $itemNumber = 0; 64 var $authorNumber = 0; 65 var $categoryNumber = 0; 66 var $enclosureNumber = 0; 67 var $linkNumber = 0; 68 var $itemLinkNumber = 0; 69 var $data = false; 70 var $attribs; 71 var $xmldata; 72 var $feed_xmlbase; 73 var $item_xmlbase; 74 var $xhtml_prefix; 75 76 77 78 79 /**************************************************** 80 CONSTRUCTOR 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>'; 87 88 if (!is_null($feed_url)) { 89 $this->feed_url($feed_url); 90 } 91 92 if (!is_null($cache_location)) { 93 $this->cache_location($cache_location); 94 } 95 96 if (!is_null($cache_max_minutes)) { 97 $this->cache_max_minutes($cache_max_minutes); 98 } 99 100 if (!is_null($feed_url)) { 101 return $this->init(); 102 } 103 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']); 107 } 108 } 109 110 111 112 113 /**************************************************** 114 CONFIGURE OPTIONS 115 Set various options (feed URL, XML dump, caching, etc.) 116 ****************************************************/ 117 // Feed URL 118 function feed_url($url) { 119 $url = $this->fix_protocol($url, 1); 120 $this->rss_url = $url; 121 return true; 122 } 123 124 // XML Dump 125 function enable_xmldump($enable) { 126 $this->xml_dump = (bool) $enable; 127 return true; 128 } 129 130 // Bypass Image Hotlink 131 function bypass_image_hotlink($getvar='i') { 132 $this->bypass_image_hotlink = (string) $getvar; 133 return true; 134 } 135 136 // Bypass Image Hotlink Page 137 function bypass_image_hotlink_page($page = false) { 138 $this->bypass_image_hotlink_page = (string) $page; 139 return true; 140 } 141 142 // Caching 143 function enable_caching($enable) { 144 $this->caching = (bool) $enable; 145 return true; 146 } 147 148 // Cache Timeout 149 function cache_max_minutes($minutes) { 150 $this->max_minutes = (int) $minutes; 151 return true; 152 } 153 154 // Cache Location 155 function cache_location($location) { 156 $this->cache_location = (string) $location; 157 return true; 158 } 159 160 // Replace H1, H2, and H3 tags with the less important H4 tags. 161 function replace_headers($enable) { 162 $this->replace_headers = (bool) $enable; 163 return true; 164 } 165 166 // Remove outer div in XHTML content within Atom 167 function remove_div($enable) { 168 $this->remove_div = (bool) $enable; 169 return true; 170 } 171 172 // Order the items by date 173 function order_by_date($enable) { 174 $this->order_by_date = (bool) $enable; 175 return true; 176 } 177 178 // Strip out certain well-known ads 179 function strip_ads($enable) { 180 $this->strip_ads = (bool) $enable; 181 return true; 182 } 183 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; 188 return true; 189 } 190 191 // Encode dangerous tags instead of stripping them 192 function encode_instead_of_strip($encode=true) { 193 $this->encode_instead_of_strip = (bool) $encode; 194 return true; 195 } 196 197 // Strip out potentially dangerous attributes 198 function strip_attributes($attrib) { 199 $this->strip_attributes = (string) $attrib; 200 return true; 201 } 202 203 204 205 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 ****************************************************/ 211 function init() { 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]); 216 exit; 217 } 218 } 219 220 // If Bypass Image Hotlink is enabled, send image to the page and quit. 221 if (isset($_GET['js'])) { 222 223 // JavaScript for the Odeo Player 224 $embed=''; 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+\'">'; 246 $embed.='</embed>'; 247 $embed.='</object>'; 248 $embed.='\');'; 249 $embed.='}'; 250 251 $embed.="\r\n"; 252 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/">'; 283 $embed.='</embed>'; 284 $embed.='</object>'; 285 $embed.='\');'; 286 $embed.='}'; 287 288 $embed.="\r\n"; 289 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+\'">'; 309 $embed.='</embed>'; 310 $embed.='</object>'; 311 $embed.='\');'; 312 $embed.='}'; 313 314 $embed.="\r\n"; 315 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">'; 338 $embed.='</embed>'; 339 $embed.='</object>'; 340 $embed.='\');'; 341 $embed.='}'; 342 343 $embed.="\r\n"; 344 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"); 350 echo $embed; 351 exit; 352 } 353 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); 357 } 358 359 // Clear all outdated cache from the server's cache folder 360 $this->clear_cache($this->cache_location, $this->max_minutes); 361 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')) { 367 $data = ''; 368 while (!feof($fp)) { 369 $data .= fread($fp, 2048); 370 } 371 fclose($fp); 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(); 379 } else { 380 $this->data = $mp_rss; 381 return true; 382 } 383 } else { 384 $this->caching = false; 385 return $this->init(); 386 } 387 } else { 388 // Get the file 389 $mp_rss = $this->get_file($this->rss_url); 390 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); 394 if ($discovery) { 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))); 401 fclose($fp); 402 } 403 else trigger_error("$cache_filename is not writeable", E_USER_WARNING); 404 } 405 return $this->init(); 406 } 407 } else { 408 $this->sp_error("A feed could not be found at $this->rss_url", E_USER_WARNING, __FILE__, __LINE__); 409 return false; 410 } 411 412 // Trim out any whitespace at the beginning or the end of the file 413 $mp_rss = trim($mp_rss); 414 415 // Get encoding 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) 418 $use_iconv = false; 419 $use_mbstring = false; 420 $utf8_fail = true; 421 if (preg_match('/encoding=["|\'](.*)["|\']/Ui', $mp_rss, $encoding)) { 422 $match = $encoding; 423 switch (strtolower($encoding[1])) { 424 425 // 7bit 426 case '7bit': 427 case '7-bit': 428 $encoding = '7bit'; 429 $use_mbstring = true; 430 break; 431 432 // 8bit 433 case '8bit': 434 case '8-bit': 435 $encoding = '8bit'; 436 $use_mbstring = true; 437 break; 438 439 // ARMSCII-8 440 case 'armscii-8': 441 case 'armscii': 442 $encoding = 'ARMSCII-8'; 443 $use_iconv = true; 444 break; 445 446 // ASCII 447 case 'us-ascii': 448 case 'ascii': 449 $encoding = 'US-ASCII'; 450 $use_iconv = true; 451 $use_mbstring = true; 452 $utf8_fail = false; 453 break; 454 455 // BASE64 456 case 'base64': 457 case 'base-64': 458 $encoding = 'BASE64'; 459 $use_mbstring = true; 460 break; 461 462 // Big5 - Traditional Chinese, mainly used in Taiwan 463 case 'big5': 464 case '950': 465 $encoding = 'BIG5'; 466 $use_iconv = true; 467 $use_mbstring = true; 468 break; 469 470 // Big5 with Hong Kong extensions, Traditional Chinese 471 case 'big5-hkscs': 472 $encoding = 'BIG5-HKSCS'; 473 $use_iconv = true; 474 $use_mbstring = true; 475 break; 476 477 // byte2be 478 case 'byte2be': 479 $encoding = 'byte2be'; 480 $use_mbstring = true; 481 break; 482 483 // byte2le 484 case 'byte2le': 485 $encoding = 'byte2le'; 486 $use_mbstring = true; 487 break; 488 489 // byte4be 490 case 'byte4be': 491 $encoding = 'byte4be'; 492 $use_mbstring = true; 493 break; 494 495 // byte4le 496 case 'byte4le': 497 $encoding = 'byte4le'; 498 $use_mbstring = true; 499 break; 500 501 // EUC-CN 502 case 'euc-cn': 503 case 'euccn': 504 $encoding = 'EUC-CN'; 505 $use_iconv = true; 506 $use_mbstring = true; 507 break; 508 509 // EUC-JISX0213 510 case 'euc-jisx0213': 511 case 'eucjisx0213': 512 $encoding = 'EUC-JISX0213'; 513 $use_iconv = true; 514 break; 515 516 // EUC-JP 517 case 'euc-jp': 518 case 'eucjp': 519 $encoding = 'EUC-JP'; 520 $use_iconv = true; 521 $use_mbstring = true; 522 break; 523 524 // EUCJP-win 525 case 'euc-jp-win': 526 case 'eucjp-win': 527 case 'eucjpwin': 528 $encoding = 'EUCJP-win'; 529 $use_iconv = true; 530 $use_mbstring = true; 531 break; 532 533 // EUC-KR 534 case 'euc-kr': 535 case 'euckr': 536 $encoding = 'EUC-KR'; 537 $use_iconv = true; 538 $use_mbstring = true; 539 break; 540 541 // EUC-TW 542 case 'euc-tw': 543 case 'euctw': 544 $encoding = 'EUC-TW'; 545 $use_iconv = true; 546 $use_mbstring = true; 547 break; 548 549 // GB18030 - Simplified Chinese, national standard character set 550 case 'gb18030-2000': 551 case 'gb18030': 552 $encoding = 'GB18030'; 553 $use_iconv = true; 554 break; 555 556 // GB2312 - Simplified Chinese, national standard character set 557 case 'gb2312': 558 case '936': 559 $encoding = 'GB2312'; 560 $use_mbstring = true; 561 break; 562 563 // GBK 564 case 'gbk': 565 $encoding = 'GBK'; 566 $use_iconv = true; 567 break; 568 569 // Georgian-Academy 570 case 'georgian-academy': 571 $encoding = 'Georgian-Academy'; 572 $use_iconv = true; 573 break; 574 575 // Georgian-PS 576 case 'georgian-ps': 577 $encoding = 'Georgian-PS'; 578 $use_iconv = true; 579 break; 580 581 // HTML-ENTITIES 582 case 'html-entities': 583 case 'htmlentities': 584 $encoding = 'HTML-ENTITIES'; 585 $use_mbstring = true; 586 break; 587 588 // HZ 589 case 'hz': 590 $encoding = 'HZ'; 591 $use_iconv = true; 592 $use_mbstring = true; 593 break; 594 595 // ISO-2022-CN 596 case 'iso-2022-cn': 597 case 'iso2022-cn': 598 case 'iso2022cn': 599 $encoding = 'ISO-2022-CN'; 600 $use_iconv = true; 601 break; 602 603 // ISO-2022-CN-EXT 604 case 'iso-2022-cn-ext': 605 case 'iso2022-cn-ext': 606 case 'iso2022cn-ext': 607 case 'iso2022cnext': 608 $encoding = 'ISO-2022-CN'; 609 $use_iconv = true; 610 break; 611 612 // ISO-2022-JP 613 case 'iso-2022-jp': 614 case 'iso2022-jp': 615 case 'iso2022jp': 616 $encoding = 'ISO-2022-JP'; 617 $use_iconv = true; 618 $use_mbstring = true; 619 break; 620 621 // ISO-2022-JP-1 622 case 'iso-2022-jp-1': 623 case 'iso2022-jp-1': 624 case 'iso2022jp-1': 625 case 'iso2022jp1': 626 $encoding = 'ISO-2022-JP-1'; 627 $use_iconv = true; 628 break; 629 630 // ISO-2022-JP-2 631 case 'iso-2022-jp-2': 632 case 'iso2022-jp-2': 633 case 'iso2022jp-2': 634 case 'iso2022jp2': 635 $encoding = 'ISO-2022-JP-2'; 636 $use_iconv = true; 637 break; 638 639 // ISO-2022-JP-3 640 case 'iso-2022-jp-3': 641 case 'iso2022-jp-3': 642 case 'iso2022jp-3': 643 case 'iso2022jp3': 644 $encoding = 'ISO-2022-JP-3'; 645 $use_iconv = true; 646 break; 647 648 // ISO-2022-KR 649 case 'iso-2022-kr': 650 case 'iso2022-kr': 651 case 'iso2022kr': 652 $encoding = 'ISO-2022-KR'; 653 $use_iconv = true; 654 $use_mbstring = true; 655 break; 656 657 // ISO-8859-1 658 case 'iso-8859-1': 659 case 'iso8859-1': 660 $encoding = 'ISO-8859-1'; 661 $use_iconv = true; 662 $use_mbstring = true; 663 $utf8_fail = false; 664 break; 665 666 // ISO-8859-2 667 case 'iso-8859-2': 668 case 'iso8859-2': 669 $encoding = 'ISO-8859-2'; 670 $use_iconv = true; 671 $use_mbstring = true; 672 break; 673 674 // ISO-8859-3 675 case 'iso-8859-3': 676 case 'iso8859-3': 677 $encoding = 'ISO-8859-3'; 678 $use_iconv = true; 679 $use_mbstring = true; 680 break; 681 682 // ISO-8859-4 683 case 'iso-8859-4': 684 case 'iso8859-4': 685 $encoding = 'ISO-8859-4'; 686 $use_iconv = true; 687 $use_mbstring = true; 688 break; 689 690 // ISO-8859-5 691 case 'iso-8859-5': 692 case 'iso8859-5': 693 $encoding = 'ISO-8859-5'; 694 $use_iconv = true; 695 $use_mbstring = true; 696 break; 697 698 // ISO-8859-6 699 case 'iso-8859-6': 700 case 'iso8859-6': 701 $encoding = 'ISO-8859-6'; 702 $use_iconv = true; 703 $use_mbstring = true; 704 break; 705 706 // ISO-8859-7 707 case 'iso-8859-7': 708 case 'iso8859-7': 709 $encoding = 'ISO-8859-7'; 710 $use_iconv = true; 711 $use_mbstring = true; 712 break; 713 714 // ISO-8859-8 715 case 'iso-8859-8': 716 case 'iso8859-8': 717 $encoding = 'ISO-8859-8'; 718 $use_iconv = true; 719 $use_mbstring = true; 720 break; 721 722 // ISO-8859-9 723 case 'iso-8859-9': 724 case 'iso8859-9': 725 $encoding = 'ISO-8859-9'; 726 $use_iconv = true; 727 $use_mbstring = true; 728 break; 729 730 // ISO-8859-10 731 case 'iso-8859-10': 732 case 'iso8859-10': 733 $encoding = 'ISO-8859-10'; 734 $use_iconv = true; 735 $use_mbstring = true; 736 break; 737 738 // mbstring/iconv functions don't appear to support 11 & 12 739 740 // ISO-8859-13 741 case 'iso-8859-13': 742 case 'iso8859-13': 743 $encoding = 'ISO-8859-13'; 744 $use_iconv = true; 745 $use_mbstring = true; 746 break; 747 748 // ISO-8859-14 749 case 'iso-8859-14': 750 case 'iso8859-14': 751 $encoding = 'ISO-8859-14'; 752 $use_iconv = true; 753 $use_mbstring = true; 754 break; 755 756 // ISO-8859-15 757 case 'iso-8859-15': 758 case 'iso8859-15': 759 $encoding = 'ISO-8859-15'; 760 $use_iconv = true; 761 $use_mbstring = true; 762 break; 763 764 // ISO-8859-16 765 case 'iso-8859-16': 766 case 'iso8859-16': 767 $encoding = 'ISO-8859-16'; 768 $use_iconv = true; 769 break; 770 771 // JIS 772 case 'jis': 773 $encoding = 'JIS'; 774 $use_mbstring = true; 775 break; 776 777 // JOHAB - Korean 778 case 'johab': 779 $encoding = 'JOHAB'; 780 $use_iconv = true; 781 break; 782 783 // Russian 784 case 'koi8-r': 785 case 'koi8r': 786 $encoding = 'KOI8-R'; 787 $use_iconv = true; 788 $use_mbstring = true; 789 break; 790 791 // Turkish 792 case 'koi8-t': 793 case 'koi8t': 794 $encoding = 'KOI8-T'; 795 $use_iconv = true; 796 break; 797 798 // Ukrainian 799 case 'koi8-u': 800 case 'koi8u': 801 $encoding = 'KOI8-U'; 802 $use_iconv = true; 803 break; 804 805 // Russian+Ukrainian 806 case 'koi8-ru': 807 case 'koi8ru': 808 $encoding = 'KOI8-RU'; 809 $use_iconv = true; 810 break; 811 812 // Macintosh (Mac OS Classic) 813 case 'macintosh': 814 $encoding = 'Macintosh'; 815 $use_iconv = true; 816 break; 817 818 // MacArabic (Mac OS Classic) 819 case 'macarabic': 820 $encoding = 'MacArabic'; 821 $use_iconv = true; 822 break; 823 824 // MacCentralEurope (Mac OS Classic) 825 case 'maccentraleurope': 826 $encoding = 'MacCentralEurope'; 827 $use_iconv = true; 828 break; 829 830 // MacCroatian (Mac OS Classic) 831 case 'maccroatian': 832 $encoding = 'MacCroatian'; 833 $use_iconv = true; 834 break; 835 836 // MacCyrillic (Mac OS Classic) 837 case 'maccyrillic': 838 $encoding = 'MacCyrillic'; 839 $use_iconv = true; 840 break; 841 842 // MacGreek (Mac OS Classic) 843 case 'macgreek': 844 $encoding = 'MacGreek'; 845 $use_iconv = true; 846 break; 847 848 // MacHebrew (Mac OS Classic) 849 case 'machebrew': 850 $encoding = 'MacHebrew'; 851 $use_iconv = true; 852 break; 853 854 // MacIceland (Mac OS Classic) 855 case 'maciceland': 856 $encoding = 'MacIceland'; 857 $use_iconv = true; 858 break; 859 860 // MacRoman (Mac OS Classic) 861 case 'macroman': 862 $encoding = 'MacRoman'; 863 $use_iconv = true; 864 break; 865 866 // MacRomania (Mac OS Classic) 867 case 'macromania': 868 $encoding = 'MacRomania'; 869 $use_iconv = true; 870 break; 871 872 // MacThai (Mac OS Classic) 873 case 'macthai': 874 $encoding = 'MacThai'; 875 $use_iconv = true; 876 break; 877 878 // MacTurkish (Mac OS Classic) 879 case 'macturkish': 880 $encoding = 'MacTurkish'; 881 $use_iconv = true; 882 break; 883 884 // MacUkraine (Mac OS Classic) 885 case 'macukraine': 886 $encoding = 'MacUkraine'; 887 $use_iconv = true; 888 break; 889 890 // MuleLao-1 891 case 'mulelao-1': 892 case 'mulelao1': 893 $encoding = 'MuleLao-1'; 894 $use_iconv = true; 895 break; 896 897 // Shift_JIS 898 case 'shift_jis': 899 case 'sjis': 900 case '932': 901 $encoding = 'Shift_JIS'; 902 $use_iconv = true; 903 $use_mbstring = true; 904 break; 905 906 // Shift_JISX0213 907 case 'shift-jisx0213': 908 case 'shiftjisx0213': 909 $encoding = 'Shift_JISX0213'; 910 $use_iconv = true; 911 break; 912 913 // SJIS-win 914 case 'sjis-win': 915 case 'sjiswin': 916 case 'shift_jis-win': 917 $encoding = 'SJIS-win'; 918 $use_iconv = true; 919 $use_mbstring = true; 920 break; 921 922 // TCVN - Vietnamese 923 case 'tcvn': 924 $encoding = 'TCVN'; 925 $use_iconv = true; 926 break; 927 928 // TDS565 - Turkish 929 case 'tds565': 930 $encoding = 'TDS565'; 931 $use_iconv = true; 932 break; 933 934 // TIS-620 Thai 935 case 'tis-620': 936 case 'tis620': 937 $encoding = 'TIS-620'; 938 $use_iconv = true; 939 $use_mbstring = true; 940 break; 941 942 // UCS-2 943 case 'ucs-2': 944 case 'ucs2': 945 case 'utf-16': 946 case 'utf16': 947 $encoding = 'UCS-2'; 948 $use_iconv = true; 949 $use_mbstring = true; 950 break; 951 952 // UCS-2BE 953 case 'ucs-2be': 954 case 'ucs2be': 955 case 'utf-16be': 956 case 'utf16be': 957 $encoding = 'UCS-2BE'; 958 $use_iconv = true; 959 $use_mbstring = true; 960 break; 961 962 // UCS-2LE 963 case 'ucs-2le': 964 case 'ucs2le': 965 case 'utf-16le': 966 case 'utf16le': 967 $encoding = 'UCS-2LE'; 968 $use_iconv = true; 969 $use_mbstring = true; 970 break; 971 972 // UCS-2-INTERNAL 973 case 'ucs-2-internal': 974 case 'ucs2internal': 975 $encoding = 'UCS-2-INTERNAL'; 976 $use_iconv = true; 977 break; 978 979 // UCS-4 980 case 'ucs-4': 981 case 'ucs4': 982 case 'utf-32': 983 case 'utf32': 984 $encoding = 'UCS-4'; 985 $use_iconv = true; 986 $use_mbstring = true; 987 break; 988 989 // UCS-4BE 990 case 'ucs-4be': 991 case 'ucs4be': 992 case 'utf-32be': 993 case 'utf32be': 994 $encoding = 'UCS-4BE'; 995 $use_iconv = true; 996 $use_mbstring = true; 997 break; 998 999 // UCS-4LE 1000 case 'ucs-4le': 1001 case 'ucs4le': 1002 case 'utf-32le': 1003 case 'utf32le': 1004 $encoding = 'UCS-4LE'; 1005 $use_iconv = true; 1006 $use_mbstring = true; 1007 break; 1008 1009 // UCS-4-INTERNAL 1010 case 'ucs-4-internal': 1011 case 'ucs4internal': 1012 $encoding = 'UCS-4-INTERNAL'; 1013 $use_iconv = true; 1014 break; 1015 1016 // UCS-16 1017 case 'ucs-16': 1018 case 'ucs16': 1019 $encoding = 'UCS-16'; 1020 $use_iconv = true; 1021 $use_mbstring = true; 1022 break; 1023 1024 // UCS-16BE 1025 case 'ucs-16be': 1026 case 'ucs16be': 1027 $encoding = 'UCS-16BE'; 1028 $use_iconv = true; 1029 $use_mbstring = true; 1030 break; 1031 1032 // UCS-16LE 1033 case 'ucs-16le': 1034 case 'ucs16le': 1035 $encoding = 'UCS-16LE'; 1036 $use_iconv = true; 1037 $use_mbstring = true; 1038 break; 1039 1040 // UCS-32 1041 case 'ucs-32': 1042 case 'ucs32': 1043 $encoding = 'UCS-32'; 1044 $use_iconv = true; 1045 $use_mbstring = true; 1046 break; 1047 1048 // UCS-32BE 1049 case 'ucs-32be': 1050 case 'ucs32be': 1051 $encoding = 'UCS-32BE'; 1052 $use_iconv = true; 1053 $use_mbstring = true; 1054 break; 1055 1056 // UCS-32LE 1057 case 'ucs-32le': 1058 case 'ucs32le': 1059 $encoding = 'UCS-32LE'; 1060 $use_iconv = true; 1061 $use_mbstring = true; 1062 break; 1063 1064 // UTF-7 1065 case 'utf-7': 1066 case 'utf7': 1067 $encoding = 'UTF-7'; 1068 $use_iconv = true; 1069 $use_mbstring = true; 1070 break; 1071 1072 // UTF7-IMAP 1073 case 'utf-7-imap': 1074 case 'utf7-imap': 1075 case 'utf7imap': 1076 $encoding = 'UTF7-IMAP'; 1077 $use_mbstring = true; 1078 break; 1079 1080 // VISCII - Vietnamese ASCII 1081 case 'viscii': 1082 $encoding = 'VISCII'; 1083 $use_iconv = true; 1084 break; 1085 1086 // Windows-specific Central & Eastern Europe 1087 case 'cp1250': 1088 case 'windows-1250': 1089 case 'win-1250': 1090 case '1250': 1091 $encoding = 'Windows-1250'; 1092 $use_iconv = true; 1093 break; 1094 1095 // Windows-specific Cyrillic 1096 case 'cp1251': 1097 case 'windows-1251': 1098 case 'win-1251': 1099 case '1251': 1100 $encoding = 'Windows-1251'; 1101 $use_iconv = true; 1102 $use_mbstring = true; 1103 break; 1104 1105 // Windows-specific Western Europe 1106 case 'cp1252': 1107 case 'windows-1252': 1108 case '1252': 1109 $encoding = 'Windows-1252'; 1110 $use_iconv = true; 1111 $use_mbstring = true; 1112 break; 1113 1114 // Windows-specific Greek 1115 case 'cp1253': 1116 case 'windows-1253': 1117 case '1253': 1118 $encoding = 'Windows-1253'; 1119 $use_iconv = true; 1120 break; 1121 1122 // Windows-specific Turkish 1123 case 'cp1254': 1124 case 'windows-1254': 1125 case '1254': 1126 $encoding = 'Windows-1254'; 1127 $use_iconv = true; 1128 break; 1129 1130 // Windows-specific Hebrew 1131 case 'cp1255': 1132 case 'windows-1255': 1133 case '1255': 1134 $encoding = 'Windows-1255'; 1135 $use_iconv = true; 1136 break; 1137 1138 // Windows-specific Arabic 1139 case 'cp1256': 1140 case 'windows-1256': 1141 case '1256': 1142 $encoding = 'Windows-1256'; 1143 $use_iconv = true; 1144 break; 1145 1146 // Windows-specific Baltic 1147 case 'cp1257': 1148 case 'windows-1257': 1149 case '1257': 1150 $encoding = 'Windows-1257'; 1151 $use_iconv = true; 1152 break; 1153 1154 // Windows-specific Vietnamese 1155 case 'cp1258': 1156 case 'windows-1258': 1157 case '1258': 1158 $encoding = 'Windows-1258'; 1159 $use_iconv = true; 1160 break; 1161 1162 // Default to UTF-8 1163 default: 1164 $encoding = 'UTF-8'; 1165 break; 1166 } 1167 } else { 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); 1171 $use_iconv = true; 1172 $use_mbstring = true; 1173 $utf8_fail = false; 1174 $encoding = 'UTF-8'; 1175 } 1176 $this->encoding = $encoding; 1177 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'; 1183 } 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'; 1188 } 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); 1192 } 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) 1195 1196 // If we're RSS 1197 if (preg_match('/<rdf:rdf/i', $mp_rss) || preg_match('/<rss/i', $mp_rss)) { 1198 $sp_elements = array( 1199 'author', 1200 'link', 1201 ); 1202 // Or if we're Atom 1203 } else { 1204 $sp_elements = array( 1205 'content', 1206 'copyright', 1207 'name', 1208 'subtitle', 1209 'summary', 1210 'tagline', 1211 'title', 1212 ); 1213 } 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); 1221 } 1222 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); 1226 echo $mp_rss; 1227 exit; 1228 } 1229 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)) 1239 { 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;')); 1245 } 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)); 1250 fclose($fp); 1251 } 1252 else trigger_error("$cache_filename is not writeable", E_USER_WARNING); 1253 } 1254 return true; 1255 } 1256 else 1257 { 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(); 1261 return false; 1262 } 1263 } 1264 } 1265 else { 1266 return false; 1267 } 1268 } 1269 1270 1271 1272 1273 /**************************************************** 1274 SIMPLEPIE ERROR (internal function) 1275 ****************************************************/ 1276 function sp_error($message, $level, $file, $line) { 1277 $this->error = $message; 1278 switch ($level) { 1279 case E_USER_ERROR: 1280 $note = 'PHP Error'; 1281 break; 1282 case E_USER_WARNING: 1283 $note = 'PHP Warning'; 1284 break; 1285 case E_USER_NOTICE: 1286 $note = 'PHP Notice'; 1287 break; 1288 default: 1289 $note = 'Unknown Error'; 1290 break; 1291 } 1292 error_log("$note: $message in $file on line $line", 0); 1293 } 1294 1295 1296 1297 1298 /**************************************************** 1299 GET FEED ENCODING 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; 1307 } 1308 1309 function handle_content_type($mime='text/html') { 1310 if (!headers_sent() && $this->get_encoding()) header('Content-type: ' . $mime . '; charset=' . $this->get_encoding()); 1311 } 1312 1313 1314 1315 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']; 1322 } 1323 else return false; 1324 } 1325 1326 1327 1328 1329 /**************************************************** 1330 SUBSCRIPTION URLS 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); 1335 } 1336 1337 function subscribe_feed() { 1338 return (empty($this->rss_url)) ? false : $this->fix_protocol($this->rss_url, 2); 1339 } 1340 1341 function subscribe_podcast() { 1342 return (empty($this->rss_url)) ? false : $this->fix_protocol($this->rss_url, 3); 1343 } 1344 1345 function subscribe_aol() { 1346 return (empty($this->rss_url)) ? false : 'http://feeds.my.aol.com/add.jsp?url=' . rawurlencode($this->subscribe_url()); 1347 } 1348 1349 function subscribe_bloglines() { 1350 return (empty($this->rss_url)) ? false : 'http://www.bloglines.com/sub/' . rawurlencode($this->subscribe_url()); 1351 } 1352 1353 function subscribe_google() { 1354 return (empty($this->rss_url)) ? false : 'http://fusion.google.com/add?feedurl=' . rawurlencode($this->subscribe_url()); 1355 } 1356 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()); 1359 } 1360 1361 function subscribe_netvibes() { 1362 return (empty($this->rss_url)) ? false : 'http://www.netvibes.com/subscribe.php?url=' . rawurlencode($this->subscribe_url()); 1363 } 1364 1365 function subscribe_newsburst() { 1366 return (empty($this->rss_url)) ? false : 'http://www.newsburst.com/Source/?add=' . rawurlencode($this->subscribe_url()); 1367 } 1368 1369 function subscribe_newsgator() { 1370 return (empty($this->rss_url)) ? false : 'http://www.newsgator.com/ngs/subscriber/subext.aspx?url=' . rawurlencode($this->subscribe_url()); 1371 } 1372 1373 function subscribe_odeo() { 1374 return (empty($this->rss_url)) ? false : 'http://www.odeo.com/listen/subscribe?feed=' . rawurlencode($this->subscribe_url()); 1375 } 1376 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()); 1379 } 1380 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()); 1383 } 1384 1385 function subscribe_rojo() { 1386 return (empty($this->rss_url)) ? false : 'http://www.rojo.com/add-subscription?resource=' . rawurlencode($this->subscribe_url()); 1387 } 1388 1389 function subscribe_yahoo() { 1390 return (empty($this->rss_url)) ? false : 'http://add.my.yahoo.com/rss?url=' . rawurlencode($this->subscribe_url()); 1391 } 1392 1393 1394 1395 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; 1402 } 1403 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; 1407 } 1408 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; 1412 } 1413 1414 // Reads the feed's description 1415 function get_feed_description() { 1416 return (isset($this->data['info']['description'])) ? $this->data['info']['description'] : false; 1417 } 1418 1419 // Reads the feed's copyright information. 1420 function get_feed_copyright() { 1421 return (isset($this->data['info']['copyright'])) ? $this->data['info']['copyright'] : false; 1422 } 1423 1424 // Reads the feed's language 1425 function get_feed_language() { 1426 return (isset($this->data['info']['language'])) ? $this->data['info']['language'] : false; 1427 } 1428 1429 1430 1431 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; 1439 } 1440 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; 1444 } 1445 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; 1449 } 1450 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; 1454 } 1455 1456 // Get the image width 1457 function get_image_width() { 1458 return (isset($this->data['info']['image']['width'])) ? $this->data['info']['image']['width'] : false; 1459 } 1460 1461 // Get the image height 1462 function get_image_height() { 1463 return (isset($this->data['info']['image']['height'])) ? $this->data['info']['image']['height'] : false; 1464 } 1465 1466 1467 1468 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; 1476 else return $qty; 1477 } 1478 1479 function get_item($key) { 1480 return $this->data['items'][$key]; 1481 } 1482 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); 1485 } 1486 1487 1488 1489 1490 /**************************************************** 1491 FIX PROTOCOL 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. 1495 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; 1502 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"; 1508 1509 if ($http == 1) return $url; 1510 else if ($http == 2) { 1511 if (strstr($url, 'http://')) { 1512 $url = substr_replace($url, 'feed', 0, 4); 1513 return $url; 1514 } 1515 else return $url; 1516 } 1517 else if ($http == 3) { 1518 if (strstr($url, 'http://')) { 1519 $url = substr_replace($url, 'podcast', 0, 4); 1520 return $url; 1521 } 1522 else return $url; 1523 } 1524 } 1525 1526 1527 1528 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) { 1535 1536 $this->url = $url; 1537 $this->parsed_url = parse_url($url); 1538 if (!isset($this->parsed_url['path'])) { 1539 $this->parsed_url['path'] = '/'; 1540 } 1541 1542 // Check is the URL we're given is a feed 1543 if ($this->is_feed($data, false)) { 1544 return $url; 1545 } 1546 1547 // Feeds pointed to by LINK tags in the header of the page (autodiscovery) 1548 $stage1 = $this->check_link_elements($data); 1549 if ($stage1) { 1550 return $stage1; 1551 } 1552 1553 // Grab all the links in the page, and put them into two arrays (local, and external) 1554 if ($this->get_links($data)) { 1555 1556 // <A> links to feeds on the same server ending in ".rss", ".rdf", ".xml", or ".atom" 1557 $stage2 = $this->check_link_extension($this->local); 1558 if ($stage2) { 1559 return $stage2; 1560 } 1561 1562 // <A> links to feeds on the same server containing "rss", "rdf", "xml", or "atom" 1563 $stage3 = $this->check_link_body($this->local); 1564 if ($stage3) { 1565 return $stage3; 1566 } 1567 1568 // <A> links to feeds on external servers ending in ".rss", ".rdf", ".xml", or ".atom" 1569 $stage4 = $this->check_link_extension($this->elsewhere); 1570 if ($stage4) { 1571 return $stage4; 1572 } 1573 1574 // <A> links to feeds on external servers containing "rss", "rdf", "xml", or "atom" 1575 $stage5 = $this->check_link_body($this->elsewhere); 1576 if ($stage5) { 1577 return $stage5; 1578 } 1579 } 1580 1581 return false; 1582 } 1583 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)) { 1592 return $href; 1593 } 1594 } 1595 } 1596 } 1597 } else return false; 1598 } 1599 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); 1607 } 1608 } 1609 } 1610 return false; 1611 } 1612 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); 1619 } else { 1620 $value3 = $value; 1621 } 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); 1624 } 1625 } 1626 } 1627 return false; 1628 } 1629 1630 function get_links($data) { 1631 if (preg_match_all('/href="(.*)"/iU', $data, $matches)) { 1632 $this->parse_links($matches); 1633 } 1634 if (preg_match_all('/href=\'(.*)\'/iU', $data, $matches)) { 1635 $this->parse_links($matches); 1636 } 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]); 1641 } 1642 } 1643 $this->parse_links($matches); 1644 } 1645 if (!empty($this->local) || !empty($this->elsewhere)) { 1646 $this->local = array_unique($this->local); 1647 $this->elsewhere = array_unique($this->elsewhere); 1648 return true; 1649 } else return false; 1650 } 1651 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); 1658 } else { 1659 $this->elsewhere[] = $this->absolutize_url($match, $this->parsed_url); 1660 } 1661 } 1662 } 1663 } 1664 1665 function is_feed($data, $is_url = true) { 1666 if ($is_url) { 1667 $data = $this->get_file($data); 1668 } 1669 if (stristr($data, '<!DOCTYPE HTML')) { 1670 return false; 1671 } 1672 else if (stristr($data, '<rss') || stristr($data, '<rdf:RDF') || preg_match('/<([a-z0-9]+\:)?feed/mi', $data)) { 1673 return true; 1674 } else { 1675 return false; 1676 } 1677 } 1678 1679 function absolutize_url($href, $location) { 1680 @$href_parts = parse_url($href); 1681 if (!empty($href_parts['scheme'])) { 1682 return $href; 1683 } else { 1684 if (isset($location['host'])) { 1685 $full_url = $location['scheme'] . '://' . $location['host']; 1686 } else { 1687 $full_url = ''; 1688 } 1689 if (isset($location['port'])) { 1690 $full_url .= ':' . $location['port']; 1691 } 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']; 1697 } else { 1698 $full_url .= $href_parts['path']; 1699 } 1700 } else if (!empty($location['path'])) { 1701 $full_url .= $location['path']; 1702 } else { 1703 $full_url .= '/'; 1704 } 1705 if (!empty($href_parts['query'])) { 1706 $full_url .= '?' . $href_parts['query']; 1707 } else if (!empty($location['query'])) { 1708 $full_url .= '?' . $location['query']; 1709 } 1710 if (!empty($href_parts['fragment'])) { 1711 $full_url .= '#' . $href_parts['fragment']; 1712 } else if (!empty($location['fragment'])) { 1713 $full_url .= '#' . $location['fragment']; 1714 } 1715 return $full_url; 1716 } 1717 } 1718 1719 1720 1721 1722 /**************************************************** 1723 DISPLAY IMAGES 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); 1730 1731 switch($suffix) { 1732 case 'bmp': 1733 $mime='image/bmp'; 1734 break; 1735 case 'gif': 1736 $mime='image/gif'; 1737 break; 1738 case 'ico': 1739 $mime='image/icon'; 1740 break; 1741 case 'jpe': 1742 case 'jpg': 1743 case 'jpeg': 1744 $mime='image/jpeg'; 1745 break; 1746 case 'jfif': 1747 $mime='image/pipeg'; 1748 break; 1749 case 'png': 1750 $mime='image/png'; 1751 break; 1752 case 'tif': 1753 case 'tiff': 1754 $mime='image/tiff'; 1755 break; 1756 default: 1757 $mime='image'; 1758 } 1759 1760 header('Content-type: ' . $mime); 1761 echo $image; 1762 //echo $image_url; 1763 exit; 1764 } 1765 1766 1767 1768 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"); 1784 } 1785 } 1786 closedir($handle); 1787 } 1788 } 1789 1790 1791 1792 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')) { 1798 $gch = curl_init(); 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); 1807 curl_close ($gch); 1808 } else { 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); 1815 $data = ''; 1816 while (!feof($fp) && !$status['timed_out']) { 1817 $data .= fread($fp, 2048); 1818 $status = socket_get_status($fp); 1819 } 1820 if ($status['timed_out']) 1821 return false; 1822 fclose($fp); 1823 } else return false; 1824 ini_set('user_agent', $old_ua); 1825 } 1826 return $data; 1827 } 1828 1829 1830 1831 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); 1838 else 1839 return is_writeable(dirname($file)); 1840 } 1841 1842 1843 1844 1845 /**************************************************** 1846 GET ATTRIBUTE 1847 ****************************************************/ 1848 function get_attribute($data, $attribute_name) { 1849 if (preg_match("/$attribute_name='(.*)'/iU", $data, $match)) { 1850 return $match; 1851 } else if (preg_match("/$attribute_name=\"(.*)\"/iU", $data, $match)) { 1852 return $match; 1853 } else if (preg_match("/$attribute_name=(.*)[ |\/|>]/iU", $data, $match)) { 1854 return $match; 1855 } 1856 } 1857 1858 1859 1860 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]>"; 1867 } 1868 1869 1870 1871 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); 1877 } 1878 1879 1880 1881 1882 /**************************************************** 1883 ADD DATA TO XMLDATA 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; 1890 } 1891 1892 1893 1894 1895 /**************************************************** 1896 PARSE XMLDATA 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']); 1902 } 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']); 1905 } 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']); 1908 } else { 1909 $this->feed_xmlbase = $this->parsed_url; 1910 } 1911 1912 // Feed Info 1913 if (isset($this->xmldata['feedinfo']['type'])) { 1914 $this->data['feedinfo'] = $this->xmldata['feedinfo']; 1915 } 1916 1917 // Feed Title 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']); 1920 } 1921 1922 // Feed Link(s) 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); 1928 } else { 1929 $this->data['info']['link'][$num] = $this->sanitise($link['data'], $link['attribs'], true); 1930 } 1931 } 1932 } 1933 } 1934 1935 // Feed Description 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']); 1938 } 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']); 1941 } 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']); 1944 } 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']); 1947 } 1948 1949 // Feed Language 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']); 1952 } 1953 1954 // Feed Copyright 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']); 1957 } 1958 1959 // Feed Image 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']); 1962 } 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); 1965 } 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); 1968 } 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); 1971 } 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']); 1974 } 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']); 1977 } 1978 1979 // Items 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)); 1985 } 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)); 1988 } 1989 1990 // Clear vars 1991 $id = null; 1992 $title = null; 1993 $description = null; 1994 $categories = array(); 1995 $author = array(); 1996 $date = null; 1997 $links = array(); 1998 $enclosures = array(); 1999 2000 // Title 2001 if (!empty($item['title']['data'])) { 2002 $title = $this->sanitise($item['title']['data'], $item['title']['attribs']); 2003 } 2004 else if (!empty($item['dc:title']['data'])) { 2005 $title = $this->sanitise($item['dc:title']['data'], $item['dc:title']['attribs']); 2006 } 2007 2008 // Description 2009 if (!empty($item['content']['data'])) { 2010 $description = $this->sanitise($item['content']['data'], $item['content']['attribs']); 2011 } 2012 else if (!empty($item['encoded']['data'])) { 2013 $description = $this->sanitise($item['encoded']['data'], $item['encoded']['attribs']); 2014 } 2015 else if (!empty($item['summary']['data'])) { 2016 $description = $this->sanitise($item['summary']['data'], $item['summary']['attribs']); 2017 } 2018 else if (!empty($item['description']['data'])) { 2019 $description = $this->sanitise($item['description']['data'], $item['description']['attribs']); 2020 } 2021 else if (!empty($item['dc:description']['data'])) { 2022 $description = $this->sanitise($item['dc:description']['data'], $item['dc:description']['attribs']); 2023 } 2024 else if (!empty($item['longdesc']['data'])) { 2025 $description = $this->sanitise($item['longdesc']['data'], $item['longdesc']['attribs']); 2026 } 2027 2028 // Link 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); 2034 } else { 2035 $links[sizeof($links)] = $this->sanitise($link['data'], $link['attribs'], true); 2036 } 2037 } else if ($link['attribs']['REL'] == 'enclosure' && !empty($link['attribs']['HREF'])) { 2038 $href = null; 2039 $type = null; 2040 $length = null; 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']); 2044 } 2045 if (!empty($link['attribs']['LENGTH'])) { 2046 $length = $this->sanitise($link['attribs']['LENGTH'], $link['attribs']); 2047 } 2048 $enclosures[] = new SimplePie_Enclosure($href, $type, $length); 2049 } 2050 } 2051 } 2052 2053 // Enclosures 2054 if (!empty($item['enclosure'])) { 2055 foreach ($item['enclosure'] as $enclosure) { 2056 if (!empty($enclosure['attribs']['URL'])) { 2057 $href = null; 2058 $type = null; 2059 $length = null; 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']); 2063 } 2064 if (!empty($enclosure['attribs']['LENGTH'])) { 2065 $length = $this->sanitise($enclosure['attribs']['LENGTH'], $enclosure['attribs']); 2066 } 2067 $enclosures[] = new SimplePie_Enclosure($href, $type, $length); 2068 } 2069 } 2070 } 2071 2072 // ID 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']); 2076 } 2077 $id = $this->sanitise($item['guid']['data'], $item['guid']['attribs']); 2078 } 2079 else if (!empty($item['id']['data'])) { 2080 $id = $this->sanitise($item['id']['data'], $item['id']['attribs']); 2081 } 2082 2083 // Date 2084 if (!empty($item['pubdate']['data'])) { 2085 $date = $this->parse_date($this->sanitise($item['pubdate']['data'], $item['pubdate']['attribs'])); 2086 } 2087 else if (!empty($item['dc:date']['data'])) { 2088 $date = $this->parse_date($this->sanitise($item['dc:date']['data'], $item['dc:date']['attribs'])); 2089 } 2090 else if (!empty($item['issued']['data'])) { 2091 $date = $this->parse_date($this->sanitise($item['issued']['data'], $item['issued']['attribs'])); 2092 } 2093 else if (!empty($item['published']['data'])) { 2094 $date = $this->parse_date($this->sanitise($item['published']['data'], $item['published']['attribs'])); 2095 } 2096 else if (!empty($item['modified']['data'])) { 2097 $date = $this->parse_date($this->sanitise($item['modified']['data'], $item['modified']['attribs'])); 2098 } 2099 else if (!empty($item['updated']['data'])) { 2100 $date = $this->parse_date($this->sanitise($item['updated']['data'], $item['updated']['attribs'])); 2101 } 2102 2103 // Categories 2104 if (!empty($item['category'])) { 2105 foreach ($item['category'] as $category) { 2106 $categories[sizeof($categories)] = $this->sanitise($category['data'], $category['attribs']); 2107 } 2108 } 2109 if (!empty($item['subject'])) { 2110 foreach ($item['subject'] as $category) { 2111 $categories[sizeof($categories)] = $this->sanitise($category['data'], $category['attribs']); 2112 } 2113 } 2114 2115 // Author 2116 $authors = array(); 2117 if (!empty($item['creator'])) { 2118 foreach($item['creator'] as $creator) { 2119 $authors[] = new SimplePie_Author($this->sanitise($creator['data'], $creator['attribs']), null, null); 2120 } 2121 } 2122 if (!empty($item['author'])) { 2123 foreach($item['author'] as $author) { 2124 $name = null; 2125 $link = null; 2126 $email = null; 2127 if (!empty($author['name'])) { 2128 $name = $this->sanitise($author['name']['data'], $author['name']['attribs']); 2129 } 2130 if (!empty($author['url'])) { 2131 $link = $this->sanitise($author['url']['data'], $author['url']['attribs'], true); 2132 } 2133 else if (!empty($author['uri'])) { 2134 $link = $this->sanitise($author['uri']['data'], $author['uri']['attribs'], true); 2135 } 2136 else if (!empty($author['homepage'])) { 2137 $link = $this->sanitise($author['homepage']['data'], $author['homepage']['attribs'], true); 2138 } 2139 if (!empty($author['email'])) { 2140 $email = $this->sanitise($author['email']['data'], $author['email']['attribs']); 2141 } 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]"); 2147 } else { 2148 $email = $sane; 2149 } 2150 } 2151 $authors[] = new SimplePie_Author($name, $link, $email); 2152 } 2153 } 2154 $this->data['items'][] = new SimplePie_Item($id, $title, $description, array_unique($categories), array_unique($authors), $date, array_unique($links), array_unique($enclosures)); 2155 } // End Items 2156 } 2157 unset($this->xmldata); 2158 } // End parse_xml_data_array(); 2159 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); 2167 } 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); 2171 } else { 2172 $data = preg_replace('/<div( .*)?>/msiU', '<div>', $data, 1); 2173 } 2174 $data = preg_replace("/<(\/)?$this->xhtml_prefix:/msiU", '<\\1', $data); 2175 } 2176 } else { 2177 if (empty($attribs['SPENCODED']) || $attribs['SPENCODED'] != 'false') { 2178 $data = $this->entities_decode($data); 2179 } 2180 } 2181 $data = trim($data); 2182 $data = str_replace(' spencoded="false">', '>', $data); 2183 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); 2195 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); 2200 } 2201 else { 2202 $data = preg_replace('/(<|<)(!)?(\/)?'. trim($tag) .'(\w|\s|=|-|"|\'|"|:|;|%|\/|\.|\?|&|,|#|!|\+|\(|\))*(>|>)/i', '', $data); 2203 } 2204 } 2205 } 2206 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); 2211 } 2212 } 2213 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); 2220 } 2221 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 2228 } 2229 2230 if ($is_url) { 2231 $data = $this->replace_urls($data, true); 2232 } else { 2233 $data = preg_replace_callback('/<(.+)>/msiU', array(&$this, 'replace_urls'), $data); 2234 } 2235 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); 2239 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); 2242 } 2243 else $data = preg_replace('/<img(\w|\s|=|-|"|\'|"|:|;|\/|\.|\?|&|,|#|!)*src=("|"|\')?/i', '\\0?i=', $data); 2244 } 2245 2246 return $data; 2247 } 2248 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)); 2253 } else { 2254 $attrib_xmlbase = parse_url($this->absolutize_url($this->attribs['XML:BASE'], $this->feed_xmlbase)); 2255 } 2256 } 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)); 2260 } else { 2261 $attrib_xmlbase = parse_url($this->absolutize_url($this->attribs[$this->namespaces['xml'] . ':BASE'], $this->feed_xmlbase)); 2262 } 2263 } 2264 if (!empty($attrib_xmlbase)) { 2265 $xmlbase = $attrib_xmlbase; 2266 } else if (!empty($this->item_xmlbase)) { 2267 $xmlbase = $this->item_xmlbase; 2268 } else { 2269 $xmlbase = $this->feed_xmlbase; 2270 } 2271 if ($raw_url) { 2272 return $this->absolutize_url($data, $xmlbase); 2273 } else { 2274 $attributes = array( 2275 'background', 2276 'href', 2277 'src', 2278 'longdesc', 2279 'usemap', 2280 'codebase', 2281 'data', 2282 'classid', 2283 'cite', 2284 'action', 2285 'profile', 2286 'for' 2287 ); 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]); 2292 } 2293 return $data[0]; 2294 } 2295 } 2296 2297 function entities_decode($data) { 2298 return preg_replace_callback('/&(#)?(x)?([0-9a-z]+);/mi', array(&$this, 'do_entites_decode'), $data); 2299 } 2300 2301 function do_entites_decode($data) 2302 { 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); 2307 } else { 2308 return $entity_html; 2309 } 2310 } 2311 2312 /* 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". 2317 * 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/). 2321 */ 2322 function replace_num_entity($ord) { 2323 $ord = $ord[1]; 2324 if (preg_match('/^x([0-9a-f]+)$/i', $ord, $match)) 2325 $ord = hexdec($match[1]); 2326 else 2327 $ord = intval($ord); 2328 $no_bytes = 0; 2329 $byte = array(); 2330 if ($ord < 128) 2331 return chr($ord); 2332 if ($ord < 2048) 2333 $no_bytes = 2; 2334 else if ($ord < 65536) 2335 $no_bytes = 3; 2336 else if ($ord < 1114112) 2337 $no_bytes = 4; 2338 else return; 2339 switch ($no_bytes) { 2340 case 2: 2341 $prefix = array(31, 192); 2342 break; 2343 2344 case 3: 2345 $prefix = array(15, 224); 2346 break; 2347 2348 case 4: 2349 $prefix = array(7, 240); 2350 break; 2351 } 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]; 2355 $ret = ''; 2356 for ($i=0; $i < $no_bytes; ++$i) 2357 $ret .= chr($byte[$i]); 2358 return $ret; 2359 } 2360 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) 2364 $matches[6]++; 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) 2368 $matches[6]++; 2369 return strtotime("$matches[1]-$matches[2]-$matches[3] $matches[4]:$matches[5]:$matches[6] $matches[8]$matches[9]$matches[10]"); 2370 } else { 2371 return strtotime($date); 2372 } 2373 } 2374 2375 2376 2377 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) { 2386 case 'ITEM': 2387 case $this->namespaces['rss2'] . ':ITEM': 2388 case $this->namespaces['rss1'] . ':ITEM': 2389 case 'ENTRY': 2390 case $this->namespaces['atom'] . ':ENTRY': 2391 $this->insideItem = true; 2392 $this->do_add_content($this->xmldata['items'][$this->itemNumber], ''); 2393 break; 2394 2395 case 'CHANNEL': 2396 case $this->namespaces['rss2'] . ':CHANNEL': 2397 case $this->namespaces['rss1'] . ':CHANNEL': 2398 $this->insideChannel = true; 2399 break; 2400 2401 case 'RSS': 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']); 2407 } 2408 break; 2409 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; 2414 break; 2415 2416 case 'FEED': 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']); 2422 } 2423 break; 2424 2425 case 'IMAGE': 2426 case $this->namespaces['rss2'] . ':IMAGE': 2427 case $this->namespaces['rss1'] . ':IMAGE': 2428 if ($this->insideChannel) $this->insideImage = true; 2429 break; 2430 } 2431 2432 if (isset($this->xmldata['feedinfo']['type']) && $this->xmldata['feedinfo']['type'] == 'Atom') { 2433 switch ($this->tagName) { 2434 case 'AUTHOR': 2435 case $this->namespaces['atom'] . ':AUTHOR': 2436 $this->insideAuthor = true; 2437 break; 2438 } 2439 } 2440 $this->dataHandler($this->xml, ''); 2441 } 2442 2443 function dataHandler($parser, $data) { 2444 if ($this->insideItem) { 2445 switch ($this->tagName) { 2446 case 'TITLE': 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); 2451 break; 2452 2453 case $this->namespaces['dc'] . ':TITLE': 2454 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['dc:title'], $data); 2455 break; 2456 2457 case 'CONTENT': 2458 case $this->namespaces['atom'] . ':CONTENT': 2459 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['content'], $data); 2460 break; 2461 2462 case $this->namespaces['content'] . ':ENCODED': 2463 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['encoded'], $data); 2464 break; 2465 2466 case 'SUMMARY': 2467 case $this->namespaces['atom'] . ':SUMMARY': 2468 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['summary'], $data); 2469 break; 2470 2471 case 'LONGDESC': 2472 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['longdesc'], $data); 2473 break; 2474 2475 case 'DESCRIPTION': 2476 case $this->namespaces['rss1'] . ':DESCRIPTION': 2477 case $this->namespaces['rss2'] . ':DESCRIPTION': 2478 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['description'], $data); 2479 break; 2480 2481 case $this->namespaces['dc'] . ':DESCRIPTION': 2482 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['dc:description'], $data); 2483 break; 2484 2485 case 'LINK': 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); 2490 break; 2491 2492 case 'ENCLOSURE': 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); 2496 break; 2497 2498 case 'GUID': 2499 case $this->namespaces['rss1'] . ':GUID': 2500 case $this->namespaces['rss2'] . ':GUID': 2501 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['guid'], $data); 2502 break; 2503 2504 case 'ID': 2505 case $this->namespaces['atom'] . ':ID': 2506 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['id'], $data); 2507 break; 2508 2509 case 'PUBDATE': 2510 case $this->namespaces['rss1'] . ':PUBDATE': 2511 case $this->namespaces['rss2'] . ':PUBDATE': 2512 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['pubdate'], $data); 2513 break; 2514 2515 case $this->namespaces['dc'] . ':DATE': 2516 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['dc:date'], $data); 2517 break; 2518 2519 case 'ISSUED': 2520 case $this->namespaces['atom'] . ':ISSUED': 2521 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['issued'], $data); 2522 break; 2523 2524 case 'PUBLISHED': 2525 case $this->namespaces['atom'] . ':PUBLISHED': 2526 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['published'], $data); 2527 break; 2528 2529 case 'MODIFIED': 2530 case $this->namespaces['atom'] . ':MODIFIED': 2531 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['modified'], $data); 2532 break; 2533 2534 case 'UPDATED': 2535 case $this->namespaces['atom'] . ':UPDATED': 2536 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['updated'], $data); 2537 break; 2538 2539 case 'CATEGORY': 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); 2544 break; 2545 2546 case $this->namespaces['dc'] . ':SUBJECT': 2547 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['subject'][$this->categoryNumber], $data); 2548 break; 2549 2550 case $this->namespaces['dc'] . ':CREATOR': 2551 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['creator'][$this->authorNumber], $data); 2552 break; 2553 2554 case 'AUTHOR': 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); 2558 break; 2559 } 2560 2561 if ($this->insideAuthor) { 2562 switch ($this->tagName) { 2563 case 'NAME': 2564 case $this->namespaces['atom'] . ':NAME': 2565 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['name'], $data); 2566 break; 2567 2568 case 'URL': 2569 case $this->namespaces['atom'] . ':URL': 2570 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['url'], $data); 2571 break; 2572 2573 case 'URI': 2574 case $this->namespaces['atom'] . ':URI': 2575 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['uri'], $data); 2576 break; 2577 2578 case 'HOMEPAGE': 2579 case $this->namespaces['atom'] . ':HOMEPAGE': 2580 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['homepage'], $data); 2581 break; 2582 2583 case 'EMAIL': 2584 case $this->namespaces['atom'] . ':EMAIL': 2585 $this->do_add_content($this->xmldata['items'][$this->itemNumber]['author'][$this->authorNumber]['email'], $data); 2586 break; 2587 } 2588 } 2589 } 2590 2591 else if (($this->insideChannel && !$this->insideImage) || (isset($this->xmldata['feedinfo']['type']) && $this->xmldata['feedinfo']['type'] == 'Atom')) { 2592 switch ($this->tagName) { 2593 case 'TITLE': 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); 2598 break; 2599 2600 case 'LINK': 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); 2605 break; 2606 2607 case 'DESCRIPTION': 2608 case $this->namespaces['rss1'] . ':DESCRIPTION': 2609 case $this->namespaces['rss2'] . ':DESCRIPTION': 2610 $this->do_add_content($this->xmldata['info']['description'], $data); 2611 break; 2612 2613 case $this->namespaces['dc'] . ':DESCRIPTION': 2614 $this->do_add_content($this->xmldata['info']['dc:description'], $data); 2615 break; 2616 2617 case 'TAGLINE': 2618 case $this->namespaces['atom'] . ':TAGLINE': 2619 $this->do_add_content($this->xmldata['info']['tagline'], $data); 2620 break; 2621 2622 case 'SUBTITLE': 2623 case $this->namespaces['atom'] . ':SUBTITLE': 2624 $this->do_add_content($this->xmldata['info']['subtitle'], $data); 2625 break; 2626 2627 case 'COPYRIGHT': 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); 2632 break; 2633 2634 case 'LANGUAGE': 2635 case $this->namespaces['rss1'] . ':LANGUAGE': 2636 case $this->namespaces['rss2'] . ':LANGUAGE': 2637 $this->do_add_content($this->xmldata['info']['language'], $data); 2638 break; 2639 2640 case 'LOGO': 2641 case $this->namespaces['atom'] . ':LOGO': 2642 $this->do_add_content($this->xmldata['info']['logo'], $data); 2643 break; 2644 2645 } 2646 } 2647 2648 else if ($this->insideChannel && $this->insideImage) { 2649 switch ($this->tagName) { 2650 case 'TITLE': 2651 case $this->namespaces['rss1'] . ':TITLE': 2652 case $this->namespaces['rss2'] . ':TITLE': 2653 $this->do_add_content($this->xmldata['info']['image']['title'], $data); 2654 break; 2655 2656 case 'URL': 2657 case $this->namespaces['rss1'] . ':URL': 2658 case $this->namespaces['rss2'] . ':URL': 2659 $this->do_add_content($this->xmldata['info']['image']['url'], $data); 2660 break; 2661 2662 case 'LINK': 2663 case $this->namespaces['rss1'] . ':LINK': 2664 case $this->namespaces['rss2'] . ':LINK': 2665 $this->do_add_content($this->xmldata['info']['image']['link'], $data); 2666 break; 2667 2668 case 'WIDTH': 2669 case $this->namespaces['rss1'] . ':WIDTH': 2670 case $this->namespaces['rss2'] . ':WIDTH': 2671 $this->do_add_content($this->xmldata['info']['image']['width'], $data); 2672 break; 2673 2674 case 'HEIGHT': 2675 case $this->namespaces['rss1'] . ':HEIGHT': 2676 case $this->namespaces['rss2'] . ':HEIGHT': 2677 $this->do_add_content($this->xmldata['info']['image']['height'], $data); 2678 break; 2679 } 2680 } 2681 $this->is_first = false; 2682 } 2683 2684 function endHandler($parser, $name) { 2685 $this->tagName = ''; 2686 switch ($name) { 2687 case 'ITEM': 2688 case $this->namespaces['rss1'] . ':ITEM': 2689 case $this->namespaces['rss2'] . ':ITEM': 2690 case 'ENTRY': 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; 2698 break; 2699 2700 case 'CHANNEL': 2701 case $this->namespaces['rss1'] . ':CHANNEL': 2702 case $this->namespaces['rss2'] . ':CHANNEL': 2703 $this->insideChannel = false; 2704 break; 2705 2706 case 'IMAGE': 2707 case $this->namespaces['rss1'] . ':IMAGE': 2708 case $this->namespaces['rss2'] . ':IMAGE': 2709 if ($this->insideChannel) $this->insideImage = false; 2710 break; 2711 2712 case 'AUTHOR': 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; 2718 break; 2719 2720 case 'CATEGORY': 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++; 2726 break; 2727 2728 case 'ENCLOSURE': 2729 case $this->namespaces['rss1'] . ':ENCLOSURE': 2730 case $this->namespaces['rss2'] . ':ENCLOSURE': 2731 $this->enclosureNumber++; 2732 break; 2733 2734 case 'LINK': 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++; 2740 else 2741 $this->linkNumber++; 2742 break; 2743 } 2744 } 2745 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; 2751 } 2752 else if ($prefix == 'RSS2' || $uri == 'HTTP://BACKEND.USERLAND.COM/RSS2') { 2753 $this->namespaces['rss2'] = $uri; 2754 } 2755 else if ($prefix == 'RDF' || $uri == 'HTTP://WWW.W3.ORG/1999/02/22-RDF-SYNTAX-NS#') { 2756 $this->namespaces['rdf'] = $uri; 2757 } 2758 else if ($prefix == 'RSS' || $uri == 'HTTP://PURL.ORG/RSS/1.0/') { 2759 $this->namespaces['rss1'] = $uri; 2760 } 2761 else if ($prefix == 'DC' || $uri == 'HTTP://PURL.ORG/DC/ELEMENTS/1.1/') { 2762 $this->namespaces['dc'] = $uri; 2763 } 2764 else if ($prefix == 'XHTML' || $uri == 'HTTP://WWW.W3.ORG/1999/XHTML') { 2765 $this->namespaces['xhtml'] = $uri; 2766 $this->xhtml_prefix = $prefix; 2767 } 2768 else if ($prefix == 'CONTENT' || $uri == 'HTTP://PURL.ORG/RSS/1.0/MODULES/CONTENT/') { 2769 $this->namespaces['content'] = $uri; 2770 } 2771 } 2772 2773 function endNameSpace($parser, $prefix) { 2774 if ($key = array_search(strtoupper($prefix), $this->namespaces)) { 2775 if ($key == 'atom') { 2776 $this->namespaces['atom'] = 'ATOM'; 2777 } 2778 else if ($key == 'rss2') { 2779 $this->namespaces['rss2'] = 'RSS'; 2780 } 2781 else if ($key == 'rdf') { 2782 $this->namespaces['rdf'] = 'RDF'; 2783 } 2784 else if ($key == 'rss1') { 2785 $this->namespaces['rss1'] = 'RSS'; 2786 } 2787 else if ($key == 'dc') { 2788 $this->namespaces['dc'] = 'DC'; 2789 } 2790 else if ($key == 'xhtml') { 2791 $this->namespaces['xhtml'] = 'XHTML'; 2792 $this->xhtml_prefix = 'XHTML'; 2793 } 2794 else if ($key == 'content') { 2795 $this->namespaces['content'] = 'CONTENT'; 2796 } 2797 } 2798 } 2799 } 2800 2801 class SimplePie_Item 2802 { 2803 function SimplePie_Item($id, $title, $description, $category, $author, $date, $links, $enclosure) { 2804 $this->id = $id; 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; 2812 } 2813 2814 /**************************************************** 2815 PARSE OUT ITEM-RELATED DATA 2816 ****************************************************/ 2817 // Get the id of the item 2818 function get_id() { 2819 return (empty($this->id)) ? false : $this->id; 2820 } 2821 // Get the title of the item 2822 function get_title() { 2823 return (empty($this->title)) ? false : $this->title; 2824 } 2825 2826 // Get the description of the item 2827 function get_description() { 2828 return (empty($this->description)) ? false : $this->description; 2829 } 2830 2831 // Get the category of the item 2832 function get_category() { 2833 return (empty($this->category)) ? false : $this->category; 2834 } 2835 2836 // Get the author of the item 2837 function get_author($key) { 2838 return (empty($this->author[$key])) ? false : $this->author[$key]; 2839 } 2840 2841 // Get the author of the item 2842 function get_authors() { 2843 return (empty($this->author)) ? false : $this->author; 2844 } 2845 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); 2850 } 2851 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]; 2857 } 2858 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); 2862 } 2863 else return false; 2864 } 2865 2866 // Get all links 2867 function get_links() { 2868 return (empty($this->links)) ? false : $this->links; 2869 } 2870 2871 // Get the enclosure of the item 2872 function get_enclosure($key) { 2873 return (empty($this->enclosure[$key])) ? false : $this->enclosure[$key]; 2874 } 2875 2876 // Get the enclosure of the item 2877 function get_enclosures() { 2878 return (empty($this->enclosure)) ? false : $this->enclosure; 2879 } 2880 2881 2882 2883 2884 /**************************************************** 2885 "ADD TO" LINKS 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()); 2890 } 2891 2892 function add_to_delicious() { 2893 return "http://del.icio.us/post/?v=3&url=" . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title()); 2894 } 2895 2896 function add_to_digg() { 2897 return "http://digg.com/submit?phase=2&URL=" . rawurlencode($this->get_permalink()); 2898 } 2899 2900 function add_to_furl() { 2901 return "http://www.furl.net/storeIt.jsp?u=" . rawurlencode($this->get_permalink()) . "&t=" . rawurlencode($this->get_title()); 2902 } 2903 2904 function add_to_magnolia() { 2905 return "http://ma.gnolia.com/bookmarklet/add?url=" . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title()); 2906 } 2907 2908 function add_to_myweb20() { 2909 return "http://myweb2.search.yahoo.com/myresults/bookmarklet?u=" . rawurlencode($this->get_permalink()) . "&t=" . rawurlencode($this->get_title()); 2910 } 2911 2912 function add_to_newsvine() { 2913 return "http://www.newsvine.com/_wine/save?u=" . rawurlencode($this->get_permalink()) . "&h=" . rawurlencode($this->get_title()); 2914 } 2915 2916 function add_to_reddit() { 2917 return 'http://reddit.com/submit?url=' . rawurlencode($this->get_permalink()) . "&title=" . rawurlencode($this->get_title()); 2918 } 2919 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()); 2922 } 2923 2924 2925 2926 2927 /**************************************************** 2928 SEARCHES 2929 Metadata searches 2930 ****************************************************/ 2931 function search_technorati() { 2932 return 'http://www.technorati.com/search/' . rawurlencode($this->get_permalink()); 2933 } 2934 } 2935 2936 class SimplePie_Author 2937 { 2938 var $name; 2939 var $link; 2940 var $email; 2941 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; 2947 } 2948 2949 function get_name() { 2950 return (empty($this->name)) ? false : $this->name; 2951 } 2952 2953 function get_link() { 2954 return (empty($this->link)) ? false : $this->link; 2955 } 2956 2957 function get_email() { 2958 return (empty($this->email)) ? false : $this->email; 2959 } 2960 } 2961 2962 class SimplePie_Enclosure 2963 { 2964 var $link; 2965 var $type; 2966 var $length; 2967 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; 2973 } 2974 2975 function get_link() { 2976 return (empty($this->link)) ? false : $this->link; 2977 } 2978 2979 function get_extension() { 2980 if (!empty($this->link)) { 2981 return pathinfo($this->link, PATHINFO_EXTENSION); 2982 } else { 2983 return false; 2984 } 2985 } 2986 2987 function get_type() { 2988 return (empty($this->type)) ? false : $this->type; 2989 } 2990 2991 function get_length() { 2992 return (empty($this->length)) ? false : $this->length; 2993 } 2994 2995 function get_size() { 2996 return (empty($this->length)) ? false : round(($this->length/1048576), 2); 2997 } 2998 2999 function embed($options) { 3000 3001 // Set up defaults 3002 $audio=''; 3003 $video=''; 3004 $alt=''; 3005 $altclass=''; 3006 $loop='false'; 3007 $width='auto'; 3008 $height='auto'; 3009 $bgcolor='#ffffff'; 3010 $embed=''; 3011 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]; 3024 } 3025 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'; 3030 else $width='100%'; 3031 } 3032 if ($height == 'auto') { 3033 if (stristr($this->type, 'audio/')) $height=0; 3034 else if (stristr($this->type, 'video/')) $height=240; 3035 else $height=256; 3036 } 3037 3038 // Set proper placeholder value 3039 if (stristr($this->type, 'audio/')) $placeholder=$audio; 3040 else if (stristr($this->type, 'video/')) $placeholder=$video; 3041 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>'; 3045 3046 // Odeo Feed MP3's 3047 if (substr(strtolower($this->link), 0, 15) == 'http://odeo.com') { 3048 $embed.='<script type="text/javascript">embed_odeo("'.$this->link.'");</script>'; 3049 } 3050 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') { 3053 $height+=16; 3054 $embed.='<script type="text/javascript">embed_quicktime("'.$this->type.'", "'.$bgcolor.'", "'.$width.'", "'.$height.'", "'.$this->link.'", "'.$placeholder.'", "'.$loop.'");</script>'; 3055 } 3056 3057 // Flash 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>'; 3060 } 3061 3062 // Windows Media 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') { 3064 $height+=45; 3065 $embed.='<script type="text/javascript">embed_wmedia("'.$width.'", "'.$height.'", "'.$this->link.'");</script>'; 3066 } 3067 3068 // Everything else 3069 else $embed.='<a href="' . $this->link . '" class="' . $altclass . '">' . $alt . '</a>'; 3070 3071 return $embed; 3072 } 3073 } 3074 3075 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Tue Apr 3 20:47:31 2007 | par Balluche grâce à PHPXref 0.7 |