$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)', $this->options->cssclassby_tag, $this->options->cssclassby, $this->options->version, $this->options->cssclassby_tag); // change // // printf( '
Powered by BlogPeople
Mod by Trivial Tracks
', $this->options->cssclassby); } else { printf( '<%s class="%s">RSS Reader by T.T. (Ver.%s)', $this->options->cssclassby_tag, $this->options->cssclassby, $this->options->version, $this->options->cssclassby_tag); // change // // printf( '
RSS Reader by T.T.
', $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( '', $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( '', $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( '%s'."\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( '', $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(); } ?>