Variables: [@ feed= URL to RSS feed file. Defaults to pmwiki.org's Site/AllRecentChanges. cache_time= Time to cache data... be nice to the providers. Defaults to 2000 seconds. max_count= Number of items to read. Defaults to 0. newwin= Open links to items in a new window. Defaults to true. overrides= Set this to false to prevent URL line GET overrides to these parameters. showitems= Defaults to true. If false, don't show RSS items. showitemdescr= Defaults to true. If false, don't include the description along with the item. showtitle= Defaults to true. If false, don't show the feed title. title= Alternate title instead of using RSS title. unsafe= Defaults to false. If true, allows setting of title and feed from the URL line (_GET). @] ***********************************************************/ /* ====================================================================== lastRSS 0.9.1 Simple yet powerfull PHP class to parse RSS files. by Vojtech Semecky, webmaster @ webdot . cz Latest version, features, manual and examples: http://lastrss.webdot.cz/ ---------------------------------------------------------------------- LICENSE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. To read the license please visit http://www.gnu.org/copyleft/gpl.html ====================================================================== */ /** * lastRSS * Simple yet powerfull PHP class to parse RSS files. */ class lastRSS { // ------------------------------------------------------------------- // Public properties // ------------------------------------------------------------------- var $default_cp = 'UTF-8'; var $CDATA = 'content'; var $cp = ''; var $items_limit = 0; var $stripHTML = False; var $date_format = ''; // ------------------------------------------------------------------- // Private variables // ------------------------------------------------------------------- var $channeltags = array ('title', 'link', 'description', 'language', 'copyright', 'managingEditor', 'webMaster', 'lastBuildDate', 'rating', 'docs'); var $itemtags = array('title', 'link', 'description', 'author', 'category', 'comments', 'enclosure', 'guid', 'pubDate', 'source'); var $imagetags = array('title', 'url', 'link', 'width', 'height'); var $textinputtags = array('title', 'description', 'name', 'link'); // ------------------------------------------------------------------- // Parse RSS file and returns associative array. // ------------------------------------------------------------------- function Get ($rss_url) { // If CACHE ENABLED if ($this->cache_dir != '') { $cache_file = $this->cache_dir . '/rsscache_' . md5($rss_url); $timedif = @(time() - filemtime($cache_file)); if ($timedif < $this->cache_time) { // cached file is fresh enough, return cached array $result = unserialize(join('', file($cache_file))); // set 'cached' to 1 only if cached file is correct if ($result) $result['cached'] = 1; } else { // cached file is too old, create new $result = $this->Parse($rss_url); $serialized = serialize($result); if ($f = @fopen($cache_file, 'w')) { fwrite ($f, $serialized, strlen($serialized)); fclose($f); } if ($result) $result['cached'] = 0; } } // If CACHE DISABLED >> load and parse the file directly else { $result = $this->Parse($rss_url); if ($result) $result['cached'] = 0; } // return result return $result; } // ------------------------------------------------------------------- // Modification of preg_match(); return trimed field with index 1 // from 'classic' preg_match() array output // ------------------------------------------------------------------- function my_preg_match ($pattern, $subject) { // start regullar expression preg_match($pattern, $subject, $out); // if there is some result... process it and return it if(isset($out[1])) { // Process CDATA (if present) if ($this->CDATA == 'content') { // Get CDATA content (without CDATA tag) $out[1] = strtr($out[1], array(''', ']]>'=>'')); } elseif ($this->CDATA == 'strip') { // Strip CDATA $out[1] = strtr($out[1], array(''', ']]>'=>'')); } // If code page is set convert character encoding to required if ($this->cp != '') //$out[1] = $this->MyConvertEncoding($this->rsscp, $this->cp, $out[1]); $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]); // Return result return trim($out[1]); } else { // if there is NO result, return empty string return ''; } } // ------------------------------------------------------------------- // Replace HTML entities &something; by real characters // ------------------------------------------------------------------- function unhtmlentities ($string) { // Get HTML entities table $trans_tbl = get_html_translation_table (HTML_ENTITIES, ENT_QUOTES); // Flip keys<==>values $trans_tbl = array_flip ($trans_tbl); // Add support for ' entity (missing in HTML_ENTITIES) $trans_tbl += array(''' => "'"); // Replace entities by values return strtr ($string, $trans_tbl); } // ------------------------------------------------------------------- // Parse() is private method used by Get() to load and parse RSS file. // Don't use Parse() in your scripts - use Get($rss_file) instead. // ------------------------------------------------------------------- function Parse ($rss_url) { // Open and load RSS file if ($f = @fopen($rss_url, 'r')) { $rss_content = ''; while (!feof($f)) { $rss_content .= fgets($f, 4096); } fclose($f); // Parse document encoding $result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content); // if document codepage is specified, use it if ($result['encoding'] != '') { // This is used in my_preg_match() $this->rsscp = $result['encoding']; } else { // This is used in my_preg_match() // otherwise use the default codepage $this->rsscp = $this->default_cp; } // Parse CHANNEL info preg_match("'(.*?)'si", $rss_content, $out_channel); foreach($this->channeltags as $channeltag) { $temp = $this->my_preg_match("'<$channeltag.*?>(.*?)'si", $out_channel[1]); if ($temp != '') $result[$channeltag] = $temp; // Set only if not empty } // If date_format is specified and lastBuildDate is valid if ($this->date_format != '' && ($timestamp = strtotime($result['lastBuildDate'])) !==-1) { // convert lastBuildDate to specified date format $result['lastBuildDate'] = date($this->date_format, $timestamp); } // Parse TEXTINPUT info preg_match("']*[^/])>(.*?)'si", $rss_content, $out_textinfo); // This a little strange regexp means: // Look for tag with or without any attributes, // but skip truncated version (it's not beggining tag) if (isset($out_textinfo[2])) { foreach($this->textinputtags as $textinputtag) { $temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)'si", $out_textinfo[2]); if ($temp != '') { // Set only if not empty $result['textinput_'.$textinputtag] = $temp; } } } // Parse IMAGE info preg_match("'(.*?)'si", $rss_content, $out_imageinfo); if (isset($out_imageinfo[1])) { foreach($this->imagetags as $imagetag) { $temp = $this->my_preg_match("'<$imagetag.*?>(.*?)'si", $out_imageinfo[1]); if ($temp != '') { // Set only if not empty $result['image_'.$imagetag] = $temp; } } } // Parse ITEMS preg_match_all("'(.*?)'si", $rss_content, $items); $rss_items = $items[2]; $i = 0; $result['items'] = array(); // create array even if there are no items foreach($rss_items as $rss_item) { // If number of items is lower then limit: Parse one item if ($i < $this->items_limit || $this->items_limit == 0) { foreach($this->itemtags as $itemtag) { $temp = $this->my_preg_match("'<$itemtag.*?>(.*?)'si", $rss_item); if ($temp != '') $result['items'][$i][$itemtag] = $temp; // Set only if not empty } // Strip HTML tags and other stuff from DESCRIPTION if ($this->stripHTML && $result['items'][$i]['description']) $result['items'][$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['description']))); // Strip HTML tags and other stuff from TITLE if ($this->stripHTML && $result['items'][$i]['title']) $result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title']))); // If date_format is specified and pubDate is valid if ($this->date_format != '' && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !==-1) { // convert pubDate to specified date format $result['items'][$i]['pubDate'] = date($this->date_format, $timestamp); } // Item counter $i++; } } $result['items_count'] = $i; return $result; } else { // Error in opening return False return False; } } } /** * End lastRSS */ /* pmfeed */ Markup('pmfeed','directives',"/^\(:pmfeed[ ]*(.*?):\)\s*$/e", "pmfeed('$1')"); // For users prior to PHP 4.3.0 you may do this: function pmfeedunhtmlentities($string) { // replace numeric entities $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string); $string = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $string); // replace literal entities $trans_tbl = get_html_translation_table(HTML_ENTITIES); $trans_tbl = array_flip($trans_tbl); return strtr($string, $trans_tbl); } function pmfeed($opts) { global $FarmD, $pagename, $MaxIncludes, $HTMLHeaderFmt, $PmFeedCacheDir, $PmFeedTitleMark, $PmFeedItemMark, $PmFeedDescrBold, $PmFeedDescrItalic, $PmFeedDescrUnderline, $PmFeedDescrSmall, $PmFeedDescrStrong, $PmFeedMarkupReplace; SDV($PmFeedCacheDir, $FarmD.'/pub/pmfeed'); //Initial PmWiki markup for feed title SDV($PmFeedTitleMark, '!!'); //Initial PmWiki markup for items SDV($PmFeedItemMark, '*'); //Convert bold tags SDV($PmFeedDescrBold, '\'\'\'$1\'\'\''); //Convert italic tags SDV($PmFeedDescrItalic, '\'\'$1\'\''); //Convert underline tags SDV($PmFeedDescrUnderline, '{+$1+}'); //Convert small tags SDV($PmFeedDescrSmall, '[-$1-]'); //Convert strong tags: text to '''''text''''' SDV($PmFeedDescrStrong, '\'\'\'\'\'$1\'\'\'\'\''); //Attempt to escape markups special to PmWiki that might be found in description SDV($PmFeedMarkupReplace, '/([#*])/'); // Determine this Group // $group = FmtPageName('$Group',$pagename); $name = FmtPageName('$Name',$pagename); // Process markup arguments first // $defaults = array( 'feed'=>'http://www.pmwiki.org/wiki/Site/AllRecentChanges?action=rss', 'title'=>'', 'cache_time'=>2000, 'max_count'=>0, 'showitems'=>'true', 'showitemdescr'=>'true', 'showtitle'=>'true', 'showfeedxmllink'=>'false', 'newwin'=>'true', 'overrides'=>'true', 'unsafe'=>'false' ); $args = array_merge($defaults, ParseArgs($opts)); $urladd=''; // Allows overrides=false in the :pmfeed: markup to disallow // settings on the URL line. // $overrides = $args['overrides']; if ($overrides == 'false') { $_GET = NULL; } $cache_time = isset($_GET['cache_time']) ? $_GET['cache_time'] : $args['cache_time']; if (isset($_GET['cache_time'])) $urladd.="&cache_time=".urlencode($_GET['cache_time']); $showitemdescr = isset($_GET['showitemdescr']) ? $_GET['showitemdescr'] : $args['showitemdescr']; if (isset($_GET['showitemdescr'])) $urladd.="&showitemdescr=".urlencode($_GET['showitemdescr']); $showitems = isset($_GET['showitems']) ? $_GET['showitems'] : $args['showitems']; if (isset($_GET['showitems'])) $urladd.="&showitems=".urlencode($_GET['showitems']); $showtitle = isset($_GET['showtitle']) ? $_GET['showtitle'] : $args['showtitle']; if (isset($_GET['showtitle'])) $urladd.="&showtitle=".urlencode($_GET['showtitle']); $showfeedxmllink = isset($_GET['showfeedxmllink']) ? $_GET['showfeedxmllink'] : $args['showfeedxmllink']; if (isset($_GET['showfeedxmllink'])) $urladd.="&showfeedxmllink=".urlencode($_GET['showfeedxmllink']); $max_count = isset($_GET['max_count']) ? $_GET['max_count'] : $args['max_count']; if (isset($_GET['max_count'])) $urladd.="&max_count=".urlencode($_GET['max_count']); $newwin= isset($_GET['newwin']) ? $_GET['newwin'] : $args['newwin']; if (isset($_GET['newwin'])) $urladd.="&newwin=".urlencode($_GET['newwin']); // For unsafe (?) things // Enabling unsafe would allow you to create a totally user driven // feed. It's possible that some "nasty" markup could come in via // title if made user modifiable. $unsafe=$args['unsafe']; if ($unsafe == 'true') { $feed= isset($_GET['feed']) ? $_GET['feed'] : $args['feed']; if (isset($_GET['feed'])) $urladd.="&feed=".urlencode($_GET['feed']); $title= isset($_GET['title']) ? $_GET['title'] : $args['title']; if (isset($_GET['title'])) $urladd.="&title=".urlencode($_GET['title']); } else { $title=$args['title']; $feed=$args['feed']; } $out=''; // Create lastRSS object $rss = new lastRSS; // $rss->stripHTML = True; // Set cache dir and cache time limit // (don't forget to chmod cache to allow writing) $rss->cache_dir = $PmFeedCacheDir; $rss->cache_time = $cache_time; $out.="\n"; if ($newwin == 'true') { $pmnewwin='newwin '; } else { $pmnewwin=''; } // Try to load and parse RSS file $feed=str_replace('&', '&', $feed); if ($rs = $rss->get($feed)) { // Show title or clickable website rss title if not supplied if ($showtitle == 'true') { if ($title != '') { $out.="\n$PmFeedTitleMark %".$pmnewwin."class=pmfeedtitle%[[$rs[link]|$title\"$rs[title]\"]]"; } else { $out.="\n$PmFeedTitleMark %".$pmnewwin."class=pmfeedtitle%[[$rs[link]|$rs[title]]]"; } } //Hack to convert destroyed german 'umlauts' (Ä, ä, Ü, ü, Ö, ö, ß(= double s in german)) back. //Works on the original Feed name! //(Axel) $out=preg_replace('/ü/', 'ü', $out); //ü $out=preg_replace('/Ä/', 'Ä', $out); //Ä $out=preg_replace('/ä/', 'ä', $out); //ä $out=preg_replace('/Ö/', 'Ö', $out); //Ö $out=preg_replace('/ö/', 'ö', $out); //ö $out=preg_replace('/ß/', 'ß', $out); //ß // Display a link to the original feed xml if ($showfeedxmllink == 'true') { $out.="[[$feed|(XML)]]"; } $out.="\n"; // Show last published articles (title, link, description) if ($showitems == 'true') { $i=0; foreach($rs['items'] as $item) { if ($max_count && $i >= $max_count) { break; } $pmfeedtitle=preg_replace('/\n/','',strip_tags(pmfeedunhtmlentities($item['title']))); $pmfeedlink=$item['link']; if ($pmfeedlink == '') { $pmfeeditem="$PmFeedItemMark %class=pmfeeditem%".$pmfeedtitle; } else { $pmfeeditem="$PmFeedItemMark %".$pmnewwin."class=pmfeeditem%[[$pmfeedlink|$pmfeedtitle]]"; } //Hack to convert destroyed german 'umlauts' (Ä, ä, Ü, ü, Ö, ö, ß(= double s in german)) back. //Works on the news headers! //(Axel) $pmfeeditem=preg_replace('/ü/', 'ü', $pmfeeditem); //ü $pmfeeditem=preg_replace('/Ä/', 'Ä', $pmfeeditem); //Ä $pmfeeditem=preg_replace('/ä/', 'ä', $pmfeeditem); //ä $pmfeeditem=preg_replace('/Ö/', 'Ö', $pmfeeditem); //Ö $pmfeeditem=preg_replace('/ö/', 'ö', $pmfeeditem); //ö $pmfeeditem=preg_replace('/ß/', 'ß', $pmfeeditem); //ß $out.="$pmfeeditem\n"; if ($showitemdescr == 'true') { $d=pmfeedunhtmlentities($item['description']); // Get rid of initial para or br $d=preg_replace('/^

/i','', $d); $d=preg_replace('/^<[bh]r \/>/i','', $d); // Attempt to convert name to [[url|name]] $d=preg_replace('/]*>([^<]+)<\/a>/is', '[[$1|$2]]', $d); //Convert bold tags $d=preg_replace('/(.*?)<\/b>/', $PmFeedDescrBold, $d); //Convert italics tags $d=preg_replace('/(.*?)<\/i>/', $PmFeedDescrItalic, $d); //Convert underline tags $d=preg_replace('/(.*?)<\/u>/', $PmFeedDescrUnderline, $d); //Convert small tags $d=preg_replace('/(.*?)<\/small>/', $PmFeedDescrSmall, $d); //Convert strong tags: text to '''''text''''' ////$d=preg_replace('/(.*?)<\/strong>/', $PmFeedDescrStrong, $d); //Convert breaks and paragraphs $d=preg_replace('/


/', '\\\\\\\\'."\n", $d); $d=preg_replace('/
/', '\\\\'."\n", $d); // $d=preg_replace('/
/', "\n".'\\\\\\', $d); $d=preg_replace('/

/', '\\\\\\\\'."\n", $d); //Hack to hide PmWiki Markup, pound and asterisk //... sigh, there could be a ton of these. $d=preg_replace($PmFeedMarkupReplace, '[=$1=]', $d); // Slaughter the rest of the html tags $d="%block class=indent ".$pmnewwin."%".ltrim(strip_tags($d))."%%\n"; $d=preg_replace('/^\s+/', '', $d); //Hack to convert destroyed german 'umlauts' (Ä, ä, Ü, ü, Ö, ö, ß(= double s in german)) back. //Works on new's bodies! //(Axel) $d=preg_replace('/ü/', 'ü', $d); //ü $d=preg_replace('/Ä/', 'Ä', $d); //Ä $d=preg_replace('/ä/', 'ä', $d); //ä $d=preg_replace('/Ö/', 'Ö', $d); //Ö $d=preg_replace('/ö/', 'ö', $d); //ö $d=preg_replace('/ß/', 'ß', $d); //ß $out.=$d; } $i++; } } } else { $out.="Error: It's not possible to reach RSS file $feed ...\n"; } PRR(); return $out; }