$val ) {
$this->$key = $val;
}
if ( $this->tbp ) {
// for TrackBackPeople
$this->cssclass = 'blogpeople-tbp';
$this->cssclassitem = $this->cssclass.'-link';
$this->cssclasslabel = $this->cssclass.'-credit';
$this->cssclassby = $this->cssclass.'-poweredby';
}
}
}
class News {
var $channel;
var $options;
function News( &$init/*!REFERENTIAL!*/ ) {
// assuming the object of NewsOptions given
$this->options = &$init;
register_shutdown_function( array(&$this,"shutdown") );
}
function readRSS( $filename ) {
$filecontent = "";
$fh;
if ( !($fh = @fopen( $filename, 'r' )) ) {
if ( !$this->options->suppresserror )
print("network trouble! skipping...");
return FALSE;
}
stream_set_timeout( $fh, $this->options->timeout );
while ( !feof($fh) ) {
if ( $tmp = fgets( $fh, 4096 ) ) {
$filecontent .= $tmp;
} else {
// when run out of the time
if ( !$this->options->suppresserror )
print("laggy network! skipping...");
return FALSE;
}
}
fclose( $fh );
// convert character encoding at a time
mb_convert_variables( $this->options->charset, $this->options->sourcecharset, $filecontent );
// xml
$xmlparser = xml_parser_create();
xml_parser_set_option( $xmlparser,XML_OPTION_CASE_FOLDING,0 );
xml_parser_set_option( $xmlparser,XML_OPTION_SKIP_WHITE,1 );
xml_parse_into_struct( $xmlparser, $filecontent, $values, $tags );
xml_parser_free( $xmlparser );
// create Channel object first
$objs = $this->createObject( $tags['channel'], $values, 'Channel' );
$this->channel = $objs[0];
// trace for each other tag
foreach ( $tags as $tkey=>$tval ) {
switch( $tkey ){
// these statements should be called just one time
case 'image':
$objs = $this->createObject( $tval, $values, 'Image' );
$this->channel->addImage( $objs[0] );
break;
case 'item':
$this->channel->addItem( $this->createObject( $tval, $values, 'Item' ) );
break;
}
}
return TRUE;
}
// create and return Objects
function createObject( $tval, &$values, $classname ) {
$items = array();
$currentlevel = $values[$tval[0]]['level'];
// loop for index tags which locate the array-index of values.
for ( $i = 0; $i < count($tval); $i+=2 ) {
$item = array();
// loop for extracting each value of the tag
for ( $ii = $tval[$i]+1; $ii < $tval[$i+1]; $ii++ ) {
//we need only one deeper level of data
if ( $currentlevel +1 == $values[$ii]['level'] )
$item[$values[$ii]['tag']] = htmlspecialchars($values[$ii]['value'], ENT_QUOTES, $this->options->charset);
}
// create classes detecting the class's name automatically.
$items[] = new $classname( $item, $this->options );
}
// for TrackBackPeople
if ( $this->options->tbp && $classname == 'Image' && $items[0] ) {
//currently 'title' property of Image isn't used
$data['width'] = '106';
$data['height'] = '24';
$data['url'] = $values[$tval[0]]['attributes']['rdf:resource'];
unset($items);
$items[] = new $classname( $data, $this->options );
}
return $items;
}
function show() {
if ( $this->channel ) {
$this->channel->show();
}
// discarding the channel variable means you can't print the same list again
unset( $channel );
// change labelsubstitute to the default value
$this->options->labelsubstitute = "";
}
function createCache( $filename ) {
if ( !$this->readRSS( $filename ) )
return FALSE;
if ( !is_dir($this->options->cachedir) ) {
mkdir( $this->options->cachedir ) or die('cannot create the cache directry');
}
$cachepath = substr($this->options->cachedir.urlencode($filename),0,250);
$fh = fopen( $cachepath, 'w' ) or die('cannot open the cache file');
flock( $fh, LOCK_EX ) or die('cannot lock the cache file');
fputs( $fh, serialize($this->channel) );
flock( $fh, LOCK_UN );
fclose( $fh );
$this->options->untag = TRUE;
return TRUE;
}
function readCache( $filename ) {
$result = FALSE;
$cachepath = substr($this->options->cachedir.urlencode($filename),0,250);
$fh = @fopen( $cachepath, 'r' );
if ( $fh ) {
@flock( $fh, LOCK_SH );
if ( $bytes = @fgets( $fh ) ) {
$this->channel = unserialize( $bytes );
if ( count($this->channel->item) );
$result = TRUE;
}
@flock( $fh, LOCK_UN );
@fclose( $fh );
}
if ( !$result ) {
// fail soft: don't use cache if some error occured
$this->readRSS( $filename );
}
return $result;
}
function shutdown() {
$this->poweredby();
}
function poweredby() {
static $flag = 0;
if ( !$flag && !$this->options->untag ) {
if ( $this->options->tbp || $this->options->bpll ) {
printf( '<%s class="%s">Powered by BlogPeople
Mod by Trivial Tracks (Ver.%s)%s>', $this->options->cssclassby_tag, $this->options->cssclassby, $this->options->version, $this->options->cssclassby_tag); // change //
// printf( '
', $this->options->cssclassby);
} else {
printf( '<%s class="%s">RSS Reader by T.T. (Ver.%s)%s>', $this->options->cssclassby_tag, $this->options->cssclassby, $this->options->version, $this->options->cssclassby_tag); // change //
// printf( '', $this->options->cssclassby);
}
$flag++;
}
}
}
class Channel extends Element {
var $image;
var $item = array();
function addItem( $item ) {
$this->item = $item;
}
function addImage( $image ) {
if ( $this->options->tbp ) {
// for TrackBackPeople
$image->data['link'] = $this->data['link'];
}
$this->image = $image;
}
function show() {
printf( '<%s class="%s">', $this->options->cssclass_tag, $this->options->cssclass ); // change //
// printf( '', $this->options->cssclass );
printf( '<%s class="%s">', $this->options->cssclasslabel_tag, $this->options->cssclasslabel ); // change //
// printf( '
', $this->options->cssclasslabel );
// use Title Image
if ( $this->image && !$this->options->blockimagelabel ) {
$this->image->show( $this->data['title'] );
// use Title Text
} else {
printf( '
%s',
$this->data['link'], $this->trimString( $this->data['description'] ), ($this->options->labelsubstitute)?$this->options->labelsubstitute:$this->data['title'] );
}
printf( '%s>', $this->options->cssclasslabel_tag ); // change //
// print '
';// -label
// a section of printing items
if ( $this->options->sort ) {
usort( $this->item, 'compareDate' );
}
$itemrepeat = ($this->options->maxitem)?min(count($this->item),$this->options->maxitem): count($this->item);
for ( $i=0; $i < $itemrepeat; $i++ ) {
$this->item[$i]->show();
}
printf( '%s>', $this->options->cssclass_tag ); // change //
// print '
';// -
}
}
class Image extends Element {
function show( $title ) {
$width = $this->data['width'];
$height = $this->data['height'];
$this->fixDimension( $width, $height );
printf( '
'."\n",
$this->data['link'], $title, $this->data['url'], $title, $width, $height );
}
function fixDimension( &$width, &$height ) {
//debug printf('',$width,$this->options->labelwidth,$width / $this->options->labelwidth,$height,$this->options->labelheight,$height / $this->options->labelheight);
// everything's ok
if ( $width <= $this->options->labelwidth && $height <= $this->options->labelheight ) {
;//nothign happens
// either's exeeded
} else if ( ($width / $this->options->labelwidth) > ($height / $this->options->labelheight) ) {
// width length is relatively more exceeded than height
$height = round( $this->options->labelwidth / $width * $height );
$width = $this->options->labelwidth;
} else {
// height
$width = round( $this->options->labelheight / $height * $width );
$height = $this->options->labelheight;
}
}
}
class Item extends Element {
function show() {
$id = rand();
printf( '<%s id="item%s" class="%s">', $this->options->cssclassitem_tag, $id, $this->options->cssclassitem ); // change //
// printf( '', $id, $this->options->cssclassitem );
$date = $this->getDate( "[n/j G:i] ", $this->options->backwardtime );
$description = ($this->options->striptag)?htmlspecialchars(strip_tags($this->unhtmlspecialchars( $this->data['description'] ),$this->options->excludetag)):$this->data['description'];
// for popup
if ( $this->options->popup ) {
printf( '
%s%s
', $this->data['link'], $id, $this->sanitizePossibleTags($this->data['title']), $id, $date.'
'.$description );
// ordinary
} else {
printf( '
%s',
$this->data['link'], $date.$this->trimString( $description ), $this->sanitizePossibleTags($this->data['title']) );
}
printf( '%s>', $this->options->cssclassitem_tag ); // change //
// print '
';
}
}
class Element {
var $data = array();
var $options;
function Element( $init, &$options/*!REFERENTIAL!*/ ) {
$this->options = &$options;
foreach ( $init as $k => $v ) {
$this->data[$k] = $v;
}
}
function trimString( $str ) {
return mb_convert_kana( mb_strimwidth( $str, 0, $this->options->descriptionlength, '...', $this->options->charset ), 'aKs', $this->options->charset );
}
// mostly for Google blog search
function sanitizePossibleTags( $str ) {
return str_replace(
array('<b>','<B>','</b>','</B>'),
'',
$str
);
}
function getTimestamp() {
$timestamp;
$datetime;
if ( $this->data['dc:date'] || $this->data['pubDate'] ) {
$datetime = ($this->data['dc:date'])?$this->data['dc:date']: $this->data['pubDate'];
} else {
return;
}
// ordinary date format
if ( strtotime( $datetime ) != -1 ) {
$timestamp = strtotime( $datetime );
} else {// other date format
// Year
if(preg_match("/^(\d{4})$/", $datetime, $val)) {
$year = $val[1];
// Year and month
} elseif(preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])$/", $datetime, $val)) {
$year = $val[1];
$month = $val[2];
// Complete date
} elseif(preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $datetime, $val)) {
$year = $val[1];
$month = $val[2];
$day = $val[3];
// Complete date plus hours and minutes
} elseif(preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([0-5][0-9]):([0-5][0-9])(Z|(\+|-)[0-5][0-9]:[0-5][0-9])$/", $datetime, $val)) {
$year = $val[1];
$month = $val[2];
$day = $val[3];
$hour = $val[4];
$minute = $val[5];
$timezone = $val[6];
// Complete date plus hours, minutes and seconds
} elseif(preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([0-5][0-9]):([0-5][0-9]):([0-5][0-9])(Z|(\+|-)[0-5][0-9]:[0-5][0-9])$/", $datetime, $val)) {
$year = $val[1];
$month = $val[2];
$day = $val[3];
$hour = $val[4];
$minute = $val[5];
$second = $val[6];
$timezone = $val[7];
// Complete date plus hours, minutes, seconds and a decimal fraction of a second
} elseif(preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([0-5][0-9]):([0-5][0-9]):([0-5][0-9]).([0-9]+)(Z|(\+|-)[0-5][0-9]:[0-5][0-9])$/", $datetime, $val)) {
$year = $val[1];
$month = $val[2];
$day = $val[3];
$hour = $val[4];
$minute = $val[5];
$second = $val[6];
$fraction = $val[7];
$timezone = $val[8];
// Not W3C-DTF
} else {
return;
}
// Offset of Timezone for gmmktime()
if($timezone != "Z") {
$offset_sign = substr($timezone, 0, 1);
$offset_hour = substr($timezone, 1, 2);
$offset_minute = substr($timezone, 4, 2);
}
$timestamp = gmmktime($hour - ($offset_sign . $offset_hour), $minute - ($offset_sign . $offset_minute), $second, $month, $day, $year);
}
return $timestamp;
}
function getDate( $format, $isbackward ) {
$timestamp = $this->getTimestamp();
if ( !$timestamp ) {
return "";
}
else if ( $isbackward ) {
$diff = time() - $timestamp;
$suffix;
if ( $diff < 60 ) {
$suffix = ($diff == 1)?'second':'seconds';
} else if ( $diff < 3600/*<1hour*/ ) {
$diff = floor( $diff / 60 );
$suffix = ($diff == 1)?'minute':'minutes';
} else if ( $diff < 172800/*<2day*/ ) {
$diff = floor( $diff / 3600 );
$suffix = ($diff == 1)?'hour':'hours';
} else {
$diff = floor( $diff / 86400 );
$suffix = ($diff == 1)?'day':'days';
}
// ignore $format with the backwardtime option
return '['.$diff.' '.$suffix.' ago]';
} else {
return date( $format, $timestamp );
}
}
function unhtmlspecialchars( $string ) {
$string = str_replace ( '&', '&', $string );
$string = str_replace ( ''', '\'', $string );
$string = str_replace ( '"', '"', $string );
$string = str_replace ( '<', '<', $string );
$string = str_replace ( '>', '>', $string );
return $string;
}
}
// sort function
function compareDate( $a, $b ) {
return $b->getTimestamp() - $a->getTimestamp();
}
?>