mod_perl + Apache2::Filterで文字コード変換

Apache::Adsfilter.pmなんてのを書いてみた
mod_layoutApache::Layoutみたいにフッターにテキストだとか広告を付加するモジュール

Perl/CGIPHPの場合、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
とするだけ

つか絵文字変換とかApache+Mod_perl使えば簡単にできそうな予感