lib/class_feedcreator.inc.php

Go to the documentation of this file.
00001 <?php
00005 /*
00006 * \file  
00007 */
00008 
00009 
00202 // your local timezone, set to "" to disable or for GMT
00203 define("TIME_ZONE","+01:00");
00204 
00205 
00206 
00207 
00212 define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2-ppt (info@mypapit.net)");
00213 
00214 
00215 
00222 class FeedItem extends HtmlDescribable {
00223 
00224     public $thumb;          ###Spread: added declaration to prevent error
00225     
00229     public $title, $description, $link;
00230     
00234     public $author, $authorEmail, $image, $category, $comments, $guid, $source, $creator;
00235     
00249     public $date;
00250     
00260     public $enclosure;
00261     
00270     public $additionalElements = Array();
00271 
00272     // on hold
00273     // public $source;
00274 }
00275 
00276 class EnclosureItem extends HtmlDescribable {
00277     /*
00278     * 
00279     * core variables
00280     *
00281     **/
00282     public $url,$length,$type;
00283     
00284     /*
00285     * For use with another extension like Yahoo mRSS
00286     * Warning :
00287     * These variables might not show up in 
00288     * later release / not finalize yet!
00289     *
00290     */
00291     public $width, $height, $title, $description, $keywords, $thumburl;
00292     
00293     public $additionalElements = Array();
00294 
00295 }
00296 
00297 
00303 class FeedImage extends HtmlDescribable {
00307     public $title, $url, $link;
00308     
00312     public $width, $height, $description;
00313 }
00314 
00315 
00316 
00321 class HtmlDescribable {
00325     public $descriptionHtmlSyndicated;
00326     
00330     public $descriptionTruncSize;
00331     
00337      function getDescription($overrideSyndicateHtml = false) {
00338         $descriptionField = new FeedHtmlField($this->description);
00339         $descriptionField->syndicateHtml = $overrideSyndicateHtml || $this->descriptionHtmlSyndicated;
00340         $descriptionField->truncSize = $this->descriptionTruncSize;
00341         return $descriptionField->output();
00342     }
00343 
00344 }
00345 
00346 
00347 
00355 class FeedHtmlField {
00359     public $rawFieldContent;
00360     
00365     public $truncSize, $syndicateHtml;
00366     
00371     function FeedHtmlField($parFieldContent) {
00372         if ($parFieldContent) {
00373             $this->rawFieldContent = $parFieldContent;
00374         }
00375     }
00376         
00377         
00382     function output() {
00383         // when field available and syndicated in html we assume 
00384         // - valid html in $rawFieldContent and we enclose in CDATA tags
00385         // - no truncation (truncating risks producing invalid html)
00386         if (!$this->rawFieldContent) {
00387             $result = "";
00388         }   elseif ($this->syndicateHtml) {
00389             $result = "<![CDATA[".$this->rawFieldContent."]]>";
00390         } else {
00391             if ($this->truncSize and is_int($this->truncSize)) {
00392                 $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize);
00393             } else {
00394                 $result = htmlspecialchars($this->rawFieldContent);
00395             }
00396         }
00397         return $result;
00398     }
00399 
00400 }
00401 
00402 
00403 
00413 class UniversalFeedCreator extends FeedCreator {
00414     public $_feed;
00415     
00416     function _setMIME($format) {
00417         switch (strtoupper($format)) {
00418             
00419                 case "BASE":
00420                         $this->format = $format;
00421             
00422             case "2.0":
00423                 // fall through
00424             case "RSS2.0":
00425                 header('Content-type: text/xml', true);
00426                 break;
00427             
00428             case "GEOPHOTORSS":
00429             case "PHOTORSS":
00430             case "GEORSS":
00431                 $this->format = $format;
00432             case "1.0":
00433                 // fall through
00434             case "RSS1.0":
00435                 header('Content-type: text/xml', true);
00436                 break;
00437             
00438             case "PIE0.1":
00439                 header('Content-type: text/xml', true);
00440                 break;
00441             
00442             case "MBOX":
00443                 header('Content-type: text/plain', true);
00444                 break;
00445             
00446             case "OPML":
00447                 header('Content-type: text/xml', true);
00448                 break;
00449                 
00450             case "TOOLBAR":
00451                 $this->format = $format;
00452             case "ATOM":
00453                 // fall through: always the latest ATOM version
00454             case "ATOM1.0":
00455                 header('Content-type: application/xml', true);
00456                 break;
00457                 
00458             case "ATOM0.3":
00459                 header('Content-type: application/xml', true);
00460                 break;
00461     
00462                 
00463             case "HTML":
00464                 header('Content-type: text/html', true);
00465                 break;
00466             
00467             case "JS":
00468                 // fall through
00469             case "JAVASCRIPT":
00470                 header('Content-type: text/javascript', true);
00471                 break;
00472 
00473             default:
00474             case "0.91":
00475                 // fall through
00476             case "RSS0.91":
00477                 header('Content-type: text/xml', true);
00478                 break;
00479         }
00480     }
00481     
00482     function _setFormat($format) {
00483         switch (strtoupper($format)) {
00484 
00485             case "BASE":
00486                         $this->format = $format;
00487 
00488             case "2.0":
00489                 // fall through
00490             case "RSS2.0":
00491                 $this->_feed = new RSSCreator20();
00492                 break;
00493 
00494             case "GEOPHOTORSS":
00495             case "PHOTORSS":
00496             case "GEORSS":
00497                 $this->format = $format;
00498             case "1.0":
00499                 // fall through
00500             case "RSS1.0":
00501                 $this->_feed = new RSSCreator10();
00502                 break;
00503             
00504             case "0.91":
00505                 // fall through
00506             case "RSS0.91":
00507                 $this->_feed = new RSSCreator091();
00508                 break;
00509             
00510             case "PIE0.1":
00511                 $this->_feed = new PIECreator01();
00512                 break;
00513             
00514             case "MBOX":
00515                 $this->_feed = new MBOXCreator();
00516                 break;
00517             
00518             case "OPML":
00519                 $this->_feed = new OPMLCreator();
00520                 break;
00521                 
00522             case "TOOLBAR":
00523                 $this->format = $format;
00524             case "ATOM":
00525                 // fall through: always the latest ATOM version
00526             case "ATOM1.0":
00527                 $this->_feed = new AtomCreator10();
00528                 break;
00529             
00530                 
00531             case "ATOM0.3":
00532                 $this->_feed = new AtomCreator03();
00533                 break;
00534                             
00535             case "HTML":
00536                 $this->_feed = new HTMLCreator();
00537                 break;
00538 
00539             case "PHP":
00540                 $this->_feed = new PHPCreator();
00541                 break;
00542             case "GPX":
00543                 $this->_feed = new GPXCreator();
00544                 break;
00545             case "KML":
00546                 $this->_feed = new KMLCreator();
00547                 break;
00548             
00549             case "JS":
00550                 // fall through
00551             case "JAVASCRIPT":
00552                 $this->_feed = new JSCreator();
00553                 break;
00554             
00555             default:
00556                 $this->_feed = new RSSCreator091();
00557                 break;
00558         }
00559         
00560         $vars = get_object_vars($this);
00561         foreach ($vars as $key => $value) {
00562             // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself
00563             if (!in_array($key, array("_feed", "contentType", "encoding"))) {
00564                 $this->_feed->{$key} = $this->{$key};
00565             }
00566         }
00567     }
00568     
00577     function createFeed($format = "RSS0.91") {
00578         $this->_setFormat($format);
00579         return $this->_feed->createFeed();
00580     }
00581     
00582     
00583     
00594     function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {
00595         $this->_setFormat($format);
00596         $this->_feed->saveFeed($filename, $displayContents);
00597     }
00598 
00599 
00612    function useCached($format="RSS0.91", $filename="", $timeout=3600) {
00613       $this->_setFormat($format);
00614       $this->_feed->useCached($filename, $timeout);
00615    }
00616 
00617    
00624    function outputFeed($format='RSS0.91') {
00625         $this->_setFormat($format);
00626         $this->_setMIME($format);
00627         $this->_feed->outputFeed();
00628    }
00629    
00630    
00631 }
00632 
00633 
00642 class FeedCreator extends HtmlDescribable {
00643 
00644     public $format;         ###Spread: added declaration to prevent error
00645     
00649     public $title, $description, $link;
00650     
00651     
00655     public $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
00656 
00661     public $xslStyleSheet = "";
00662     
00663     
00667     public $items = Array();
00668     
00669     
00675     public $contentType = "application/xml";
00676     
00677     
00682     public $encoding = "utf-8";             ###Spread: default encoding set to utf-8
00683     
00684     
00693     public $additionalElements = Array();
00694    
00695     
00702     function addItem($item) {
00703         $this->items[] = $item;
00704     }
00705     
00706     
00719     static function iTrunc($string, $length) {          ###Spread: set to static
00720         if (strlen($string)<=$length) {
00721             return $string;
00722         }
00723         
00724         $pos = strrpos($string,".");
00725         if ($pos>=$length-4) {
00726             $string = substr($string,0,$length-4);
00727             $pos = strrpos($string,".");
00728         }
00729         if ($pos>=$length*0.4) {
00730             return substr($string,0,$pos+1)." ...";
00731         }
00732         
00733         $pos = strrpos($string," ");
00734         if ($pos>=$length-4) {
00735             $string = substr($string,0,$length-4);
00736             $pos = strrpos($string," ");
00737         }
00738         if ($pos>=$length*0.4) {
00739             return substr($string,0,$pos)." ...";
00740         }
00741         
00742         return substr($string,0,$length-4)." ...";
00743             
00744     }
00745     
00746     
00752     function _createGeneratorComment() {
00753         return "<!-- generator=\"".FEEDCREATOR_VERSION."\" -->\n";
00754     }
00755     
00756     
00764     function _createAdditionalElements($elements, $indentString="") {
00765         $ae = "";
00766         if (is_array($elements)) {
00767             foreach($elements AS $key => $value) {
00768                 $ae.= $indentString."<$key>$value</$key>\n";
00769             }
00770         }
00771         return $ae;
00772     }
00773     
00774     function _createStylesheetReferences() {
00775         $xml = "";
00776         if (!empty($this->cssStyleSheet)) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n";
00777         if (!empty($this->xslStyleSheet)) $xml .= "<?xml-stylesheet href=\"".$this->xslStyleSheet."\" type=\"text/xsl\"?>\n";
00778         return $xml;
00779     }
00780     
00781     
00787     function createFeed() {
00788     }
00789     
00806     function _generateFilename() {
00807         $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
00808         return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".xml";
00809     }
00810     
00811     
00816     function _redirect($filename) {
00817         // attention, heavily-commented-out-area
00818         
00819         // maybe use this in addition to file time checking
00820         //Header("Expires: ".date("r",time()+$this->_timeout));
00821         
00822         /* no caching at all, doesn't seem to work as good:
00823         Header("Cache-Control: no-cache");
00824         Header("Pragma: no-cache");
00825         */
00826         
00827         // HTTP redirect, some feed readers' simple HTTP implementations don't follow it
00828         //Header("Location: ".$filename);
00829 
00830         Header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename));
00831         if (preg_match("/\.(kml|gpx)$/",$filename)) {
00832             Header("Content-Disposition: attachment; filename=".basename($filename));
00833         } else {
00834             Header("Content-Disposition: inline; filename=".basename($filename));
00835         }
00836         readfile($filename, "r");
00837         die();
00838     }
00839     
00850     function useCached($filename="", $timeout=3600) {
00851         $this->_timeout = $timeout;
00852         if ($filename=="") {
00853             $filename = $this->_generateFilename();
00854         }
00855         if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) {
00856             $this->_redirect($filename);
00857         }
00858     }
00859     
00860     
00869     function saveFeed($filename="", $displayContents=true) {
00870         if ($filename=="") {
00871             $filename = $this->_generateFilename();
00872         }
00873         $feedFile = fopen($filename, "w+");
00874         if ($feedFile) {
00875             fputs($feedFile,$this->createFeed());
00876             fclose($feedFile);
00877             if ($displayContents) {
00878                 $this->_redirect($filename);
00879             }
00880         } else {
00881             echo "<br /><b>Error creating feed file, please check write permissions.</b><br />";
00882         }
00883     }
00884 
00891     function outputFeed() {
00892         echo $this->createFeed();
00893     }
00894 
00895     
00896 }
00897 
00898 
00903 class FeedDate {
00904     public $unix;
00905     
00911     function FeedDate($dateString="") {
00912         if ($dateString=="") $dateString = date("r");
00913         
00914         if (is_numeric($dateString)) {
00915             $this->unix = $dateString;
00916             return;
00917         }
00918         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)) {
00919             $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);
00920             $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);
00921             if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
00922                 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
00923             } else {
00924                 if (strlen($matches[7])==1) {
00925                     $oneHour = 3600;
00926                     $ord = ord($matches[7]);
00927                     if ($ord < ord("M")) {
00928                         $tzOffset = (ord("A") - $ord - 1) * $oneHour;
00929                     } elseif ($ord >= ord("M") AND $matches[7]!="Z") {
00930                         $tzOffset = ($ord - ord("M")) * $oneHour;
00931                     } elseif ($matches[7]=="Z") {
00932                         $tzOffset = 0;
00933                     }
00934                 }
00935                 switch ($matches[7]) {
00936                     case "UT":
00937                     case "GMT": $tzOffset = 0;
00938                 }
00939             }
00940             $this->unix += $tzOffset;
00941             return;
00942         }
00943         if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {
00944             $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
00945             if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
00946                 $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
00947             } else {
00948                 if ($matches[7]=="Z") {
00949                     $tzOffset = 0;
00950                 }
00951             }
00952             $this->unix += $tzOffset;
00953             return;
00954         }
00955         $this->unix = 0;
00956     }
00957 
00963     function rfc822() {
00964         //return gmdate("r",$this->unix);
00965         $date = gmdate("D, d M Y H:i:s T", $this->unix);                    ###Spread
00966         #if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE);     ###Spread
00967         return $date;
00968     }
00969     
00975     function iso8601() {
00976         $date = gmdate("Y-m-d\TH:i:sO",$this->unix);
00977         $date = substr($date,0,22) . ':' . substr($date,-2);
00978         if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date);
00979         return $date;
00980     }
00981     
00982         
00988     function unix() {
00989         return $this->unix;
00990     }
00991 }
00992 
00993 
01001 class RSSCreator10 extends FeedCreator {
01002 
01008     function createFeed() {     
01009         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01010         $feed.= $this->_createGeneratorComment();
01011         if (empty($this->cssStyleSheet)) {
01012             $this->cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
01013         }
01014         $feed.= $this->_createStylesheetReferences();
01015         $feed.= "<rdf:RDF\n";
01016         $feed.= "    xmlns=\"http://purl.org/rss/1.0/\"\n";
01017         $feed.= "    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"; 
01018         $feed.= "    xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n";
01019         if ($this->items[0]->thumb!="")
01020             $feed.= "    xmlns:photo=\"http://www.pheed.com/pheed/\"\n";
01021         if ($this->items[0]->lat!="")
01022             $feed.= "    xmlns:georss=\"http://www.georss.org/georss/\"\n";
01023         $feed.= "    xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
01024         $feed.= "    <channel rdf:about=\"".$this->syndicationURL."\">\n";
01025         $feed.= "        <title>".htmlspecialchars($this->title)."</title>\n";
01026         $feed.= "        <description>".htmlspecialchars($this->description)."</description>\n";
01027         $feed.= "        <link>".$this->link."</link>\n";
01028         if ($this->image!=null) {
01029             $feed.= "        <image rdf:resource=\"".$this->image->url."\" />\n";
01030         }
01031         $now = new FeedDate();
01032         $feed.= "       <dc:date>".htmlspecialchars($now->iso8601())."</dc:date>\n";
01033         $feed.= "        <items>\n";
01034         $feed.= "            <rdf:Seq>\n";
01035         for ($i=0;$i<count($this->items);$i++) {
01036             $feed.= "                <rdf:li rdf:resource=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
01037         }
01038         $feed.= "            </rdf:Seq>\n";
01039         $feed.= "        </items>\n";
01040         $feed.= "    </channel>\n";
01041         if ($this->image!=null) {
01042             $feed.= "    <image rdf:about=\"".$this->image->url."\">\n";
01043             $feed.= "        <title>".$this->image->title."</title>\n";
01044             $feed.= "        <link>".$this->image->link."</link>\n";
01045             $feed.= "        <url>".$this->image->url."</url>\n";
01046             $feed.= "    </image>\n";
01047         }
01048         $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
01049         
01050         for ($i=0;$i<count($this->items);$i++) {
01051             $feed.= "    <item rdf:about=\"".htmlspecialchars($this->items[$i]->link)."\">\n";
01052             //$feed.= "        <dc:type>Posting</dc:type>\n";
01053             $feed.= "        <dc:format>text/html</dc:format>\n";
01054             if ($this->items[$i]->date!=null) {
01055                 $itemDate = new FeedDate($this->items[$i]->date);
01056                 $feed.= "        <dc:date>".htmlspecialchars($itemDate->iso8601())."</dc:date>\n";
01057             }
01058             if ($this->items[$i]->source!="") {
01059                 $feed.= "        <dc:source>".htmlspecialchars($this->items[$i]->source)."</dc:source>\n";
01060             }
01061             if ($this->items[$i]->author!="") {
01062                 $feed.= "        <dc:creator>".htmlspecialchars($this->items[$i]->author)."</dc:creator>\n";
01063             }
01064             if ($this->items[$i]->lat!="") {
01065                 $feed.= "        <georss:point>".$this->items[$i]->lat." ".$this->items[$i]->long."</georss:point>\n";
01066             }
01067             if ($this->items[$i]->thumb!="") {
01068                 $feed.= "        <photo:thumbnail>".htmlspecialchars($this->items[$i]->thumb)."</photo:thumbnail>\n";
01069             }
01070             $feed.= "        <title>".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r","  ")))."</title>\n";
01071             $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
01072             $feed.= "        <description>".htmlspecialchars($this->items[$i]->description)."</description>\n";
01073             $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
01074             $feed.= "    </item>\n";
01075         }
01076         $feed.= "</rdf:RDF>\n";
01077         return $feed;
01078     }
01079 }
01080 
01081 
01082 
01090 class RSSCreator091 extends FeedCreator {
01091 
01096     public $RSSVersion;
01097 
01098     function RSSCreator091() {
01099         $this->_setRSSVersion("0.91");
01100         $this->contentType = "application/rss+xml";
01101         $this->encoding = "utf-8";                      ###Spread: set utf-8 encoding
01102     }
01103     
01108     function _setRSSVersion($version) {
01109         $this->RSSVersion = $version;
01110     }
01111 
01117     function createFeed() {
01118         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01119         $feed.= $this->_createGeneratorComment();
01120         $feed.= $this->_createStylesheetReferences();
01121         $feed.= "<rss version=\"".$this->RSSVersion."\">\n"; 
01122         if ($this->format == 'BASE') {
01123             $feed.= "    <channel xmlns:g=\"http://base.google.com/ns/1.0\">\n";
01124         } else {
01125             $feed.= "    <channel>\n";
01126         }
01127         $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
01128         $this->descriptionTruncSize = 500;
01129         $feed.= "        <description>".$this->getDescription()."</description>\n";
01130         $feed.= "        <link>".htmlspecialchars($this->link)."</link>\n";     ###Spread: allow & in link
01131         $now = new FeedDate();
01132         $feed.= "        <lastBuildDate>".htmlspecialchars($now->rfc822())."</lastBuildDate>\n";
01133         $feed.= "        <generator>".FEEDCREATOR_VERSION."</generator>\n";
01134 
01135         if ($this->image!=null) {
01136             $feed.= "        <image>\n";
01137             $feed.= "            <url>".$this->image->url."</url>\n"; 
01138             $feed.= "            <title>".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."</title>\n"; 
01139             $feed.= "            <link>".$this->image->link."</link>\n";
01140             if ($this->image->width!="") {
01141                 $feed.= "            <width>".$this->image->width."</width>\n";
01142             }
01143             if ($this->image->height!="") {
01144                 $feed.= "            <height>".$this->image->height."</height>\n";
01145             }
01146             if ($this->image->description!="") {
01147                 $feed.= "            <description>".$this->image->getDescription()."</description>\n";
01148             }
01149             $feed.= "        </image>\n";
01150         }
01151         if ($this->language!="") {
01152             $feed.= "        <language>".$this->language."</language>\n";
01153         }
01154         if ($this->copyright!="") {
01155             $feed.= "        <copyright>".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."</copyright>\n";
01156         }
01157         if ($this->editor!="") {
01158             $feed.= "        <managingEditor>".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."</managingEditor>\n";
01159         }
01160         if ($this->webmaster!="") {
01161             $feed.= "        <webMaster>".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."</webMaster>\n";
01162         }
01163         if ($this->pubDate!="") {
01164             $pubDate = new FeedDate($this->pubDate);
01165             $feed.= "        <pubDate>".htmlspecialchars($pubDate->rfc822())."</pubDate>\n";
01166         }
01167         if ($this->category!="") {
01168             $feed.= "        <category>".htmlspecialchars($this->category)."</category>\n";
01169         }
01170         if ($this->docs!="") {
01171             $feed.= "        <docs>".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."</docs>\n";
01172         }
01173         if ($this->ttl!="") {
01174             $feed.= "        <ttl>".htmlspecialchars($this->ttl)."</ttl>\n";
01175         }
01176         if ($this->rating!="") {
01177             $feed.= "        <rating>".FeedCreator::iTrunc(htmlspecialchars($this->rating),500)."</rating>\n";
01178         }
01179         if ($this->skipHours!="") {
01180             $feed.= "        <skipHours>".htmlspecialchars($this->skipHours)."</skipHours>\n";
01181         }
01182         if ($this->skipDays!="") {
01183             $feed.= "        <skipDays>".htmlspecialchars($this->skipDays)."</skipDays>\n";
01184         }
01185         $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
01186 
01187         for ($i=0;$i<count($this->items);$i++) {
01188             $feed.= "        <item>\n";
01189             $feed.= "            <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
01190             $feed.= "            <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
01191             $feed.= "            <description>".$this->items[$i]->getDescription()."</description>\n";
01192             
01193             if ($this->items[$i]->author!="") {
01194                 $feed.= "            <author>".htmlspecialchars($this->items[$i]->author)."</author>\n";
01195             }
01196             /*
01197             // on hold
01198             if ($this->items[$i]->source!="") {
01199                     $feed.= "            <source>".htmlspecialchars($this->items[$i]->source)."</source>\n";
01200             }
01201             */
01202             if ($this->items[$i]->category!="") {
01203                 $feed.= "            <category>".htmlspecialchars($this->items[$i]->category)."</category>\n";
01204             }
01205             if ($this->items[$i]->comments!="") {
01206                 $feed.= "            <comments>".htmlspecialchars($this->items[$i]->comments)."</comments>\n";
01207             }
01208             if ($this->items[$i]->date!="") {
01209             $itemDate = new FeedDate($this->items[$i]->date); ###Spread
01210                  $feed.= "            <pubDate>".htmlspecialchars($itemDate->rfc822())."</pubDate>\n"; ###Spread
01211                 # $feed.= "            <pubDate>GMT ".htmlspecialchars(gmdate("Y-m-d H:i:s", $this->items[$i]->date))."</pubDate>\n";   ###Spread: always store modified timestamp as GMT       
01212             }
01213             if ($this->items[$i]->guid!="") {
01214                 $feed.= "            <guid>".htmlspecialchars($this->items[$i]->guid)."</guid>\n";
01215             }
01216             if ($this->items[$i]->thumb!="") {
01217                 $feed.= "            <g:image_link>".htmlspecialchars($this->items[$i]->thumb)."</g:image_link>\n";
01218             }
01219             $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
01220             
01221             if ($this->RSSVersion == "2.0" && $this->items[$i]->enclosure != NULL)
01222                 {
01223                                 $feed.= "            <enclosure url=\"";
01224                                 $feed.= $this->items[$i]->enclosure->url;
01225                                 $feed.= "\" length=\"";
01226                                 $feed.= $this->items[$i]->enclosure->length;
01227                                 $feed.= "\" type=\"";
01228                                 $feed.= $this->items[$i]->enclosure->type;
01229                                 $feed.= "\"/>\n";
01230                         }
01231                 
01232         
01233         
01234             $feed.= "        </item>\n";
01235         }
01236         
01237         $feed.= "    </channel>\n";
01238         $feed.= "</rss>\n";
01239         return $feed;
01240     }
01241 }
01242 
01243 
01244 
01252 class RSSCreator20 extends RSSCreator091 {
01253 
01254     function RSSCreator20() {
01255         parent::_setRSSVersion("2.0");
01256     }
01257     
01258 }
01259 
01266 class KMLCreator extends FeedCreator {
01267     
01268     function KMLCreator() {
01269         $this->contentType = "application/vnd.google-earth.kml+xml";
01270         $this->encoding = "utf-8";
01271     }
01272 
01273 
01274     
01275                
01276     function createFeed() {
01277         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01278         $feed.= $this->_createStylesheetReferences();
01279         $feed.= "<kml xmlns=\"http://earth.google.com/kml/2.0\">\n"; 
01280         $feed.= "<Document>\n";
01281         if ($_GET['LinkControl'])
01282             $feed.= "<NetworkLinkControl>\n<minRefreshPeriod>3600</minRefreshPeriod>\n</NetworkLinkControl>\n";
01283         if (!empty($_GET['simple']) && count($this->items) > 0) {
01284         $feed.= "<Style id=\"defaultIcon\">
01285     <LabelStyle>
01286         <scale>0</scale>
01287     </LabelStyle>
01288 </Style>
01289 <Style id=\"hoverIcon\">".
01290 (($this->items[0]->thumb!="")?"
01291     <IconStyle id=\"hoverIcon\">
01292         <scale>2.1</scale>
01293     </IconStyle>":'')."
01294 </Style>
01295 <StyleMap id=\"defaultStyle\">
01296     <Pair>
01297         <key>normal</key>
01298         <styleUrl>#defaultIcon</styleUrl>
01299     </Pair>
01300     <Pair>
01301         <key>highlight</key>
01302         <styleUrl>#hoverIcon</styleUrl>
01303     </Pair>
01304 </StyleMap>
01305 ";
01306           $style = "#defaultStyle";
01307         } else {
01308           $style = "root://styleMaps#default?iconId=0x307";
01309         }
01310         $feed.= "<Folder>\n";
01311         $feed.= "  <name>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</name>
01312   <description>".$this->getDescription()."</description>
01313   <visibility>1</visibility>\n";
01314         $this->truncSize = 500;
01315         
01316         for ($i=0;$i<count($this->items);$i++) {
01317             //added here beucase description gets auto surrounded by cdata
01318             if ($this->items[$i]->thumbTag!="") {
01319                 $this->items[$i]->description = "<a href=\"".htmlspecialchars($this->items[$i]->link)."\">".$this->items[$i]->thumbTag."</a><br/>".$this->items[$i]->description;
01320             }
01321             
01322             $this->items[$i]->description = "<p align=\"center\"><b>".$this->items[$i]->description."</b><br/>
01323             ".$this->items[$i]->licence."
01324                 <br/><br/><a href=\"".htmlspecialchars($this->items[$i]->link)."\">View Online</a></b>";
01325             
01326             $feed.= "
01327         <Placemark>
01328             <description>".$this->items[$i]->getDescription(true)."</description>
01329             <name>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</name>
01330             <visibility>1</visibility>
01331             <Point>
01332                 <coordinates>".$this->items[$i]->long.",".$this->items[$i]->lat.",25</coordinates>
01333             </Point>";
01334             if ($this->items[$i]->thumb!="") {
01335                 $feed.= "
01336             <styleUrl>$style</styleUrl>
01337             <Style>
01338                 <icon>".htmlspecialchars($this->items[$i]->thumb)."</icon>
01339             </Style>";
01340             }
01341             $feed.= "
01342         </Placemark>\n";
01343         }
01344         $feed .= "</Folder>\n</Document>\n</kml>\n";
01345         return $feed;
01346     }
01347     
01354     function _generateFilename() {
01355         $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
01356         return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".kml";
01357     }
01358 }
01359 
01366 class GPXCreator extends FeedCreator {
01367     
01368     function GPXCreator() {
01369         $this->contentType = "text/xml";
01370         $this->encoding = "utf-8";
01371     }
01372 
01373 function createFeed() {
01374         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01375         $feed.= $this->_createStylesheetReferences();
01376         $feed.= "<gpx xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"1.0\"
01377 creator=\"".FEEDCREATOR_VERSION."\"
01378 xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\" xmlns=\"http://www.topografix.com/GPX/1/0\">\n"; 
01379 
01380         $now = new FeedDate();
01381         $feed.= "<desc>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</desc>
01382 <author>{$http_host}</author>
01383 <url>".htmlspecialchars($this->link)."</url>
01384 <time>".htmlspecialchars($now->iso8601())."</time>
01385 \n";
01386             
01387         for ($i=0;$i<count($this->items);$i++) {
01388             $feed.= "<wpt lat=\"".$this->items[$i]->lat."\" lon=\"".$this->items[$i]->long."\">
01389                 <name>".substr(htmlspecialchars(strip_tags($this->items[$i]->title)),0,6)."</name>
01390                 <desc>".htmlspecialchars(strip_tags($this->items[$i]->title))."</desc>
01391                 <src>".htmlspecialchars($this->items[$i]->author)."</src>
01392                 <url>".htmlspecialchars($this->items[$i]->link)."</url>
01393             </wpt>\n";
01394         }
01395         $feed .= "</gpx>\n";
01396         return $feed;
01397     }
01398 }
01399 
01400 
01401 
01408 class PHPCreator extends FeedCreator {
01409     
01410     function PHPCreator() {
01411         $this->contentType = "text/plain";
01412         $this->encoding = "utf-8";
01413     }
01414     
01415     function createFeed() {
01416         $feed = "<?php\n";
01417         $feed.= "class FeedItem {}\n";
01418         $feed.= "  \$feedTitle='".addslashes(FeedCreator::iTrunc(htmlspecialchars($this->title),100))."';\n";
01419         $this->truncSize = 500;
01420         $feed.= "  \$feedDescription='".addslashes($this->getDescription())."';\n";
01421         $feed.= "  \$feedLink='".$this->link."';\n";
01422         $feed.= "  \$feedItem = array();\n";
01423         for ($i=0;$i<count($this->items);$i++) {
01424             $feed.= "   \$feedItem[$i] = new FeedItem();\n";
01425             if ($this->items[$i]->guid!="") {
01426                 $feed.= "    \$feedItem[$i]->id='".htmlspecialchars($this->items[$i]->guid)."';\n";
01427             }
01428             $feed.= "    \$feedItem[$i]->title='".addslashes(FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100))."';\n";
01429             $feed.= "    \$feedItem[$i]->link='".htmlspecialchars($this->items[$i]->link)."';\n";
01430             $feed.= "    \$feedItem[$i]->date=".htmlspecialchars($this->items[$i]->date).";\n";
01431             if ($this->items[$i]->author!="") {
01432                 $feed.= "    \$feedItem[$i]->author='".htmlspecialchars($this->items[$i]->author)."';\n";
01433                 if ($this->items[$i]->authorEmail!="") {
01434                     $feed.= "    \$feedItem[$i]->authorEmail='".$this->items[$i]->authorEmail."';\n";
01435                 }
01436             }
01437             $feed.= "    \$feedItem[$i]->description='".addslashes($this->items[$i]->getDescription())."';\n";
01438             if ($this->items[$i]->thumb!="") {
01439                 $feed.= "    \$feedItem[$i]->thumbURL='".htmlspecialchars($this->items[$i]->thumb)."';\n";
01440             }
01441         }
01442         $feed .= "?>\n";
01443         return $feed;
01444     }
01445 }
01446 
01455 class PIECreator01 extends FeedCreator {
01456     
01457     function PIECreator01() {
01458         $this->encoding = "utf-8";
01459     }
01460     
01461     function createFeed() {
01462         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01463         $feed.= $this->_createStylesheetReferences();
01464         $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n"; 
01465         $feed.= "    <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
01466         $this->truncSize = 500;
01467         $feed.= "    <subtitle>".$this->getDescription()."</subtitle>\n";
01468         $feed.= "    <link>".$this->link."</link>\n";
01469         for ($i=0;$i<count($this->items);$i++) {
01470             $feed.= "    <entry>\n";
01471             $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
01472             $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
01473             $itemDate = new FeedDate($this->items[$i]->date);
01474             $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
01475             $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
01476             $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
01477             $feed.= "        <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n";
01478             if ($this->items[$i]->author!="") {
01479                 $feed.= "        <author>\n";
01480                 $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
01481                 if ($this->items[$i]->authorEmail!="") {
01482                     $feed.= "            <email>".$this->items[$i]->authorEmail."</email>\n";
01483                 }
01484                 $feed.="        </author>\n";
01485             }
01486             $feed.= "        <content type=\"text/html\" xml:lang=\"en-us\">\n";
01487             $feed.= "            <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n";
01488             $feed.= "        </content>\n";
01489             $feed.= "    </entry>\n";
01490         }
01491         $feed.= "</feed>\n";
01492         return $feed;
01493     }
01494 }
01495 
01512  class AtomCreator10 extends FeedCreator {
01513  
01514     function AtomCreator10() {
01515         $this->contentType = "application/atom+xml";
01516         $this->encoding = "utf-8";
01517     }
01518 
01519     function createFeed() {
01520         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01521         $feed.= $this->_createGeneratorComment();
01522         $feed.= $this->_createStylesheetReferences();
01523         $feed.= "<feed xmlns=\"http://www.w3.org/2005/Atom\"";
01524         if ($this->language!="") {
01525             $feed.= " xml:lang=\"".$this->language."\"";
01526         }
01527         $feed.= ">\n"; 
01528         $feed.= "    <title>".htmlspecialchars($this->title)."</title>\n";
01529         $feed.= "    <subtitle>".htmlspecialchars($this->description)."</subtitle>\n";
01530         $feed.= "    <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";
01531         $feed.= "    <id>".htmlspecialchars($this->link)."</id>\n";
01532         $now = new FeedDate();
01533         $feed.= "    <updated>".htmlspecialchars($now->iso8601())."</updated>\n";
01534         if ($this->editor!="") {
01535             $feed.= "    <author>\n";
01536             $feed.= "        <name>".$this->editor."</name>\n";
01537             if ($this->editorEmail!="") {
01538                 $feed.= "        <email>".$this->editorEmail."</email>\n";
01539             }
01540             $feed.= "    </author>\n";
01541         }
01542         $feed.= "    <generator>".FEEDCREATOR_VERSION."</generator>\n";
01543         $feed.= "<link rel=\"self\" type=\"application/atom+xml\" href=\"". $this->syndicationURL . "\" />\n";
01544         $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
01545         for ($i=0;$i<count($this->items);$i++) {
01546             $feed.= "    <entry>\n";
01547             $feed.= "        <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";
01548             $feed.= "        <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
01549             if ($this->items[$i]->date=="") {
01550                 $this->items[$i]->date = time();
01551             }
01552             $itemDate = new FeedDate($this->items[$i]->date);
01553             $feed.= "        <published>".htmlspecialchars($itemDate->iso8601())."</published>\n";
01554             $feed.= "        <updated>".htmlspecialchars($itemDate->iso8601())."</updated>\n";
01555             $feed.= "        <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";
01556             $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
01557             if ($this->items[$i]->author!="") {
01558                 $feed.= "        <author>\n";
01559                 $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
01560                 $feed.= "        </author>\n";
01561             }
01562             if ($this->items[$i]->description!="") {
01563                 $feed.= "        <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";
01564             }
01565             if ($this->items[$i]->enclosure != NULL) {
01566             $feed.="        <link rel=\"enclosure\" href=\"". $this->items[$i]->enclosure->url ."\" type=\"". $this->items[$i]->enclosure->type."\"  length=\"". $this->items[$i]->enclosure->length . "\" />\n";
01567             }
01568             $feed.= "    </entry>\n";
01569         }
01570         $feed.= "</feed>\n";
01571         return $feed;
01572     }
01573 
01574     
01575 }
01576  
01577  
01594 class AtomCreator03 extends FeedCreator {
01595 
01596     function AtomCreator03() {
01597         $this->contentType = "application/atom+xml";
01598         $this->encoding = "utf-8";
01599     }
01600     
01601     function createFeed() {
01602         $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
01603         $feed.= $this->