Home

JeffreyFrancesco.org

feedback プラグイン導入メモ - (3)

前回の続き。

実は feedback プラグインを導入した最大の動機が、Akismet による強力なスパム対策。既に WordPress に標準で提供され (有効化は必要ですが) 実績を上げているとなれば、Blosxom でも使いたくなるというのが人情というもので(?)

実際に有効化するためには、Net::Akismet という Perl モジュールが必要です。モジュールがインストールできる環境にあればインストール、でなければ blosxom.cgi 本体と同じ階層に Net というディレクトリを作り、その下に Akismet.pm を置いても OK です。API Key の取得も忘れずに (取得方法の解説サイト)。

/cgi-bin + blosxom.cgi
         |
         - /Net        - Akismet.pm

で、実際にスパムと判断されそうな適当なコメント ("casino" とか "poker" とかのキーワードを入れたもの) を投稿してみましたが…普通に通ってしまいます。アレ? ローカルでやってるからダメなの? なら実際に構築したサイトの方でテスト。

…やっぱり普通に通ってしまいます。適当な他のサイトからスパムっぽいコメントを拾ってきて、そのままコピペして投稿しても通ってしまう。ダメじゃん。

で、サーバのエラーログを見てみますと、何か Use of uninitialized value in string eq ていうエラーが一杯出てる。「初期化されていない変数が比較に使われてる」というエラーだそうで。エラーが出てる部分のプラグインのスクリプトは:

    return 1 if $akismet->check(%fields) eq 'true';

ということは、$akismet->check(%fields) が初期化されていないって事でしょうか? その少し前のコードにて:

    # Attempt to connect to the Askimet service.
    my $akismet = Net::Akismet->new(KEY => $wordpress_api_key,
                    URL => $blosxom::url);
    unless ($akismet) {
    warn "feedback: Akismet key verification failed\n";
    return 0;
    }

    # Set up fields to be verified. Note that we do not use the REFERRER,
    # PERMALINK, or COMMENT_AUTHOR_EMAIL fields supported by Akismet.

    my %fields = (USER_IP => $ENV{'REMOTE_ADDR'});
    if ($is_comment) {
    $fields{COMMENT_TYPE} = 'comment';
    $fields{COMMENT_CONTENT} = $$params_ref{'comment'};
    $fields{COMMENT_AUTHOR} = $$params_ref{'name'};
    $fields{COMMENT_AUTHOR_URL} = $$params_ref{'url'};
    } else {
    $fields{COMMENT_TYPE} = 'trackback';
    $fields{COMMENT_CONTENT} =
        $$params_ref{'title'} . "\n" . $$params_ref{'excerpt'};
    $fields{COMMENT_AUTHOR} = $$params_ref{'blog_name'};
    $fields{COMMENT_AUTHOR_URL} = $$params_ref{'url'};
    }

ってやってるんだけど。で、上記と同じように %fields を埋めたテストスクリプトを書いて走らせてみると、どうも $akismet->check(%fields)undef を返しているようです。うーん…という訳で、Net::Akismet の和訳ドキュメントを読んでみると:

COMMENT_USER_AGENT

必須。コメント投稿者のユーザーエージェント文字列を示します。

ってなってる。改めて先のコードを見直すと、%fieldsUSER_IP は設定されてるけど、COMMENT_USER_AGENT が設定されていません。なるほど、必須パラメータが抜けてるので、undef を返してるんですね。という訳で、コードを以下のように手直し。

    my %fields = (USER_IP => $ENV{'REMOTE_ADDR'});
    # 追加部分
    $fields{COMMENT_USER_AGENT} = $ENV{'HTTP_USER_AGENT'}

これで改めてテストコメントを投稿しますと、今度はちゃんと弾いてくれました。ほっ。

次回は、コメントの処理まわりをもう少し弄ってますので、その辺の解説を。でも一旦この話題はしばらく休むかも。

feedback プラグイン導入メモ - (2)

前回書いたように修正しておけば、とりあえず謎な文字化けは回避できるけど、トラックバックが有効にしてあるサイトなどでは、トラックバック元の文字コードが UTF-8 じゃなければ文字化けが発生しますし、普通に個別ページからコメントする分にはまず問題ないけどそうじゃない場合もある (悪意でわざと文字コードを変えてコメント投稿をされるなど)ので、それに対しては我々の方で対策してやる必要があります。

feedback プラグインのコードを読んでみると、受け取ったコメントやトラックバックのサニタイズ処理を行なっているのは save_feedbacksave_preview の2つのサブルーチンで、それぞれ1157行目と1216行目で:

    $value = escapeHTML($value);

とやってるだけなので、この部分に文字コード判別と変換の処理を加えておきます (ちなみにこの部分は前回書いた通り、自前の escape_HTML サブルーチンで処理するように変更します)。という訳で、変更後の save_feedbacksave_preview サブルーチンの該当部分は:

    my $charset = getcode(\$value);
    $value = Jcode->new(\$value, $charset)->utf8
        if $charset and $charset !~ /^(ascii|utf8)$/;
    $value = escape_HTML($value);

という風に変更しました。始めに getcode で判別した文字コードを変数 $charset に格納した後、$charset があって (つまり undef でない) かつ ascii utf8 以外の時にのみ、Jcode で UTF-8 に変換、その後 escape_HTML してサニタイズ処理を行なう、という具合です。

SuiteX サーバには Perl 5.8.7 がインストールされているので Encode モジュールを使っても良いんでしょうが、UTF-8 フラグが今一理解できてない頃に修正したので、Jcode モジュールを使ってます。まあどちらもインストールされているのですが。

次回は Akismet によるスパム対策の有効化について書く予定です。

feedback プラグイン導入メモ - (1)

という訳で、1回目。

ダウンロードしたのをそのまま plugin ディレクトリに放り込んだだけでは、日本語環境だと少し不具合が起こりました。デフォルトの状態でブラウザからテスト投稿してみると、文字コードの変換は全く起こってない状態にも関わらず、何故か一部のコメントが文字化けしてしまうんです。

色々調べてみると、feedback プラグインは投稿されたコメントを処理する際に、& < > " を実体参照化するために CGI モジュール内の escapeHTML サブルーチンに処理を任せているのですが、どうやらこのサブルーチンの仕様が悪さをしているようで

escapeHTML() を読むと、文字コードが "ISO-8859-1" か "WINDOWS-1252" だった場合に、 "\x8b" と "\x9b" という二文字をエスケープしてそれぞれ "‹" と "›" にしている。コメントによると、 "# Handle bug in some browsers with Latin charsets" だそうで、ブラウザのバグに対処するためのコードらしい。

この "\x8b" "\x9b" という二文字は、 Terminal.app で文字エンコーディングを「欧米 (Windows Latin 1)」にしたときに以下のようにすると表示される文字(UTF-8 だと ? になってしまう)。 wordpress で作ってあるブログのタイトル部分によく使われている、 < と > の小さいっぽい文字のようだ。

ということなのですが、おそらくプラグインから escapeHTML に処理を渡す部分で文字コード (UTF-8) を指定して渡していないため、デフォルトの "ISO-8859-1" と判断されて上記引用部分のエスケープ処理がされ、この二つのバイトを含む文字が化けてしまうのだと思います。なので、プラグインの内部に新規で escape_HTML というサブルーチンを作り:

sub escape_HTML {
    my $text = shift;

    $text =~ s/&/&amp;/mg;
    $text =~ s/</&lt;/mg;
    $text =~ s/>/&gt;/mg;
    $text =~ s/"/&quot;/mg;
    $text =~ s/'/&#39;/mg;  # 無くてもいいかもしれないけど一応

    return $text;
}

んで、コメント処理 etc. で escapeHTML を呼び出しているところを escape_HTML に変更し、実体参照化をプラグイン内部で行なってやるようにすることで対処しておくことにしました。オリジナルのコードでいうと 1157 行目辺りと 1216 行目辺りの2ヶ所になりますね。やってることはほぼ同じ、余計な処理だけ省いたってだけなんですが (笑) とりあえずこれで普通の文字化け (謎) は回避することが出来ます。

という訳で、次回は普通じゃない文字化け (?) への対処法を、近いうちに書きます。

feedback プラグイン導入メモ - 前書き

Blosxom でサイト作ってる人の殆どは、コメント機能をつけるのに writeback プラグイン (もしくはその派生品) を使っていると思うのですが、ウチで使ってるのは feedback プラグインです。わざわざマイノリティにならなくてもいいのに、とか思う。

後発なだけあって機能は充実してるけど、後発なだけあって解説記事も少ないので (既に writeback 使っている人はわざわざ置き換えて試さないだろうし、新規で Blosxom なサイトを作る人が導入するにしても、既にネット上にさまざまな解説記事が充実してる writeback を選択するよな普通)、ローカルで実験中にもさまざまな問題にぶつかり、試行錯誤しながら何とか導入してたりします。

なので、もしこれから新規で Blosxom なサイトを構築しようとする人が feedback プラグインを使ってみようと考えた時に、もしかしたら何かの役に立てばと思い、自分の試行錯誤の結果をメモしておこうと考えてみたのがこのエントリなんですが、既にどんな改造・修正をしているか忘れてしまったのと、ここまで文章書くのだけでもう3日ほど推敲してはっきり言って疲れたので(ぉ 今後何回かに分けて、思い出しながらエントリを書いていこうと思います。

べっ別に更新するために同じネタを引っ張ろうって訳じゃないんだからっ(ツンデレ

Home

About Author
Syndication

Return to page top