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