日記/2009-3-1

最終更新時間:2009年03月01日 12時23分06秒

RSS関連(RSS1.0、RSS2.0、Atom0.3)プラグインの修正

 

 「世紀末キッズのためのSF100冊」で使ってみて、FreeStyleWikiの本家のサイトに投稿されているRSS関連(RSS1.0、RSS2.0、Atom0.3)プラグインの、rss プラグインに、以下のような不具合を見つけました。

  1. 与えるRSSフィードのURIが長すぎるとエラーになる
  2. フィードのアイテム数が1つしかないとエラーになる

 まず、1.について。
 RSS情報をキャッシュする際、RSSフィードのURIをそのままURIエンコードしてファイル名を作り、このファイル名でRSS情報を保存しようとするのですが、当然ながらURIが長いとキャッシュのファイル名もその分長くなり、それがあんまり長い(ファイルシステムによるようですが、だいたい255バイトまで)と File name too long と怒られてしまいます。
 これを避けるため、MD5でとったURIのハッシュをファイル名に使うようにしました(下記のdiffの出力の50行目あたりからの変更に対応)。
 
 次に2.について。
 RSSフィードのアイテム数というんでしょうか、例えばRSS2.0の場合だと、フィードの構造は以下のような感じですが、

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title> TITLE </title> 
    <link> LINK </link> 
    <description> DESCRIPTION </description> 
    <language>ja</language> 
    <ttl>120</ttl> 
    <copyright>Copyright (C) 2009 XXXXXX</copyright> 
    <lastBuildDate>Sun, 01 Mar 2009 11:31:05 +0900</lastBuildDate> 
    <item>
      <title> TITLE </title> 
      <link> LINK </link> 
      <description> DESCRIPTION </description> 
      <pubDate>Wed, 26 Dec 2007 01:38:40 +0900</pubDate> 
    </item>
    <item>
      <title> TITLE </title> 
      <link> LINK </link> 
      <description> DESCRIPTION </description> 
      <pubDate>Wed, 15 Aug 2007 00:40:23 +0900</pubDate> 
    </item>
  </channel>
</rss>

 上記の例だと2つある<item>のタグでくくられている要素が1つしかないと、Not an ARRAY reference at plugin/rss2/Aggregater.pm line 136 と怒られてしまいます。
 これを避けるために、XML::TreePPのforce_arrayプロパティを指定して、<item>、および、<entry>というタグでくくられた要素は必ず配列としてパースされるようにしました(下記のdiffの出力の95行目あたりからの変更に対応)。
 
 以下が、FreeStyleWikiの本家のサイトのRSS関連(RSS1.0、RSS2.0、Atom0.3)プラグインのページに添付された、rss2_20061224.zip に含まれるファイル Aggregater.pm と、今回の修正を施したファイルとの差分です。

--- Aggregater.pm.org	2006-10-16 13:22:00.000000000 +0900
+++ Aggregater.pm	2009-03-01 10:03:20.799000000 +0900
@@ -50,7 +50,8 @@
 		return &Util::paragraph_error("RSSのURLが指定されていません。");
 	}
 	my $filename = $url;
-	my $cache = $wiki->config('log_dir')."/".&Util::url_encode($filename).".rss";
+	my $cache = &Util::url_encode($filename);
+	$cache = $wiki->config('log_dir')."/".&Util::md5($cache).".rss";
 
 	my $readflag = 0;
 	if(-e $cache){
@@ -95,6 +96,7 @@
 EOM
 
 	my $tpp = XML::TreePP->new();
+	$tpp->set(force_array => [ "item","entry" ]);
 	my $tree = $tpp->parse( $content );
 
 	my $ver = "RSS1.0";

参考

追記