Created
December 23, 2010 05:06
-
-
Save koshiaaaaan/752587 to your computer and use it in GitHub Desktop.
そのまま使うと結構マズイかもなので、セキュリティに問題ありそうなのはよしなに処理してください。 キャッシュファイルをドキュメントルート以下に置かないとか、そんな感じで。 ※割とテキトーに作った物なので(;´ω`)ゞ あと、cacheフォルダは書き込み可として作成下さいませ。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
define( 'DEFAULT_CHARSET', 'UTF-8' ) ; | |
mb_language( 'Japanese' ) ; | |
mb_internal_encoding( DEFAULT_CHARSET ) ; | |
mb_detect_order( array( 'UTF-8', 'EUC-JP', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ASCII', 'ISO-2022-JP', 'ISO-8859-1', 'ISO-8859-2' ) ) ; | |
if( get_magic_quotes_gpc() ) { | |
$_GET = ss( $_GET ) ; | |
$_POST = ss( $_POST ) ; | |
$_COOKIE = ss( $_COOKIE ) ; | |
$_REQUEST = ss( $_REQUEST ) ; | |
} | |
// 現在のタイムスタンプ | |
define( 'TIMESTAMP_NOW', time() ) ; | |
// キャッシュのライフタイム(秒) | |
define( 'CACHE_LIFETIME', 3600 ) ; | |
// キャッシュを置くディレクトリ | |
define( 'CACHE_DIR', dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'cache' ) ; | |
// 表示するエントリ数 | |
define( 'ENTRY_COUNT', 5 ) ; | |
// ディレクトリの存在確認 | |
if( realpath( CACHE_DIR ) === false ) { | |
if( ! mkdir( CACHE_DIR, 0777 ) ) { | |
exit( 'Error!' ) ; | |
} | |
} | |
// 読み込むフィードのリスト | |
$feeds = array( | |
'blog.livedoor.jp/petaweb' => 'http://blog.livedoor.jp/petaweb/index.rdf', | |
'coliss.com' => 'http://feeds.feedburner.jp/coliss', | |
'phpspot.org/blog' => 'http://feeds.feedburner.com/phpspot/ccuf', | |
'e0166.blog89.fc2.com' => 'http://feeds.fc2.com/fc2/xml?host=e0166.blog89', | |
'www.designwalker.com' => 'http://www.designwalker.com/feed', | |
'kachibito.net' => 'http://kachibito.net/feed/atom', | |
'www.webcreatorbox.com' => 'http://www.webcreatorbox.com/feed/', | |
'webdesignrecipes.com' => 'http://webdesignrecipes.com/feed/', | |
'photoshopvip.net' => 'http://photoshopvip.net/feed', | |
) ; | |
// htmlentitiesのラッパ関数 | |
function h( $str, $flags = ENT_QUOTES, $charset = null, $double_encode = true ) { | |
if( is_array( $str ) ) { | |
$cnt = count( $str ) ; | |
$flags = array_fill( 0, $cnt, $flags ) ; | |
$charset = array_fill( 0, $cnt, $charset ) ; | |
$double_encode = array_fill( 0, $cnt, $double_encode ) ; | |
return array_map( 'h', $str, $flags, $charset, $double_encode ) ; | |
} else { | |
if( $charset === null ) { | |
$charset = mb_detect_encoding( $str, mb_detect_order() ) ; | |
} | |
return htmlentities( $str, $flags, $charset, $double_encode ) ; | |
} | |
} | |
// stripslashesのラッパ関数 | |
function ss( $str ) { | |
return ( is_array( $str ) ) ? array_map( 'ss', $str ) : stripslashes( $str ) ; | |
} | |
// 文字エンコーディングを変換 | |
function conv( $str, $to_encoding = false, $from_encoding = false ) { | |
if( $to_encoding === false ) { | |
$to_encoding = mb_internal_encoding() ; | |
} | |
if( $from_encoding === false ) { | |
$from_encoding = mb_detect_encoding( $str, mb_detect_order() ) ; | |
} | |
return mb_convert_encoding( $str, $to_encoding, $from_encoding ) ; | |
} | |
// RSS1.0フォーマットのデータを取得 | |
function getRss10( $xml ) { | |
$return[ 'summary' ][ 'title' ] = conv( $xml->channel->title ) ; | |
$return[ 'summary' ][ 'link' ] = conv( $xml->channel->link ) ; | |
$return[ 'summary' ][ 'description' ] = conv( $xml->channel->description ) ; | |
$child = $xml->channel->children( 'http://purl.org/dc/elements/1.1/' ) ; | |
if( $child ) { | |
$return[ 'summary' ][ 'language' ] = conv( $child->language ) ; | |
$return[ 'summary' ][ 'rights' ] = conv( $child->rights ) ; | |
$return[ 'summary' ][ 'date' ] = conv( $child->date ) ; | |
} | |
$return[ 'summary' ][ 'rss_version' ] = 'rss1.0' ; | |
foreach( $xml->item as $it ) { | |
$item[ 'title' ] = conv( $it->title ) ; | |
$item[ 'link' ] = conv( $it->link ) ; | |
$item[ 'description' ] = conv( $it->description ) ; | |
$child = $it->children( 'http://purl.org/dc/elements/1.1/' ) ; | |
if( $child ) { | |
$item[ 'date' ] = conv( $child->date ) ; | |
} | |
$return[ 'child' ][] = $item ; | |
} | |
return $return ; | |
} | |
// RSS2.0フォーマットのデータを取得 | |
function getRss20( $xml ) { | |
$return[ 'summary' ][ 'title' ] = conv( $xml->channel->title ) ; | |
$return[ 'summary' ][ 'link' ] = conv( $xml->channel->link ) ; | |
$return[ 'summary' ][ 'description' ] = conv( $xml->channel->description ) ; | |
$return[ 'summary' ][ 'language' ] = conv( $xml->channel->language ) ; | |
$return[ 'summary' ][ 'rights' ] = null ; | |
$return[ 'summary' ][ 'date' ] = conv( $xml->channel->pubDate ) ; | |
$return[ 'summary' ][ 'rss_version' ] = 'rss2.0' ; | |
foreach( $xml->channel->item as $it ) { | |
$item[ 'title' ] = conv( $it->title ) ; | |
$item[ 'link' ] = conv( $it->link ) ; | |
$item[ 'description' ] = conv( $it->description ) ; | |
$item[ 'date' ] = conv( $it->pubDate ) ; | |
$return[ 'child' ][] = $item ; | |
} | |
return $return ; | |
} | |
// Atomフォーマットのデータを取得 | |
function getAtom( $xml ) { | |
$return[ 'summary' ][ 'title' ] = conv( $xml->title ) ; | |
$return[ 'summary' ][ 'link' ] = conv( $xml->link[ 'href' ] ) ; | |
$return[ 'summary' ][ 'description' ] = null ; | |
$return[ 'summary' ][ 'language' ] = null ; | |
$return[ 'summary' ][ 'rights' ] = null ; | |
$return[ 'summary' ][ 'date' ] = conv( $xml->updated ) ; | |
$return[ 'summary' ][ 'rss_version' ] = 'Atom' ; | |
foreach( $xml->entry as $it ) { | |
$item[ 'title' ] = conv( $it->title ) ; | |
$item[ 'link' ] = conv( $it->link[ 'href' ] ) ; | |
$item[ 'description' ] = conv( $it->content ) ; | |
$item[ 'date' ] = conv( $it->updated ) ; | |
$return[ 'child' ][] = $item ; | |
} | |
return $return ; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once 'config.php' ; | |
$output = array() ; | |
// フィードリストをぶん回す | |
foreach( $feeds as $name => $feed ) { | |
// ファイル名はURLのmd5ハッシュ値とする。 | |
$file = CACHE_DIR . DIRECTORY_SEPARATOR . md5( $feed ) ; | |
// キャッシュファイルが無いか、ライフタイムが過ぎていれば次の処理 | |
if( ! file_exists( $file ) || ( TIMESTAMP_NOW - CACHE_LIFETIME ) >= filemtime( $file ) ) { | |
/** | |
* 次回以降もファイルが生成されていなければフィードとして正しくない可能性があるので、 | |
* カウンターの実装や、フィードリストから外す機能の実装があればより良くなる。 | |
**/ | |
// フィードからデータを取得する。 | |
// エラー時にWarningが発生するので@でエラー制御 | |
$contents = @file_get_contents( $feed ) ; | |
// データの取得に失敗したらエラー。 | |
if( $contents === false ) { | |
$output[ $name ] = false ; | |
continue ; | |
} | |
// キャッシュファイルを更新 | |
// 本来キャッシュファイルは人から見れない位置に置くべきだが、置けない場合を考えて、エンティティ化して出力しておく。 | |
file_put_contents( $file, htmlentities( $contents, ENT_QUOTES ), LOCK_EX ) ; | |
touch( $file, TIMESTAMP_NOW ) ; | |
} | |
// キャッシュファイルが有り、ライフタイムが過ぎていなければ次の処理 | |
else { | |
// ファイルからデータを読み込む。 | |
// エラー時にWarningが発生するので@でエラー制御 | |
$contents = @file_get_contents( $file ) ; | |
// データの取得に失敗したらエラー。 | |
if( $contents === false ) { | |
$output[ $name ] = false ; | |
continue ; | |
} | |
// 出力時にエンティティ化された文字列を戻す。 | |
$contents = html_entity_decode( $contents, ENT_QUOTES ) ; | |
} | |
// XMLとしてロード出来なければエラー。 | |
if( ! ( $xml = simplexml_load_string( $contents ) ) ) { | |
$output[ $name ] = false ; | |
continue ; | |
} | |
// RSSのフォーマットでデータの取得処理を変更 | |
$format = $xml->getName() ; | |
switch( $format ) { | |
case 'RDF' : | |
$output[ $name ] = getRss10( $xml ) ; | |
break ; | |
case 'rss' : | |
$output[ $name ] = getRss20( $xml ) ; | |
break ; | |
case 'feed' : | |
$output[ $name ] = getAtom( $xml ) ; | |
break ; | |
default : | |
$output[ $name ] = false ; | |
break ; | |
} | |
} | |
?> | |
<!DOCTYPE HTML> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>RSS Reader</title> | |
<link rel="stylesheet" href="/common/css/style.css" type="text/css" /> | |
<style type="text/css"> | |
<!-- | |
h1, h2, h3, ul, li { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
outline: 0; | |
font-size: 100%; | |
vertical-align: baseline; | |
background: transparent; | |
} | |
body { | |
font: 13px/1.231 "メイリオ", Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "MS Pゴシック", "Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, sans-serif; | |
*font-family: "MS Pゴシック", "MS PGothic", Sans-Serif; | |
*font-size: small; | |
*font: x-small; | |
color: #777; | |
line-height: 1; | |
} | |
h1 { | |
font-size: 138.5%; | |
} | |
h2 { | |
margin: 5px 0; | |
font-size: 108%; | |
} | |
.feeds { | |
margin: 0; | |
padding: 0; | |
list-style-type: none; | |
} | |
.feeds .feed { | |
vertical-align: top; | |
display: -moz-inline-block; | |
display: inline-block; | |
*display: inline; | |
*zoom: 1; | |
width: 200px; | |
height: 200px; | |
} | |
.feeds .feed ul li { | |
display: block; | |
margin-top: 5px; | |
padding: 5px; | |
border: 1px solid #ccc; | |
} | |
.feeds .feed ul li h3 { | |
font-weight: normal; | |
height: 1.5em; | |
line-height: 1.5em; | |
overflow: hidden; | |
} | |
--> | |
</style> | |
<!--[if lt IE 9]> | |
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> | |
<![endif]--> | |
</head> | |
<body> | |
<h1>RSS Reader</h1> | |
<ul class="feeds"> | |
<?php foreach( $output as $name => $feed ) : ?> | |
<li class="feed"> | |
<?php if( $feed !== false ) : ?> | |
<h2><?php echo h( $feed[ 'summary' ][ 'title' ] ) ?></h2> | |
<ul> | |
<?php for( $i = 0 ; $i < ENTRY_COUNT ; $i++ ) : ?> | |
<?php if( isset( $feed[ 'child' ][ $i ] ) ) : ?> | |
<li><h3><a href="<?php echo h( $feed[ 'child' ][ $i ][ 'link' ] ) ?>" target="_blank"><?php echo h( $feed[ 'child' ][ $i ][ 'title' ] ) ?></a></h3></li> | |
<?php endif ; ?> | |
<?php endfor ; ?> | |
</ul> | |
<?php else : ?> | |
<h2><?php echo h( $name ) ?></h2> | |
<ul> | |
<li><h3>読み込み失敗</h3></li> | |
</ul> | |
<?php endif ; ?> | |
</li> | |
<?php endforeach ; ?> | |
</ul> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment