2006年04月28日
Apache::RequestからPOSTデータがとれない!?
うおーーーーー、Apache::RequestからPOSTデータがとれない!!なぜだーと小一時間悩んでいたら、こんなコード書いてました。
sub handler {
my $r = Apache::Request->new(shift)
my @keys = qw(foo bar baz);
for my $key ( @keys) {
my $val = $r->param($_);
warn "$val\n";
}
}
原因に気づいて愕然としました。。。
Posted by horiuchi at 20:19 | Permalink | Comments (3) | TrackBack (1)
2006年04月19日
LWPのバージョンあげたらファイルアップロードが遅くなった
ここ最近AtomPPを使ったサービスを作っているんですが、そのためにXML::Atomをインストールしたら、LWPを使って10MBくらいの大きいファイルをアップロードすると異常に時間がかかるようになってしまいました。
アップロード時のサーバの様子を見ているとメモリとCPUをやたらと消費しているようです。
LWPのドキュメントを読んでいるとHTTP::Request::Commonのドキュメントに$DYNAMIC_FILE_UPLOADをTRUEにセットすれば大きなファイルをメモリをあまり使わずにアップロードできるよと書いてあったので、これをTRUEにしたところ、劇的にアップロードの時間が短縮されました。
めでたしめでたし。
Posted by horiuchi at 20:45 | Permalink | Comments (0) | TrackBack (0)
2006年03月20日
Template::Plugin::Encode
内部エンコーディングをFlagged UTF-8にしたところ、テンプレート内の日本語を含んだURLにuriフィルタを適用すると、空になるという現象が発生してしまいました。
uriフィルタをハックして、、とも思いましたが、テンプレート内でEncodeモジュールが使えたら便利かなと思い、プラグインを書いてみました。
使い方はこんな感じ。メソッドの実装は、Template::Plugin::Jcodeを参考に、virtual methodとして扱えるようにしてみました。
[% USE Encode %]
# encode
<a href="/foo/bar?jword=[% ja_str.encode.encode('utf-8')|html|uri %]">click here</a>
# decode
[% foo.encode.decode('euc-jp') %]
# from_to
[% num = bar.encode.from_to('sjis','euc-jp') %]
[% bar %]
こういうプラグインはすでにCPANにあるだろうと思ったんですが、ミストを感じなかったので、作成してみました。
Posted by horiuchi at 21:06 | Permalink | Comments (0) | TrackBack (0)
2006年03月14日
FormValidator::Simple::Extension - アップロードファイルのバリデーションなど
前回のエントリでFormValidator::Simpleでアップロードされたファイルのバリデーションができるように拡張したモジュールを書いているといいましたが、それっぽいものができました。
FormValidator-Simpe-Extension-0.01.tar.gz
SimpleのExtensionてどっちやねんという感じですが、アップロードファイルのバリデーション以外に、メッセージをFlaggedなUTF-8にデコードした形でgetできるような機能もつけてみたので、名前をなんにするか悩んだ挙句、とりあえずExtensionにしておきました。使い方はこんな感じです。
use FormValidator::Simple::Extension;
## アップロードファイルのバリデーション
FormValiator::Simple::Extension->check( $q, [
thumbnail => [
'UPLOAD_NOT_BLANK', # ファイルがアップされたかどうか
[UPLOAD_FILESIZE,0, 1024], # ファイルサイズは1kBまで
[UPLOAD_FILENAME_REGEX, 'jpe?g|gif|png$'] #画像っぽいファイル名ならOK
],
]);
## メッセージをFlagged UTF-8でうけとる
FormValidator::Simple::Extension->set_messages('messages.yml');
# どんな文字コードからデコードするか文字コードをセット
FormValidator::Simple::Extension->set_message_decode_parms('utf-8');
my $result = FormValidator::Simple::Extension->check($q, $prof);
# メッセージはデコードされる
my $messages = $result->messages;
これらの拡張が本家のFormValidator::Simpleに取り込まれたらうれしいのですが、アップロードファイルを取得する方法がApache::Requestのuploadメソッドしか想定してないので、ちょっとマイナー過ぎるきもします。。
CGI.pmのuploadメソッドも考慮したものにすれば、取り込んでもらえるかなー。
Posted by horiuchi at 23:39 | Permalink | Comments (2) | TrackBack (0)
2006年03月13日
MIME::Lite::TT::Japanese 0.08
TokuLog!な人にSubjectだけじゃなくて、FromもMIMEエンコードしないと、携帯で返信できないyo!というメールをパッチとともにいただいたので、早速適用して、CPANにアップロードしておきました。
どうもありがとうございました。
ところで、SledgeのValidatorのほうですが、FormValidator::Simpleだとアップロードされたファイルについてのバリデーションができないことに気づいて、ちょっとなやんでます。とりあえず、アップロードできるように拡張したモジュールを書いてみているんですが、いまいちしっくりきません。。もうちょい時間がかかりそう。
Posted by horiuchi at 22:13 | Permalink | Comments (0) | TrackBack (0)
2006年03月10日
FormValidator::Simple::ProfileManager::YAML
SledgeのValidatorを作るにあたって、FormValidator::Simple用のプロファイルをYAMLで定義するためのモジュールを書いてみました。
FormValidator::Simple::ProfileManager::YAML
まずは以下のようなYAMLファイルを用意します。
# sample yaml profile
group1 :
- name
- [ [NOT_BLANK] ]
- email
- [ [NOT_BLANK], [EMAIL_LOOSE] ]
- tel
- [ [NOT_BLANK], [NUMBER_PHONE_JP] ]
- content
- [ [NOT_BLANK] ]
group2 :
subgroup1 :
- userid
- [ [NOT_BLANK]]
- password
- [ [NOT_BLANK]]
- name
- [ [NOT_BLANK] ]
- email
- [ [NOT_BLANK], [EMAIL_LOOSE] ]
subgroup2 :
- tel
- [ [NOT_BLANK], [NUMBER_PHONE_JP] ]
- { zip : [zip1, zip2] }
- [ [ZIP_JP] ]
- address
- [ [NOT_BLANK] ]
group1とかsubgroup1というのはプロファイルをグルーピングするのに使います。
使い方は簡単です。まずオブジェクトを作成します。
use FormValidator::Simple::ProfileManager::YAML;
my $manager = FormValidator::Simple::ProfileManager::YAML->new('/path/to/profile.yml');
デフォルトではYAMLをロードするのにYAMLモジュールを使いますが以下のようにloaderをオプションとして渡すと、YAML::Syckを使うこともできます。
my $manager = FormValidator::Simple::ProfileManager::YAML->new(
'/path/to/profile.yml',
{
loader => 'YAML::Syck',
}
);
プロファイルを取得するには、get_profileメソッドを使います。パラメータとして、グループ名を渡せば、そのグループに属するプロファイルを取得することができます。
取得したプロファイルはそのままFormValidato::Simpleに渡すせます。
# group1のプロファイルを取得
my $profile1 = $manager->get_profile('group1');
# subgroup2のプロファイルを取得
my $profile2 = $manager->get_profile( 'group2', 'subgroup2' );
#取得したgroup1のプロファイルをそのままわたす。
my $result = FormValidator::Simple->check($q , $profile1);
Posted by horiuchi at 19:25 | Permalink | Comments (0) | TrackBack (0)
2005年11月04日
shibyya.pm テクニカルトーク#6に行ってきました。
shibyya.pm テクニカルトーク#6に行ってきました。告知から開催までの期間がかなり短かったにもかかわらず、会場は満員。少し遅れていったのですが、席は満席で立ち見になってしまいました。
これが会場が満席の様子。120人強いたみたいです。さすが世界最大のperl mongersです。恐るべし。
今回印象に残ったのは、発表直前までデモ用のコードをいじってたnaoyaさんの後ろ姿でしょうかw
それと2次会であんのうんぷれいすのなかの人といろいろお話できたのが刺激になりました。2pass試さねば。
Posted by horiuchi at 15:49 | Permalink | Comments (3) | TrackBack (0)
2005年10月27日
Sledge::Plugin::IfModifiedSince
ひさしぶりにSledgeのプラグインを書いてみました。
Sledge::Plugin::IfModifiedSince 0.01
<追記 date="2005/10/30">上のリンク先が404だったのを直しておきました。失礼しました</追記>
If-Modified-Sinceヘッダからコンテンツが更新されたかを判定するif_modified_sinceメソッドと、レスポンスとしてNot Modifiedを返すnot_modifiedメソッドをPagesクラスにインポートします。
各メソッドはこんな感じで使います。
package Your:Pages;
use Sledge::Plugin::IfModifiedSince;
sub dispatch_foo {
my $self = shift;
my $last_modified_epoch = ...;
unless ( $self->if_modified_since($last_modified_epoch) ) {
$self->not_modified;
return;
}
}
If-Modified-Sinceを投げてくれるやさしいエージェントにはこちらもやさしくしないとってことでちょこっと書いてみました。
Posted by horiuchi at 21:57 | Permalink | Comments (2) | TrackBack (0)
2005年10月26日
Shibuya Perl Mongers テクニカルトーク #6
Perlっ子なら誰もが参加したいであろうShibuya Perl Mongersテクニカルトークの6回目、Shibuya Perl Mongers テクニカルトーク #6が11月2日に開催されるそうなので、僕も早速申し込みました。
miyagawaさんのSixApartのカルチャーと開発手法はぜひ聞いてみたい!
Ajax,Catalystなどの旬な技術の紹介も面白そうですし、今回もおなかいっぱいになりそうなこゆーい内容になってます。
Posted by horiuchi at 17:09 | Permalink | Comments (2) | TrackBack (0)
2005年09月11日
Class::DBI 3.0.1の中身は0.96
MFPMのRecent MailでClass::DBIが3.0.1にバージョンアップしたことを知りました。
search.cpan.org: Tony Bowden / Class-DBI-3.0.1
早速何が変わったのかChangesを見てみると、、
3.0.1 UNRELEASED3.0.0 UNRELEASED
- Code is identical to 0.96
- New section added to documentation on Release Philosophy
- Replace eq_set with is_deeply in t/04 to work around Test::More bug
- IDENTICAL to 0.96. Only difference is version renumbering.
ということで、中身は0.96と同じで、バージョンを付け直しただけみたいです。
これから大きなバージョンアップを行う下準備というところでしょうか。
Posted by horiuchi at 20:54 | Permalink | Comments (0) | TrackBack (0)
2005年08月17日
Class::DBI::Sweet
CDBIのメーリングリストを眺めていたら、複数のテーブルにまたがった検索なんかをClass::DBI::Sweetを使えば簡単にできるよみたいな投稿があったので、マニュアルを眺めてみましたが結構いろいろできそう。
ざっと見た感じ
- Class::DBI::PagerのようなData::Pageを利用したページング
- Class::DBI::Plguin::CountSearchでできるようなカウント検索
- SQL::Abstractを使った複雑な検索
- JOINを使った検索
- retrieve_allでorder_by
- キャッシング機能
といったようにかゆいところに手が届く機能が満載です。
それぞれの機能は個別のプラグインとしてだいたいCPANにアップされてますが、これひとつですべて住むってのは便利かも。
Posted by horiuchi at 09:45 | Permalink | Comments (0) | TrackBack (0)
2005年08月08日
MIME::Lite::TT::Japanese0.06
MIME::Lite::TT::Japaneseを0.06にバージョンアップし、CPANにアップしました。
今回の変更点は2つです。
- 長すぎる本文を自動改行するようにした。
- perlのバージョンでEncodeとJcodeの利用を切り替えていたのをJcode一本にした。
最初の自動改行については、やろうやろうと思っていたのですが、ついつい先延ばしになっていたのをやっと実装しました。デフォルトで72byte以上(文字数で35文字くらい)の行は自動的に改行されます。この値は変更可能で、MIME::Lite::TT::Japaneseのインスタンス作成時に「LineWidth」という名前で渡してやればOKです。また、自動改行したくない場合は「LineWidth」に0をセットすればOKです。
この自動改行の実装にJcodeのjfoldメソッドを使っているため、今回思い切って、Encodeの使用をやめて、Jcodeで一本化しました。最新のJcodeはperl5.8以降ではEncodeのラッパーとして動作するので、バージョンの切り分けはJcodeに任せようと思ったのも一本化の要因です。
EncodeでISO-2022-JPなMIMEエンコーディングができるようになったのをきっかけにMIME::Lite::TT::Japaneseのバージョンアップを思い立ったのですが、結果として、Encodeを使わないということに。。
Posted by horiuchi at 00:12 | Permalink | Comments (0) | TrackBack (0)
2005年08月07日
Encode 2.11
Encode 2.11がリリースされ、CPANにアップロードされています。
DanさんのエントリーEncode-2.11 releasedからトラックバックをいただいてバージョンアップを知りました。ありがとうございます。
今回のバージョンアップの目玉はなんと言ってもISO-2022-JPのMIMEエンコードに対応したことでしょう。以下のようなコードで簡単にエンコードできるみたいです。
$header = encode('MIME-Header-ISO_2022_JP', $utf8);
これでまかまかさんのおっしゃるとおり、MIME::Lite::TT::Japaneseのコードを簡単にできそうです。
Posted by horiuchi at 17:18 | Permalink | Comments (0) | TrackBack (0)
2005年08月01日
Class::DBIの開発が大変なことになっている模様。。
Class::DBIの作者が最近立ち上げたメーリングリストを削除、さらに、アーカイブとWikiも削除してしまったそうです。
そろそろ1.0のリリースかなんて思っていたので、かなりの衝撃です。。
今後の動向に注目です。
via:Class::DBI の開発でトラブル: blog.bulknews.net
Posted by horiuchi at 01:08 | Permalink | Comments (0) | TrackBack (0)
2005年07月08日
Class::DBI::Plugin::Factory
昨日書いたselectトリガを使ったClass::DBIのFactoryパターンをLost-SeasonのkatoさんがClass::DBIのプラグインにしてらっしゃいます。仕事はやっ!
ちなみに、Class::DBIのFactoryの実装方法について、インスタンス生成専門のFactoryクラスを別に作るという方法も考えたんですが、この実装方法だと、retrieve_allやsearchなどのリスト取得系の検索メソッドでインスタンスのリストを取得する際にサブクラスのインスタンスを生成ってところまでは感知できないので、やめにしました。
Posted by horiuchi at 09:15 | Permalink | Comments (0) | TrackBack (0)
2005年07月07日
selectトリガを使ったClass::DBIのFactoryパターン
以前からClass::DBIでFactoryパターンを使えたらなーと思ってました。
たとえば、有料、無料、VIPのように複数の会員タイプがあるような会員サイトを作る場合、Class::DBIを継承したMyService::MemberがFactoryとなり、会員のタイプによって、MyService::Member::Basic, MyService::Member::Free, MyService::Member::VIPというようなサブクラスのインスタンスを作成するというようなイメージです。
さらにFactoryクラスでMyService::Member->retrieve_allとかすると、適切なサブクラスのインスタンスのリストがとれると最高です。
そんなことができないかなーとClass::DBIのドキュメントやソースを眺めていたんですが、Class::DBIに組み込まれているselectトリガを使えば実現できそうだったので、試してみました。
selectトリガはインスタンス生成時に必ず呼ばれているので、ここで会員のタイプを判別し、サブクラスにreblessしてやります。ソースコードはこんな感じです。このコードそのままではないですが、実際に同じようなコードを書いて試してみたところ、うまく動いているようです。
*MyService::Member - Factory
package MyService::Member
use base qw(Class::DBI);
require MyService::Member::Basic
require MyService::Member::Free
require MyService::Member::VIP
__PACKAGE__->set_db('Main', @datasource);
__PACKAGE__->table('member');
__PACKAGE__->columns(Primary => qw(member_id));
__PACKAGE__->columns(Essential => qw(member_type name age));
# select トリガにrebless用のメソッドをセット
__PACKAGE__->add_trigger( select => \&_rebless );
# サブクラスにrebless
sub _rebless {
my $self = shift;
#会員タイプ(member_type)でreblesするサブクラスを選択
my $class = 'MyService::Member::Basic';
if ($self->member_type eq 'Free'){
$class = 'MyService::Member::Free';
} elsif($self->member_type eq 'VIP'){
$class = 'MyService::Member::VIP';
}
bless $self, $class;
}
# abstract method
sub is_free {}
sub monthly_cost {}
* MyService::Member::Basic - 一般会員
package MyService::Member::Basic;
use strict;
use base qw(MyService::Member);
sub is_free { 0 } # 無料ではない
sub monthly_cost { 500 } # 月額500円
* MyService::Member::Free - 無料会員
package MyService::Member::Free;
use strict;
use base qw(MyService::Member);
sub is_free { 1 } # 無料
sub monthly_cost { 0 } # 月額0円
* MyService::Member::VIP - VIP会員
package MyService::Member::VIP;
use strict;
use base qw(MyService::Member);
sub is_free { 0 } # 無料ではない
sub monthly_cost { 250 } # VIPは月額250円
Posted by horiuchi at 09:27 | Permalink | Comments (0) | TrackBack (1)
2005年07月01日
Web2.0な世界ではPerlがいい
antipop2.0 - Perler な Blog を列挙祭りのエントリでhori-uchi.comを取り上げてくださっていただいたのに最近Perlの話題あんまり書いてない!ということでちょっと思うところを書いてみたいと思います。
世の中にはいろいろなプログラミング言語が存在しますが、Web2.0な世界ではPerlがいいんじゃない?って話です。
Web2.0というと幅が広いですが、ここで言うWeb2.0はアプリケーション同士がAPIを通して相互に接続される世界とします。
このWeb2.0な世界でなぜPerlがいいのか、僕が考える理由は以下の3つです。
- 型のない言語
- 強力な正規表現
- CPANの存在
APIの実装はRESTやXML-RPC、SOAPなどを使った、XMLをデータのフォーマットとしてやりとりするというものが一般的です。ですので、各アプリケーションはXMLを解析し、処理すると必要がでてきます。XMLをプログラム内で扱う際にはXMLデータをXMLの階層構造を表現したハッシュであるとか、構造体のような形式にする必要がありますが、型を指定しなければいけない言語だと、いかようにもできるXMLをそういうデータ形式にするのは大変だろうなーと思います。その点PerlはXML::Simpleなんかをつかうと、
my $xml_href = XML::Simple->XMLin($xmlfile);
という一行でXMLのデータ構造をそのまま表したハッシュに変換してくれます。
また、XMLを解析してデータ形式に変換というような作業は結構時間のかかるものですが、Perlには高速で強力な正規表現があるので、これを使って、高速に特定のデータを抜き出すなんてことも簡単にできます。
最後にCPANの存在を忘れてはいけません。今後はAPIを提供するようなサービスが次々に出てくると思います。CPANには人気があるサービスだとそれらのAPIを簡単に使えるようにしてくれるモジュールがたいてい存在しています。Net::Amazon、Net::Google、WebService::Bloglines、WebService::Hatena::Fotolifeなど数え上げればきりがありません。
これらを使えば旬なサービスを簡単に使うことができます。
こんな訳で、APIでサービス同士がつながるWeb2.0な世界では、Perlがまた脚光をあびるんじゃないかなと思いました。
Posted by horiuchi at 10:18 | Permalink | Comments (0) | TrackBack (0)
2005年05月17日
Jcode 2.0 リリース
Jcode-2.00がリリースされました!
Jcode2.0の変更点はこんな感じです。
- Perl 5.8.1 以降の場合は Encode の Wrapper として機能する。
- Encode の Wrapper として機能する場合、パスの通ったところに置くだけで利用できる。
- 日本語podが付いた
JcodeのホームページではEncodeを使うことを推奨していますが、mime_encodeでMIME-B-encoded ISO-2022-JPを返してくれたり、jlengthとかjfoldとか便利なメソッドもあるので、これからもJcodeのお世話になりそうです。
Posted by horiuchi at 12:37 | Permalink | Comments (0) | TrackBack (0)
2005年04月19日
702MOと702sMOひどいな
久しぶりに携帯の個体情報を利用するシステムを作るため、ボーダフォンのサイトを調べていて唖然。
3G携帯はユーザエージェントがえらいことになっているとは聞いていましたが、702MOと702sMOは特にひどいですね。。
ユーザーエージェントがMOT-で始まるのも相当ひどいけど、ボーダフォンをみると個体情報も送らないっぽい。。
そりゃあ、HTTP::MobileAgent::Vodafoneにこんなコメントもつきますよね。
#for 3gc orz
Posted by horiuchi at 23:58 | Permalink | Comments (0) | TrackBack (0)
2005年04月06日
Acme::MorningMusume
antipop2.0 - Acme::MorningMusume リリース
より
Acmeというカテゴリ、いままで知りませんでした。CPANておもしろい。
Posted by horiuchi at 10:59 | Permalink | Comments (0) | TrackBack (0)
2005年04月03日
Template::Plugin::TagRescue0.04が特定条件で文字化け
あるサーバに移すとTempalte::Plugin::TagRescueを使ってタグをエスケープした部分の文字が化けるという現象が発生したため、原因を調査してみました。
サーバにインストールされていたのはその時点で最新のTemplate::Plugin::TagRescue0.04。
ソースをのぞくとタグのエスケープにApache::Util::escape_htmlもしくは、HTML::Entities::encode_entitiesが利用されていて、Apache::Utilが利用できない環境ではHTML::Entitiesが使われるという設計になっていました。
問題のサーバを調べてみるとApache::Utilが利用できない環境で、エスケープにはHTML::Entitiesが使われていて、どうやらそのHTML::Entitiesでエスケープを行うと文字化けが発生するようです。
そこでHTML::Entitiesのドキュメントを眺めると、以下のような記述が。
encode_entities( $string, $unsafe_chars ) This routine replaces unsafe characters in $string with their entity representation. A second argument can be given to specify which characters to consider unsafe (i.e., which to escape). The default set of characters to encode are control chars, high-bit chars, and the <, &, >, and " characters. But this, for example, would encode just the <, &, >, and " characters:
encode_entitiesの2つめの引数に明示的にエスケープを行う文字を指定しないと、マルチバイト文字もエンコードの対象になるようで、これが原因で文字化けしていたようです。試しに第2引数をわたしてやると、文字化けが解消されました。
今回の件は作者のtanimotoさんに報告し、パッチを送ったのですが、送った数時間後には修正しCPANにアップしてくださいました。仕事がはやい!
しかも僕のパッチからさらに改良して、実行速度を向上させるあたり、さすがだなーと思いました。
Posted by horiuchi at 23:20 | Permalink | Comments (0) | TrackBack (1)
2005年03月30日
Magic number checking on storable string failed
あるバージョンのStorableでシリアライズしたデータを別のバージョンのStorableでデシリアライズしようとすると吐かれるエラー。Storableのバージョンアップを行うなどした場合に注意が必要。
Posted by horiuchi at 23:06 | Permalink | Comments (0) | TrackBack (0)
2005年03月25日
mod_perl + encodingプラグマでサイト全体が文字化け
perl5.8から導入されたencodingプラグマを利用してSTDOUTの文字コードを透過的にエンコーディングして出力するようなスクリプトをmod_perl環境で実行すると、encodingプラグマの影響がそれを実行したapacheプロセスに残ってしまい、それ以降に実行されるすべてのスクリプトもこの影響を受けてしまうようです。
仮にEUCでサイトを構築していた場合、
#!/usr/bin/env perl use strict; use encoding 'euc-jp', STDOUT => 'utf8'; print "Content-type: text/html; charset=utf8;\n\n"; print "こんにちは";
のようなスクリプトを実行してしまうと、このスクリプトを実行したApacheの子プロセスにおいて、それ以降のすべての出力がUTF8にエンコーディングされてしまい、結果サイトが文字化けしてしまうことになります。
mod_perl環境ではencodingプラグマは使用しないで、JcodeとかEncodeモジュールを利用するほうがよさそうです。
- Jcodeを使う場合
#!/usr/bin/env perl
use strict;
use Jcode;
print "Content-type: text/html; charset=utf8;\n\n";
print Jcode->new("こんにちは", 'euc')->utf8;
- Encodeのfrom_toを使う場合
#!/usr/bin/env perl use strict; use Encode; my $str = "こんにちは"; Encode::from_to( $str, 'euc-jp', 'utf8'); print "Content-type: text/html; charset=utf8;\n\n"; print $str;
Posted by horiuchi at 00:29 | Permalink | Comments (0) | TrackBack (1)
2005年03月19日
gonzui Perl対応
gonzui Perl 対応: blog.bulknews.netより
miyagawaさんがgonzuiのPerl対応をしたそうです!熱すぎます!
さらにCPANモジュールをgonzuiを使って検索できるCPAN code search by gonzuiも同時に公開。ため息が出ます。。
これでperlユーザはCPANに登録された大量のコードをいつでも簡単に参照することができるようになるわけですね。
Posted by horiuchi at 01:59 | Permalink | Comments (0) | TrackBack (0)
2005年03月15日
Class::Dateで扱えるのは1902年から2038年まで
search.cpan.org: Class::Date - Class for easy date and time manipulation
Class::Dateに「1900-01-01」を渡すとなぜか2038年になってしまうのでドキュメントを見直すとBUGS AND LIMITATIONSのセクションに以下の記述がありました。
This module uses the POSIX functions for date and time calculations, so it is not working for dates beyond 2038 and before 1902. I don't know what systems support dates in 1902-1970 range, it may not work on your system. I know it works on the Linux glibc system with perl 5.6.1 and 5.7.2. I know it does not work with perl 5.005_03 (it may be the bug of the Time::Local module). Please report if you know any system where it does _not_ work with perl 5.6.1 or later. I hope that someone will fix this with new time_t in libc. If you really need dates over 2038 and before 1902, you need to completely rewrite this module or use Date::Calc or other date modules.
時間関係はTime::Pieceを使った方がいいかも。
Posted by horiuchi at 17:52 | Permalink | Comments (0) | TrackBack (0)
2005年03月01日
Path::Class - Cross-platform path specification manipulation
search.cpan.org: Ken Williams / Path-Class
ファイルのPathをオブジェクトとして扱えないかなーと思って探していて見つけたモジュール。
File::Specよりシンプルにパスを扱えるてよさげ。
Posted by horiuchi at 21:43 | Permalink | Comments (0) | TrackBack (0)
2005年02月23日
Class::Dateいい感じ
Class::DBIのWikiで使われてたのをみてから、時間を扱うモジュールとして、Class::Dateを利用しています。時間をオブジェクトとして扱うモジュールといえば、Time::PieceとかDate::Simpleが有名ですが、Class::Dateも結構いい感じです。Class:DBIと一緒に使うと便利で、has_aでDATETIME型のカラムにマッピングするのが以下の一行で行えます。
__PACKAGE__->has_a( modify_date => 'Class::Date' );
Posted by horiuchi at 20:39 | Permalink | Comments (0) | TrackBack (0)
2005年01月27日
Template::Toolkit - 文字列の連結
Template::Toolkitのテンプレート内の文字列の連結は'_'(アンダースコア)を使う。忘れるのでメモ。
Template Toolkit ManualYou can concatenate strings together using the ' _ ' operator. In Perl 5, the '.' is used for string concatenation, but in Perl 6, as in the Template Toolkit, the '.' will be used as the method calling operator and ' _ ' will be used for string concatenation. Note that the operator must be specified with surrounding whitespace which, as Larry says, is construed as a feature:
[% copyright = '(C) Copyright' _ year _ ' ' _ author %]
You can, of course, achieve a similar effect with double quoted string interpolation.
[% copyright = "(C) Copyright $year $author" %]
Posted by horiuchi at 17:39 | Permalink | Comments (0) | TrackBack (0)
2005年01月25日
Extreme Perl オンラインドキュメント
Extreme Perl is online: blog.bulknews.netをみて知ったんですが、Extreme PerlというPerlを使ったXP(Extreme Programming)について書かれた本のHTML,PDFが公開されたそうです。
読まなくては。
Posted by horiuchi at 09:48 | Permalink | Comments (0) | TrackBack (0)
2005年01月17日
Date::Simple::Month 0.02
Date::Simple::Monthのバージョンを0.02にアップしました。
といっても特に機能追加はなく致命的なバグの修正のみです。0.01では内部で使用しているDate::Simpleをuseするのを忘れていて、単純に動いていませんでした。。
使おうとしてくださった方々、ごめんなさい。
Posted by horiuchi at 12:12 | Permalink | Comments (0) | TrackBack (0)
2005年01月14日
MFPM - My Favorite Perl Modules
お気に入りのPerlモジュールを管理できるMFPMというサイトが公開されたということで、早速登録してみました。
現在のところ、主な機能はこんな感じで、これからも便利な機能がどんどん追加されていきそうな予感。
- CPANモジュールの検索
- コメントをつきのお気に入りリスト
- モジュールのバージョンアップの検知
- モジュールに関する他人のコメント閲覧
- 他人のお気に入りリスト閲覧
- 自分のお気に入りリストを自分のBlogに貼り付けられる
- CPANモジュールに対してトラックバック送信可能
- お気に入りに登録しないモジュールに対してメモを残せる
モジュールに関する他人のコメントが読めるのはいいですね。新しいモジュールを試してみたいって時にまずはここにきて、そのモジュールの評判をみてみるってかんじで使えそう。
とりあえず自分のBlogにもリストを貼り付けてみました。
Posted by horiuchi at 09:45 | Permalink | Comments (0) | TrackBack (0)
2005年01月11日
自作PerlモジュールをCPANでインストールする
今まで、新しくサーバを構築する時には、自作のPerlモジュールのインストールは一つ一つ、makeしてインストールってことをしていたんですが、モジュールの数が多くなってきていちいちインストールするのがしんどくなってきました。モジュールのインストールというとCPANモジュールを利用した方法が非常に簡単なので、自作モジュールも何とかCPANモジュールを使ってインストールできないか調べてみました。
すると、CPAN::Siteなるモジュールを発見。モジュールの作成日時が相当古いんでちょっと心配でしたが、とりあえず、試してみました。ドキュメントの通りに試してみるととりあえず、自作モジュールをCPAMモジュールを使ってインストールできるようになったんですが、普通にCPANに登録されているモジュールのインストールができなくなってしまいました。(検索してもHITしない)
何か設定が悪いのか、仕様なのかちょっと調べきれてませんが、なにやらいまいち。。
自作モジュールのインストール、他の人はいったいどうやっているんでしょうか。。
Posted by horiuchi at 00:50 | Permalink | Comments (0) | TrackBack (0)
bundleを作成してPerlモジュールのインストールを簡単に
perlにはCPANというとても便利で強力なサイトがあり、そこに登録されている膨大な数のPerlモジュールを利用することにより、面倒なプログラミングを簡単にできたりするんですが、Perlモジュールを多用しはじめると、そのインストールが結構面倒くさくなってきます。特に新たにサーバをたてて、システムを新規に構築するなんて時はモジュールのインストールだけでかなり時間がかかってしまうってことになりかねません。
そこでいつも使うようなモジュールをリストにまとめておき、一発でインストールできれば、非常に便利ですし時間も節約できます。CPANではBundleを使うことによりそのようなことを実現できます。
Bundleはそれ自体がPerlモジュールです。Bundleは以下の手順で作成します。
- まずBundle::の名前空間を持つモジュールとして作成する
- =head1 CONTENTSというPODセクションを作成し、そこにモジュールのリストを記述する
- 記述方法はModule_Name [Version_String] [- optional text]
- 作成したBndle::Fooをパスの通った場所におき、perl -MCPAN -e install 'Bundle::Foo'
詳しくはperldoc CPANすると書いてあります。また、CPANでBundleで検索するとたくさんヒットしますので、それを参考にすれば簡単にかけると思います。
Posted by horiuchi at 00:20 | Permalink | Comments (2) | TrackBack (1)
2004年12月26日
Class::DBIとApache::ReloadでInternal Server Error
mod_perlで動作するアプリケーションを開発する場合、更新されたモジュールをリロードしてくれるApache::Reloadのようなモジュールを利用するのが一般的だと思いますが、Apache::Reloadが有効になっている状態でClass::DBIを継承したモジュールを更新すると以下のようなエラーメッセージをはいてInternal Server Errorになるという現象に悩んでました。
[Sun Dec 26 20:06:02 2004] [error] Can't use an undefined value as a HASH reference at /usr/local/perl-5.8.5/lib/site_perl/5.8.5/Class/DBI/Relationship/HasMany.pm line 51.\n Compilation failed in require at /usr/local/perl-5.8.5/lib/site_perl/5.8.5/Apache/Reload.pm line 140.\n
そこで少し調べてみると、Re: Apache::Reload and CDBI won't play togetherに次のような記述が。
Class::DBI prevents you from overwriting already declared methods. To fix this, you would need to hack Apache::Reload to clear the symbol table of your package just before reloading it, or hack Class::DBI to ignore overwriting subs.
Class::DBIはすでに宣言されているメソッドの上書きをさせないのが原因で、これを回避するには、リロードされる前にシンボルテーブルをクリアするようにApache::Reloadをhackするか、上書きを無視するようにClass::DBIをhackしろということのようです。
そこで今回は開発環境でしか使わないApache::Reloadをhackし、パッチを書いてみました。(Class::DBIに比べてApache::Reloadはコードの量が少ないのでhackが簡単。)
--- Reload.pm.orig 2004-12-26 19:35:31.000000000 +0900
+++ Reload.pm 2004-12-26 20:22:40.000000000 +0900
@@ -122,6 +122,14 @@
}
if ($mtime > $Stat{$file}) {
+ my $package = $key;
+ $package =~ s/\//::/g;
+ $package =~ s/\.pm$//;
+ if ( UNIVERSAL::isa($package, 'Class::DBI') ){
+ no strict 'refs';
+ warn "Apache::Reload: clear the symbol table of $package\n" if $DEBUG;
+ %{"$package\::"} = ();
+ }
delete $INC{$key};
# warn "Reloading $key\n";
if (my $symref = $UndefFields{$key}) {
Posted by horiuchi at 20:21 | Permalink | Comments (0) | TrackBack (0)
2004年12月24日
Class::DBI::DTO
前々からClass::DBIでデータをcreateする際の引数にハッシュのリファレンスでなく、オブジェクトを渡せたらいいなーと思っていたので、そんな感じのことができるClass::DBI::DTOというモジュールを書いてみました。
Class::DBI::DTO - Data Transfer Object for Class::DBI
ドキュメントは途中ですがあしからず。。
dtoメソッドで生成されるインスタンスはparamメソッドを持っているので、SledgeのFillinFormではadd_fobjectにそのままインスタンスを渡せます。
DTOという単語はオブジェクト脳のつくり方―Java・UML・EJBをマスターするための究極の基礎講座を読んでいたときに出てきたもので、JAVAの偉い人が考えた概念らしいです。このモジュールの用途として、データをセッションに入れたり、そのままフィルインさせたりと何となくTransferな感じかなーと思ってこの名前を付けました。勝手に使ったら怒られるんだろうか。。
Posted by horiuchi at 10:32 | Permalink | Comments (0) | TrackBack (0)
2004年12月17日
Shibuya Perl Mongers テクニカルトーク #5
Shibuya Perl Mongers : Shibuya Perl Mongers テクニカルトーク #5に行ってきました。アルファギークな方々による技術的に濃ゆい話(iPod,ITunesのAPI,SpiderMonkey,SOAP,XML-RPC,TDD,JAPHなど)をたっぷり聞いてきました。
特に参考になったのが竹迫さんのXML::ParserのUTF8フラグ問題の対処方法。perl5.6、5.8のどちらにも通用する対処方法は今後の開発に使えそうです。
また、JAPHを読むでは、マジカルインクリメントを用いて「perl」と表示するというコードに関心。
my $A="a";for(1..285075){$A++;}print"$A";
文字aをインクリメントしていくと、285075番目がperlという文字列になるということですが、ふと「horiuchi」は何番目なんだろうと気になり、それを出すコードを書いてみました。
my$a='a';my$b=1;my$c=shift;while($a ne $c){$a++;$b++}print"$b";
今朝の9時半から計算し始めましたがまだ計算してます。。現在「112348132」。。いつ終わるかなー。。
Perl Mongersに初めて参加したのが去年の今頃。そのときは自分が何も知らなすぎてこの人たちは何を言ってるんだとかなりのカルチャーショックを受けたのを覚えています。今回もSpiderMonkeyとか初めて聞く単語もあって、いい刺激になりました。
それと、帰りにh.g.lさんとボンディ 神保町本店 で食べたカレーがおいしかったです。
Posted by horiuchi at 09:18 | Permalink | Comments (2) | TrackBack (0)
2004年12月16日
MIME::Lite::TT::Japanese-0.05
MIME::Lite::TT::Japaneseを0.05にアップデートしました。
search.cpan.org: Yasuhiro Horiuchi / MIME-Lite-TT-Japanese
アップロードしたばかりでCPANにはまだ反映されてませんがそのうち反映されると思います。
反映されました 11/16 9:00
0.04からの変更点は
- Dateフィールドに日本のローカルタイムをセットするようにした。
の一点です。MIME::Lite::TT::Japaneseから受け取ったメールの日時がユニバーサルタイムになっていて、Beckyなどで受信するとぱっと見、日付がずれているように見えるのが気になったので、修正しました。ローカルタイムの生成にはMail::Dateを使わせて頂きました。
Posted by horiuchi at 01:47 | Permalink | Comments (0) | TrackBack (0)
Sledge::Plugin::SaveUploadImage-0.02
アップロードされたファイルをjpg,gif,png形式で保存するSledge::Plugin::SaveUploadImageを0.02にバージョンアップしました。
Sledge::Plugin::SaveUploadImage-0.02
保存の際の画像のサイズを指定できるようにしました。
また、0.01からインターフェースを変えました。
0.01では保存先のディレクトリとファイル名を別々に渡してやる必要がありましたが、
0.02ではこれを一つにまとめてパスとし、パスの最後が/で終わっている場合はディレクトリと見なし、ファイル名は自動的に発行するようにしました。
返値はファイル名でなく保存先のパスに変更しました。
Posted by horiuchi at 01:38 | Permalink | Comments (0) | TrackBack (1)
2004年12月06日
Template::Plugin::TagRescue
Webアプリケーション開発において、ユーザが入力したデータをブラウザに表示するような場合には、XSSなどの脆弱性を排除するため、HTMLタグのエスケープは必須です。
でも、What's Newをブラウザから更新するようなアプリケーションの場合、aタグは使いたいとか、imgタグは使いたいというような特定のタグのみ許可してほしいという要望は結構あるものです。
これを簡単にやってくれるのがTemplate::Plugin::TagRescueです。フィルターとして動作するので、使い方も簡単。
[% USE TagRescue%]
[% '<a href="http://hori-uchi.com">hori-uchi.com</a><b>bold</b>' | html_except_for('a') %]
Posted by horiuchi at 16:52 | Permalink | Comments (2) | TrackBack (1)
Template::Toolkitのテンプレート内で割り算
Template::Toolkitのテンプレート内で割り算の商を取得したくて、
[% c = int (a / b) %]
などと直感的に書いてみたんですが、やっぱり構文エラーになってしまいました。しょうがなくマニュアルを眺めていると、以下のような記述が。
Template Toolkit Manual: Directives
The 'div' operator returns the integer result of division. Both '%' and 'mod' return the modulus (i.e. remainder) of division. 'mod' is provided as an alias for '%' for backwards compatibility with version 1.
[% 15 / 6 %] # 2.5
[% 15 div 6 %] # 2
[% 15 mod 6 %] # 3
[% c = a div b %]
でできるんですね。絶対忘れるのでメモ。
Posted by horiuchi at 16:10 | Permalink | Comments (0) | TrackBack (0)
perl 5.8.6 released
perl5.8.6がリリースされました。
5.8.5からの変更点はsearch.cpan.org: perldelta - what is new for perl v5.8.6で確認できます。
Posted by horiuchi at 10:21 | Permalink | Comments (0) | TrackBack (0)
Jcodeが0.88にバージョンアップ
search.cpan.org: Dan Kogai / Jcode-0.88
CPANのアップデートをみてたらJcodeが0.88にバージョンアップされてました。
Encodeのラッパーになるって話を聞きましたがそれはまだのようです。
Posted by horiuchi at 10:17 | Permalink | Comments (0) | TrackBack (0)
2004年12月03日
ビッダーズWebサービスもいじってみました
先日のアマゾンウェブサービスに続いてビッダーズWebサービスもいじってみました。少しいじってできたものがこれです。今回もperl, Sledge, mod_perlで作ってます。
hori-uchi.com: Bidders Keyword Search
機能は前回のアマゾンと同じくただ検索できるだけ。。
とりあえずさわってみた印象として、
- まだ利用者数が少ないのかレスポンスが早くて快適
- 検索キーをUTF-8でなくShift_JISで渡すのにちょっと驚いた。
- レスポンスに画像のリンクあるけど商品へのリンクはない??
ビッダーズWebサービス自体はまだベータ版ということでこれからも機能拡張していきそうです。
ビッダーズもアマゾンなどと同じくアフィリエイトをやっているようなのでほんとはこれと絡めたかったんですが、明日は朝から、Internet Week 2004のWeb and Internet Applications Day に参加するのでとりあえず今日は寝ることにします。
Posted by horiuchi at 02:27 | Permalink | Comments (0) | TrackBack (0)
2004年11月28日
perl 5.6 -> 5.8 on FreeBSD
今日はNet::Amazonをいじっていたんですが、XMLいじるならperlのバージョンは5.8系がいいよねとふと思い立ち、テスト用のFreeBSDサーバのperlのバージョンを5.6.1から5.8.5にアップしてみました。
とりあえず、/usr/ports/lang/perl5.8に移動してmakeしてみるとすんなりOK。問題あればエラーでこけるだろうとmake installも実行。。すんなりインストール完了。とっても簡単。(本当はportupgrade -o lang/perl5.8 -f perl-5.6.1_15 とやるのが正解みたいです。。)
# cd /usr/ports/lang/perl5.8 # make # make install clean
次にシステムにperl5.8.5がインストールされたよということを知らせるためにuse.perlコマンドを実行しました。
# use.perl port
次にperlを使っている他のports達に5.8になりましたよと伝る作業を行いました。これにはワイルドカードが使えるportupgageを使うのが簡単です。これはインストールされているperlモジュールを5.8用にアップグレードするコマンドです。
# portupgrade -f p5-\*
さらにmod_perlもインストールし直しました。これでだいたいOKだと思います。後は何か問題が起こったらその場で対応ということにします。
今回の作業を行うに当たり、下記のサイトを参考にさせて頂きました。
SpamAssassinの導入設定メモ. [FreeBSD](fkimura.com)
Posted by horiuchi at 03:05 | Permalink | Comments (0) | TrackBack (0)
2004年11月15日
perl5.8.5でClass::Fieldがtestでこける
新しいサーバにSledgeをインストールしていたところ、Sledgeを動かすのに必要なモジュール、Class::Fieldがmake testでこけました。原因はperlのバージョンによるwarnningのメッセージの違いによるもののようなので、特に気にせずmake installしてしまってOKだと思います。
::ok( $warnings eq <<WARN, 'Improper use of fields & base warned about' ); Bar is inheriting from Foo but already has its own fields! This will cause problems with pseudo-hashes. Be sure you use base BEFORE declaring fields WARN
ちなみにエラーがでていたコードは上の部分で「with pseudo-hashes」の部分を削除すれば5.8.5でもテストに通りました。
Posted by horiuchi at 14:47 | Permalink | Comments (0) | TrackBack (0)
2004年11月10日
Template::Plugin::Dumper
search.cpan.org: Template::Plugin::Dumper - Plugin interface to Data::Dumper
テンプレート内のパラメータをダンプするためのTTプラグイン。TT標準のプラグインなのに今まで使ったことありませんでした。普段はwarn Dumperで事足りるんですが、テンプレート内で演算なんかしたときのデータを確認したいときなんかに使えますね。というか今までこのプラグインに気づかなくてうかつ。
Posted by horiuchi at 21:58 | Permalink | Comments (0) | TrackBack (0)
2004年11月02日
DBD::mysql2.9005_3
DBD::mysqlがバージョンアップしたみたいです。変更点はこんな感じです。
- DBI1.43が必要になった。
- $dbh->last_insert_id()が使えるようになった。
- mysql_unsafe_bind_type_guessingオプションをセットすると数字っぽいスカラー値を数字として扱い、クオートしない。(自己責任で使ってね。)
- 最近のmysqlでカラムが壊れるのを修正した。
- Makefile.PL実行時、5.008ではLANGがCに設定されてない場合、文句を言ってCに変えまて実行します。
うーむ、カラムが壊れるって何でしょうか。。
以下実際のChangelogです。
2004-10-27 Rudolf Lippan
(2.9005_3)
- Removed requirement that mysql.mtest be included in the distribution.
- DBI 1.43 is required -- It is needed for support of $dbh->last_insert_id().
- Added $dbh->{mysql_unsafe_bind_type_guessing} = 2 which will look at each bind_param and make guess based on whether it looks like a number, and if the parameter looks like a number, it will not be quoted. [thanks to dragonchild for cleaning up the initial rough draft impementation making it ready for prime time]
- Applied patch to fix column which broke with later version of mysql [Tim Bunce]
- Merged $dbh->last_inert_id() from the 3.0 dev tree
- If you are using perl 5.008 without a $ENV{LANG} of "C". Makefile.PL will now 1. Complain loudly, and 2. set LANG to "C" and then exec itself with the new lang setting.
- Added '$dbh->{mysql_unsafe_bind_type_guessing}'. When this flag is enabled any scalar that is passed to execute() and was used innumeric context will be treated as a number when being sent to the database backend. This can be a secuity problem in that if you use a string in numeric context, it will NOT be quoted before being passed to the database -- use at your own risk. The default is off.
- fixed typo in pod changing failed_auto_reconnects_failed to auto_reconnects_failed [Paul DuBois
]
Posted by horiuchi at 09:49 | Permalink | Comments (0) | TrackBack (0)
2004年10月22日
mod_perl使用時はMaxClientsの値に気をつけましょう
導入するだけで既存のCGIスクリプトがお手軽に10~200倍高速になるmod_perlですが、mod_perl自体がサイズがでかいのと、高速化のため、モジュールをキャッシュするため、apacheのプロセスサイズが結構大きくなってしまいます。経験的にはだいたい1プロセスあたり20~30MByte位にはなります。このような性質上、mod_perlを使う場合はメモリの使用量を考えなくてはいけません。
ところで、Apacheのデフォルトの設定ではMaxClientsの値は150に設定されています。これは同時に最大150のリクエストをさばく、つまり最大150まで子プロセスを同時に生成するということです。仮に150個の子プロセスを生成するとすると、mod_perlを利用時の1プロセスのサイズをおよそ20Mbyteとすれば20×150=3000[MByte]=3[GByte]のメモリを必要とすることになります。この場合、スワップ領域を含めてメモリの容量が3[GByte]に満たないサーバはすべてメモリを使い切り、最悪落ちることになります。
ということでほんとに落ちるかどうか実際に試してみました。 方法はApache付属のベンチマークツールabを使い同時アクセス数100、で1000回のリクエストを送るというものです。
ab -c 100 -n 1000 -k http://targetsite.hostname/対象サーバのスペックはCPU:Pentium3の600MHz、メモリ:512MByte、スワップ領域は1GByteです。
結果はというと、、abはタイムアウトで測定不能となりました(当たり前)。さらに、ab終了後のサーバにも問題が。。サーバが落ちることはなかったんですが、abはタイムアウトで終了しているのにめちゃめちゃサーバのレスポンスが悪くなってしまいました。sshでの接続にも数十分かかる始末。やっとの事でログインし、Apacheを終了させるとようやくレスポンスが生き返りました。
結論、mod_perlを使うときはMaxClientsの値に注意しましょう。Apacheのデフォルト設定で運用すると最悪サーバが落ちます。MaxClientsの値は「サーバのメモリ容量 / Apacheの1子プロセスのサイズ」でおおざっぱに計算できます。今回試したサーバでは512/20=25位に設定しておけば、メモリを使い切ってサーバが落ちる危険がなくなります。
Posted by horiuchi at 09:31 | Permalink | Comments (0) | TrackBack (1)
2004年09月14日
MIME::Lite::TT::Japanese 0.04
MIME::Lite::TT::Japaneseを0.04にバージョンアップして、CPANにアップロードしました。
変更点は以下の通りです。
- perl5.8.0以上でもMIME-HeaderのエンコーディングをUTF8からISO-2022-JPに変更した。
- それに伴って5.8.0以上でもJcodeを必須モジュールとした。
今までは楽をしてperlのバージョンが5.8.0以上の場合、Encode.pmのEncode::MIME::Header を使っていたので、MIME-HeaderのエンコードがUTF8でしたが、携帯のメーラなどがUTF8にエンコードされたヘッダを解釈できないので、Jcodeを利用してISO-2022-JPにエンコードするようにしました。
Posted by horiuchi at 14:34 | Permalink | Comments (0) | TrackBack (2)
2004年09月10日
Perlモジュールのバージョン確認
たとえばこのサーバにインストールされているCGI.pmのバージョンを確認したいなんて時はperl -MCGI -e 'print $CGI::VERSION'なんてコマンドを打ってやれば確認できますが、これをいちいち打つのはめんどくさいので、簡単なスクリプトを書いてみました。
#!/usr/bin/env perl
use strict;
use File::Basename;
use Getopt::Std;
getopts('v', \my %opt);
die "Usage: ". basename $0. "[-v] [ ...]\n"
if @ARGV == 0;
no strict 'refs';
for (@ARGV) {
(my $path = $_) =~ s{::}{/};
eval {require "$path.pm"};
if ( $@ ) {
print "$_: not found.\n" if $opt{v};
} else {
print "$_: ", ${join '::',$_,'VERSION'}, "\n";
}
}
Posted by horiuchi at 09:23 | Permalink | Comments (0) | TrackBack (0)
