'/www/data/rsscache',
'cacheinterval'=>60,
'cachetime'=>'',
'timeout'=>15,
'sendhost'=>1,
'descriptiontags'=>'b|/b|i|/i|br|p|/p|hr|span|/span|font|/font',
'newwindow'=>0,
'showdesc'=>0,
'maxdesc'=>0,
'truncdesc'=>0,
'posttruncdesc'=>'... continues',
'maxitems'=>15,
'maxtitle'=>80,
'defaulttitle'=>'(no title)',
'linkclass'=>'',
'linkstyle'=>'',
'linkdiv'=>'',
'preitem'=>'',
'postitem'=>'
',
'preitems'=>'',
'postitems'=>'',
'showctitle'=>0,
'showclink'=>1,
'showcdesc'=>0,
'maxctitle'=>80,
'cclass'=>'',
'cstyle'=>'',
'cdiv'=>'',
'encodingin'=>'',
'encodingout'=>'',
'maxredir'=>10,
/* If you modify or override the next line, please post a similar link
somewhere on your website. If you incorporate CaRP into another product and
feel the need to change this line, please ensure that there is a similar link
which will be displayed by default somewhere in your product. Thanks! */
'poweredby'=>'
Newsfeed display by CaRP'
);
class RSSParser {
var $insideitem=0;
var $insidechannel=0;
var $tag='';
var $title='';
var $description='';
var $link='';
var $ctitle='';
var $cdescription='';
var $clink='';
var $itemcount=0;
var $top='';
var $body='';
var $truncdesc=0;
function startElement($parser,$tagName,$attrs) {
$this->tag=$tagName;
if ($tagName=="ITEM") $this->insideitem=1;
if ($tagName=="CHANNEL") $this->insidechannel=1;
else if ($this->insidechannel&&!(($tagName=="TITLE")||($tagName=="DESCRIPTION")||($tagName=="LINK"))) $this->insidechannel++;
}
function endElement($parser,$tagName) {
global $carpconf;
if ($tagName=="ITEM") {
if ($this->itemcount<$carpconf['maxitems']) {
if (strlen($this->title)>$carpconf['maxtitle']) $this->title=substr($this->title,0,$carpconf['maxtitle']-3).'...';
$this->title=htmlspecialchars(trim($this->title));
if (!strlen($this->title)) $this->title=$carpconf['defaulttitle'];
$this->body.=$carpconf['preitem'].$carpconf['linkdiv'];
$this->body.="link)."\"".($carpconf['newwindow']?' target="_blank"':'').
(strlen($carpconf['linkclass'])?(' class="'.$carpconf['linkclass'].'"'):'').
(strlen($carpconf['linkstyle'])?(' style="'.$carpconf['linkstyle'].'"'):'').
'>'.$this->title.''.(strlen($carpconf['linkdiv'])?"\n":($carpconf['showdesc']?"
\n":''));
if ($carpconf['showdesc']) {
if (strlen($carpconf['desctags'])) $adddesc=trim(preg_replace("#<(?!".$carpconf['desctags'].")(.*?)>#is","<\\1\\2>",$this->description));
else $adddesc=trim(preg_replace("#<(.*?)>#is","<\\1>",$this->description));
if ($carpconf['maxdesc']&&(strlen($adddesc)>$carpconf['maxdesc'])) $this->body.=substr($adddesc,0,$this->truncdesc).$carpconf['posttruncdesc'];
else $this->body.=$adddesc;
}
$this->body.=$carpconf['postitem']."\n";
$this->itemcount++;
$this->title=$this->description=$this->link='';
}
$this->insideitem=false;
} else if ($tagName=="CHANNEL") {
if ($carpconf['showctitle']) {
if (strlen($this->ctitle)>$carpconf['maxctitle']) $this->ctitle=substr($this->ctitle,0,$carpconf['maxctitle']-3).'...';
$this->ctitle=htmlspecialchars(trim($this->ctitle));
if (!strlen($this->ctitle)) $this->ctitle=$carpconf['defaulttitle'];
$this->top.=$carpconf['cdiv'];
if ($carpconf['showclink']) $this->top.="clink)."\"".($carpconf['newwindow']?' target="_blank"':'').
(strlen($carpconf['cclass'])?(' class="'.$carpconf['cclass'].'"'):'').
(strlen($carpconf['cstyle'])?(' style="'.$carpconf['cstyle'].'"'):'').
">".$this->ctitle."";
else if (strlen($carpconf['cclass'].$carpconf['cstyle'])) $this->top.=''.$this->ctitle."";
else $this->top.=$this->ctitle;
$this->top.=strlen($carpconf['cdiv'])?"\n":"
\n";
if ($carpconf['showcdesc']) {
if (strlen($carpconf['desctags'])) $this->top.=trim(preg_replace("#<(?!".$carpconf['desctags'].")(.*?)>#is","<\\1\\2>",$this->cdescription))."
\n"; else $this->top.=trim(preg_replace("#<(.*?)>#is","<\\1>",$this->cdescription))."
\n";
}
}
$this->ctitle=$this->cdescription=$this->clink='';
$this->insidechannel=false;
} else if ($this->insidechannel>1) $this->insidechannel--;
}
function characterData($parser,$data) {
if ($this->insideitem) {
switch ($this->tag) {
case "TITLE": $this->title.=$data; break;
case "DESCRIPTION": $this->description.=$data; break;
case "LINK": $this->link.=$data; break;
}
} else if ($this->insidechannel==1) {
switch ($this->tag) {
case "TITLE": $this->ctitle.=$data; break;
case "DESCRIPTION": $this->cdescription.=$data; break;
case "LINK": $this->clink.=$data; break;
}
}
}
}
function CaRPError($s) { echo "
\n[CaRP] $s
\n"; }
function OpenRSSFeed($url) {
global $carpconf,$carpversion,$CaRPRedirs;
if (preg_match("#^http://#i",$url)) {
list($domain,$therest)=explode('/',substr($url,7),2);
if (preg_match("/\:[0-9]+$/",$domain)) list($domain,$port)=explode(':',$domain,2);
else $port=80;
$fp=fsockopen($domain,$port,$errno,$errstr,$carpconf['timeout']);
if ($fp) {
$slash=preg_match("#^http://#i",$therest)?'':'/';
$senddomain=$carpconf['sendhost']?"\r\nHost: $domain":'';
fputs($fp,"GET $slash$therest HTTP/1.0$senddomain\r\nUser-Agent: CaRP/$carpversion\r\n\r\n");
while ((!feof($fp))&&preg_match("/[^\r\n]/",$header=fgets($fp,1000))) {
if (preg_match("/^Location:/i",$header)) {
fclose($fp);
if (count($CaRPRedirs)<$carpconf['maxredir']) {
$loc=trim(preg_replace("/^Location:/i",'',$header));
$lochttp=preg_match("#^http://#i",$loc);
if (!(strlen($slash)||$lochttp)) {
list($rdomain,$rtherest)=explode('/',substr($therest,strpos($therest,':')+3),2);
$loc="http://$rdomain$loc";
}
if (!(strlen($slash)&&$lochttp)) $loc="http://$domain".(($port==80)?'':":$port").(strlen($slash)?'':'/').$loc;
for ($i=count($CaRPRedirs)-1;$i>=0;$i--) if (!strcmp($loc,$CaRPRedirs[$i])) {
CaRPError('Redirection loop detected. Giving up.');
return 0;
}
$CaRPRedirs[count($CaRPRedirs)]=$loc;
return OpenRSSFeed($loc);
} else {
CaRPError('Too many redirects. Giving up.');
return 0;
}
}
}
} else echo CaRPError("$errstr ($errno)");
} else $fp=fopen($url,'r');
return $fp;
}
function ShowRSSPage($url,$cachefile) { ShowRSSFeed($url,$cachefile); }
function ShowRSSFeed($url,$cachefile='') {
global $carpconf,$CaRPRedirs;
$carpconf['desctags']=preg_replace("/\|/",'\b|',$carpconf['descriptiontags']).'\b';
$cache=0;
if (strlen($cachefile)) {
$cachefile=preg_replace("/\.\./",'.',$cachefile);
if (file_exists($carpconf['cachepath']."/$cachefile")) {
$mtime=filemtime($carpconf['cachepath']."/$cachefile");
$nowtime = adodb_mktime();
if (strlen($carpconf['cachetime'])) {
list($hour,$min)=explode(':',$carpconf['cachetime']);
$limtime = adodb_mktime($hour,$min,0);
$cache=($mtime>$limtime-(($nowtime<$limtime)?86400:0))?1:2;
} else $cache=(($nowtime-$mtime)<($carpconf['cacheinterval']*60))?1:2;
} else $cache=2;
}
if ($cache%2==0) {
$xml_parser=xml_parser_create($carpconf['encodingin']);
if (strlen($carpconf['encodingout'])) xml_parser_set_option($xml_parser,XML_OPTION_TARGET_ENCODING,$carpconf['encodingout']);
$rss_parser=new RSSParser();
xml_set_object($xml_parser,$rss_parser);
xml_set_element_handler($xml_parser,"startElement","endElement");
xml_set_character_data_handler($xml_parser,"characterData");
if ($cache) {
if (!($cfp=fopen($carpconf['cachepath']."/$cachefile",'w'))) {
CaRPError("Unable to create/open RSS cache file.");
xml_parser_free($xml_parser);
return;
}
}
$CaRPRedirs=array();
if ($fp=OpenRSSFeed($url)) {
if ($carpconf['maxdesc']) $rss_parser->truncdesc=$carpconf['truncdesc']?$carpconf['truncdesc']:($carpconf['maxdesc']-strlen($carpconf['posttruncdesc']));
while ($data=preg_replace("/&(?!lt|gt|amp|apos|quot)(.*\b)/is","&\\1\\2",fread($fp,4096))) {
if (!xml_parse($xml_parser,$data,feof($fp))) {
CaRPError("XML error: ".xml_error_string(xml_get_error_code($xml_parser))." at line ".xml_get_current_line_number($xml_parser));
fclose($fp);
xml_parser_free($xml_parser);
return;
}
}
fclose($fp);
echo $rss_parser->top.$carpconf['preitems'].$rss_parser->body.$carpconf['postitems'].$carpconf['poweredby'];
if ($cfp) {
fwrite($cfp,$rss_parser->top.$carpconf['preitems'].$rss_parser->body.$carpconf['postitems'].$carpconf['poweredby']);
fclose($cfp);
}
xml_parser_free($xml_parser);
} else readfile($carpconf['cachepath']."/$cachefile");
} else readfile($carpconf['cachepath']."/$cachefile");
}
?>