Skip to content

Instantly share code, notes, and snippets.

@koshiaaaaan
Created December 23, 2010 05:06
Show Gist options
  • Save koshiaaaaan/752587 to your computer and use it in GitHub Desktop.
Save koshiaaaaan/752587 to your computer and use it in GitHub Desktop.
そのまま使うと結構マズイかもなので、セキュリティに問題ありそうなのはよしなに処理してください。 キャッシュファイルをドキュメントルート以下に置かないとか、そんな感じで。 ※割とテキトーに作った物なので(;´ω`)ゞ あと、cacheフォルダは書き込み可として作成下さいませ。
<?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 ;
}
<?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