| [ Index ] |
|
Code source de Joomla 1.0.13 |
1 <?php 2 /*************************************************************************** 3 4 FeedCreator class v1.7.2 5 originally (c) Kai Blankenhorn 6 www.bitfolge.de 7 kaib@bitfolge.de 8 v1.3 work by Scott Reynen (scott@randomchaos.com) and Kai Blankenhorn 9 v1.5 OPML support by Dirk Clemens 10 11 This library is free software; you can redistribute it and/or 12 modify it under the terms of the GNU Lesser General Public 13 License as published by the Free Software Foundation; either 14 version 2.1 of the License, or (at your option) any later version. 15 16 This library is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 Lesser General Public License for more details. 20 21 You should have received a copy of the GNU Lesser General Public 22 License along with this library; if not, write to the Free Software 23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 25 **************************************************************************** 26 27 28 Changelog: 29 30 v1.7.2 Joomla! 1.0.8 31 12-Feb-2005 Rey Gigataras 32 - Fixed artf3438 : RSS Feed Created it not base on the same encoding of the content 33 34 v1.7.2 Joomla! 1.0 35 15-Sep-2005 Rey Gigataras 36 ^ Added publish date to syndicated feeds output [credit: gharding] 37 ^ Added RSS Enclosure support to feedcreator [credit: Joseph L. LeBlanc] 38 ^ Added Google Sitemap support to feedcreator 39 40 ********************************* 41 42 v1.7.2 10-11-04 43 license changed to LGPL 44 45 v1.7.1 46 fixed a syntax bug 47 fixed left over debug code 48 49 v1.7 07-18-04 50 added HTML and JavaScript feeds (configurable via CSS) (thanks to Pascal Van Hecke) 51 added HTML descriptions for all feed formats (thanks to Pascal Van Hecke) 52 added a switch to select an external stylesheet (thanks to Pascal Van Hecke) 53 changed default content-type to application/xml 54 added character encoding setting 55 fixed numerous smaller bugs (thanks to S�ren Fuhrmann of golem.de) 56 improved changing ATOM versions handling (thanks to August Trometer) 57 improved the UniversalFeedCreator's useCached method (thanks to S�ren Fuhrmann of golem.de) 58 added charset output in HTTP headers (thanks to S�ren Fuhrmann of golem.de) 59 added Slashdot namespace to RSS 1.0 (thanks to S�ren Fuhrmann of golem.de) 60 61 v1.6 05-10-04 62 added stylesheet to RSS 1.0 feeds 63 fixed generator comment (thanks Kevin L. Papendick and Tanguy Pruvot) 64 fixed RFC822 date bug (thanks Tanguy Pruvot) 65 added TimeZone customization for RFC8601 (thanks Tanguy Pruvot) 66 fixed Content-type could be empty (thanks Tanguy Pruvot) 67 fixed author/creator in RSS1.0 (thanks Tanguy Pruvot) 68 69 v1.6 beta 02-28-04 70 added Atom 0.3 support (not all features, though) 71 improved OPML 1.0 support (hopefully - added more elements) 72 added support for arbitrary additional elements (use with caution) 73 code beautification :-) 74 considered beta due to some internal changes 75 76 v1.5.1 01-27-04 77 fixed some RSS 1.0 glitches (thanks to St�phane Vanpoperynghe) 78 fixed some inconsistencies between documentation and code (thanks to Timothy Martin) 79 80 v1.5 01-06-04 81 added support for OPML 1.0 82 added more documentation 83 84 v1.4 11-11-03 85 optional feed saving and caching 86 improved documentation 87 minor improvements 88 89 v1.3 10-02-03 90 renamed to FeedCreator, as it not only creates RSS anymore 91 added support for mbox 92 tentative support for echo/necho/atom/pie/??? 93 94 v1.2 07-20-03 95 intelligent auto-truncating of RSS 0.91 attributes 96 don't create some attributes when they're not set 97 documentation improved 98 fixed a real and a possible bug with date conversions 99 code cleanup 100 101 v1.1 06-29-03 102 added images to feeds 103 now includes most RSS 0.91 attributes 104 added RSS 2.0 feeds 105 106 v1.0 06-24-03 107 initial release 108 109 110 111 ***************************************************************************/ 112 113 /*** GENERAL USAGE ********************************************************* 114 115 include("feedcreator.class.php"); 116 117 $rss = new UniversalFeedCreator(); 118 $rss->useCached(); // use cached version if age<1 hour 119 $rss->title = "PHP news"; 120 $rss->description = "daily news from the PHP scripting world"; 121 122 //optional 123 $rss->descriptionTruncSize = 500; 124 $rss->descriptionHtmlSyndicated = true; 125 126 $rss->link = "http://www.dailyphp.net/news"; 127 $rss->syndicationURL = "http://www.dailyphp.net/".$_SERVER["PHP_SELF"]; 128 129 $image = new FeedImage(); 130 $image->title = "dailyphp.net logo"; 131 $image->url = "http://www.dailyphp.net/images/logo.gif"; 132 $image->link = "http://www.dailyphp.net"; 133 $image->description = "Feed provided by dailyphp.net. Click to visit."; 134 135 //optional 136 $image->descriptionTruncSize = 500; 137 $image->descriptionHtmlSyndicated = true; 138 139 $rss->image = $image; 140 141 // get your news items from somewhere, e.g. your database: 142 mysql_select_db($dbHost, $dbUser, $dbPass); 143 $res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC"); 144 while ($data = mysql_fetch_object($res)) { 145 $item = new FeedItem(); 146 $item->title = $data->title; 147 $item->link = $data->url; 148 $item->description = $data->short; 149 150 //optional 151 item->descriptionTruncSize = 500; 152 item->descriptionHtmlSyndicated = true; 153 154 $item->date = $data->newsdate; 155 $item->source = "http://www.dailyphp.net"; 156 $item->author = "John Doe"; 157 158 $rss->addItem($item); 159 } 160 161 // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1 (deprecated), 162 // MBOX, OPML, ATOM, ATOM0.3, HTML, JS 163 echo $rss->saveFeed("RSS1.0", "news/feed.xml"); 164 165 166 *************************************************************************** 167 * A little setup * 168 **************************************************************************/ 169 170 // no direct access 171 defined( '_VALID_MOS' ) or die( 'Restricted access' ); 172 173 174 // your local timezone, set to "" to disable or for GMT 175 define("TIME_ZONE","+01:00"); 176 177 178 179 /** 180 * Version string. 181 **/ 182 define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2"); 183 184 185 186 /** 187 * A FeedItem is a part of a FeedCreator feed. 188 * 189 * @author Kai Blankenhorn <kaib@bitfolge.de> 190 * @since 1.3 191 */ 192 class FeedItem extends HtmlDescribable { 193 /** 194 * Mandatory attributes of an item. 195 */ 196 var $title, $description, $link; 197 198 /** 199 * Optional attributes of an item. 200 */ 201 var $author, $authorEmail, $image, $category, $comments, $guid, $source, $creator; 202 203 /** 204 * Publishing date of an item. May be in one of the following formats: 205 * 206 * RFC 822: 207 * "Mon, 20 Jan 03 18:05:41 +0400" 208 * "20 Jan 03 18:05:41 +0000" 209 * 210 * ISO 8601: 211 * "2003-01-20T18:05:41+04:00" 212 * 213 * Unix: 214 * 1043082341 215 */ 216 var $date; 217 218 /** 219 * Any additional elements to include as an assiciated array. All $key => $value pairs 220 * will be included unencoded in the feed item in the form 221 * <$key>$value</$key> 222 * Again: No encoding will be used! This means you can invalidate or enhance the feed 223 * if $value contains markup. This may be abused to embed tags not implemented by 224 * the FeedCreator class used. 225 */ 226 var $additionalElements = Array(); 227 228 229 // Added by Joseph LeBlanc, contact@jlleblanc.com 230 231 var $enclosures = Array(); 232 233 function addEnclosure($url, $length = 0, $type) { 234 $this->enclosures[] = array("url" => $url, "length" => $length, "type" => $type); 235 } 236 237 // end add, Joseph LeBlanc 238 239 // on hold 240 // var $source; 241 } 242 243 244 245 /** 246 * An FeedImage may be added to a FeedCreator feed. 247 * @author Kai Blankenhorn <kaib@bitfolge.de> 248 * @since 1.3 249 */ 250 class FeedImage extends HtmlDescribable { 251 /** 252 * Mandatory attributes of an image. 253 */ 254 var $title, $url, $link; 255 256 /** 257 * Optional attributes of an image. 258 */ 259 var $width, $height, $description; 260 } 261 262 263 264 /** 265 * An HtmlDescribable is an item within a feed that can have a description that may 266 * include HTML markup. 267 */ 268 class HtmlDescribable { 269 /** 270 * Indicates whether the description field should be rendered in HTML. 271 */ 272 var $descriptionHtmlSyndicated; 273 274 /** 275 * Indicates whether and to how many characters a description should be truncated. 276 */ 277 var $descriptionTruncSize; 278 279 /** 280 * Returns a formatted description field, depending on descriptionHtmlSyndicated and 281 * $descriptionTruncSize properties 282 * @return string the formatted description 283 */ 284 function getDescription() { 285 $descriptionField = new FeedHtmlField($this->description); 286 $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated; 287 $descriptionField->truncSize = $this->descriptionTruncSize; 288 return $descriptionField->output(); 289 } 290 291 } 292 293 294 /** 295 * An FeedHtmlField describes and generates 296 * a feed, item or image html field (probably a description). Output is 297 * generated based on $truncSize, $syndicateHtml properties. 298 * @author Pascal Van Hecke <feedcreator.class.php@vanhecke.info> 299 * @version 1.6 300 */ 301 class FeedHtmlField { 302 /** 303 * Mandatory attributes of a FeedHtmlField. 304 */ 305 var $rawFieldContent; 306 307 /** 308 * Optional attributes of a FeedHtmlField. 309 * 310 */ 311 var $truncSize, $syndicateHtml; 312 313 /** 314 * Creates a new instance of FeedHtmlField. 315 * @param $string: if given, sets the rawFieldContent property 316 */ 317 function FeedHtmlField($parFieldContent) { 318 if ($parFieldContent) { 319 $this->rawFieldContent = $parFieldContent; 320 } 321 } 322 323 324 /** 325 * Creates the right output, depending on $truncSize, $syndicateHtml properties. 326 * @return string the formatted field 327 */ 328 function output() { 329 // when field available and syndicated in html we assume 330 // - valid html in $rawFieldContent and we enclose in CDATA tags 331 // - no truncation (truncating risks producing invalid html) 332 if (!$this->rawFieldContent) { 333 $result = ""; 334 } elseif ($this->syndicateHtml) { 335 $result = "<![CDATA[".$this->rawFieldContent."]]>"; 336 } else { 337 if ($this->truncSize and is_int($this->truncSize)) { 338 $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize); 339 } else { 340 $result = htmlspecialchars($this->rawFieldContent); 341 } 342 } 343 return $result; 344 } 345 346 } 347 348 349 350 /** 351 * UniversalFeedCreator lets you choose during runtime which 352 * format to build. 353 * For general usage of a feed class, see the FeedCreator class 354 * below or the example above. 355 * 356 * @since 1.3 357 * @author Kai Blankenhorn <kaib@bitfolge.de> 358 */ 359 class UniversalFeedCreator extends FeedCreator { 360 var $_feed; 361 362 function _setFormat($format) { 363 switch (strtoupper($format)) { 364 365 case "2.0": 366 // fall through 367 case "RSS2.0": 368 $this->_feed = new RSSCreator20(); 369 break; 370 371 case "1.0": 372 // fall through 373 case "RSS1.0": 374 $this->_feed = new RSSCreator10(); 375 break; 376 377 case "0.91": 378 // fall through 379 case "RSS0.91": 380 $this->_feed = new RSSCreator091(); 381 break; 382 383 case "PIE0.1": 384 $this->_feed = new PIECreator01(); 385 break; 386 387 case "MBOX": 388 $this->_feed = new MBOXCreator(); 389 break; 390 391 case "OPML": 392 $this->_feed = new OPMLCreator(); 393 break; 394 395 case "ATOM": 396 // fall through: always the latest ATOM version 397 398 case "ATOM0.3": 399 $this->_feed = new AtomCreator03(); 400 break; 401 402 case "HTML": 403 $this->_feed = new HTMLCreator(); 404 break; 405 406 case "JS": 407 // fall through 408 case "JAVASCRIPT": 409 $this->_feed = new JSCreator(); 410 break; 411 412 default: 413 $this->_feed = new RSSCreator091(); 414 break; 415 } 416 417 $vars = get_object_vars($this); 418 foreach ($vars as $key => $value) { 419 // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself 420 if (!in_array($key, array("_feed", "contentType"))) { 421 $this->_feed->{$key} = $this->{$key}; 422 } 423 } 424 } 425 426 /** 427 * Creates a syndication feed based on the items previously added. 428 * 429 * @see FeedCreator::addItem() 430 * @param string format format the feed should comply to. Valid values are: 431 * "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS" 432 * @return string the contents of the feed. 433 */ 434 function createFeed($format = "RSS0.91") { 435 $this->_setFormat($format); 436 return $this->_feed->createFeed(); 437 } 438 439 440 441 /** 442 * Saves this feed as a file on the local disk. After the file is saved, an HTTP redirect 443 * header may be sent to redirect the use to the newly created file. 444 * @since 1.4 445 * 446 * @param string format format the feed should comply to. Valid values are: 447 * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS" 448 * @param string filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()). 449 * @param boolean displayContents optional send the content of the file or not. If true, the file will be sent in the body of the response. 450 */ 451 function saveFeed($format="RSS0.91", $filename="", $displayContents=true) { 452 $this->_setFormat($format); 453 $this->_feed->saveFeed($filename, $displayContents); 454 } 455 456 457 /** 458 * Turns on caching and checks if there is a recent version of this feed in the cache. 459 * If there is, an HTTP redirect header is sent. 460 * To effectively use caching, you should create the FeedCreator object and call this method 461 * before anything else, especially before you do the time consuming task to build the feed 462 * (web fetching, for example). 463 * 464 * @param string format format the feed should comply to. Valid values are: 465 * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3". 466 * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()). 467 * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour) 468 */ 469 function useCached($format="RSS0.91", $filename="", $timeout=3600) { 470 $this->_setFormat($format); 471 $this->_feed->useCached($filename, $timeout); 472 } 473 474 } 475 476 477 /** 478 * FeedCreator is the abstract base implementation for concrete 479 * implementations that implement a specific format of syndication. 480 * 481 * @abstract 482 * @author Kai Blankenhorn <kaib@bitfolge.de> 483 * @since 1.4 484 */ 485 class FeedCreator extends HtmlDescribable { 486 487 /** 488 * Mandatory attributes of a feed. 489 */ 490 var $title, $description, $link; 491 492 493 /** 494 * Optional attributes of a feed. 495 */ 496 var $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays; 497 498 /** 499 * The url of the external xsl stylesheet used to format the naked rss feed. 500 * Ignored in the output when empty. 501 */ 502 var $xslStyleSheet = ""; 503 504 505 /** 506 * @access private 507 */ 508 var $items = Array(); 509 510 511 /** 512 * This feed's MIME content type. 513 * @since 1.4 514 * @access private 515 */ 516 var $contentType = "application/xml"; 517 518 519 /** 520 * This feed's character encoding. 521 * @since 1.6.1 522 **/ 523 var $encoding = "ISO-8859-1"; 524 525 526 /** 527 * Any additional elements to include as an assiciated array. All $key => $value pairs 528 * will be included unencoded in the feed in the form 529 * <$key>$value</$key> 530 * Again: No encoding will be used! This means you can invalidate or enhance the feed 531 * if $value contains markup. This may be abused to embed tags not implemented by 532 * the FeedCreator class used. 533 */ 534 var $additionalElements = Array(); 535 536 537 /** 538 * Adds an FeedItem to the feed. 539 * 540 * @param object FeedItem $item The FeedItem to add to the feed. 541 * @access public 542 */ 543 function addItem($item) { 544 $this->items[] = $item; 545 } 546 547 548 /** 549 * Truncates a string to a certain length at the most sensible point. 550 * First, if there's a '.' character near the end of the string, the string is truncated after this character. 551 * If there is no '.', the string is truncated after the last ' ' character. 552 * If the string is truncated, " ..." is appended. 553 * If the string is already shorter than $length, it is returned unchanged. 554 * 555 * @static 556 * @param string string A string to be truncated. 557 * @param int length the maximum length the string should be truncated to 558 * @return string the truncated string 559 */ 560 function iTrunc($string, $length) { 561 if (strlen($string)<=$length) { 562 return $string; 563 } 564 565 $pos = strrpos($string,"."); 566 if ($pos>=$length-4) { 567 $string = substr($string,0,$length-4); 568 $pos = strrpos($string,"."); 569 } 570 if ($pos>=$length*0.4) { 571 return substr($string,0,$pos+1)." ..."; 572 } 573 574 $pos = strrpos($string," "); 575 if ($pos>=$length-4) { 576 $string = substr($string,0,$length-4); 577 $pos = strrpos($string," "); 578 } 579 if ($pos>=$length*0.4) { 580 return substr($string,0,$pos)." ..."; 581 } 582 583 return substr($string,0,$length-4)." ..."; 584 585 } 586 587 588 /** 589 * Creates a comment indicating the generator of this feed. 590 * The format of this comment seems to be recognized by 591 * Syndic8.com. 592 */ 593 function _createGeneratorComment() { 594 return "<!-- generator=\"".FEEDCREATOR_VERSION."\" -->\n"; 595 } 596 597 598 /** 599 * Creates a string containing all additional elements specified in 600 * $additionalElements. 601 * @param elements array an associative array containing key => value pairs 602 * @param indentString string a string that will be inserted before every generated line 603 * @return string the XML tags corresponding to $additionalElements 604 */ 605 function _createAdditionalElements($elements, $indentString="") { 606 $ae = ""; 607 if (is_array($elements)) { 608 foreach($elements AS $key => $value) { 609 $ae.= $indentString."<$key>$value</$key>\n"; 610 } 611 } 612 return $ae; 613 } 614 615 function _createStylesheetReferences() { 616 $xml = ""; 617 if ($this->cssStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n"; 618 if ($this->xslStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->xslStyleSheet."\" type=\"text/xsl\"?>\n"; 619 return $xml; 620 } 621 622 623 /** 624 * Builds the feed's text. 625 * @abstract 626 * @return string the feed's complete text 627 */ 628 function createFeed() { 629 } 630 631 /** 632 * Generate a filename for the feed cache file. The result will be $_SERVER["PHP_SELF"] with the extension changed to .xml. 633 * For example: 634 * 635 * echo $_SERVER["PHP_SELF"]."\n"; 636 * echo FeedCreator::_generateFilename(); 637 * 638 * would produce: 639 * 640 * /rss/latestnews.php 641 * latestnews.xml 642 * 643 * @return string the feed cache filename 644 * @since 1.4 645 * @access private 646 */ 647 function _generateFilename() { 648 $fileInfo = pathinfo($_SERVER["PHP_SELF"]); 649 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".xml"; 650 } 651 652 653 /** 654 * @since 1.4 655 * @access private 656 */ 657 function _redirect($filename) { 658 // attention, heavily-commented-out-area 659 660 // maybe use this in addition to file time checking 661 //Header("Expires: ".date("r",time()+$this->_timeout)); 662 663 /* no caching at all, doesn't seem to work as good: 664 Header("Cache-Control: no-cache"); 665 Header("Pragma: no-cache"); 666 */ 667 668 // HTTP redirect, some feed readers' simple HTTP implementations don't follow it 669 //Header("Location: ".$filename); 670 671 //Header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename)); 672 Header("Content-Type: ".$this->contentType."; charset=".$this->encoding); 673 Header("Content-Disposition: inline; filename=".basename($filename)); 674 readfile($filename, "r"); 675 die(); 676 } 677 678 /** 679 * Turns on caching and checks if there is a recent version of this feed in the cache. 680 * If there is, an HTTP redirect header is sent. 681 * To effectively use caching, you should create the FeedCreator object and call this method 682 * before anything else, especially before you do the time consuming task to build the feed 683 * (web fetching, for example). 684 * @since 1.4 685 * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()). 686 * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour) 687 */ 688 function useCached($filename="", $timeout=3600) { 689 $this->_timeout = $timeout; 690 if ($filename=="") { 691 $filename = $this->_generateFilename(); 692 } 693 if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) { 694 $this->_redirect($filename); 695 } 696 } 697 698 699 /** 700 * Saves this feed as a file on the local disk. After the file is saved, a redirect 701 * header may be sent to redirect the user to the newly created file. 702 * @since 1.4 703 * 704 * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()). 705 * @param redirect boolean optional send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file. 706 */ 707 function saveFeed($filename="", $displayContents=true) { 708 if ($filename=="") { 709 $filename = $this->_generateFilename(); 710 } 711 $feedFile = fopen($filename, "w+"); 712 if ($feedFile) { 713 fputs($feedFile,$this->createFeed()); 714 fclose($feedFile); 715 if ($displayContents) { 716 $this->_redirect($filename); 717 } 718 } else { 719 echo "<br /><b>Error creating feed file, please check write permissions.</b><br />"; 720 } 721 } 722 723 } 724 725 726 /** 727 * FeedDate is an internal class that stores a date for a feed or feed item. 728 * Usually, you won't need to use this. 729 */ 730 class FeedDate { 731 var $unix; 732 733 /** 734 * Creates a new instance of FeedDate representing a given date. 735 * Accepts RFC 822, ISO 8601 date formats as well as unix time stamps. 736 * @param mixed $dateString optional the date this FeedDate will represent. If not specified, the current date and time is used. 737 */ 738 function FeedDate($dateString="") { 739 if ($dateString=="") $dateString = date("r"); 740 741 if (is_integer($dateString)) { 742 $this->unix = $dateString; 743 return; 744 } 745 if (preg_match("~(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s+)?(\\d{1,2})\\s+([a-zA-Z]{3})\\s+(\\d{4})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\s+(.*)~",$dateString,$matches)) { 746 $months = Array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12); 747 $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]); 748 if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') { 749 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60; 750 } else { 751 if (strlen($matches[7])==1) { 752 $oneHour = 3600; 753 $ord = ord($matches[7]); 754 if ($ord < ord("M")) { 755 $tzOffset = (ord("A") - $ord - 1) * $oneHour; 756 } elseif ($ord >= ord("M") AND $matches[7]!="Z") { 757 $tzOffset = ($ord - ord("M")) * $oneHour; 758 } elseif ($matches[7]=="Z") { 759 $tzOffset = 0; 760 } 761 } 762 switch ($matches[7]) { 763 case "UT": 764 case "GMT": $tzOffset = 0; 765 } 766 } 767 $this->unix += $tzOffset; 768 return; 769 } 770 if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) { 771 $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]); 772 if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') { 773 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60; 774 } else { 775 if ($matches[7]=="Z") { 776 $tzOffset = 0; 777 } 778 } 779 $this->unix += $tzOffset; 780 return; 781 } 782 $this->unix = 0; 783 } 784 785 /** 786 * Gets the date stored in this FeedDate as an RFC 822 date. 787 * 788 * @return a date in RFC 822 format 789 */ 790 function rfc822() { 791 //return gmdate("r",$this->unix); 792 $date = gmdate("D, d M Y H:i:s", $this->unix); 793 if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE); 794 return $date; 795 } 796 797 /** 798 * Gets the date stored in this FeedDate as an ISO 8601 date. 799 * 800 * @return a date in ISO 8601 format 801 */ 802 function iso8601() { 803 $date = gmdate("Y-m-d\TH:i:sO",$this->unix); 804 $date = substr($date,0,22) . ':' . substr($date,-2); 805 if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date); 806 return $date; 807 } 808 809 /** 810 * Gets the date stored in this FeedDate as unix time stamp. 811 * 812 * @return a date as a unix time stamp 813 */ 814 function unix() { 815 return $this->unix; 816 } 817 } 818 819 820 /** 821 * RSSCreator10 is a FeedCreator that implements RDF Site Summary (RSS) 1.0. 822 * 823 * @see http://www.purl.org/rss/1.0/ 824 * @since 1.3 825 * @author Kai Blankenhorn <kaib@bitfolge.de> 826 */ 827 class RSSCreator10 extends FeedCreator { 828 829 /** 830 * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0. 831 * The feed will contain all items previously added in the same order. 832 * @return string the feed's complete text 833 */ 834 function createFeed() { 835 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n"; 836 $feed.= $this->_createGeneratorComment(); 837 if ($this->cssStyleSheet=="") { 838 $cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css"; 839 } 840 $feed.= $this->_createStylesheetReferences(); 841 $feed.= "<rdf:RDF\n"; 842 $feed.= " xmlns=\"http://purl.org/rss/1.0/\"\n"; 843 $feed.= " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"; 844 $feed.= " xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n"; 845 $feed.= " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"; 846 $feed.= " <channel rdf:about=\"".$this->syndicationURL."\">\n"; 847 $feed.= " <title>".htmlspecialchars($this->title)."</title>\n"; 848 $feed.= " <description>".htmlspecialchars($this->description)."</description>\n"; 849 $feed.= " <link>".$this->link."</link>\n"; 850 if ($this->image!=null) { 851 $feed.= " <image rdf:resource=\"".$this->image->url."\" />\n"; 852 } 853 $now = new FeedDate(); 854 $feed.= " <dc:date>".htmlspecialchars($now->iso8601())."</dc:date>\n"; 855 $feed.= " <items>\n"; 856 $feed.= " <rdf:Seq>\n"; 857 for ($i=0;$i<count($this->items);$i++) { 858 $feed.= " <rdf:li rdf:resource=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n"; 859 } 860 $feed.= " </rdf:Seq>\n"; 861 $feed.= " </items>\n"; 862 $feed.= " </channel>\n"; 863 if ($this->image!=null) { 864 $feed.= " <image rdf:about=\"".$this->image->url."\">\n"; 865 $feed.= " <title>".$this->image->title."</title>\n"; 866 $feed.= " <link>".$this->image->link."</link>\n"; 867 $feed.= " <url>".$this->image->url."</url>\n"; 868 $feed.= " </image>\n"; 869 } 870 $feed.= $this->_createAdditionalElements($this->additionalElements, " "); 871 872 for ($i=0;$i<count($this->items);$i++) { 873 $feed.= " <item rdf:about=\"".htmlspecialchars($this->items[$i]->link)."\">\n"; 874 //$feed.= " <dc:type>Posting</dc:type>\n"; 875 $feed.= " <dc:format>text/html</dc:format>\n"; 876 if ($this->items[$i]->date!=null) { 877 $itemDate = new FeedDate($this->items[$i]->date); 878 $feed.= " <dc:date>".htmlspecialchars($itemDate->iso8601())."</dc:date>\n"; 879 } 880 if ($this->items[$i]->source!="") { 881 $feed.= " <dc:source>".htmlspecialchars($this->items[$i]->source)."</dc:source>\n"; 882 } 883 if ($this->items[$i]->author!="") { 884 $feed.= " <dc:creator>".htmlspecialchars($this->items[$i]->author)."</dc:creator>\n"; 885 } 886 $feed.= " <title>".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," ")))."</title>\n"; 887 $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n"; 888 $feed.= " <description>".htmlspecialchars($this->items[$i]->description)."</description>\n"; 889 $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " "); 890 $feed.= " </item>\n"; 891 } 892 $feed.= "</rdf:RDF>\n"; 893 return $feed; 894 } 895 } 896 897 898 899 /** 900 * RSSCreator091 is a FeedCreator that implements RSS 0.91 Spec, revision 3. 901 * 902 * @see http://my.netscape.com/publish/formats/rss-spec-0.91.html 903 * @since 1.3 904 * @author Kai Blankenhorn <kaib@bitfolge.de> 905 */ 906 class RSSCreator091 extends FeedCreator { 907 908 /** 909 * Stores this RSS feed's version number. 910 * @access private 911 */ 912 var $RSSVersion; 913 914 function RSSCreator091() { 915 $this->_setRSSVersion("0.91"); 916 $this->contentType = "application/rss+xml"; 917 } 918 919 /** 920 * Sets this RSS feed's version number. 921 * @access private 922 */ 923 function _setRSSVersion($version) { 924 $this->RSSVersion = $version; 925 } 926 927 /** 928 * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0. 929 * The feed will contain all items previously added in the same order. 930 * @return string the feed's complete text 931 */ 932 function createFeed() { 933 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n"; 934 $feed.= $this->_createGeneratorComment(); 935 $feed.= $this->_createStylesheetReferences(); 936 $feed.= "<rss version=\"".$this->RSSVersion."\">\n"; 937 $feed.= " <channel>\n"; 938 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n"; 939 $this->descriptionTruncSize = 500; 940 $feed.= " <description>".$this->getDescription()."</description>\n"; 941 $feed.= " <link>".$this->link."</link>\n"; 942 $now = new FeedDate(); 943 $feed.= " <lastBuildDate>".htmlspecialchars($now->rfc822())."</lastBuildDate>\n"; 944 $feed.= " <generator>".FEEDCREATOR_VERSION."</generator>\n"; 945 946 if ($this->image!=null) { 947 $feed.= " <image>\n"; 948 $feed.= " <url>".$this->image->url."</url>\n"; 949 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."</title>\n"; 950 $feed.= " <link>".$this->image->link."</link>\n"; 951 if ($this->image->width!="") { 952 $feed.= " <width>".$this->image->width."</width>\n"; 953 } 954 if ($this->image->height!="") { 955 $feed.= " <height>".$this->image->height."</height>\n"; 956 } 957 if ($this->image->description!="") { 958 $feed.= " <description>".$this->image->getDescription()."</description>\n"; 959 } 960 $feed.= " </image>\n"; 961 } 962 if ($this->language!="") { 963 $feed.= " <language>".$this->language."</language>\n"; 964 } 965 if ($this->copyright!="") { 966 $feed.= " <copyright>".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."</copyright>\n"; 967 } 968 if ($this->editor!="") { 969 $feed.= " <managingEditor>".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."</managingEditor>\n"; 970 } 971 if ($this->webmaster!="") { 972 $feed.= " <webMaster>".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."</webMaster>\n"; 973 } 974 if ($this->pubDate!="") { 975 $pubDate = new FeedDate($this->pubDate); 976 $feed.= " <pubDate>".htmlspecialchars($pubDate->rfc822())."</pubDate>\n"; 977 } 978 if ($this->category!="") { 979 $feed.= " <category>".htmlspecialchars($this->category)."</category>\n"; 980 } 981 if ($this->docs!="") { 982 $feed.= " <docs>".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."</docs>\n"; 983 } 984 if ($this->ttl!="") { 985 $feed.= " <ttl>".htmlspecialchars($this->ttl)."</ttl>\n"; 986 } 987 if (isset( $this->rating_count ) && $this->rating_count > 0) { 988 $rating = round( $this->rating_sum / $this->rating_count ); 989 $feed.= " <rating>".FeedCreator::iTrunc(htmlspecialchars($rating),500)."</rating>\n"; 990 } 991 if ($this->skipHours!="") { 992 $feed.= " <skipHours>".htmlspecialchars($this->skipHours)."</skipHours>\n"; 993 } 994 if ($this->skipDays!="") { 995 $feed.= " <skipDays>".htmlspecialchars($this->skipDays)."</skipDays>\n"; 996 } 997 $feed.= $this->_createAdditionalElements($this->additionalElements, " "); 998 999 for ($i=0;$i<count($this->items);$i++) { 1000 $feed.= " <item>\n"; 1001 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n"; 1002 $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n"; 1003 $feed.= " <description>".$this->items[$i]->getDescription()."</description>\n"; 1004 1005 if ($this->items[$i]->author!="") { 1006 $feed.= " <author>".htmlspecialchars($this->items[$i]->author)."</author>\n"; 1007 } 1008 /* 1009 // on hold 1010 if ($this->items[$i]->source!="") { 1011 $feed.= " <source>".htmlspecialchars($this->items[$i]->source)."</source>\n"; 1012 } 1013 */ 1014 if ($this->items[$i]->category!="") { 1015 $feed.= " <category>".htmlspecialchars($this->items[$i]->category)."</category>\n"; 1016 } 1017 if ($this->items[$i]->comments!="") { 1018 $feed.= " <comments>".htmlspecialchars($this->items[$i]->comments)."</comments>\n"; 1019 } 1020 if ($this->items[$i]->date!="") { 1021 $itemDate = new FeedDate($this->items[$i]->date); 1022 $feed.= " <pubDate>".htmlspecialchars($itemDate->rfc822())."</pubDate>\n"; 1023 } 1024 if ($this->items[$i]->guid!="") { 1025 $feed.= " <guid>".htmlspecialchars($this->items[$i]->guid)."</guid>\n"; 1026 } 1027 $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " "); 1028 $feed.= " </item>\n"; 1029 } 1030 $feed.= " </channel>\n"; 1031 $feed.= "</rss>\n"; 1032 return $feed; 1033 } 1034 } 1035 1036 1037 1038 /** 1039 * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0. 1040 * 1041 * @see http://backend.userland.com/rss 1042 * @since 1.3 1043 * @author Kai Blankenhorn <kaib@bitfolge.de> 1044 */ 1045 class RSSCreator20 extends RSSCreator091 { 1046 1047 function RSSCreator20() { 1048 parent::_setRSSVersion("2.0"); 1049 } 1050 1051 } 1052 1053 1054 /** 1055 * PIECreator01 is a FeedCreator that implements the emerging PIE specification, 1056 * as in http://intertwingly.net/wiki/pie/Syntax. 1057 * 1058 * @deprecated 1059 * @since 1.3 1060 * @author Scott Reynen <scott@randomchaos.com> and Kai Blankenhorn <kaib@bitfolge.de> 1061 */ 1062 class PIECreator01 extends FeedCreator { 1063 1064 function PIECreator01() { 1065 $this->encoding = "utf-8"; 1066 } 1067 1068 function createFeed() { 1069 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n"; 1070 $feed.= $this->_createStylesheetReferences(); 1071 $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n"; 1072 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n"; 1073 $this->truncSize = 500; 1074 $feed.= " <subtitle>".$this->getDescription()."</subtitle>\n"; 1075 $feed.= " <link>".$this->link."</link>\n"; 1076 for ($i=0;$i<count($this->items);$i++) { 1077 $feed.= " <entry>\n"; 1078 $feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n"; 1079 $feed.= " <link>".htmlspecialchars($this->items[$i]->link)."</link>\n"; 1080 $itemDate = new FeedDate($this->items[$i]->date); 1081 $feed.= " <created>".htmlspecialchars($itemDate->iso8601())."</created>\n"; 1082 $feed.= " <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n"; 1083 $feed.= " <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n"; 1084 $feed.= " <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n"; 1085 if ($this->items[$i]->author!="") { 1086 $feed.= " <author>\n"; 1087 $feed.= " <name>".htmlspecialchars($this->items[$i]->author)."</name>\n"; 1088 if ($this->items[$i]->authorEmail!="") { 1089 $feed.= " <email>".$this->items[$i]->authorEmail."</email>\n"; 1090 } 1091 $feed.=" </author>\n"; 1092 } 1093 $feed.= " <content type=\"text/html\" xml:lang=\"en-us\">\n"; 1094 $feed.= " <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n"; 1095 $feed.= " </content>\n"; 1096 $feed.= " </entry>\n"; 1097 } 1098 $feed.= "</feed>\n"; 1099 return $feed; 1100 } 1101 } 1102 1103 1104 /** 1105 * AtomCreator03 is a FeedCreator that implements the atom specification, 1106 * as in http://www.intertwingly.net/wiki/pie/FrontPage. 1107 * Please note that just by using AtomCreator03 you won't automatically 1108 * produce valid atom files. For example, you have to specify either an editor 1109 * for the feed or an author for every single feed item. 1110 * 1111 * Some elements have not been implemented yet. These are (incomplete list): 1112 * author URL, item author's email and URL, item contents, alternate links, 1113 * other link content types than text/html. Some of them may be created with 1114 * AtomCreator03::additionalElements. 1115 * 1116 * @see FeedCreator#additionalElements 1117 * @since 1.6 1118 * @author Kai Blankenhorn <kaib@bitfolge.de>, Scott Reynen <scott@randomchaos.com> 1119 */ 1120 class AtomCreator03 extends FeedCreator { 1121 1122 function AtomCreator03() { 1123 $this->contentType = "application/atom+xml"; 1124 $this->encoding = "utf-8"; 1125 } 1126 1127 function createFeed() { 1128 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n"; 1129 $feed.= $this->_createGeneratorComment(); 1130 $feed.= $this->_createStylesheetReferences(); 1131 $feed.= "<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\""; 1132 if ($this->language!="") { 1133 $feed.= " xml:lang=\"".$this->language."\""; 1134 } 1135 $feed.= ">\n"; 1136 $feed.= " <title>".htmlspecialchars($this->title)."</title>\n"; 1137 $feed.= " <tagline>".htmlspecialchars($this->description)."</tagline>\n"; 1138 $feed.= " <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n"; 1139 $feed.= " <id>".htmlspecialchars($this->link)."</id>\n"; 1140 $now = new FeedDate(); 1141 $feed.= " <modified>".htmlspecialchars($now->iso8601())."</modified>\n"; 1142 if ($this->editor!="") { 1143 $feed.= " <author>\n"; 1144 $feed.= " <name>".$this->editor."</name>\n"; 1145 if ($this->editorEmail!="") { 1146 $feed.= " <email>".$this->editorEmail."</email>\n"; 1147 } 1148 $feed.= " </author>\n"; 1149 } 1150 $feed.= " <generator>".FEEDCREATOR_VERSION."</generator>\n"; 1151 $feed.= $this->_createAdditionalElements($this->additionalElements, " "); 1152 for ($i=0;$i<count($this->items);$i++) { 1153 $feed.= " <entry>\n"; 1154 $feed.= " <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n"; 1155 $feed.= " <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n"; 1156 if ($this->items[$i]->date=="") { 1157 $this->items[$i]->date = time(); 1158 } 1159 $itemDate = new FeedDate($this->items[$i]->date); 1160 $feed.= " <created>".htmlspecialchars($itemDate->iso8601())."</created>\n"; 1161 $feed.= " <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n"; 1162 $feed.= " <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n"; 1163 $feed.= " <id>".htmlspecialchars($this->items[$i]->link)."</id>\n"; 1164 $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " "); 1165 if ($this->items[$i]->author!="") { 1166 $feed.= " <author>\n"; 1167 $feed.= " <name>".htmlspecialchars($this->items[$i]->author)."</name>\n"; 1168 $feed.= " </author>\n"; 1169 } 1170 if ($this->items[$i]->description!="") { 1171 $feed.= " <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n"; 1172 } 1173 $feed.= " </entry>\n"; 1174 } 1175 $feed.= "</feed>\n"; 1176 return $feed; 1177 } 1178 } 1179 1180 1181 /** 1182 * MBOXCreator is a FeedCreator that implements the mbox format 1183 * as described in http://www.qmail.org/man/man5/mbox.html 1184 * 1185 * @since 1.3 1186 * @author Kai Blankenhorn <kaib@bitfolge.de> 1187 */ 1188 class MBOXCreator extends FeedCreator { 1189 1190 function MBOXCreator() { 1191 $this->contentType = "text/plain"; 1192 $this->encoding = "ISO-8859-15"; 1193 } 1194 1195 function qp_enc($input = "", $line_max = 76) { 1196 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 1197 $lines = preg_split("/(?:\r\n|\r|\n)/", $input); 1198 $eol = "\r\n"; 1199 $escape = "="; 1200 $output = ""; 1201 while( list(, $line) = each($lines) ) { 1202 //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary 1203 $linlen = strlen($line); 1204 $newline = ""; 1205 for($i = 0; $i < $linlen; $i++) { 1206 $c = substr($line, $i, 1); 1207 $dec = ord($c); 1208 if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only 1209 $c = "=20"; 1210 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required 1211 $h2 = floor($dec/16); $h1 = floor($dec%16); 1212 $c = $escape.$hex["$h2"].$hex["$h1"]; 1213 } 1214 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted 1215 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay 1216 $newline = ""; 1217 } 1218 $newline .= $c; 1219 } // end of for 1220 $output .= $newline.$eol; 1221 } 1222 return trim($output); 1223 } 1224 1225 1226 /** 1227 * Builds the MBOX contents. 1228 * @return string the feed's complete text 1229 */ 1230 function createFeed() { 1231 for ($i=0;$i<count($this->items);$i++) { 1232 if ($this->items[$i]->author!="") { 1233 $from = $this->items[$i]->author; 1234 } else { 1235 $from = $this->title; 1236 } 1237 $itemDate = new FeedDate($this->items[$i]->date); 1238 $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n"; 1239 $feed.= "Content-Type: text/plain;\n"; 1240 $feed.= " charset=\"".$this->encoding."\"\n"; 1241 $feed.= "Content-Transfer-Encoding: quoted-printable\n"; 1242 $feed.= "Content-Type: text/plain\n"; 1243 $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n"; 1244 $feed.= "Date: ".$itemDate->rfc822()."\n"; 1245 $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n"; 1246 $feed.= "\n"; 1247 $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description)); 1248 $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body); 1249 $feed.= "\n"; 1250 $feed.= "\n"; 1251 } 1252 return $feed; 1253 } 1254 1255 /** 1256 * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types. 1257 * @return string the feed cache filename 1258 * @since 1.4 1259 * @access private 1260 */ 1261 function _generateFilename() { 1262 $fileInfo = pathinfo($_SERVER["PHP_SELF"]); 1263 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox"; 1264 } 1265 } 1266 1267 1268 /** 1269 * OPMLCreator is a FeedCreator that implements OPML 1.0. 1270 * 1271 * @see http://opml.scripting.com/spec 1272 * @author Dirk Clemens, Kai Blankenhorn 1273 * @since 1.5 1274 */ 1275 class OPMLCreator extends FeedCreator { 1276 1277 function OPMLCreator() { 1278 $this->encoding = "utf-8"; 1279 } 1280 1281 function createFeed() { 1282 $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n"; 1283 $feed.= $this->_createGeneratorComment(); 1284 $feed.= $this->_createStylesheetReferences(); 1285 $feed.= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"; 1286 $feed.= " <head>\n"; 1287 $feed.= " <title>".htmlspecialchars($this->title)."</title>\n"; 1288 if ($this->pubDate!="") { 1289 $date = new FeedDate($this->pubDate); 1290 $feed.= " <dateCreated>".$date->rfc822()."</dateCreated>\n"; 1291 } 1292 if ($this->lastBuildDate!="") { 1293 $date = new FeedDate($this->lastBuildDate); 1294 $feed.= " <dateModified>".$date->rfc822()."</dateModified>\n"; 1295 } 1296 if ($this->editor!="") { 1297 $feed.= " <ownerName>".$this->editor."</ownerName>\n"; 1298 } 1299 if ($this->editorEmail!="") { 1300 $feed.= " <ownerEmail>".$this->editorEmail."</ownerEmail>\n"; 1301 } 1302 $feed.= " </head>\n"; 1303 $feed.= " <body>\n"; 1304 for ($i=0;$i<count($this->items);$i++) { 1305 $feed.= " <outline type=\"rss\" "; 1306 $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," "))); 1307 $feed.= " title=\"".$title."\""; 1308 $feed.= " text=\"".$title."\""; 1309 //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\""; 1310 $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\""; 1311 $feed.= "/>\n"; 1312 } 1313 $feed.= " </body>\n"; 1314 $feed.= "</opml>\n"; 1315 return $feed; 1316 } 1317 } 1318 1319 1320 1321 /** 1322 * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific 1323 * location, overriding the createFeed method of the parent FeedCreator. 1324 * The HTML produced can be included over http by scripting languages, or serve 1325 * as the source for an IFrame. 1326 * All output by this class is embedded in <div></div> tags to enable formatting 1327 * using CSS. 1328 * 1329 * @author Pascal Van Hecke 1330 * @since 1.7 1331 */ 1332 class HTMLCreator extends FeedCreator { 1333 1334 var $contentType = "text/html"; 1335 1336 /** 1337 * Contains HTML to be output at the start of the feed's html representation. 1338 */ 1339 var $header; 1340 1341 /** 1342 * Contains HTML to be output at the end of the feed's html representation. 1343 */ 1344 var $footer ; 1345 1346 /** 1347 * Contains HTML to be output between entries. A separator is only used in 1348 * case of multiple entries. 1349 */ 1350 var $separator; 1351 1352 /** 1353 * Used to prefix the stylenames to make sure they are unique 1354 * and do not clash with stylenames on the users' page. 1355 */ 1356 var $stylePrefix; 1357 1358 /** 1359 * Determines whether the links open in a new window or not. 1360 */ 1361 var $openInNewWindow = true; 1362 1363 var $imageAlign ="right"; 1364 1365 /** 1366 * In case of very simple output you may want to get rid of the style tags, 1367 * hence this variable. There's no equivalent on item level, but of course you can 1368 * add strings to it while iterating over the items ($this->stylelessOutput .= ...) 1369 * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored 1370 * in the function createFeed(). 1371 */ 1372 var $stylelessOutput =""; 1373 1374 /** 1375 * Writes the HTML. 1376 * @return string the scripts's complete text 1377 */ 1378 function createFeed() { 1379 // if there is styleless output, use the content of this variable and ignore the rest 1380 if ($this->stylelessOutput!="") { 1381 return $this->stylelessOutput; 1382 } 1383 1384 //if no stylePrefix is set, generate it yourself depending on the script name 1385 if ($this->stylePrefix=="") { 1386 $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_"; 1387 } 1388 1389 //set an openInNewWindow_token_to be inserted or not 1390 if ($this->openInNewWindow) { 1391 $targetInsert = " target='_blank'"; 1392 } 1393 1394 // use this array to put the lines in and implode later with "document.write" javascript 1395 $feedArray = array(); 1396 if ($this->image!=null) { 1397 $imageStr = "<a href='".$this->image->link."'".$targetInsert.">". 1398 "<img src='".$this->image->url."' border='0' alt='". 1399 FeedCreator::iTrunc(htmlspecialchars($this->image->title),100). 1400 "' align='".$this->imageAlign."' "; 1401 if ($this->image->width) { 1402 $imageStr .=" width='".$this->image->width. "' "; 1403 } 1404 if ($this->image->height) { 1405 $imageStr .=" height='".$this->image->height."' "; 1406 } 1407 $imageStr .="/></a>"; 1408 $feedArray[] = $imageStr; 1409 } 1410 1411 if ($this->title) { 1412 $feedArray[] = "<div class='".$this->stylePrefix."title'><a href='".$this->link."' ".$targetInsert." class='".$this->stylePrefix."title'>". 1413 FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</a></div>"; 1414 } 1415 if ($this->getDescription()) { 1416 $feedArray[] = "<div class='".$this->stylePrefix."description'>". 1417 str_replace("]]>", "", str_replace("<![CDATA[", "", $this->getDescription())). 1418 "</div>"; 1419 } 1420 1421 if ($this->header) { 1422 $feedArray[] = "<div class='".$this->stylePrefix."header'>".$this->header."</div>"; 1423 } 1424 1425 for ($i=0;$i<count($this->items);$i++) { 1426 if ($this->separator and $i > 0) { 1427 $feedArray[] = "<div class='".$this->stylePrefix."separator'>".$this->separator."</div>"; 1428 } 1429 1430 if ($this->items[$i]->title) { 1431 if ($this->items[$i]->link) { 1432 $feedArray[] = 1433 "<div class='".$this->stylePrefix."item_title'><a href='".$this->items[$i]->link."' class='".$this->stylePrefix. 1434 "item_title'".$targetInsert.">".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100). 1435 "</a></div>"; 1436 } else { 1437 $feedArray[] = 1438 "<div class='".$this->stylePrefix."item_title'>". 1439 FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100). 1440 "</div>"; 1441 } 1442 } 1443 if ($this->items[$i]->getDescription()) { 1444 $feedArray[] = 1445 "<div class='".$this->stylePrefix."item_description'>". 1446 str_replace("]]>", "", str_replace("<![CDATA[", "", $this->items[$i]->getDescription())). 1447 "</div>"; 1448 } 1449 } 1450 if ($this->footer) { 1451 $feedArray[] = "<div class='".$this->stylePrefix."footer'>".$this->footer."</div>"; 1452 } 1453 1454 $feed= "".join($feedArray, "\r\n"); 1455 return $feed; 1456 } 1457 1458 /** 1459 * Overrrides parent to produce .html extensions 1460 * 1461 * @return string the feed cache filename 1462 * @since 1.4 1463 * @access private 1464 */ 1465 function _generateFilename() { 1466 $fileInfo = pathinfo($_SERVER["PHP_SELF"]); 1467 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".html"; 1468 } 1469 } 1470 1471 1472 /** 1473 * JSCreator is a class that writes a js file to a specific 1474 * location, overriding the createFeed method of the parent HTMLCreator. 1475 * 1476 * @author Pascal Van Hecke 1477 */ 1478 class JSCreator extends HTMLCreator { 1479 var $contentType = "text/javascript"; 1480 1481 /** 1482 * writes the javascript 1483 * @return string the scripts's complete text 1484 */ 1485 function createFeed() 1486 { 1487 $feed = parent::createFeed(); 1488 $feedArray = explode("\n",$feed); 1489 1490 $jsFeed = ""; 1491 foreach ($feedArray as $value) { 1492 $jsFeed .= "document.write('".trim(addslashes($value))."');\n"; 1493 } 1494 return $jsFeed; 1495 } 1496 1497 /** 1498 * Overrrides parent to produce .js extensions 1499 * 1500 * @return string the feed cache filename 1501 * @since 1.4 1502 * @access private 1503 */ 1504 function _generateFilename() { 1505 $fileInfo = pathinfo($_SERVER["PHP_SELF"]); 1506 return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".js"; 1507 } 1508 1509 } 1510 1511 1512 /** 1513 * GoogleSiteMapIndex is a FeedCreator that implements Google Sitemap Index 0.84. 1514 * 1515 * @see https://www.google.com/webmasters/sitemaps/docs/en/protocol.html#sitemapFileRequirements 1516 * taken from http://phpbb.bitfolge.de/viewtopic.php?t=102 1517 */ 1518 class GoogleSiteMapIndex extends FeedCreator { 1519 /** 1520 * Builds the Google Sitemap feed's text. 1521 * The feed will contain all items previously added in the same order. 1522 * @return string the feed's complete text 1523 */ 1524 function createFeed() { 1525 $feed = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 1526 $feed .= "<sitemapindex xmlns=\"http://www.google.com/schemas/sitemap/0.84\"\n"; 1527 $feed .= " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; 1528 $feed .= " xsi:schemaLocation=\"http://www.google.com/schemas/sitemap/0.84\n"; 1529 $feed .= " http://www.google.com/schemas/sitemap/0.84/siteindex.xsd\">\n"; 1530 1531 $total = count( $this->items ) ; 1532 for ( $i=0; $i < $total; $i++ ) { 1533 $feed .= " <sitemap>\n"; 1534 $feed .= " <loc>".htmlspecialchars($this->items[$i]->link)."</loc>\n"; 1535 if ( $this->items[$i]->date != "" ) { 1536 $itemDate = new FeedDate( $this->items[$i]->date ); 1537 $feed .= " <lastmod>".htmlspecialchars($itemDate->iso8601())."</lastmod>\n"; 1538 } 1539 $feed.= " </sitemap>\n"; 1540 } 1541 $feed.= "</sitemapindex>\n"; 1542 1543 return $feed; 1544 } 1545 } 1546 1547 /*** TEST SCRIPT ********************************************************* 1548 1549 //include("feedcreator.class.php"); 1550 1551 $rss = new UniversalFeedCreator(); 1552 $rss->useCached(); 1553 $rss->title = "PHP news"; 1554 $rss->description = "daily news from the PHP scripting world"; 1555 1556 //optional 1557 //$rss->descriptionTruncSize = 500; 1558 //$rss->descriptionHtmlSyndicated = true; 1559 //$rss->xslStyleSheet = "http://feedster.com/rss20.xsl"; 1560 1561 $rss->link = "http://www.dailyphp.net/news"; 1562 $rss->feedURL = "http://www.dailyphp.net/".$PHP_SELF; 1563 1564 $image = new FeedImage(); 1565 $image->title = "dailyphp.net logo"; 1566 $image->url = "http://www.dailyphp.net/images/logo.gif"; 1567 $image->link = "http://www.dailyphp.net"; 1568 $image->description = "Feed provided by dailyphp.net. Click to visit."; 1569 1570 //optional 1571 $image->descriptionTruncSize = 500; 1572 $image->descriptionHtmlSyndicated = true; 1573 1574 $rss->image = $image; 1575 1576 // get your news items from somewhere, e.g. your database: 1577 //mysql_select_db($dbHost, $dbUser, $dbPass); 1578 //$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC"); 1579 //while ($data = mysql_fetch_object($res)) { 1580 $item = new FeedItem(); 1581 $item->title = "This is an the test title of an item"; 1582 $item->link = "http://localhost/item/"; 1583 $item->description = "<b>description in </b><br/>HTML"; 1584 1585 //optional 1586 //item->descriptionTruncSize = 500; 1587 $item->descriptionHtmlSyndicated = true; 1588 1589 $item->date = time(); 1590 $item->source = "http://www.dailyphp.net"; 1591 $item->author = "John Doe"; 1592 1593 $rss->addItem($item); 1594 //} 1595 1596 // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML, ATOM0.3, HTML, JS 1597 echo $rss->saveFeed("RSS0.91", "feed.xml"); 1598 1599 1600 1601 ***************************************************************************/ 1602 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 14:43:32 2007 | par Balluche grâce à PHPXref 0.7 |
|