[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

/libraries/bitfolge/ -> feedcreator.php (source)

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


Generated: Wed Mar 28 15:54:07 2012 Cross-referenced by PHPXref 0.7.1