[ Index ]
 

Code source de DokuWiki 2006-11-06

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/inc/ -> feedcreator.class.php (source)

   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  ?>


Généré le : Tue Apr 3 20:47:31 2007 par Balluche grâce à PHPXref 0.7