Perl: 2009年7月アーカイブ

色々事情があって、OpenPNE の「メッセージを送る」画面でメッセージ送信をすると、OpenPNE のユーザのメールアドレスに直接メールを送信する機能を Perl で実装した。

OpenPNE ではメールアドレスは暗号化されているので、OpenPNE のソースを元に、以下のような復号化スクリプトを書いて復号を行った。

#!/usr/local/bin/php
<?php
    $address = $argv[1];
    define('ENCRYPT_KEY', 'hogehoge_key');
    $path ="/www/lib/include";
    set_include_path(get_include_path() . PATH_SEPARATOR . $path);
    include_once 'Crypt/Blowfish.php';
    $blowfish = new Crypt_Blowfish(ENCRYPT_KEY);
    $address = base64_decode($address);
    $address = $blowfish->decrypt($address);
    echo $address;
?>

で、不思議なことに、hogehoge3@exsample.co.jp宛のメールアドレスにはメールが届くのに、hoge@exsample.co.jp宛には届かない。
どちらも、ちゃんと存在しているメールアドレスなのにだ。

原因は、復号されたメールアドレスにあった。
どうも、上記のスクリプトで復号すると、24バイト以下のメールアドレスの後ろに 0x00 のコード(NULL)がセットされてた・・・

一応、後ろにスペースがセットされてたらやだなと思って、Perl 側で、

$address =~ s/\s//g;

な置換はかけてたんだけど、NULL値は \s じゃ引っかからんのね・・・

ということで、

$address =~ s/[\x00]//g;

として不要な NULL値を削ってやったら、問題なくメールが届くようになった。

ああ、ほんまに、ラピッドサイトサーバは maillog が見れないんで駄目駄目サーバだ。
独自のシステムを動かしたい企業は、月数千円の金をケチるのはやめて、WebARENA とかを使うべきである。(・・・て話は、この間もしたな(^^;)

某ホスティングサイト上でシステムの開発をしているんだが、そのサーバには許せないことに、Perl モジュールの Jcode.pm が入っていない。

root 権限もくれないので、普通に make 出来ないし。
なので、展開したファイルを手動でコピーして使ってたんだが、それだと UTF-8 の変換で問題があるんだよねえ。

その辺の原因を追及する時間がもったいなかったので、IN/OUT のデータも、Perl のソースも全て UTF-8 にして、変換が必要ないようにしてたんだけど、どうしてもメール送信しなくちゃいけなくなって。
メールも Unicode のままでも良いんだけど、俺の使ってる AL-Mail が Unicode のメールが読めないんでねえ。(笑)

ということで、Jcode.pm を使って変換することにしたんだけど、いやぁ、ハマった、ハマった。(^^;

変換時にエラーが出る対応で、Jcode/_Classic.pm を修正しちゃったもんだから(「Unicode 変換時の Jcode のエラー」に書いたように、これは誤った対処方法)、その後、エラーが出ないのに、何で正しく UTF-8 がらみの変換が出来ないのか悩むことに・・・(^^;

これで、丸一日無駄にしちゃった。(^^;

最後には、nkf 使って、

    my $str    = join '', @_;
    my $tmp    = (time) . $$ . '.txt';
    open(NKF, ">$tmp");
    print NKF $str;
    close(NKF);
    $str    = `cat $tmp|/usr/local/bin/nkf -j`;
    unlink $tmp;
    return($str);

みたいな関数作って対応してたんだけど、さすがに美しくないので・・・(^^;
結局、ユーザ環境に Jcode.pm を make install することにした。

% perl Makefile.PL INSTALLDIRS=site INSTALLSITELIB=/usr/home/hoge/www/cgi-bin
% make
% make install

でOK。
make install の時に、(一般ユーザの書込権限の無いディレクトリに書き込もうとするので)perllocal.pod のインストールで失敗するが、Jcode.pm の実行には影響無い。
もちろん、perllocal.pod をユーザ環境にインストールするよう設定出来るが、ま、インストールしなくても困んないので、今回はこれでヨシ。

これで、Jcode/Unicode.pm が作られるので、「Unicode 変換時の Jcode のエラー」に書いたように、Jcode/Unicode/NoXS.pm を修正する必要は無い。

この時に、必ず @INC に含まれるディレクトリをインストール先にすること。(でないと、Perl スクリプトの頭で、いちいちインストール先を @INC に加える処理が必要になるけえ)
なので、俺は、cgi-bin の直下にインストールした。(. ディレクトリは @INC に含まれているからね)

ああ。root 権限くれるホスティングサービスだったら、こんな苦労しなくていいのにな。
Perl で作った独自システムを動かしたい会社は、月々数千円の金を惜しまず、WebARENA とか使えばええのだ。いや、マジで。
う~む、何か、Jcode.pm を使って、EUC から UTF-8 に変換しようとすると、

Undefined subroutine &Jcode::_Classic::euc_utf8 called at lib/Jcode/_Classic.pm line 255.

てなエラーが出てしまう。

サイトによっては「Perl のバージョンが古いせい」とか訳の分からない説明をしてるところもあるけど、実際にはそんな単純な話ではない。

この原因は、ちゃんと Jcode.pm のインストール時に make; make install をして Unicode.pm を作成していないから。
なので、本来なら make して、Unicode.pm を作ってやるのが一番だが、ホスティング環境によっては SSH 接続等でのシェル使用を許してなくて(FTP のみ可とかで) make 出来ないケースもあるしな。

解決策として、

Jcode/_Classic.pm の 255行目付近を、

sub utf8{
    load_module("Jcode::Unicode");
    euc_utf8(${$_[0]->[0]});
}
    ↓
sub utf8{
    load_module("Jcode::Unicode");
    Jcode::euc_utf8(${$_[0]->[0]});
}

と変更し、Jcode::Unicode(Unocode.pm)の euc_utf8 ではなく、Unicode/NoXS.pm 内の Jcode::euc_utf8 を呼ぶようにしてやると書いているサイトもあるが嘘。
これだと、確かにエラーで落ちることはなくなるが、UTF-8 がらみの変換が正しく行われない。

UTF-8 がらみの変換、

$str    = Jcode->new($str, 'utf8')->h2z->jis;

とか

$str    = Jcode->new($str, 'utf8')->h2z->euc;

が正しく行われるようにするには、Jcode/Unicode/NoXS.pm を以下のように編集する。

% diff NoXS.pm NoXS.pm_org
56c56
< sub Jcode::_Classic::ucs2_euc{
---
> sub Jcode::ucs2_euc{
71c71
< sub Jcode::_Classic::euc_ucs2{
---
> sub Jcode::euc_ucs2{
87c87
< sub Jcode::_Classic::euc_utf8{
---
> sub Jcode::euc_utf8{
90,91c90,91
<     &Jcode::_Classic::euc_ucs2($r_str);
<     &Jcode::_Classic::ucs2_utf8($r_str);
---
>     &Jcode::euc_ucs2($r_str);
>     &Jcode::ucs2_utf8($r_str);
94c94
< sub Jcode::_Classic::utf8_euc{
---
> sub Jcode::utf8_euc{
97,98c97,98
<     &Jcode::_Classic::utf8_ucs2($r_str);
<     &Jcode::_Classic::ucs2_euc($r_str);
---
>     &Jcode::utf8_ucs2($r_str);
>     &Jcode::ucs2_euc($r_str);
101c101
< sub Jcode::_Classic::ucs2_utf8{
---
> sub Jcode::ucs2_utf8{
124c124
< sub Jcode::_Classic::utf8_ucs2{
---
> sub Jcode::utf8_ucs2{

これでバッチリ!
Jcode/_Classic.pm の編集はしちゃあいかんぜ。
rtf_test.jpg
現在提案中の Webシステムの話。

入力した内容を反映させた書類を出力する必要があったので、PDF ファイルを出力する仕様で見積もっていたのだが、MS-Word 用の ファイルを出力してほしいとの要望あり。
Perl での開発を考えていたので、RTF::Writer モジュールを入れて RTF(Rich Text Format)ファイル出力のテストをしてみた。

RTF::Writer モジュールは、CPAN モジュールを使ったインストールで一発OK。
何か、CPAN モジュールできれいにインストール出来る Perl モジュールに出会ったのが久しぶりなので妙に嬉しい。(笑)何かと Test で失敗する事が多いからなあ。(^^;

で、早速、Writer.pod に載っているサンプルを元に、日本語がうまく扱えるかテスト用のスクリプトを書いてみた。

use RTF::Writer;

my $rtf = RTF::Writer->new_to_file("test.rtf");
$rtf->prolog('title' => "テスト帳票", 'fonts' => ["MS Pゴシック"]);
$rtf->number_pages;
$rtf->paragraph(
  \'\fs40\b\i',  # 20pt, bold, italic
  "これは RTF 出力のテストです"
);
$rtf->close;

実行結果は上の画像のとおり。ちゃんと、RTF フォーマットのファイルが作られて、Windows2000 上の Microsoft Word 2000 で読み込むことが出来た。
RTF ファイルで良いということなら何とかなりそうだ。

ちなみに、日本語の含まれたファイルは Shift_JIS で出力されるようだ。
なので、セットする文字列自体も Shift_JIS でないと文字化けする。今回は、テストということで、スクリプト自体を Shift_JIS で書いて対処した。
本番プログラムを Shift_JIS で書くわけにはいかんので、その時は Jcode とか使って Shift_JIS に変換してやる必要がありますな。

ま、問題無し。

でも、エンドユーザさんとこで、「RTF って何?DOC ファイルじゃなきゃ嫌だ!」とか言い出したら面倒だなあ。(^^;

俺が直接エンドユーザ折衝してたら、思わず「はぁ?今時 DOC ファイルじゃないと駄目って、何?DOC ファイルじゃないと表現できない部分ってありましたっけ?まさか、拡張子が rtf じゃ Word 用のファイルってわからないから?みんなちゃんとした社会人なんだから、一回説明すれば大丈夫でしょ?」くらいの厭みは口走っちゃいそうで怖いけど。(笑)

どうしても DOC でなきゃ嫌だということになれば、Java で Jakarta POI 使ってほげほげか。

いや、大した話ではないんだけど。

Tools/sequencer を使うと、メーリングリストに投稿したメールの本文に、

Message for test-ml
Sender: owner-test-ml
Precedence: bulk

みたいなものが付いてしまう。

設定で出す出さないが出来ると思うのだが調べている時間がなかったので、Tools/sequencer の該当箇所をコメントにして対応。

199行 print OUT $subject, "\n";
202行 print OUT "Sender: $sender\n";
204行 print OUT "Precedence: $opt_p\n";

あたりね。

Perl で書かれているので楽勝。

ところで、唐突に話は変わるが、UNIX の世界では Perl で書かれたツールも多いので、やっぱ、Perl の習得はインターネットの世界を商売のネタにしている者には必須条件だろう。

よく、「Perl vs PHP」みたいな図式で話をしたがる人もいるが、そもそもそれは同列に並べて比較することが間違っているだろう。

Perl を「普通自動車」とすれば、PHP は「小型自動二輪」じゃないか?
どっちが良いとか悪いとかじゃなく、「やっぱ、普通免許は取っておいたほうが良いよな」の世界ってことだ。
その上で、「二輪免許もあると便利だよな」ということだと思う。

ただ、PHP は「普通二輪」や「大型二輪」ではないと思うけどね。(笑)

まあ、もし、単なる「Web プログラマ」の世界から一歩踏みだしたいと思っているのなら、「俺は Perl なんか嫌いじゃけんね。Perl 覚えるのなら Java 勉強するよ」なんて言ってないで、素直に「Perl を習得することを次のステップに進むための最初の一歩にする」と考えたほうがいいよ。

このアーカイブについて

このページには、2009年7月以降に書かれたブログ記事のうちPerlカテゴリに属しているものが含まれています。

前のアーカイブはPerl: 2009年6月です。

次のアーカイブはPerl: 2009年10月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら