【Webプログラミング - Code.005】CGI(Perl)基本動作 その5:「文字コード対応(Jcode.pm)」

   Code.005                                                 2002年11月4日発行
■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■
                           【 Webプログラミング 】

                       〜 猫的プログラマーとその軌跡 〜
■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■

              ▼毎週月曜日に配信しています。
              ▼等幅フォントでご覧いただくとキレイに見えます。
              ▼登録・解除はこちらから可能です。
                < http://www.ichikoro.com/webp/ >
                  ※ぜひお友達にもご紹介ください(^^)/


○お休みのお知らせ
  ~~~~~~~~~~~~~~~~
  11月11日配信分は、都合によりお休みいたします。
  あしからずご了承くださいませ。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 CGI(Perl)基本動作 その5:「文字コード対応(Jcode.pm)」
──────────────────────────────────────
小説を読んだり詩や俳句を聞いていると、その表現力に感銘を受け、
日本語が理解できるって素晴らしい!と思う反面、プログラムを組
んでいると、だんだん憎らしくなってきます(笑)

国内を中心とした日本語圏では複数の文字コードが使用されています。
例えば 'a' という文字をパソコンは内部的には 97 という数値で扱って
います(*1)。このように『この文字の値はこれ』と決めたコード体系が、
日本語など「2バイト(多バイト)文字」や「全角文字」においては複数存
在するのです。

  *1 ..... パソコンは数値でしか情報を保持、計算できないためです。
           詳細な説明は割愛します。


私達が使用している物には以下のような物があります。

  ・ASCII(あすきー)
    古く1963年にアメリカで定義された物です。
    英数字や制御文字など世間一般で言う「半角文字」が定義され
    ています。ASCIIコード表は、プログラマなら誰しも一度は
    お世話になっているハズ。

  ・シフトJIS(しふとじす)
    SJISと略されることもあります。
    マイクロソフト社が策定した物。
    MS-DOS時代より使用され、Macintoshも採用している。
       ※現在のWindows(IE)はUnicodeをサポートしているらしいです。

  ・EUC(いーゆーしー)
    UNIXを開発したAT&T社が定めた物。
    現在もUNIXなどで使用されている。
       ※ASCIIとバッティングしないコード体系のため、
         好んで使用するWebプログラマが多いようです。

  ・JIS(じす)
    その名の通りJIS(日本工業規格)によって定められた文字コード。
    他のコードと違い7bitで表現される。現在ではEメールでよく使用
    される。
    ISO(国際標準化機構)の規格「ISO-2022」の中に組み込まれており、
   「ISO-2022-JP」と呼ばれることもあります。

  ・Unicode(ゆにこーど)
    ISOで標準化された文字コード。
    全ての文字を多バイトで表現し、同じコード体系で多国語の処理
    を可能にしようとした物。

ここらへんの経緯についてはあまり詳しくありません(^^;
もっと知りたい方は他のサイトや文献などでお調べください。

  ・ミケネコの 文字コードの部屋
    http://www.mikeneko.ne.jp/~lab/kcode/index.html

話を戻しましょう。
CGI側でどの文字コードが渡ってくるのか、あらかじめ知ることは出来ません。
そこで実際の処理をする前に、まずは文字コードをこちらが意図する物に変換
する必要があります。

というわけで、今回はこの「文字コードの変換」について取り上げてみたい
と思います。


  ★ポイント1
    今回の記事は、Perl5.8未満のバージョンをお使いの方に役立つ物です。
    上記バージョンより、標準モジュールに文字コードの変換を行うための
    “Encode”が実装されました。

  ★ポイント2
    最初に「実行方法」を読んでから試してください。
    今回は別途準備しなければならない物があります。


───────
 ソース1(HTML)
───────
<HTML>
<HEAD>
    <META http-equiv="content-type" content="text/html;charset=Shift_JIS">
    <TITLE>Convert Character Code</TITLE>

<!--
      ** SHIFT_JIS **
      <META http-equiv="content-type" content="text/html;charset=Shift_JIS">

      ** EUC **
      <META http-equiv="content-type" content="text/html;charset=euc-jp">

      ** JIS **
      <META http-equiv="content-type" content="text/html;charset=iso-2022-jp">
-->
</HEAD>
<BODY bgcolor="#FFFFFF">

<H2>Convert Character Code</H2>

<FORM action="c3.cgi" method="POST">
    Input <INPUT type="text" name="str" size="25"></TEXTAREA>
    <BR>
    <BR>
    <INPUT type="submit">
</FORM>

<HR>
<DIV align="right"><SMALL><I>(C) WebPrograming</I></SMALL></DIV>

</BODY>
</HTML>


───────
 ソース2(CGI)
───────
#!/usr/bin/perl

;#
;#文字コードを判定、変換する(c3.cgi)
;#

#----------------------------------------------------------------------#
#                             モジュール                               #
#----------------------------------------------------------------------#
use lib "/home/ichikoro/lib/";     #必要があればJcode.pmのインストール先を指定

use strict;    #コーディングの厳格化
use Jcode;     #日本語コードの判定・変換

#----------------------------------------------------------------------#
#                           グローバル変数                             #
#----------------------------------------------------------------------#
package G;
    BEGIN {
        #-- 変換する文字コード --#
        $G::DEFAULT_CHAR_CODE = "sjis";        # "sjis" or "euc", "jis", "ucs2", "utf8"

        #-- 表示用METAタグ --#
        $G::META = q{<META http-equiv="content-type" content="text/html;charset=Shift_JIS">};
    }


#======================================================================#
#                           メインルーチン                             #
#======================================================================#
package main;
{
    my $code_convert = $G::DEFAULT_CHAR_CODE;   #変換する文字コード
    my $meta         = $G::META;                #出力するMETAタグ
    my %form;                                   #クエリー格納用
    my $str;                                    #クエリー "str"格納用
    my $str_convert;                            #クエリー "str"を変換した物を格納
    my $code;                                   #文字コードの判定結果 格納用


    #--------------------------------------------------#
    #                  クエリー取得                    #
    #--------------------------------------------------#
    util::getQuery( \%form );

    #--------------------------------------------------#
    #            クエリーを変数へ格納し直す            #
    #--------------------------------------------------#
    $str = $form{'str'};

    #--------------------------------------------------#
    #                文字コード判定                    #
    #--------------------------------------------------#
    $code = Jcode::getcode( \$str );

    #--------------------------------------------------#
    #                文字コード変換                    #
    #--------------------------------------------------#
    $str_convert = $str;
    Jcode::convert( \$str_convert, $code_convert );

    #--------------------------------------------------#
    #                    HTML表示                      #
    #--------------------------------------------------#
    print "Content-type: text/html\n\n";
    print <<"END_OF_HTML";
<HTML>
<HEAD>
    $meta
    <TITLE>Convert Character Code</TITLE>
</HEAD>
<BODY bgcolor="#FFFFFF">

<H2 align="center">Convert Character Code</H2>

<DIV align="center">
<TABLE border="1" width="300">
<TR>
    <TD>Code</TD>
    <TD>$code</TD>
</TR>
<TR>
    <TD>Str</TD>
    <TD>$str</TD>
</TR>
<TR>
    <TD>Change Code</TD>
    <TD>$code_convert</TD>
</TR>
<TR>
    <TD>Change Str</TD>
    <TD>$str_convert</TD>
</TR>
</TABLE>
</DIV>

<HR>
<DIV align="right"><SMALL><I>(C) WebPrograming</I></SMALL></DIV>

</BODY>
</HTML>
END_OF_HTML


    #--------------------------------------------------#
    #                      正常終了                    #
    #--------------------------------------------------#
    exit(0);
}


package util;

#--------------------------------------------------------------#
#■クエリーを取得する
#    内容:GET/POST判定をしクエリーを取得する。
#          URLデコード後、指定のハッシュへ格納する。
#
#    引数:(1)格納先ハッシュ:リファレンス
#  戻り値:なし
#--------------------------------------------------------------#
sub getQuery{
    my $form = shift;    #クエリーをセットするハッシュ(リファレンス)
    my $buff;

    #-- クエリー文字列取得 --#
    if ($ENV{'REQUEST_METHOD'} eq "POST"){
        read(STDIN, $buff, $ENV{'CONTENT_LENGTH'});
    }
    else{
        $buff = $ENV{'QUERY_STRING'};
    }

    #-- デコードしつつハッシュにセット --#
    foreach ( split(/&/, $buff) ){
        my( $name, $value ) = split(/=/);

        #-- URLデコード --#
        $value =~ tr/+/ /;    #“+”を空白に
        $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;   # %XX を本来の
                                                                       # 文字コードに

        #-- ハッシュにセットする --#
        if( exists( $form->{$name} ) ) {
            $form->{$name} .= "\0" . $value;    #同名の場合は'\0'で連結する
        }
        else{
            $form->{$name} = $value;
        }
    }

}

__END__


───────
   実行方法
───────
まずは「Jcode.pm」が必要です。
以下からファイルをDownloadし、解凍してください。

    ・Jcode-0.82
      http://search.cpan.org/author/DANKOGAI/Jcode-0.82/
        ※Windowsの場合はlhazなどで解凍できます。
          telnetなどでUNIX環境が使用できる人は素直にtarを
          使いましょう。

            ・lhaz
              http://www.vector.co.jp/soft/win95/util/se107748.html

            ・telnetで
              % tar zxvf Jcode-0.82.tar.gz

その中に含まれるファイル「Jcode.pm」とディレクトリ「Jcode」を
サーバの適当な場所にUPします。

その後、CGIの以下の行を変更してください。

>  use lib "/home/ichikoro/lib/";     #必要があればJcode.pmのインストール先を指定


★経験者の方へ
  無論“いつもの”やり方でOKです。

      % cd Jcode-0.82
      % perl Makefile.PL
      % make
      % make test
      % make install

  や、

     % perl -MCPAN -e shell
     cpan> install Jcode

  です。

その後は複数の文字コードに対応したテキストエディタで上記のソースを保存して
ください。Windowsなら「EmEditor」「秀丸エディタ」、Macintoshなら「Jedit4.0」
「LightWayText」あたりが対応しているようです。

    ・EmEditor
     http://www.vector.co.jp/soft/win95/writing/se152689.html

    ・秀丸エディタ
     http://www.vector.co.jp/soft/win95/writing/se086280.html

    ・Jedit
     http://www.vector.co.jp/soft/mac/writing/se163485.html

    ・LightWayText
     http://www.vector.co.jp/soft/mac/writing/se031021.html

ソース1は適当な名前(xxxx.html)でOKです。
ソース2は「c3.cgi」とすると、HTMLを変更せずにすみます。

CGIの詳しい実行方法については、Code.001をご参照ください。
http://backno.mag2.com/reader/BackBody?id=200210050820000000080329000

HTML(ソース1)のMETAタグを変更したり、CGI側で変換する文字コードを変える
などして実験してみてください。

  ★重要!
    このCGIはセキュリティーホールを含みます。
    学習以外の用途には使用しないでください。


───────
    解 説
───────

■jcode.pl と Jcode.pm

    CGIの設置をされた方なら一度は「jcode.pl」というファイルを見たことがあると
    思います。このjcode.plは、文字コードの判定や、変換を行ってくれるサブルー
    チンなどが記述された物です。

        ・jcode.pl official page
          http://srekcah.org/jcode/

    これをモジュール化したのがJcode.pmです。
    Unicodeに対応するなどいくつかの機能が追加されていますが、基本的な部分は
    同じのようです。


    これらの無償で提供されているライブラリを使用することで、一から組む必要は
    無く、意図も簡単に目的が達成できるのです。あなたがやろうとしている事は、
    世界中にいるPerl使いがすでに行っている場合がほとんどです。

        「車輪の再発明をしない」

    Perlプログラマなら、まずは他の誰かが同じ事をやっていないか探すことから
    始めましょう。ちなみにこれらのモジュールが集結されているのが「CPAN」と
    呼ばれるWebサイトです。

        ・CPAN
         http://search.cpan.org/


■Jcode.pm

    ここでは代表的なサブルーチン「getcode」と「convert」の基本的な使い方
    についてご紹介します。

        $code = getcode( $str );

            getcodeは、引数$strの文字コードを判定するための物です。
            戻り値$codeには以下のような値が入ります。

                binary  テキスト情報でない場合<画像など
                ascii   Ascii<日本語が含まれない
                euc     EUC-JP
                sjis    SHIFT_JIS
                jis     JIS (ISO-2022-JP)
                ucs2    UCS2 (Raw Unicode)
                utf8    UTF8
                undef   これ以外の場合、「undef」が返ります。
                          ※undefという文字列ではありません(^^;

            ただし、半角カナが入り混じった文字列についての判定は
            保証されていないようです。


        Jcode::convert( \$str, $code );

            文字列$str を $codeで指定した文字コードへ変換します。
            $codeで指定するのは、getcodeの戻り値と同じ文字列になります。

            これらの引数に続いて

                Jcode::convert( \$str, "sjis", "euc" );

            と記述した場合$strは"euc"であると識別され、"sjis"へ変換されます。
            指定しない場合は内部で getcode が呼び出されます。
                ※つまりあらかじめ分かっている場合は指定した方が高速です。

            また、

                Jcode::convert( \$str, "sjis", "euc", "z" );

            と、第4引数を指定すると、半角カナに対する処理が行われます。

                z    半角カナ → 全角カナ
                h    全角カナ → 半角カナ


    その他の機能については、付属のドキュメントなどをご覧ください。


───────
   次回予告
───────
今まではサブルーチン「getQuery」を使用し、クエリーを取得してきました。
しかし明らかにこの行為は“車輪の再発明”です。

次回はもっと簡潔にコードを記述できるよう、いくつかのモジュールを
ご紹介したいと思います。


───────
  分からない
───────
いまいちよく分からない場合は、以下へれっつらごー。

  ・サポートBBS
    このメルマガ専用のサポート掲示板
      http://www.ichikoro.com/webp/bbs/

  ・CGIプログラミングML
    CGIなどWebに関する話題を繰り広げるメーリングリスト
    このメルマガとは何の関係もありませんので発言時は注意を。
      http://www.ichikoro.com/cgi/ml/

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                           編    集    後    記
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

先週の日曜日、高校時代の友人が仕事の関係で静岡県の御前崎に来ていると
いうので、埼玉からクルマを飛ばして会いに行ってきました。

今回のドライブはまさに「ドライビングプレジャー」の連続でした。
真っ青に晴れた空の下、海からの日差しを浴びつつ走るのは何とも言えず、その後
友人と会った後もドライブ三昧。気がついたら一日で600kmくらい走ってました。
クルマがあるだけでこんなに世界が広がるんだなぁと改めて感じました。

    ・静岡県最南端の岬 御前崎町
     http://plaza.across.or.jp/~town-omaezaki/
        ウミガメの産卵地だそうです。
        後、加藤剛さん(<大岡越前(笑))の故郷だとか。
        途中、道の両脇にずら〜っとヤシの木が植えられている道が好き。


クルマと言えば、

    「死にたくなければ夜間にクルマに乗ってはならない」

万が一事故を起こしてもまともな医者に診てもらえる可能性は限りなく低い。
夜間の病院には研修医(大学卒業後、医師免許を取得したばかりの医者)しか
いないなんて珍しいことではない。

しかも、調査を行った研修医のうち90%が単独で手術を行った経験があり、
その中の80%以上が不安を感じながら行っている事実。

そんなことを、何気なしに買った「ブラックジャックによろしく」を読んで
知りました。「医者って一体、なんなんだ?」そんなシンプルな疑問から始
まり、医師が抱える日々の葛藤が切々と描かれています。


私達が「当然」だと思っていることも、一つ裏を返せば様々な矛盾があり、
そこにあるのは同じ人間である、当たり前だけど普段忘れてしまっている
そんなことに気がつかされました。

色々な見方があると思うので、この本の全てが正しいとは言いませんが、
読む価値有りです。

    ・ブラックジャックによろしく
     http://www.amazon.co.jp/exec/obidos/ASIN/4063288250


さて、週末はいよいよ受験です。
その直後、広島に旅立ちます。
詳しくは再来週のこの場所で。

それでは、今度は11月18日にお会いしましょう (^-^)/~~

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                   【 Webプログラミング Code Sample 】

                    発  行 : ichikoro.com
                発行責任者 : 勝部 麻季人
                              < katsube@ichikoro.com >
                 Webサイト : < http://www.ichikoro.com/webp/ >
            お問い合わせ先 : < mm-webp@ichikoro.com >

                            Powerd by まぐまぐ
    All Right Reserved, CopyRight(C) 2001 Webプログラミング Code Sample
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■