Atomフィードブラウザのコンテンツ出力用CGI - 「atom2content.cgi」
「atom2msrdb_read_js2.cgi」の出力のハイパーリンクに埋め込まれて起動するCGIです。AtomフィードのURLと記事を特定するデータから、記事の内容あるいは要約を取り出し、HTMLとして出力します。
スクリプト
CGIパラメータ
「atom2msrdb_read_js2.cgi」がHTML出力する「atom2content.cgi」へのリンクは次の部分です。
# atom2content.cgiへのリンク生成
$linkstr
= "http://localhost:$port$cgidir/atom2content.cgi?atom=
$esc_atomurl\&id=$esc_id";
URI::EscapeモジュールでエスケープしたAtomフィードのURL(パラメータ名:atom)と記事を特定するための更新日時などの値(パラメータ名:id)をCGIパラメータとして「atom2content.cgi」に渡しています。
SQLデータベースへの問い合わせ
スクリプトのコメント「entriesテーブルへのアクセス」の部分を参照してください。次のようになっています。
SELECT atom, issued, published, link, title, content,
name, modified, created, id, updated, summary, category
FROM entries
WHERE atom = \"$atom\"
AND (updated = \"$id\" OR modified = \"$id\" OR title = \"$id\")
「atomfeeds」データベースの「entries」テーブルから、atomカラム、すなわちAtomフィードのURLと、記事を特定するためのキーとして更新日時を取得します。
Atomバージョン1.0の場合はupdated
カラムの値、Atomバージョン0.3の場合はmodified
カラムの値、更新日付データがない場合は記事タイトル、またはtitle
カラムの値のいずれかが一致する記事のデータを選び出します。「atom2msrdb.cgi」が正常に動作していれば、記事は1つのはずです。
content要素の実体参照のデコード
Atomフィードデータベースのcontent
カラムにはAtomのcontent
要素が格納されています。ただし、単に取り出しただけでは正常に表示できません。「atom2msrdb.cgi」がAtomフィードを解析するために実体参照エンコードしたデータを格納しているからで、実体参照のデコードが必要です。また、二重にエンコードされている場合があるので、その際は二重にデコードを行います。
content要素とsummary要素
「atom2msrdb_read_js2.cgi」を検討しながら、content
要素がなく、summary
要素のみを持つAtomフィードが存在することに気が付きました。「atom2content.cgi」は、content
カラムが空の場合は、summary
カラムの内容を出力します。
#!/Perl5.8/bin/perl.exe use strict; use warnings; use DBI; use CGI qw(:cgi); use URI::Escape; # CGI 最初の部分の出力 print <<HEADER; Content-type: text/html; charset=UTF-8 <html> <head> <title>ATOM Content</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" type="text/css" href="/mystyle.css" /> <script language="Javascript"> <!-- if(navigator.appCodeName.indexOf("Mozilla") != -1){ document.write( "<link rel='stylesheet' type='text/css' href='/firefox.css' />"); } //--> </script> </head> <body> HEADER #CGIパラメータの取得 my $atom = param('atom'); my $id = param('id'); # Atomフィードデータベース(atomfeeds)へのアクセス my $dbh = DBI->connect( "DBI:mysql:database=atomfeeds;host=localhost;port=3306", "root", "password", {'RaiseError' => 1}); # entriesテーブルへのアクセス my $sth = $dbh->prepare(qq{ SELECT atom, issued, published, link, title, content, name, modified, created, id, updated, summary, category FROM entries WHERE atom = \"$atom\" AND (updated = \"$id\" OR modified = \"$id\" OR title = \"$id\")}); $sth->execute(); while(my $row = $sth->fetchrow_hashref()){ if($row->{content}){ my $content = &entities_decode($row->{content}); if($content =~ /(&[a-z0-9]{2};|&#\d+;)/){ print &entities_decode($content); }else{ print $content; } }elsif($row->{summary}){ my $summary = &entities_decode($row->{summary}); if($summary =~ /(&[a-z0-9]{2};|&#\d+;)/){ print &entities_decode($summary); }else{ print $summary; } } } # Atomフィードデータベースの終了 $sth->finish(); $dbh->disconnect(); # CGI 最後の部分の出力 print <<FOOTER; </body> </html> FOOTER exit(0); # マークアップ記号の実体参照デコード # 文字実体参照と数値文字参照(注1)の両方に対応 sub entities_decode{ my($str) = @_; $str =~ s/(<|<|<)/</g; $str =~ s/(>|>|>)/>/g; $str =~ s/('|'|')/'/g; $str =~ s/("|"|")/"/g; $str =~ s/(&|&|&)/&/g; return $str; }
デスクトップCGIの変更
Atomフィードリスト出力 - 「atom2msrdb_feeds.cgi」
「atom2msrdb_feeds.cgi」はAtomフィードデータベース(atomfeeds)に問い合わせて、フィードのリストを取得、AtomリーダーにURLをパラメータとして与えるリンクを生成します。連載第4回では、フィードリーダーとして、「atom2msrdb_read.cgi」のCGIファイル名をスクリプト中に埋め込んでいましたが、切り替えやすくするために変数$atomreader
に設定するように変更しました。
改版したスクリプトをサンプルに添付していますので、差し替えてください。スクリプトの最初の方に下記のような部分がありますので、「atom2msrdb_read_js.cgi」と「atom2msrdb_read_js2.cgi」のいずれを使うか、設定の切り替えをお願いします。
いずれは、見方に応じてリーダー/ブラウザを切り替えることができるように変更する予定です。
# フィードリーダーの設定 my $atomreader = "atom2msrdb_read_js2.cgi";# フィードリーダーの設定
Atomフィードリーダー/MySQLデータベース入力 - 「atom2msrdb.cgi」
「atom2msrdb.cgi」は、「feeds.cgi」の生成するFirefoxのブックマークのATOMフォルダのURLをパラメータとして、Atomフィードを解析してHTMLの表形式で表示しつつ、Atomフィードデータベース(atomfeeds)に内容を格納するスクリプトです。
本稿でテスト中に、EUC-JPの文字コードのサイトのデータを正常に表示できないことに気が付きました(Atomの場合はほとんどUTF-8の文字コードが使用されるので気付くのが遅れました)。「Encode.pm」の動作が、単にuse Encode;
としただけでは不安定で、次のように変更すると意図どおりに動作します。また、EUC-JPを指定する場合には、「euc-jp」と指定する必要があるので、エンコーディングの変換部分も変更しました。以下、変更部分のみ示します。改版したスクリプトをサンプルに添付していますので差し替えてください。
use Encode qw/encode decode from_to/; : :中略 : $encoding =~ s/^euc-*j*p*$/euc-jp/i;# EUC-JP
まとめ
JavaScriptを含むHTMLをCGIで出力する方法により、インタラクティブなデスクトップCGI・フレームワークの可能性を示すことができたと思います。次回は流行中のAjaxを応用することを検討してみましょう。本稿のIFRAME版とAjax版はどのように違うのか、デスクトップCGI・フレームワークにおいてメリットはあるのかどうかを検証していきます。「デスクトップCGI 2.0」にご期待ください。
CodeZineの連載は、考えながら、試しながら、書きながらのリアルタイム記事です。結論がどのようになるのか、本当に実現できるのかどうかはスクリプトを書いて試してみるまでは分かりません。現時点でのTodoリストを残しておきます。ご要望等ありましたら、コメントをお願いいたします。
- インターフェイスのAjax化
- 各フィードやエントリへのメモを取り扱えるようなインターフェイス
- フィードデータベースの検索用インターフェイス
- RSSフィードも取り扱えるように拡張
- Web日記のMicroformatsを利用したデータベース化