mod_perl + Apache2::Filterで文字コード変換
Apache::Adsfilter.pmなんてのを書いてみた
mod_layoutやApache::Layoutみたいにフッターにテキストだとか広告を付加するモジュール
Perl/CGIやPHPの場合、mod_layoutだと正しく表示されない事が多い(途中でデータがとぎれてる。content_lengthと実際の長さが違うからか、モジュールがApacheに渡すタイミングの問題なのか)
それとフッターの文字列は特定の文字コードでかかれてる訳なので、サイトごとに文字コードが違う場合には当然化けるので広告としては価値がない文字列になってしまう。
そこでApache2::filter使ってみた
ほとんどは技術史さんのところにかいてあるのをいじっただけだけ
http://d.hatena.ne.jp/askadna/20070710
正規表現つかって文字列を置換するだけだ。
とはいえこれでほぼ目的が満たされた感じなのでとりあえずこれでいいや
package Apache::Adsfilter; BEGIN { if ( $ENV{'MOD_PERL_API_VERSION'} == 2 ) { require Apache2::Filter; push @ISA, 'Apache2::Filter'; require Apache2::Response; require Apache2::Const; require Apache2::RequestRec; require Apache2::RequestUtil; Apache2::Const->import(qw(OK DECLINED)); } } use strict; use warnings; use Jcode; use constant BUFF_LEN => 1024; sub handler { my $f = shift; unless ($f->r->content_type =~/text\/html/) { return DECLINED(); } unless ( $f->ctx ) { $f->ctx( { body => '' } ); } while ($f->read(my $buffer, BUFF_LEN)) { $f->ctx->{'body'}.= $buffer; } unless ($f->seen_eos) { return OK(); } my $ads1 = '広告'; my $adsurl = 'http://www.example.com/'; if($f->ctx->{'body'} =~ /charset=Shift_JIS/){ $ads1 = Jcode->new($ads1)->sjis; } elsif($f->ctx->{'body'} =~ /charset=EUC-JP/){ $ads1 = Jcode->new($ads1)->euc; } $f->ctx->{'body'} =~ s/<\/body>/<a href="$adsurl">$ads1<\/a><\/body>/; $f->r->set_content_length( length( $f->ctx->{'body'} ) ); $f->print( $f->ctx->{'body'} ); OK(); } 1;
使い方はmod_perlが入ったサーバで
PerlModule Apache::Adsfilter
目的の場所で
PerlOutputFilterHandler Apache::Adsfilter
とするだけ