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