CGI-2.89 > CGI

名前

CGI - 簡単なCGI(Common Gateway Interface)クラス

概要

  # 画面一杯のフォームを作成し、その値をエコーバックする
  # CGIスクリプト

  use CGI qw/:standard/;
  print header,
        start_html('A Simple Example'),
        h1('A Simple Example'),
        start_form,
        "What's your name? ",textfield('name'),p,
        "What's the combination?", p,
        checkbox_group(-name=>'words',
               -values=>['eenie','meenie','minie','moe'],
               -defaults=>['eenie','minie']), p,
        "What's your favorite color? ",
        popup_menu(-name=>'color',
               -values=>['red','green','blue','chartreuse']),p,
        submit,
        end_form,
        hr;

   if (param()) {
       print "Your name is",em(param('name')),p,
         "The keywords are: ",em(join(", ",param('words'))),p,
         "Your favorite color is ",em(param('color')),
         hr;
   }

要約

このperlライブラリは簡単にWebのフォームを作成し、その内容を解析する ためperl5オブジェクトを使っています。このパッケージはCGIオブジェクト、 現在の問い合わせ文字列の値が入ったエンティティ、そしてその他の状態変数を 定義します。CGIオブジェクトのメソッドを使って、スクリプトに渡された キーワードやパラメータの値をチェックしたり、現在の取り合わせから 取得した値で初期化したフォームを作成することが出来ます(これによって 状態情報を保存します)。このモジュールはHTMLを生成し、入力と コーディング・エラーを減らす短い名前の関数を提供します。またファイルの アップロード、カスケーディング・スタイル・シート、サーバ・プッシュ、 フレームを含めたCGIスクリプトのいくつかのさらに進んだ機能も提供します。

CGI.pmはオブジェクト指向の機能を必要としない人たちのために、簡単な 関数指向プログラミング・スタイルも提供します。

CGI.pmの現在のバージョンは以下のサイトから利用できます:

  http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
  ftp://ftp-genome.wi.mit.edu/pub/software/WWW/

説明

プログラミング・スタイル

CGI.pmでは2つのプログラミング・スタイル、オブジェクト指向スタイルと 関数指向スタイルがあります。オブジェクト指向スタイルでは、1つまたは 複数のCGIオブジェクトを作成し、ページのさまなざな要素を作成するために オブジェクト・メソッドを使います。各オブジェクトはサーバーによって スクリプトに渡された名前付きパラメータのリストが出発点となります。 オブジェクトを変更したり、ファイルやデータベースに格納し、それを元に 戻すことが出来ます。というのも各オブジェクトはCGIスクリプトの "状態"(state)に対応しており、各オブジェクトのパラメータ・リストは、 その他のものとは独立しているため、スクリプトの状態を保存し後から 取り出すこともできるのです。

以下にオブジェクト指向スタイルを使って、簡単な"Hello World"HTMLページを どのように作成するかの例を示します:

   #!/usr/local/bin/perl -w
   use CGI;                             # CGIルーチンのロード
   $q = new CGI;                        # 新しいCGIオブジェクトの作成
   print $q->header,                    # HTTPヘッダの作成
         $q->start_html('hello world'), # HTMLの開始
         $q->h1('hello world'),         # レベル1のヘッダ
         $q->end_html;                  # HTMLの終わり

関数指向スタイルでは、直接扱うことがまずない、1つのデフォルトの CGIオブジェクトがあります。CGIパラメータを取り出し、HTMLタグを作成し、 クッキーを管理する等々のために、代りに関数を単に呼び出します。 これは、よりすっきりしたプログラミング・インタフェースを提供しますが、 一度に1つのCGIオブジェクトしか使えないよう制限します。以下の例 は同じページで関数指向インターフェースを使っています。大きな違いは 今度は名前空間に関数のセット(通常は"standard"の関数群)をインポートする 必要があること、そしてCGIオブジェクトを作成する必要がないことです。

   #!/usr/local/bin/perl
   use CGI qw/:standard/;           # 標準(standard)のCGIルーチンをロードする
   print header,                    # HTTPヘッダの作成
         start_html('hello world'), # HTMLの開始
         h1('hello world'),         # レベル1のヘッダ
         end_html;                  # HTMLの終わり

このドキュメントの例では主にオブジェクト指向スタイルを使います。 CGI.pmでの関数指向プログラミングについての重要な情報は「関数のインポート方法」を ご覧下さい。

CGI.PMルーチンの呼び出し

ほとんどのCGI.pmルーチンはさまざまな引数を受け取ります。中には20もの オプションの引数を受取るものもあります!このインターフェースを簡単に するため、すべてのルーチンは以下のような名前付き引数呼び出しスタイルを 使います:

   print $q->header(-type=>'image/gif',-expires=>'+3d');

各引数の名前の前にはダッシュがつきます。引数リストでは大文字/小文字や、 順番は問題になりません。-type、-Type、-TYPEのすべてが受取られます。 実際には、最初の引数だけがダッシュから始まる必要があります。最初の 引数にダッシュがあれば、CGI.pmは後のものにもダッシュがあるものとします。

さまざまなルーチンは一般に1つの引数だけで呼ばれます。それらのルーチンの 場合、引数名なしに1つの引数を与えることが出来ます。header()は、そうした ルーチンの1つです。この場合、1つの引数はドキュメント・タイプです。

   print $q->header('text/html');

他のそのようなルーチンは下記で記述しています。

名前付き引数はあるときはスカラを期待し、あるときは配列へのリファレンス、 あるいはハッシュへのリファレンスを期待します。多くの場合、どんな種類の 引数も渡すことができ、ルーチンはそれに対して最も適切なことを行います。 例えばparam()ルーチンはCGIパラメータに1つあるいは複数の値を設定する ために使われます。2つのケースを以下に示します:

   $q->param(-name=>'veggie',-value=>'tomato');
   $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']);

CGI.pmのルーチンの多くがモジュール内で特に定義されておらず、必要に応じて 自動的に生成されます。これらは動的に生成されるページで使われ、HTMLを 生成する"HTMLショートカット"ルーチンです。HTMLタグは属性(タグ自身に 入っている属性="値"の組)と内容(開始と終了の組の間の部分)の両方を持ちます。 属性と内容とを区別するため、CGI.pmはHTML属性をハッシュ・リファレンスで最初の 引数として、そして内容があればその後の引数として、渡すような約束を使っています。 それは以下のように機能します:

   コード                          作成されるHTML
   ----                           --------------
   h1()                           <H1>
   h1('some','contents');         <H1>some contents</H1>
   h1({-align=>left});            <H1 ALIGN="LEFT">
   h1({-align=>left},'contents'); <H1 ALIGN="LEFT">contents</H1>

HTMLタグについては後で詳しく記述します。

CGIを使い始めたばかりの人の多くが、HTMLタグ属性を囲む曲括弧を必要とする HTMLショートカットの呼び出し方と、曲括弧無しに属性の生成を管理する他の ルーチンの呼び出し方との違いに惑わされます。混乱しないで下さい。便宜上、 曲括弧はHTMLを除くすべてでオプションです。もし好きであれば、名前付き 引数を取る全てのルーチンも呼び出すときに曲括弧を使うことが出来ます。 例えば:

   print $q->header( {-type=>'image/gif',-expires=>'+3d'} );

-wスイッチを使うと、いくつかのCGI.pm引数はPerl組込関数と名前が ぶつかっていることを警告されるでしょう。これらのほとんどは、 複数の値を持つメニュー(multi-valued menu)、ラジオボタン(radio button)、 クラスター(cluster)などを作成するために使われる-values引数です。 この警告を回避するためには、いくつかの選択肢があります:

  1. もし他の名前が使えれば、引数に他の名前を使う。 例えば-valueは-valuesのための別名です。

  2. 先頭を大文字化する。例. -Values

  3. 引数名の周りをクォートで囲む。 例. '-values'

多くのルーチンが理解できない名前付き引数についても、なんらかの有効なことを 行います。例えば、名前付きの引数として与えることにより標準ではない HTTPヘッダ・フィールドを作成することが出来ます:

  print $q->header(-type  =>  'text/html',
                   -cost  =>  'Three smackers',
                   -annoyance_level => 'high',
                   -complaints_to   => 'bit bucket');

これは以下の標準ではないHTTPヘッダを作成します:

   HTTP/1.0 200 OK
   Cost: Three smackers
   Annoyance-level: high
   Complaints-to: bit bucket
   Content-type: text/html

アンダースコアが自動的にハイフンに変換される方法について注意してください。 HTML作成ルーチンは異なる変換をします。

この機能はHTTPとHTMLの"標準"に迅速に追いかけることを可能にします。

新しい問い合わせオブジェクトの作成(オブジェクト指向スタイル):

     $query = new CGI;

これは(POSTとGETメソッドの両方からの)入力を解析し、 $queryと呼ばれるperl5オブジェクトに格納します。

入力ファイルからの新しい問い合わせオブジェクトの作成

     $query = new CGI(INPUTFILE);

もしファイル・ハンドルをnew()メソッドに与えると、ファイル(またはSTDINでもなんでも) からパラメータを読み込みます。デバッグ中、ファイルには以下に説明する 形式ならば、何にでもすることができます(つまり改行で区切られたタグ=値の組が機能します)。 便利なことに、このファイルのタイプはsave()メソッドにより作成されます。 複数のレコードを保存し、元に戻すことが出来ます。

Perl純粋主義者はこの文法がファイル・ハンドルを、ファイルハンドル・グロブさえも 受取ることを知って喜ぶでしょう、これはファイルハンドルを渡す"公式の"方法です:

    $query = new CGI(\*STDIN);

CGIオブジェクトをFileHandleまたはIO::Fileオブジェクトで初期化することも 出来ます。

関数指向インターフェースを使っていて、CGI状態をファイル・ハンドルで 初期化したければ、restore_parameters()でおこないます。これはデフォルトの CGIオブジェクトを指定されたファイル・ハンドルで(再)初期化します。

    open (IN,"test.in") || die;
    restore_parameters(IN);
    close IN;

連想配列リファレンスから問い合わせオブジェクトを初期化することも出来ます:

    $query = new CGI( {'dinosaur'=>'barney',
               'song'=>'I love you',
               'friends'=>[qw/Jessica George Nancy/]}
            );

あるいは適切にフォーマットされた、URLエスケープされた問い合わせ文字列から:

    $query = new CGI('dinosaur=barney&color=purple');

あるいは既に存在しているCGIオブジェクトから(現在、これはパラメータ・リストの 複製を作りますが、autoescapingのようなオブジェクト特有のフィールドは 複写しません):

    $old_query = new CGI;
    $new_query = new CGI($old_query);

空の問い合わせを作成するためには、空文字列または空のハッシュで初期化します:

   $empty_query = new CGI("");

       -または-

   $empty_query = new CGI({});

問い合わせからのキーワードのリストの取り出し:

     @keywords = $query->keywords

<ISINDEX>検索の結果としてスクリプトが呼び出されれば、解析されたキーワードは keywords()メソッドを使って配列として取得することが出来ます。

スクリプトの渡された全てのパラメータの名前の取り出し:

     @names = $query->param

パラメータ付きでスクリプトが呼び出されると(例えば"name1=value1&name2=value2&name3=value3")、 param()メソッドはパラメータ名をリストで返します。もしスクリプトが<ISINDEX>スクリプトとして 呼び出され、アンパサンドのない文字列が入っていれば(例えば、"value1+value2+value3")、 "+"で区切られたキーワードが入った"keywords"という名前の1つのパラメータになります。

注意:バージョン1.5では、パラメータ名の配列はブラウザにより実行されたのと 同じ順番でした。通常、この順序はパラメータがフォームで定義された順と 同じです(しかしながら仕様には入っていないため保証はされません。)

1つの名前つきパラメータの値を取り出す:

    @values = $query->param('foo');

          -または-

    $value = $query->param('foo');

名前付きパラメータの値を取り出すためにparam()メソッドに1つの引数を 渡してください。もしそのパラメータが複数の値を持っていれば (例えばスクローリング・リスト(scrolling list)での複数の選択から)、 配列で受取るようにすることが出来ます。そうでなければ、このメソッドは 1つの値を返します。

もし値が問い合わせ文字列で与えられなければ、つまり問い合わせで "name1=&name2=""または"name1&name2"であれば、空文字列を返します。 これは2.63での新機能です。

名前つきパラメータへの値の設定:

    $query->param('foo','an','array','of','values');

これは名前付きパラメータ'foo'の値として値の配列を設定します。これは、 スクリプトが前に一度呼び出された後にフィールドの値を変更するための1つの 方法です。(もう1つの方法はフォーム要素を作成するすべてのメソッドで 受取られる -overrideパラメータを使うことです)

param()は下記でさらに詳しく記述する呼び出しの名前付きパラメータ形式も 理解します:

    $query->param(-name=>'foo',-values=>['an','array','of','values']);

                  -あるいは-

    $query->param(-name=>'foo',-value=>'the value');

名前つきパラメータに値を追加する:

   $query->append(-name=>'foo',-values=>['yet','more','values']);

これは値または値のリストを名前付きパラメータに追加します。 既にあれば、その値はパラメータの最後に追加されます。そうでなければ パラメータが作成されます。このメソッドは名前付き引数呼び出し書式しか 理解しないことに注意してください。

すべてのパラメータの名前空間へのインポート:

   $query->import_names('R');

これは一連の変数を'R'名前空間に作成します。例えば$R::foo、@R:fooのように。 キーワード・リストでは、変数@R:keywordがあります。名前空間が指定されなければ、 この引数は'Q'を想定します。警告:'main'には何もインポートしないこと。 それはセキュリティ上、大きな危険性があります!!!

古いバージョンでは、このメソッドはimport()と呼ばれていました。 バージョン2.20では、組込Perlモジュールimport演算子とぶつかることを 避けるため、この名前は完全に削除されました。

パラメータを完全に削除する:

    $query->delete('foo','bar','baz');

これは完全にパラメータをクリアします。それはスクリプト呼び出しの間で、 渡されたものが欲しくないパラメータをリセットするのに便利なこともあります。

関数呼び出しインターフェースを使っているのであれば、Perlの組込み演算子delete との衝突を避けるため、代りに"Delete()"を使ってください。

すべてのパラメータを削除する:

   $query->delete_all();

これはCGIオブジェクトを完全にクリアします。これはフォームを作成するときに、 すべてのデフォルトが取られることを保証するために便利です。

関数呼び出しインターフェースを使っているならば、代りにDelete_all()を使って ください。

パラメータリストへの直接アクセス:

   $q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
   unshift @{$q->param_fetch(-name=>'address')},'George Munster';

パラメータ・リストへアクセスする必要があれば、これまでのメソッドでは カバーされていません。その名前でparam_fetch()を呼び出すことにより、 それへの直接のリファレンスを取得することが出来ます。これは名前付き パラメータへの配列リファレンスを返します。それは好きなように扱うことが 出来ます。

-nameを使って、名前付き引数スタイルを使うことも出来ます。

パラメータリストのハッシュでの取り出し:

    $params = $q->Vars;
    print $params->{'address'};
    @foo = split("\0",$params->{'foo'});
    %params = $q->Vars;

    use CGI ':cgi-lib';
    $params = Vars;

多くの人がすべてのパラメータリストを、CGIパラメータの名前をキーとし、 そのパラメータの値を値とするハッシュとして取り出しがります。 これをVars()メソッドが行います。スカラコンテキストで呼ばれると、 タイされたハッシュ・リファレンスとしてパラメータリストを返します。 キーを変更すると、元になっているCGIパラメータリストでのパラメータの 値を変更します。配列コンテキストで呼ばれると、それは通常のハッシュ としてパラメータリストを返します。これによりパラメータリストの内容を 読むことが出来ますが、変更することはできません。

これを使うとき、複数の値を持つCGIパラメータについて気をつけなければ いけません。ハッシュはスカラーと配列のコンテキストを区別しないので、 複数の値をもつパラメータは"\0"(null)文字で区切られた、パックされた 文字列で返されます。それぞれの値を取り出すためにはパックされた 文字列を分割しなければなりません。このやり方はPerlバージョン4のための cgi-lib.plモジュールで、Steve Brrennerによって導入されました。

Vars()を関数として使いたければ、関数呼び出しセット :cgi-lib を インポートしてください。(CGI-LIBとの互換性についてのセクションも ご覧下さい)

スクリプトの状態をファイルに保存する:

    $query->save(FILEHANDLE)

これはフォームの現在の状態を指定されたファイルハンドルに 書き込みます。new()メソッドにファイルハンドルを与えることにより 読み戻すことが出来ます。ファイルハンドルは、ファイル、パイプ、 その他何にでもにすることが出来ることに注意してください!

保存されるファイルの形式は以下の通りです:

    NAME1=VALUE1
    NAME1=VALUE1'
    NAME2=VALUE2
    NAME3=VALUE3
    =

名前と値の両方がURLエスケープされます。複数の値を持つCGIパラメータは 名前を繰り返すことにより表すことができます。セッション・レコードは single=symbolによって範囲を決められます。何回もnewを呼ぶことにより、 複数のレコードを書き出し、読み戻すことが出来ます。追記(append)モードで ファイルを開くことにより、複数のセッションにまたがって、これを行うことが 出来ます、これにより原始的なゲスト・ブックやユーザの質問の履歴を 作成することが出来ます。以下は複数のセッション・レコードを作成する 短い例です:

   use CGI;

   open (OUT,">>test.out") || die;
   $records = 5;
   foreach (0..$records) {
       my $q = new CGI;
       $q->param(-name=>'counter',-value=>$_);
       $q->save(OUT);
   }
   close OUT;

   # 読み込みのために再オープン
   open (IN,"test.out") || die;
   while (!eof(IN)) {
       my $q = new CGI(IN);
       print $q->param('counter'),"\n";
   }

保存/復帰に使われるファイル・フォーマットはWhitehead Genome Centerの データ交換フォーマット"Boulderio"に使われているものと同じで、 Boulderioユーティリティを使って扱ったり、さらにはデータベース化する ことができます。さらなる詳細は

  http://stein.cshl.org/boulder/

をご覧下さい。

関数指向(非OO)からこの関数を使いたいのであれば、エクスポートされる このメソッドの名前はsave_parameters()です。

CGIエラーの取り出し

ユーザ入力を処理して切る間、特にアップロードされたファイルを処理している 間にエラーが発生することがあります。これらのエラーが発生したとき、CGIは 処理を止め、空のパラメータリストを返します。エラーの存在とその性質を cgi_error()関数を使って調べることが出来ます。エラーメッセージは HTTPステータスコードのようにフォーマットされます。HTMLページに そのエラー・テキストを入れたり、HTTPステータスの値として使うことが できます:

    my $error = $q->cgi_error;
    if ($error) {
    print $q->header(-status=>$error),
          $q->start_html('Problems'),
              $q->h2('Request not processed'),
          $q->strong($error);
        exit 0;
    }

関数指向インターフェース(次のセクションをご覧下さい)を使うとき、 エラーは最初にparam()を呼んだときにだけ発生します。 これに備えてください!

関数指向インターフェースの使い方

関数指向インタフェースを使うためには、どの CGI.pmルーチンまたは 関数群をスクリプトの名前空間にインポートするかを指定しなければいけません。 このインポートに関連して少しオーバーヘッドがありますが、大したことはありません。

   use CGI <メソッドのリスト>;

リストに入れられたメソッドは現在のパッケージにインポートされます; CGIオブジェクトを最初に作成することなく直接呼び出すことが出来ます。 この例ではどのようにparam()header()メソッドをインポートし、それらを 直接使うかを示しています:

   use CGI 'param','header';
   print header('text/plain');
   $zipcode = param('zipcode');

さらに多くの場合、名前でグループを参照することにより一般的な関数の組を インポートします。すべての関数の組の前には":html3"(HTML3標準で定義されたタグ用) のように、前に":"がつきます。

以下にインポートできる関数の組のリストを示します:

:cgi

param(), path_info()のような、CGIを扱うすべてのメソッドをインポート します。

:form

textfield()のような、フォームを作成するメソッドをインポートします。

:html2

HTML 2.0 標準要素を作成するすべてのメソッドをインポートします。

:html3

HTML 3.0 標準要素を作成するすべてのメソッドをインポートします。 (<table>、<super> そして<sub>のような)

:html4

HTML 4 標準要素を作成するすべてのメソッドをインポートします。 (<abbrev>, <acronym> そして <thead>のような)

:netscape

Netscape特有のHTML拡張を作成するすべてのメソッドをインポートします。

:html

すべてのHTML作成ショートカットをインポートします(つまり'html2' + 'html3' + 'netscape')...

:standard

"標準"の機能をインポートします。, 'html2', 'html3', 'html4', 'form' そして 'cgi'。

:all

利用可能なすべてのメソッドをインポートします。全体のリストはCGI.pmの コードをご覧下さい。%EXPORT_TAGSという変数が定義されています。

CGI.pmの一部ではない関数名をインポートすると、モジュールはそれを 新しいHTMLタグとして扱い、適切なサブルーチンを作成します。そこで 他のHTMLタグと同じように使うことが出来ます。これは急速に発展する HTMLの"標準"を提供するためです。例えばMicrosoftは<gradient>という 新しいタグを発表しています(これはマシンをリブートするまで、 ユーザのデスクトップを回転する斜線でいっぱいにします)。新しい バージョンのCGI.pmを待つ必要はありません、それをすぐに使って みてください:

   use CGI qw/:standard :html3 gradient/;
   print gradient({-start=>'red',-end=>'blue'});

実行スピードの点から、CGI.pmはロード・シンボルを指定するための 標準のExporterの書式を使わないことに注意してください。これは将来 変更されるかもしれません。

もし状態管理CGI、またはフォーム作成メソッドのいずれかをインポート すると、あることを要求するメソッドのいずれかを最初に使ったときに、 デフォルトのCGIオブジェクトが自動的に作成され初期化されます。 これにはparam(), textfield(), submit() などが含まれます。 (直接CGIオブジェクトにアクセスする必要があれば、 グローバル変数$CGI::Qがあります)。CGI.pmメソッドをインポートする ことによって、以下のようにエレガントなスクリプトを書くことが出来ます:

   use CGI qw/:standard/;
   print 
       header,
       start_html('Simple Script'),
       h1('Simple Script'),
       start_form,
       "What's your name? ",textfield('name'),p,
       "What's the combination?",
       checkbox_group(-name=>'words',
              -values=>['eenie','meenie','minie','moe'],
              -defaults=>['eenie','moe']),p,
       "What's your favorite color?",
       popup_menu(-name=>'color',
          -values=>['red','green','blue','chartreuse']),p,
       submit,
       end_form,
       hr,"\n";

    if (param) {
       print 
       "Your name is ",em(param('name')),p,
       "The keywords are: ",em(join(", ",param('words'))),p,
       "Your favorite color is ",em(param('color')),".\n";
    }
    print end_html;

プラグマ

関数セットに加えて、多くのプラグマをインポートすることができます。 プラグマの前には常にハイフンがつき、多くの方法でCGI.pm関数の動きを 変更します。プラグマ、関数セットそして個々の関数はすべて同じuse()行で インポートすることができます。例えば、以下のuseステートメントは標準の 関数セットをインポートし、デバッグ・モードを不可能にします (プラグマ -no_debug):

   use CGI qw/:standard -debug/;

プラグマの現在の一覧を以下に示します:

-any

use CGI -anyを使うとき、問い合わせオブジェクトが理解しない 全てのメソッドはHTMLタグとして解釈されます。これにより次の アドホックなNetscapeとMicrosoft特有のHTML拡張をサポートする ことが出来ます。これは新しく、まだサポートされていないタグを 自由に使わせてくれます:

   use CGI qw(-any);
   $q=new CGI;
   print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});

anyを使うと打ち間違えた<cite>どんな</cite>メソッド名も HTMLタグとして解釈されるので、使うときには注意するか、まったく 使わないかのどちらかにしてください。

-compile

これは指定されたオートロードされるメソッドが後に延期されるのではなく、 先にコンパイルされます。これはFastCGIやmod_perlなどのMalcom Beattieの Perlコンパイラにバリバリ食わせるようになっているような状況の下で、 長時間、実行されるスクリプトには有効です。使おうとしているメソッド あるいはメソッド・ファミリと結合して使ってください。

   use CGI qw(-compile :standard :html3);

あるいは以下のようにさえも

   use CGI qw(-compile :all);

このようにして-compile プラグマを使うことは、コンパイルされた 関数が現在の名前空間にインポートされる効果を常に持つことに注意して ください。インポートすることなしにコンパイルしたければ、代りに compile()メソッドを使ってください(下記をご覧下さい):

   use CGI();
   CGI->compile();

これはあなたはstartupスクリプトで全てのCGIルーチンを予めコンパイル しておき、各mod_perlスクリプトで個別に関数をインポートしたいかも しれないmod_perl環境では特に便利です。

-nosticky

これはCGI.pmにヒドゥン・フィールド .submit と .cgifieldsを 作らせません。 GETメソッドでの問い合わせ文字列で ヒドゥン・フィールドを持ちたくないときに便利です。例えば、 この方法で作られた検索スクリプトはブックマークに適した、 検索パラメータを持ったurlになります。

-no_undef_params

CGI.pmにパラメータリストでの未定義のパラメータを入れさせないようにします。

-no_xhtml

デフォルトでは、CGI.pm バージョン2.69以降はXHTML (http://www.w3.org/TR/xhtml1/)を出力します。-no_xhtmlプラグマは、 この機能を止めます。この機能について Michalis Kabrianis <[email protected]>に感謝します。

-nph

これはCGI.pmにNPH(解析されないヘッダno parsed header)スクリプトに 適したヘッダを作成させます。サーバにそのスクリプトがNPHであると 告げるのと同じように他のことをする必要があるかも知れません。 NPHスクリプトについては下記をご覧下さい。

-newstyle_urls

CGIパラメータ問い合わせ文字列の名前=値の組を、アンパサンドではなく セミコロンで分割します。例えば:

   ?name=fred;age=24;favorite_color=3

セミコロン区切りの問い合わせ文字列は常に受取られますが、 -newstyle_urls プラグマが指定されなければ、self_url()やquery_string()では出力されません。

これはバージョン2.64でデフォルトになりました。

-oldstyle_urls

CGIパラメータ問い合わせ文字列の名前=値の組を、セミコロンではなく アンパサンドで分割します。これはもはやデフォルトではありません。

-autoload

プログラム内の理解されないすべての関数が可能な評価のためにCGI.pmが 参照されるようautoloaderをオーバーライドします。これにより、それらを シンボル・テーブルに加えることなく、すべてのCGI.pm関数を使うことが出来ます。 これはメモリ消費を心配するmod_perlユーザに関連します。 警告: -autoloadが有効なとき"詩的モード(poetry mode)"(括弧のない関数)を 使うことは出来ません。hrではなくhr()を使うか、use subs qw/hr p header/の ようなものをスクリプトの先頭に加えてください。

-no_debug

これはコマンド行処理機能をオフにします。HTMLを作成するためCGI.pmをコマンド行から 実行したいけれども、標準入力やコマンド行からのリクエストCGIパラメータを解析したく ないのであれば、このプラグマを使ってください:

   use CGI qw(-no_debug :standard);
-debug

これはコマンド行処理機能をオンにします。コマンド行処理からCGI引数を 読み込むことに加えて、CGI.pmは一旦停止し、STDINから引数を読み込もうとして、 "(offline mode: enter name=value pairs on standard input)"という メッセージを出します。

さらなる詳細は「デバッグ」セクションをご覧ください。

-private_tempfiles

CGI.pmはアップロードされたファイルを処理することができます。 通常、アップロードされたファイルはテンポラリ・ディレクトリにスプールされ、 処理が終ると削除されます。しかし、これには「ファイル・アップロード」セクションでも 説明しているように盗聴の危険性があります。それが秘密の情報であっても、 アップロードの途中に他のCGIスクリプトの作成者が覗き見ることができます。 UNIXシステムでは、-private_tempfilesプラグマは、テンポラリ・ファイルを 開かれると、何かデータが書込まれる前に、すぐに削除されるようにします。 これにより盗聴の危険性を減らしますが、完全ではなりません。 (まだ潜在的に可能な状態です)アタッカーに厳しく対応するためには、 プログラムは一時ファイル名をやって来たHTTTPヘッダの32ビットチェックサムを 計算することで選択します。

一時ファイルが他のCGIスクリプトが読むことが出来ないことを保証するには、 スクリプトを実行するためにsuEXEC または CGI ラッパを使ってください。 一時ファイルはモード 0600(ワールドもグループも読むことが出来ない)で 作成されます。

一時ディレクトリは以下のアルゴリズムを使って選択されます:

    1. 現在のユーザ(例えば"nobody")がホーム・ディレクトリに"tmp"と
       いうディレクトリを持っていれば、それを使います(Unixシステムのみ)

    2. 環境変数TMPDIRがあれば、示された場所を使います

    3. そうでなければ、以下の場所を当たります /usr/tmp, /var/tmp, C:\temp,
    /tmp, /temp, ::Temporary Items, and \WWW_ROOT.

それぞれの場所はそれがディレクトリであるか、書きこみ可能かをチェックされます。 そうでなければアルゴリズムは次の選択を試してみます。

HTMLタグ関数のインポートのための特別な形式

メソッドの多くがHTMLを作成します。下記で説明するように、 タグ関数は自動的に開始と終了の両方のタグを自動的に作成します。 例えば:

  print h1('Level 1 Header');

は 以下のものを作成します。

  <h1>Level 1 Header</h1>

ときには開始と終了タグを自分自身で作成したいときがあるでしょう。 この場合、以下のようにstart_タグ名とend_タグ名の形式を 使うことができます:

  print start_h1,'Level 1 Header',end_h1;

いくつかの例外がありますが(下記で説明)、start_タグ名とend_タグ名関数は use CGIしたときに自動的に作成されません。しかし、その名前の前に アスタリスクを置くか、あるいは代わりに"start_タグ名"や"end_タグ名"を インポート・リストに要求することによって、start/end関数を作成したいタグを 指定することができます。

例:

  use CGI qw/:standard *table start_ul/;

この例では、標準の関数に加えて以下の関数が作成されます:

1. start_table() (<TABLE> タグを作成)
2. end_table() (</TABLE> タグを作成)
3. start_ul() (<UL> タグを作成)
4. end_ul() (</UL> タグを作成)

動的なドキュメント作成

CGI.pmの関数ほとんどは実行中にドキュメントを作成することを扱います。 一般的にはまずHTTPヘッダを作成し、その後にドキュメントそのものが続きます。 CGI.pmはHTMLを作成するのと同じくらい、多くのさまざまなHTTPヘッダを 作成するための関数を提供します!GIFイメージの作成についてはGD.pm モジュールをご覧ください。

これらの関数のそれぞれはHTMLやHTTPの一部を作成します。それらは 直接出力できるので、ブラウザ・ウィンドウに表示したり、文字列を 追加したり、後で使うようにファイルに保存したりといったことができます。

標準HTTPヘッダの作成:

通常、CGIスクリプトで最初にやることはHTTPヘッダを出力することです。 これはブラウザに予想されるドキュメントのタイプを伝え、言語や有効期限、 ドキュメントをキャッシュするかどうかといった他のオプションの情報を 与えます。ヘッダは、サーバー・プッシュやペイ・パー・ビューといった 特別な目的のために使われることもあります。

    print $query->header;

         -あるいは-

    print $query->header('image/gif');

         -あるいは-

    print $query->header('text/html','204 No response');

         -あるいは-

    print $query->header(-type=>'image/gif',
                 -nph=>1,
                 -status=>'402 Payment required',
                 -expires=>'+3d',
                 -cookie=>$cookie,
                             -charset=>'utf-7',
                             -attachment=>'foo.gif',
                 -Cost=>'$2.00');

header()はContent-type:ヘッダを返します。もし選択すれば、独自のMIMEタイプを 作成することができます。そうでなければデフォルトはtext/htmlです。 オプションの2番目のパラメータはステータス・コードと人間が読むことができる メッセージを指定します。例えば、204、"No response"を指定すると、ブラウザに 何もしないように伝えるスクリプトを作ることができます。

最後の例は、CGIメソッドへ引数を渡すための名前付き引数スタイルを示しています。 理解されるパラメータは-type, -status, -expires, そして-cookieです。 他の名前がついたパラメータはすべて、最初のハイフンを落とされて、 ヘッダ・フィールドに変えられます、あなたが望むすべてのHTTPヘッダを指定する ことが可能です。内部のアンダースコアはハイフンに変換されます:

    print $query->header(-Content_length=>3002);

ほとんどのブラウザはCGIスクリプトからの出力をキャッシュしません。 スクリプトが新たに呼び出されるたびに、ブラウザはページをリロードします。 この動きは-expiresで変更することができます。このパラメータで絶対または相対の 有効期間を指定すると、いくつかのブラウザとプロキシー・サーバは指定された有効期限まで、 そのスクリプトの出力をキャッシュします。以下の形式はすべて-expiresフィールドに 対して適切です:

    +30s                              今から30秒
    +10m                              今から10分
    +1h                               今から1時間
    -1d                               昨日(つまり、できるだけ早く!)
    now                               直後に
    +3M                               3ヶ月間
    +10y                              10年間
    Thursday, 25-Apr-1999 00:40:33 GMT  指定された時刻と日付

-cookieパラメータはブラウザに、この後このスクリプトとの全ての トランザクション間、"魔法のクッキー"を提供することを伝えます。Netscape クッキーは有効期限のような面白い属性が入った特別なフォーマットを持っています。 セッション・クッキーを作成し、取り出すためにはcookie()メソッドを使ってください。

-nphパラメータがtrue値に設定されれば、それはNPH(no-parse-header) スクリプトで機能するための正しいヘッダを出力させます。そのすべてのスクリプトが NPHであることを期待する、ある種のサーバで使うことは重要です。

-charsetパラメータはブラウザに送信される文字セットを制御するために 使うことが出来ます。与えられなければ、デフォルトはISO-8859-1です。 副作用として、これはcharset()メソッドも設定します。

-attachmentパラメータは添付にページを切り替えるために使うことが出来ます。 ブラウザによっては、ページを表示する代りにファイルに保存するためのプロンプトを 表示します。引数の値は保存されるファイルのための提案される名前です。 これが機能するためには、-typeを"application/octet-stream"にしなければ いけないかもしれません。

リダイレクション・ヘッダの作成

   print $query->redirect('http://somewhere.else/in/movie/land');

ときには、ドキュメントをあなた自身が作成するのではなく、おそらくURLを 時刻やユーザの識別子をベースにより選択しながら、単にブラウザをどこかに リダイレクトしたいだけかもしれません。

redirect()関数はブラウザを他のURLにリダイレクトします。もしこのような リダイレクトを使えば、headerも出力してはいけません

私が提案できる1つのヒントは、あなたのサイトの別のドキュメントへの リダイレクトを作成したとき、相対リンクは正しく機能しないことです。これは、 いくつかのサーバが使うよく考えられた最適化によるものです。それを解決する 方法はリダイレクトするドキュメントの(http: 部分も含めた)完全なURLを 使うことです。

名前付き引数も使うことができます:

    print $query->redirect(-uri=>'http://somewhere.else/in/movie/land',
               -nph=>1);

-nphパラメータがtrue値に設定されれば、それはNPH(no-parse-header) スクリプトで機能するための正しいヘッダを出力させます。 Microsoft Internet Information Server (訳者注:原文では Internet Explorer)の ように、そのすべてのスクリプトがNPHであることを期待する、ある種のサーバで 使うことは重要です。

HTMLドキュメント・ヘッダの作成

   print $query->start_html(-title=>'Secrets of the Pyramids',
                -author=>'[email protected]',
                -base=>'true',
                -target=>'_blank',
                -meta=>{'keywords'=>'pharaoh secret mummy',
                    'copyright'=>'copyright 1996 King Tut'},
                -style=>{'src'=>'/styles/style1.css'},
                -BGCOLOR=>'blue');

HTTPヘッダを作成した後、ほとんどのCGIスクリプトはHTMLドキュメントの出力を 始めます。start_html()ルーチンはページの見た目や動きを制御するたくさんの オプションの情報とともにページの先頭を作成します。

このメソッドは閉じられたHTMLヘッダと開かれた<body>タグを返します。 全てのパラメータはオプションです。名前付きパラメータ形式で、理解される パラメータは-title, -author, -base, -xbase そして -targetです (下記の説明をご覧ください)。Netscapeの非公式のBGCOLOR属性ような、 指定されたすべての追加のパラメータは<body>タグに追加されます。 追加のパラメータは前にハイフンをつけなければいけません。

引数-xbaseは以下のように、<base>タグを現在の位置から変えるために HREFを提供することを可能にします

    -xbase=>"http://home.mcom.com/"

すべての相対リンクは、このタグからの相対と解釈されます。

引数-targetはすべてのリンクとページ上のフォームのための デフォルトのターゲット・フレームを指定することができます。 これはNetscapeブラウザでのみ機能する標準でないHTTP機能です! これをどのように扱うかの詳細については、Netscapeのフレームに ついてのドキュメントをご覧ください。

    -target=>"answer_window"

すべての相対リングはこタグの相対だと解釈されます(訳者注:おそらく不要(?_?))。 -meta引数でヘッダに任意のメタ情報を追加します。この引数はメタ情報の 名前/値の組が入った連想配列へのリファレンスを期待します。 これらは以下のような、ヘッダでの一連の<meta>タグに変わります:

    <meta name="keywords" content="pharaoh secret mummy">
    <meta name="description" content="copyright 1996 King Tut">

<meta>タグのHTTP-EQUIVタイプを作るためには、以下で説明する-headを 使ってください。

-styleタグはあなたのコードにカスケーディング・スタイルシートを 入れるために使われます。さらに詳細な情報は「カスケーディング・スタイルシート」の セクションをご覧ください。

-lang引数は<html>タグにlanguage属性を入れるために使われます。 指定されなかったときのデフォルトはUS Englishのための"en-US"です。例:

    print $q->start_html(-lang=>'fr-CA');

-encoding引数を、XHTMLのためのキャラクタ・セットを指定するために使うことが 出来ます。指定されなければデフォルトはiso-8859-1です。

-headタグで他の任意のHTML要素を<head>セクションに置くことができます。 例えば、あまり使われない<link>要素をHEADセクションに置くためには、これを 使ってください:

    print start_html(-head=>Link({-rel=>'next',
                          -href=>'http://www.capricorn.com/s2.html'}));

複数のHTML要素を<head>セクションに入れるためには、単に 配列リファレンスを渡してください:

    print start_html(-head=>[ 
                             Link({-rel=>'next',
                   -href=>'http://www.capricorn.com/s2.html'}),
                     Link({-rel=>'previous',
                   -href=>'http://www.capricorn.com/s1.html'})
                 ]
             );

そして、これがHTTP-EQIV <meta>タグの作成方法です:

      print start_html(-head=>meta({-http_equiv => 'Content-Type',
                                    -content    => 'text/html'}))

JAVASCRIPTING: -script, -noScript, -onLoad, -onMouseOver, -onMouseOutそして-onUnloadパラメータがNetscape JavaScript呼出しを ページに追加するために使われます。-scriptはJavaScript関数定義が 入ったテキストのブロックを示さなければなりません。このブロックは (HTTPではなく)HTML内部の<script>ブロックに置かれます。たとえページが 完全にロードされる前にユーザがストップ・ボタンを押したとしても、 すべてのJavaScript関数が置かれるチャンスをあなたのページに与えるため、 そのブロックはヘッダに置きます。CGI.pmはJavaScriptを知らないブラウザが、 そのコードで息が詰まることのないような方法で、そのスクリプトをフォーマット しようとします:それにも関らず、残念ながらChimera for Unixのように 混乱してしまうブラウザがいくつかあります。

-onLoad-onUnloadパラメータは、それぞれブラウザによって、 そのページが開かれたときと閉じられたときに実行されるJavaScriptコードを 示します。通常これらのパラメータは-scriptフィールドで定義された 関数を呼びます:

      $query = new CGI;
      print $query->header;
      $JSCRIPT=<<END;
      // 馬鹿馬鹿しいことをたずねる
      function riddle_me_this() {
     var r = prompt("What walks on four legs in the morning, " +
               "two legs in the afternoon, " +
               "and three legs in the evening?");
     response(r);
      }
      // 馬鹿馬鹿しい答えを取得
      function response(answer) {
     if (answer == "man")
        alert("Right you are!");
     else
        alert("Wrong!  Guess again.");
      }
      END
      print $query->start_html(-title=>'The Riddle of the Sphinx',
                   -script=>$JSCRIPT);

JavaScriptを持っていないブラウザ(あるいはJavaScriptがオフになっているブラウザ)で 表示される、いくつかのHTMLテキストを渡すためには-noScriptパラメータを使ってください。

Netscape 3.0 はLANGUAGEとSRCを含めて、<script>タグの多くの属性を理解します。 後者はソースを持った各ページに散乱させるのではなく、JavaScriptpコードを ファイルまたはCGIスクリプトに保管することを可能にするため、特に興味深いものです。 この属性を使うためには、-scriptパラメータに1つまたはそれ以上の-language、-src や-codeが入ったハッシュ・リファレンスを渡してください:

    print $q->start_html(-title=>'The Riddle of the Sphinx',
             -script=>{-language=>'JAVASCRIPT',
                                   -src=>'/javascript/sphinx.js'}
             );

    print $q->(-title=>'The Riddle of the Sphinx',
           -script=>{-language=>'PERLSCRIPT',
             -code=>'print "hello world!\n;"'}
           );

最後の機能は複数の<script>セクションをヘッダに入れることを可能にします。 配列リファレンスとしてスクリプト・セクションのリストを渡すだけです。 これはJavaScriptの異なる方言のための異なるソースを指定することができます。例えば:

     print $q->start_html(-title=>'The Riddle of the Sphinx',
                          -script=>[
                                    { -language => 'JavaScript1.0',
                                      -src      => '/javascript/utilities10.js'
                                    },
                                    { -language => 'JavaScript1.1',
                                      -src      => '/javascript/utilities11.js'
                                    },
                                    { -language => 'JavaScript1.2',
                                      -src      => '/javascript/utilities12.js'
                                    },
                                    { -language => 'JavaScript28.2',
                                      -src      => '/javascript/utilities219.js'
                                    }
                                 ]
                             );

これがちょっとヒドいと見えれば、私のアドバイスを聞いてストレートなCGIスクリプトで 我慢してください。

JavaScriptについての更なる情報については

   http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/

をご覧ください。

古いスタイルの位置によるパラメータは以下の通りです。

パラメータ:
1.

タイトル

2.

作者のe-mailアドレス(もしあれば<link ref="MADE"> タグを作成します)

3.

<base>タグをヘッダに入れたければ、'true'フラグ。これはドキュメントが 動いたけれども、ドキュメントの階層は移植しないとき、相対アドレスを 絶対アドレスに解決するのを助けます。注意して使ってください。

4, 5, 6...

他のすべてのパラメータは<body>タグに入れたいものです。ここは色や壁紙の パターンのような、Netscape拡張を置くのに適した場所です。

HTMLドキュメントの終わり:

    print $query->end_html

</body></html> タグを出力することでHTMLドキュメントを終らせます。

状態情報を保持し自分自身を参照するURLの作成:

    $myself = $query->self_url;
    print q(<a href="$myself">I'm talking to myself.</a>);

self_url()は選択されたとき、今動いているすべての状態情報で、 このスクリプトを再度呼び出すURLを返します。内部のアンカーを 使ってドキュメントの中でジャンプしたいけれども、フォームの現在の 内容を壊したくないときにとても有効です。以下のようにするとうまくいきます。

     $myself = $query->self_url;
     print "<a href=\"$myself#table1\">See table 1</a>";
     print "<a href=\"$myself#table2\">See table 2</a>";
     print "<a href=\"$myself#yourself\">See for yourself</a>";

何を返すかを更に制御したければ、代わりにurl()メソッドを使ってください。

処理されていない問い合わせ文字列はquery_string()で取り出すこともできます:

    $the_string = $query->query_string;

スクリプトのURLを取得する

    $full_url      = $query->url();
    $full_url      = $query->url(-full=>1);  #別の書き方
    $relative_url  = $query->url(-relative=>1);
    $absolute_url  = $query->url(-absolute=>1);
    $url_with_path = $query->url(-path_info=>1);
    $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);
    $netloc        = $query->url(-base => 1);

url()はスクリプトのURLをさまざまなフォーマットで返します。何も 引数なしで呼ばれれば、ホスト名とポート番号を含んだURLのフルの形式を 返します。

    http://your.host.com/path/to/script.cgi

このフォーマットを以下の名前付き引数で変更することができます:

-absolute

trueであれば、絶対URLを作成します。例えば

    /path/to/script.cgi
-relative

相対URLを作成します。異なるパラメータでスクリプトを もう一度呼びたいときに、これは便利です。例えば:

    script.cgi
-full

何も引数なしに呼んだのとまったく同じく、フルのURLを作成します。 これは-relative と-absoluteを上書きします。

-path (-path_info)

URLに追加のパス情報を追加します。これは-full,-absoluteまたは -relativeと一緒にすることができます。-path_infoがシノニムとして 提供されます。

-query (-query_string)

URLに問い合わせ文字列を追加します。これは-full,-absoluteまたは -relativeと一緒にすることができます。-query_stringがシノニム として提供されます。

-base

http://www.foo.com:8000 のように単にプロトコルとネットでの位置を生成します。

POSTとURLパラメータの混合

   $color = $query-&gt;url_param('color');

問い合わせ文字列(引数が後ろについた"?"マーク)が入ったURLへ POSTするフォームを作成することにより、スクリプトはフォームと同じように CGIパラメータをURLで受け取ることは可能です。param()メソッドは、 URLの問い合わせ文字列を無視し、常にPOSTされたフォームの内容を返します。 URLパラメータを取り出すためにはurl_param()メソッドを呼び出してください。 param()と同じように使ってください。大きな違いはパラメータを読むことは常に できますが、設定はできません。

いかなる状況においても、URL問い合わせ文字列の内容がPOSTされたフォームの 同じ名前のCGIパラメータを干渉することはありません。URL問い合わせ文字列と GETメソッドでサブミットされるフォームとを混ぜてみると、その結果はあなたが 予想しなかったことになるでしょう。

標準HTML要素の作成:

HTML 3 とHTML 4タグで全てでなければ、CGI.pmは一般的なHTMLショートカット・ メソッドの大半を定義します。HTMLショートカットは1つのHTMLの後に名づけられ、 出力でき、好きなように扱うことができるHTMLテキストの一部を返します。 各ショートカットは文字列に追加したり、ファイルの保存したり、または最も 一般的にはブラウザ・ウィンドウで表示するように出力することができる HTMLコードを返します。

この例はHTMLメソッドをどのように使うかを示します:

   $q = new CGI;
   print $q->blockquote(
             "Many years ago on the island of",
             $q->a({href=>"http://crete.org/"},"Crete"),
             "there lived a Minotaur named",
             $q->strong("Fred."),
            ),
       $q->hr;

この結果は以下のHTMLコードになります(読みやすくするために改行を 入れています)

   <blockquote>
   Many years ago on the island of
   <a href="http://crete.org/">Crete</a> there lived
   a minotaur named <strong>Fred.</strong> 
   </blockquote>
   <hr>

HTMLショートカットの呼出しの書き方が不格好だと思えば、 名前空間にインポートし、オブジェクト的な書き方を完全に無くすことが できます(詳細は次のセクションをご覧ください):

   use CGI ':standard';
   print blockquote(
      "Many years ago on the island of",
      a({href=>"http://crete.org/"},"Crete"),
      "there lived a minotaur named",
      strong("Fred."),
      ),
      hr;

HTMLショートカットに引数を与える

HTMLメソッドは0、1つまたは複数の引数を受け取ります。もし引数を 与えなければ1つのタグを得ます:

   print hr;    #  <hr>

もし1つまたは複数の文字列引数を与えれば、スペースでつなげられ、 開始と終了タグに囲まれます:

   print h1("Chapter","1"); # <h1>Chapter 1</h1>"

もし最初の引数が連想配列リファレンスであれば、その連想配列のキーと 値はHTMLタグの属性になります:

   print a({-href=>'fred.html',-target=>'_new'},
      "Open a new frame");

        <a href="fred.html",target="_new">Open a new frame</a>

もしそうしたければ、属性名の前につくダッシュをはずすことができます:

   print img {src=>'fred.gif',align=>'LEFT'};

       <img align="LEFT" src="fred.gif">

HTMLタグ属性が引数を持たないこともあります。例えば順序付きリストは COMPACTとして印をつけることができます。この書き方はundef文字列を示す 引数になります:

   print ol({compact=>undef},li('one'),li('two'),li('three'));

CGI.pmバージョン2.41より以前では、空('')文字列を属性引数として与える ことはundefを与えるのと同じでした。しかし、これは<IMG ALT="">形式の タグを作りたい人たちに合わせるために変更されました。違いは以下の2つの コードで示されます:

   コード                 結果
   img({alt=>undef})      <img alt>
   img({alt=>''})         <img alt="">

HTMLショートカットの分配されるプロパティ

HTMLショートカットの素晴らしい機能の1つに、それらが分配されることが あります。リストへのリファレンスが入った引数を与えると、そのタグは リストの各要素をまたがって分配されます。例えば、順序付きのリストを 作る方法の1つを以下に示します:

   print ul(
             li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy'])
           );

これは結果として以下のようなHTML出力になります:

   <ul>
     <li type="disc">Sneezy</li>
     <li type="disc">Doc</li>
     <li type="disc">Sleepy</li>
     <li type="disc">Happy</li>
   </ul>

これはテーブルを作るのとにとても便利です。例えば:

   print table({-border=>undef},
           caption('When Should You Eat Your Vegetables?'),
           Tr({-align=>CENTER,-valign=>TOP},
           [
              th(['Vegetable', 'Breakfast','Lunch','Dinner']),
              td(['Tomatoes' , 'no', 'yes', 'yes']),
              td(['Broccoli' , 'no', 'no',  'yes']),
              td(['Onions'   , 'yes','yes', 'yes'])
           ]
           )
        );

HTMLショートカットとリストの挿入

この小さなコードについて考えてみてください:

   print blockquote(em('Hi'),'mom!'));

これは通常に、おそらく期待した文字列を返します、すなわち:

   <blockquote><em>Hi</em> mom!</blockquote>

要素"Hi"と要素"mom!"の間のスページに注意してください。CGI.pmは 配列を間に入れた場所に追加のスペースをおきます。これは特別な$"変数に より制御されます。時には、例えば一連のイメージの並べようとしているときなど、 この追加のスペースはあなたの望んでいたものではありません。この場合、 $"を空文字列に変更することによって簡単に変更することができます。

   {
      local($") = '';
      print blockquote(em('Hi'),'mom!'));
    }

コードをここで示したようにブロックにいれることを提案します。そうしなければ 明示的にリセットするまで、$"の変更が後のコードに影響を与えます。

標準ではないHTMLショートカット

いくつかのHTMLタグは多様性のために標準パターンに従いません。

comment()はHTMLコメント(<!-- comment -->)を作成します。 以下のように呼び出してください

    print comment('here is my comment');

組み込みPerl関数とぶつかるので、以下の関数は先頭の文字が大文字になります:

    Select
    Tr
    Link
    Delete
    Accept
    Sub

さらにstart_html()、end_html()、start_form()、end_form()、start_multipart_form() そして全てのフォームタグは特別です。それぞれのセクションをご覧ください。

HTMLの自動エスケープ

デフォルトでは、フォーム作成関数用により作成されるすべてのHTMLは escapeHTML()という関数を通ります:

$escaped_string = escapeHTML("unescaped string");

文字列に入っているHTMLフォーマットの文字をエスケープ。

文字セットISO-8859-1(デフォルト)を指定すると、標準のHTMLエスケープの ルールが使われます。"<"文字は"&lt;"、">"は"&gt;","&"は"&amp"、クォート文字は "&quot"になります。さらに0x8bと0x9b文字、これは多くのWindowsベースのブラウザは 左と右の斜め括弧に解釈されるのですが、は数値のHTMLエントリ("&#139"と"&#155")に 置きかえられます。charset()メソッドを明示的に呼び出すか、header()に-charset引数を 渡すことにより、手で文字設定を変更したら、CGI.pmはすべての可能性のある エンコーディングのための検索テーブルを持たないので、すべての文字は数値エントリに よって置きかえられます。

自動エスケープはh1()のような他のショートカットには適用されません。人々が ゲストブックなどにいれるかもしれない困った書き方からあなたのページを守るため、 信用できないデータにescapeHTML()を呼ぶべきです。文字セットを変更するには、 charset()を使ってください。自動エスケープを完全に止めるにはautoEscape(0)を 使ってください:

$charset = charset([$charset]);

現在の文字セットを取得あるいは設定します

$flag = autoEscape([$flag]);

自動エスケープ・フラグの値を取得または設定します。

HTMLをきれいに出力(PRETTY-PRINTING)

デフォルトでは、これらの関数により作成されるすべてのHTMLは、 改行やインデントのない1つの長い行になります。これは汚いですが、 ドキュメントの大きさを10%−20%減らします。きれいな出力を取得するには、 Brian Paulsenによって作成されたサブクララス、CGI::Prettyを 使ってください。

フォームの作成:

一般的な注意点 様々なフォーム・作成メソッドは、すべて呼び出し元に要求された フォーム要素を作成するタグが入った文字列を返します。あなたはこれらの文字列を 実際に出力する責任があります。このように設定されるので、フォーム要素の周りに フォーマットするタグを置くことが出来ます。

他の注意点フォームに指定するデフォルトの値は、(問い合わせ文字列がない時) スクリプトが呼び出された最初のときだけ使われます。その後のスクリプト呼び出し では(問い合わせ文字列があるとき)、たとえ空白であっても前の値が使われます。

前の値からフィールドの値を変更したければ2つの選択肢があります:

(1) 設定するためにparam()メソッドを呼び出す。

(2) -override (別名 -force) パラメータを使う(バージョン2.15での新しい機能)。 これは前の値に関係なく、デフォルトの値が使われるように強制します:

   print $query->textfield(-name=>'field_name',
               -default=>'starting value',
               -override=>1,
               -size=>50,
               -maxlength=>80);

さらにもう1つの注意 デフォルトでは、フォーム要素のテキストとラベルは HTMLルールにしたがってエスケープされます。つまりボタンのためのラベルとして "<CLICK ME>"を安全に使うことが出来ます。しかしそのために、フィールドにAの ような特殊なHTML文字の並びをいれることができません。自動的なエスケープを オフにしたければ、CGIオブジェクトを作成した直後にautoEscape()メソッドを falseで呼び出してください:

   $query = new CGI;
   $query->autoEscape(undef);

ISINDEXタグの作成

   print $query->isindex(-action=>$action);

     -あるいは-

   print $query->isindex($action);

<isindex> タグを出力します。あまり面白くはありません。 パラメータ -actionは、問い合わせを処理するスクリプトのURLを指定します。 デフォルトでは現在のスクリプトで問い合わせを処理します。

フォームの開始と終了

    print $query->start_form(-method=>$method,
                -action=>$action,
                -enctype=>$encoding);
      <... さまざまなフォームの内容 ...>
    print $query->endform;

    -あるいは-

    print $query->start_form($method,$action,$encoding);
      <... さまざまなフォームの内容 ...>
    print $query->endform;

start_form()は<form>タグを指定したオプションのメソッド、 アクション、フォーム・エンコーディングと一緒に返します。デフォルトは 以下の通りです:

    method: POST
    action: this script
    enctype: application/x-www-form-urlencoded

endform()は</form>タグを返します。

Start_form()のenctype引数はブラウザがフォームをサーバに送信する前にフォームの 様々なフィールドをどのようにパッケージするかを伝えます。以下の2つの値が 指定できます:

注意: このメソッドは以前startform()という名前でした。そしてstartform()は、 まだエリアスとして理解されます。

application/x-www-form-urlencoded

これはNetscape 2.0より前のすべてのブラウザによって使われた古いタイプの エンコーディングです。多くのCGIスクリプトと互換性があり、テキスト・データが 入った短いフィールドに適しています。便利なようにCGI.pmは、 このエンコーディング・タイプの名前を&$CGI::URL_ENCODEDに格納しています。

multipart/form-data

これはNetscape 2.0によって導入された新しいタイプのエンコーディングです。 これは非常に大きなフィールドを持ったフォームやバイナリ・データを 転送するフォームに適しています。最も重要なことは、これはNetscape 2.0 フォームの "ファイル・アップロード"機能を可能にすることです。便利なようにCGI.pmは、 このエンコーディング・タイプの名前を&CGI::MULTIPARTに格納しています。

CGI.pmやそれらを扱うように設計されているほかのライブラリを使わなければ、 CGIスクリプトはこのタイプのエンコーディングを使うフォームを簡単には 解釈できません。

互換性のため、start_form()メソッドはデフォルトでは古い形を使います。 デフォルトで新しい形式を使いたければ、start_form()の代りに start_multipart_form()を呼ぶことが出来ます。

JAVASCRIPTING: -name-onSubmitパラメータがJavaScriptでの 使用のために提供されています。-nameパラメータはJavaScript関数に よって識別され、扱えるようにフォームの名前を与えます。-onSubmitは フォームがサーバにサブミットされる直前に実行されるJavaScript関数を 示さなければなりません。この機会を使って、フォームの内容に矛盾が ないか、すべて入っているかをチェックすることができます。何か おかしな事を見つけたら、アラートボックスを表示したり、自分でそれを 修正するかもしれません。この関数からfalseを返すことによって サブミットを中止することが出来ます。

通常JavaScriptの固まりはHTMLヘッダでの<script>ブロックで定義され、 -onSubmitはこれらの関数呼び出しの1つを指します。詳細については start_html()をご覧下さい。

テキスト・フィールドの作成

    print $query->textfield(-name=>'field_name',
                -default=>'starting value',
                -size=>50,
                -maxlength=>80);
    -あるいは-

    print $query->textfield('field_name','starting value',50,80);

textfield()はテキスト入力フィールドを返します。

パラメータ
1.

最初のパラメータは必須で、フィールド名です (-name)。

2.

2番目のパラメータはオプションで、フィールド内容のデフォルト文字列です (-default)。

3.

3番目のパラメータはオプションで、文字数によるフィールドの大きさです (-size)。

4.

4番目のパラメータはオプションで、そのフィールドが受けつける最大文字数です (-maxlength)。

これらすべてのメソッドでは、フィールドはそのスクリプトの以前の呼び出し からの内容で初期化されます。フォームが処理されたとき、テキスト・フィールドの 値は以下のように取り出すことが出来ます:

       $value = $query->param('foo');

そのスクリプトが1度呼び出された後に初期値でリセットしたければ、 以下のようにすることが出来ます:

       $query->param('foo',"I'm taking over this value!");

2.15での新機能:フィールドを前の値にしたくなければ、-override(別名 -force) パラメータを使うことにより、現在の値に強制することが出来ます:

    print $query->textfield(-name=>'field_name',
                -default=>'starting value',
                -override=>1,
                -size=>50,
                -maxlength=>80);

JAVASCRIPTING: JavaScriptイベント・ハンドラを登録するために、-onChange-onFocus-onBlur-onMouseOver-onMouseOutそして-onSelect パラメータを提供することが出来ます。onChangeハンドラはユーザが テキスト・フィールドの内容を変更するといつでも呼び出されます。 よければテキストの有効性チェックをすることができます。 onFocusとonBlurはそれぞれ、挿入ポイントがテキスト・フィールドに 入ったとき、テキスト・フィールドから抜けたときに呼ばれます。 onSelectは選択されているテキストの部分を変えたときに呼ばれます。

大きなテキスト・フィールドの作成

   print $query->textarea(-name=>'foo',
              -default=>'starting value',
              -rows=>10,
              -columns=>50);

    -あるいは

   print $query->textarea('foo','starting value',10,50);

textarea()は、まるでテキストフィールドのようですが、複数行テキスト 入力ボックスのために行と列を指定することが出来ます。そのフィールドに 開始する値を与えることができます。それは長くしたり、複数行にすることができます。

JAVASCRIPTING: -onChange, -onFocus, -onBlur,-onMouseOver, -onMouseOutそして-onSelectパラメータが理解されます。 詳細はtextfield()をご覧下さい。

パスワード・フィールドの作成

   print $query->password_field(-name=>'secret',
                -value=>'starting value',
                -size=>50,
                -maxlength=>80);
    -あるいは-

   print $query->password_field('secret','starting value',50,80);

password_field()は、その内容がwebページでは星印で表示されることを 除いては、textfiled()と同じです。

JAVASCRIPTING: -onChange, -onFocus, -onBlur,-onMouseOver, -onMouseOutそして-onSelectパラメータが理解されます。 詳細はtextfield()をご覧下さい。

ファイル・アップロード・フィールドの作成

    print $query->filefield(-name=>'uploaded_file',
                -default=>'starting value',
                -size=>50,
                -maxlength=>80);
    -あるいは-

    print $query->filefield('uploaded_file','starting value',50,80);

filefield()はNetscape2.0ブラウザのためのファイル・アップロード・フィールドを 返します。利点をすべて生かすためには、そのフォームに 新しいマルチパート・エンコーディング・スキームを使わなければなりません。 これはエンコーディング・タイプを&CGI::MULTIPARTstart_form()を呼び出すか、 普通のstart_form()の代りに新しいメソッドstart_multipart_form()を呼び出すかの どちらかで行うことが出来ます。

パラメータ
1.

最初のパラメータは必須で、フィールド名です(-name) 。

2.

2番目のパラメータはオプションで、デフォルトのファイル名として 使われるフィールド内容のための初期値です (-default)。

セキュリティ上の理由から、ブラウザはこのフィールドには注意を 払いません、そのため初期値は常にブランクになります。さらに 悪いことに、フィールドはその"stickyな"動きを失い、 前の内容を忘れてしまいます。しかしHTML仕様では初期値フィールドが 要求されています、多分いくつかのブラウザは最終的にはそれをサポートでしょう。

3.

3番目のパラメータはオプションで、フィールドの大きさを文字数で 指定します (-size)。

4.

4番目のパラメータはオプションで、そのフィールドが受取る最大文字数です (-maxlength)。

フォームが処理されると、param()を呼ぶことによって入力されたファイル名を 取得することが出来ます:

       $filename = $query->param('uploaded_file');

ブラウザによってちょっとずつ違う名前を返します。あるブラウザは ファイル名だけを返します。あるものはユーザのマシンのパスの書き方を 使ったファイルへのフルパスを返します。いずれにせよ返される名前は常に ユーザのマシンでのファイル名で、CGI.pmがアップロードのスプーリングのさいに 作成する一時ファイルの名前には関連しません(以下をご覧ください)。

返されるファイル名はファイル・ハンドルでもあります。標準のPerlファイル読み込み 呼び出しを使ってファイルの内容を読むことが出来ます:

    # テキストファイルを読み込み、出力します
    while (<$filename>) {
       print;
    }

    # バイナリ・ファイルをどこか安全なところへコピーします
    open (OUTFILE,">>/usr/local/web/users/feedback");
    while ($bytesread=read($filename,$buffer,1024)) {
       print OUTFILE $buffer;
    }

しかしアップロード・フィールドの2つの性質に絡んで問題があります。 use strictを使っていると、Perlは文字列をファイルハンドルとして使うと 文句をいうでしょう。これはファイルの読み込みをno strictプラグマを含んだ ブロックにいれることで回避することが出来ます。さらに深刻なことは、 リモート・ユーザがアップロード・フィールドにゴミをいれると、param()は 文字列ではあっても、ファイル・ハンドルではない可能性があります。

安全のためには、upload()関数(バージョン2.47での新機能)を使って ください。アップロード・フィールドでこれを呼ぶと、upload()は ファイル・ハンドル、あるいはパラメータが正しいファイル・ハンドル でなければundefを返します。

     $fh = $query->upload('uploaded_file');
     while (<$fh>) {
       print;
     }

配列コンテキストでは、upload()はファイル・ハンドルの配列を返します。 これにより同じ名前の複数のuploadフィールドを使うフォームを作成する ことが可能になります。

これは推奨される表現です。

ファイルがアップロードされるとき、ブラウザは通常、ヘッダのフォーマットの 中にいくつかの情報を一緒に送信します。その情報には通常、MIME content typeが 入っています。将来のブラウザは他の情報も送信するかもしれません(変更日や 大きさなのような)。この情報を取り出すためには、uploadInfo()を呼び出してください。 それはすべてのドキュメント・ヘッダが入った連想配列へのリファレンスを返します

       $filename = $query->param('uploaded_file');
       $type = $query->uploadInfo($filename)->{'Content-Type'};
       unless ($type eq 'text/html') {
      die "HTML FILES ONLY!";
       }

"text"と"binary"データ・モードを理解するマシンを使っているのであれば、 それをいつ、どのように使うかを確認してください(ラクダ本をご覧下さい)。 そうでなければ、ファイル・アップロードの間にバイナリファイルが おかしくなることを発見するでしょう。

ときどきアップロードされたファイルを解析している途中に問題が発生します。 通常それはユーザがアップロードが完了する前に"Stop"を押したときにおこります。

この場合、CGI.pmはアップロードされたファイルの名前の代りにundefを、 cgi_error()に文字列"400 Bad Request (malformed multipart POST)"を 設定します。このエラーメッセージはブラウザに送信するステータス・コードに 入れることができるように考えられています。例えば:

   $file = $query->upload('uploaded_file');
   if (!$file && $query->cgi_error) {
      print $query->header(-status=>$query->cgi_error);
      exit 0;
   }

もしも望むなら、エラーについて不満をいうために独自のHTMLページを自由に 作ることができます。

WindowsプラットホームでCGI.pmを使っていて、バイナリファイルがバイナリファイルは 少し大きくなるのに、テキストファイルは同じままであることを発見したならば、 あなたは出力のファイルにバイナリモードを有効にすることを忘れています。 アップロードされたファイルをディスクに書き出すための全てのハンドルに binmode()を確実に呼び出してください。

JAVASCRIPTING: -onChange, -onFocus, -onBlur, -onMouseOver,-onMouseOutそして-onSelectパラメータが 理解されます。詳細はtextfield()をご覧下さい。

ポップアップ・メニューの作成

   print $query->popup_menu('menu_name',
                ['eenie','meenie','minie'],
                'meenie');

      -あるいは-

   %labels = ('eenie'=>'your first choice',
          'meenie'=>'your second choice',
          'minie'=>'your third choice');
   %attributes = ('eenie'=>{'class'=>'class of first choice'});
   print $query->popup_menu('menu_name',
                ['eenie','meenie','minie'],
          'meenie',\%labels,\%attributes);

    -あるいは (名前付きパラメータ形式)-

   print $query->popup_menu(-name=>'menu_name',
                -values=>['eenie','meenie','minie'],
                -default=>'meenie',
          -labels=>\%labels,
          -attributes=>\%attributes);

popup_menu() はメニューを作成します。

  1. 最初のパラメータは必須で、メニューの名前です (-name)。

  2. 2番目の引数(-values)は必須で 、メニューでのメニュー項目が入った 配列リファレンスです。例のように無名配列をメソッドに渡すことが 出来ます。また"\@foo"のように名前付き配列へのリファレンスにすることも出来ます.

  3. 3番目の引数(-default)はオプションで、デフォルトで選択されるメニューの 名前です。指定されなければ最初の項目がデフォルトです。前に選択された値が 問い合わせをまたがって維持されます。

  4. 4番目のパラメータ (-labels)はオプションで、ユーザに見えるラベルのための値と スクリプトに返される値とを違うものにしたい人のために提要されています。 メニューの値とユーザに見えるラベルとを関連付ける連想配列へのポインタです。 このパラメータを空にしておくと、デフォルトでメニューの値は表示された ものになります(もしそうしたければラベルを未定義にしておくこともできます)

  5. 5番目のパラメータ (-attributes)はオプションで、汎用的なHTML属性を 個別のメニュー要素に与えるために提供されます。メニューの値を 属性の名前をキーとし属性の値を値とする他の連想配列に関連付ける 連想配列へのポインタになります。

フォームが処理されるとき、ポップアップ・メニューの選択された値は 以下のようにして取り出すことが出来ます:

      $popup_menu_value = $query->param('menu_name');

JAVASCRIPTING: popup_menu()は以下のイベント・ハンドラを理解します: -onChange, -onFocus, -onMouseOver, -onMouseOut, そして -onBlur。いつこれらのハンドラが呼ばれるかの詳細はtextfield()を ご覧下さい。

オプション・グループの作成

名前付きパラメータのスタイル

  print $query->popup_menu(-name=>'menu_name',
                  -values=>[qw/eenie meenie minie/,
                            $q->optgroup(-name=>'optgroup_name',
                                         -values ['moe','catch'],
                                         -attributes=>{'catch'=>{'class'=>'red'}}),
                  -labels=>{'eenie'=>'one',
                            'meenie'=>'two',
                            'minie'=>'three'},
                  -default=>'meenie');

  古いスタイル
  print $query->popup_menu('menu_name',
                  ['eenie','meenie','minie',
                   $q->optgroup('optgroup_name', ['moe', 'catch'],
                         {'catch'=>{'class'=>'red'}})],'meenie',
                  {'eenie'=>'one','meenie'=>'two','minie'=>'three'});

optgroupはポップアップ・メニューの中にオプション・グループを作成します。

  1. 最初のパラメータ(-name)は必須で、optgroupのlabel属性であり、 問い合わせのパラメータ・リストには挿入されません

  2. 2番目の引数(-values)は必須で 、メニューでのメニュー項目が 入った配列リファレンスです。例のように無名配列をメソッドに渡すことが 出来ます。また\@fooのように名前付き配列へのリファレンスにすることも 出来ます. もしハッシュ・リファレンスを渡せば、キーがメニューの値として 使われ、値はメニューのラベルとして使われます(下記の-labelsをご覧ください)。

  3. 3番目のパラメータ (-labels)はオプションで、メニュー項目の1つあるいは複数の ユーザーに見えるラベルが入った連想配列へのリファレンスを渡すことを 可能にします。ユーザメニュー文字列を見て、ブラウザにはあなたに違う値を 返すことを可能にします。これを指定しないと、valueの文字列が代わりに 使われます。(この例では"eenie", "meenie" そして "minie"になります)。 これは-valuesパラメータにハッシュ・リファレンスを使うのと同じです。

  4. 4番目の引数(-labeled)はオプションで、true値に設定することができます。 valueが、optgroupの中のオプション各オプション項目のためのlabel属性として 使われることを示します。

  5. 5番目の引数(-novals)はオプションで、true値に設定することができます。 optgroupの中の各オプション項目でのval属性を抑止することを示します。

    詳細についてはW3Cでのoptgroupについての議論をご覧ください。 (http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP)

  6. 6番目の引数(-attributes)はオプションで、個別のメニュー項目に共通の HTML属性のいずれかに代入するために提供されます。メニューの値を 属性の名前をキー、属性の値を値とする連想配列に関連付ける 連想配列へのポインタとなります。

スクローリング・リストの作成

   print $query->scrolling_list('list_name',
                ['eenie','meenie','minie','moe'],
        ['eenie','moe'],5,'true',{'moe'=>{'class'=>'red'}});
      -あるいは-

   print $query->scrolling_list('list_name',
                ['eenie','meenie','minie','moe'],
                ['eenie','moe'],5,'true',
        \%labels,%attributes);

    -あるいは-

   print $query->scrolling_list(-name=>'list_name',
                -values=>['eenie','meenie','minie','moe'],
                -default=>['eenie','moe'],
                -size=>5,
                -multiple=>'true',
        -labels=>\%labels,
        -attributes=>\%attributes);

scrolling_list()はスクローリング・リストを作成します。

パラメータ:
1.

最初と2番目の引数はリストの名前(-name) と値 (-values)です。 ポップアップメニュー(訳者注:スクローリングリストの間違いらしい)では、 2番目の引数は配列リファレンスでなければなりません。

2.

3番目の引数(-default)はオプションで、デフォルトで選択される値が 入ったリストへのリファレンスか、選択される1つの値のどちらかにすることが できます。この引数がないか未定義であれば、リストがはじめて表示されたとき には何も選択されません。名前付きパラメータのバージョンでは、この パラメータにシノニム"-defaults"を使うことが出来ます。

3.

4番目の引数はオプションで、リストの大きさです (-size)。

4.

5番目の引数はオプションで、同時に複数の選択を許すためにはtrueを 設定します (-multiple)。そうでなければ一度には1つのだけが許されます。

5.

6番目の引数はオプションで、リスト要素のための長い、ユーザに見える ラベルが入った連想配列へのポインタです (-labels)。提供されなければ 値(values)が表示されます。

6.

7番目(訳注:原文では6th)の引数(-attributes)はオプションで、個別のメニュー項目に共通の HTML属性のいずれかに代入するために提供されます。メニューの値を 属性の名前をキー、属性の値を値とする連想配列に関連付ける 連想配列へのポインタとなります。

このフォームが処理されるとき、選択されたリスト要素はパラメータ名 'list_name'のリストで返されます。選択された要素の値は以下の ようにして取り出すことが出来ます:

      @selected = $query->param('list_name');

JAVASCRIPTING: scrolling_list()は以下のイベント・ハンドラを理解します: -onChange, -onFocus, -onMouseOver, -onMouseOut, そして -onBlur。いつこれらのハンドラが呼ばれるかの詳細はtextfield()を ご覧下さい。

関連付けられたチェックボックスのグループの作成

   print $query->checkbox_group(-name=>'group_name',
                -values=>['eenie','meenie','minie','moe'],
                -default=>['eenie','moe'],
                -linebreak=>'true',
        -labels=>\%labels,
        -attributes=>\%attributes);

   print $query->checkbox_group('group_name',
                ['eenie','meenie','minie','moe'],
        ['eenie','moe'],'true',\%labels,
        {'moe'=>{'class'=>'red'}});

   HTML3 互換のブラウザのみ:

   print $query->checkbox_group(-name=>'group_name',
                -values=>['eenie','meenie','minie','moe'],
                -rows=2,-columns=>2);

checkbox_group()は同じ名前によって関連付けられたチェックボックスの リストを作成します。

パラメータ:
1.

最初と2番目の引数はそれぞれ、チェックボックスの名前と値 (-nameと-values) です。ポップアップ・メニューと同じように、2番目の引数は配列リファレンスで なければなりません。これらの値は、チェックボックスの隣に出力されるユーザが 読むことが出来るラベルであり、また問い合わせ文字列でスクリプトに渡される 値でもあります。

2.

3番目の引数(-default)はオプションで、デフォルトでチェックされる値が 入ったリストへのリファレンスか、チェックされる1つの値のどちらかにする ことができます。この引数がないか、未定義であれば、最初にリストが表示 されたときには何も選択されません。

3.

4番目の引数 (-linebreak)はオプションで、trueに設定されると垂直な リストで表示されるようチェックボックスの間に改行をいれます。 そうでなければ水平に一緒になって並べられます。

4.

5番目の引数はオプションで、チェックボックスの値とチェックボックスの 隣に出力されるユーザに見えるラベルとを関連付ける連想配列へのポインタ です(-labels)。与えられなければ値(values)がデフォルトとして使われます。

5.

(ネットスケープのような)HTML3互換ブラウザの利点として、オプションの パラメータとして-rows-columnsを取ることができます。これらの パラメータは、checkbox_groupを指定された数の行と列で整形された チェックボックス・グループが入ったHTML3互換のテーブルを 返させるようにします。そうしたければ、-columnsだけを与えることも できます;check_groupは正しい行数をあなたに代って計算します。

6.

7番目(訳注:原文ではsixth)の引数(-attributes)はオプションで、 個別のメニュー項目に共通のHTML属性のいずれかに代入するために 提供されます。メニューの値を属性の名前をキー、属性の値を 値とする連想配列に関連付ける連想配列へのポインタとなります。

返されるテーブルでの行と列のヘッダを入れるために、-rowheaders-colheadersパラメータを使うことが出来ます。これらは両方とも 使用するヘッダの配列へのポインタを受取ります。そのヘッダは 単なる飾りです。チェックボックスの解析を理解しません -- それらは まだ名前がついた1つのユニットです。

フォームが処理されるとき、すべてのチェックされたボックスは パラメータ名'group_name'のリストとして返されます。"on"の値の チェックボックスは以下のようにして取り出すことが出来ます:

      @turned_on = $query->param('group_name');

checkbox_group()によって返される値は実際にはボタン要素の 配列です。以下のようにして、それらを取得し、テーブル、リストあるいは その他の作成方法で使うことが出来ます:

    @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
    &use_in_creative_way(@h);

JAVASCRIPTING: checkbox_group()は-onClickパラメータを 理解します。これは、そのグループの中のボタンのどれかを ユーザがクリックするたびに実行される、JavaScriptコードの一部、 あるいは関数を指定します。"this"変数を使って、クリックされた ボタンの識別子を取り出すことが出来ます。

独立したチェックボックスの作成

    print $query->checkbox(-name=>'checkbox_name',
               -checked=>1,
               -value=>'ON',
               -label=>'CLICK ME');

    -あるいは-

    print $query->checkbox('checkbox_name','checked','ON','CLICK ME');

checkbox()は他とは論理的に関連付けられない独立したチェックボックスを 作成するために使われます。

パラメータ:
1.

最初のパラメータは必須で、チェックボックスのための名前です (-name)。 それはチェックボックスの隣に出力されるユーザが読むことができるラベル としても使われます。

2.

2番目のパラメータ(-checked) はオプションで、デフォルトで チェックボックスがonとすることを指定します。 シノニムは-selected と-onです。

3.

3番目のパラメータ(-value)はチェックされたときのチェックボックスの 値を指定します。指定されなければ"on"が想定されます。

4.

4番目のパラメータ(-label) はチェックボックスにつけられるユーザが 読むことが出来るラベルです。指定されなければ、チェックボックスの名前が 使われます。

チェックボックスの値は以下のようにして取り出すことが出来ます:

    $turned_on = $query->param('checkbox_name');

JAVASCRIPTING: checkbox()は-onClickパラメータを理解します。 さらに詳細な情報はcheckbox_group()をご覧下さい。

ラジオボタン・グループの作成

   print $query->radio_group(-name=>'group_name',
                 -values=>['eenie','meenie','minie'],
                 -default=>'meenie',
                 -linebreak=>'true',
           -labels=>\%labels,
           -attributes=>\%attributes);

    -あるいは-

   print $query->radio_group('group_name',['eenie','meenie','minie'],
            'meenie','true',\%labels,\%attributes);


   HTML3-互換ブラウザのみ:

   print $query->radio_group(-name=>'group_name',
                 -values=>['eenie','meenie','minie','moe'],
                 -rows=2,-columns=>2);

radio_group()は論理的に関連付けられたラジオボタンのセット (グループのメンバーの1つがオンになると、他はオフになります)を 作成します。

パラメータ:
1.

最初の引数はグループ名で必須です (-name)。

2.

2番目の引数(-values) はラジオボタンのための値のリストです。 ページ上で表示される値とラベルはインデントされます。2番目の引数には 配列リファレンスか、上記に示されたような無名配列、または"\@foo"のような 名前付き配列をリファレンスにしたもの渡してください。

3.

3番目のパラメータ(-default) はオプションで、オンするデフォルトボタンの 名前です。指定されなければ最初の要素がデフォルトになります。 何もボタンが選択されていない状態で開始するために、"-"のような存在しない ボタン名を指定することが出来ます。

4.

4番目のパラメータは(-linebreak) オプションで、ボタンの間に改行を入れ、 垂直なリストを作成するために'true'に設定することが出来ます。

5.

5番目のパラメータ(-labels)はオプションで、ラジオボタンの値と表示のときに 使われるユーザに見えるラベルとを関連付ける連想配列へのポインタです。 与えられなければ、値そのものが表示されます。

6.

(Netscapeのような)HTML3互換ブラウザは、さらにオプションのパラメータ、 -rows-columnsを取ることが出来ます。これらのパラメータは radio_group()に、指定された行数、列数でフォーマットされたラジオボタンの グループが入ったHTML3互換のテーブルを返すようにします。もし望めば、 -columnsパラメータだけを与えることが出来ます;radio_groupは 正しい行数をあなたに代って計算します。

6.

7番目(訳注:原文ではsixth)の引数(-attributes)はオプションで、 個別のメニュー項目に共通のHTML属性のいずれかに代入するために 提供されます。メニューの値を属性の名前をキー、属性の値を 値とする連想配列に関連付ける連想配列へのポインタとなります。

返されるテーブルに行と列のヘッダを入れるために、-rowheader-colheaderパラメータを使うことが出来ます。これらは両方とも 使用するヘッダの配列へのポインタを受取ります。ヘッダは 単なる飾りです。それらはラジオボタンの解析を理解しません-- それらはまだ名前がついた1つのユニットです。

フォームが処理されるとき、選択されたラジオボタンは以下の ようにして取り出すことが出来ます:

      $which_radio_button = $query->param('group_name');

radio_group()により返される値は実際にはボタン要素の配列です。 以下のようにしてそれらを取得し、テーブル、リストあるいは、その他の 作成方法で使うことが出来ます:

    @h = $query->radio_group(-name=>'group_name',-values=>\@values);
    &use_in_creative_way(@h);

(訳者注:サブミット・ボタンほうに紛れ込んでいましたが、本来はここでしょう)

JAVASCRIPTING: radio_group() は-onClickパラメータを理解します。 さらなる詳細はcheckbox_group()をご覧下さい。

サブミット・ボタンの作成

   print $query->submit(-name=>'button_name',
            -value=>'value');

    -あるいは-

   print $query->submit('button_name','value');

submit()は問い合わせサブミット・ボタンを作成します。 すべてのフォームはこれらのいずれかを持たなければいけません。

パラメータ:
1.

最初の引数(-name) はオプションです。フォームにたくさんのサブミット・ボタンを 持っていて、それらを区別したければ、名前を与えることが出来ます。 名前は ユーザに見えるラベルとしても使われます。古いブラウザには、これを正しく扱わず、 ボタンからまったく送信しないものもあることに注意してください。

2.

2番目の引数 (-value) もオプションです。これはボタンに問い合わせ文字列で スクリプトに渡される値を与えます。

それぞれに異なる値を使うことによりどのボタンが押されたかを 見分けることが出来ます:

     $which_one = $query->param('button_name');

リセット・ボタンの作成

   print $query->reset

reset()は"リセット"ボタンを作成します。必ずしもデフォルトではなく、 最後にスクリプトが呼ばれたときからの値をそのフォームに再設定する ことに注意してください。

これがPerlに組込まれているreset()とぶつかることに注意してください。 元のreset関数を取得するにはCORE::reset()を使ってください。

デフォルト・ボタンの作成

   print $query->defaults('button_label')

defaults()は、呼び出されたとき、フォームを完全にデフォルトに リセットし、ユーザがそれまで行ったすべての変更を洗い流してしまう ボタンを作成します。

ヒドゥン・フィールドの作成

    print $query->hidden(-name=>'hidden_name',
                 -default=>['value1','value2'...]);

        -または-

    print $query->hidden('hidden_name','value1','value2'...);

hidden()はユーザには見えないテキスト・フィールドを作成します。 これはあるスクリプトの呼び出しから次へ状態変数情報を渡すのに便利です。

パラメータ:
1.

最初の引数は必須で、このフィールドの名前を指定します (-name)。

2.

2番目の引数も必須で、その値を指定します (-default)。呼び出しの 名前付きパラメータ形式では、1つの値またはリスト全体へのリファレンスを 指定することが出来ます。

ヒドゥン・フィールドの値は以下のようにして取り出してください:

     $hidden_value = $query->param('hidden_name');

他のすべてのフォーム要素と同じように、ヒドゥン・フィールドは"sticky"で あることに注意してください。スクリプトが一度呼び出された後に、何か 他の値でヒドゥン・フィールドを置き換えたければ、手動でおこなう必要が あります:

     $query->param('hidden_name','new','values','here');

クリッカブル・イメージ・ボタンの作成

     print $query->image_button(-name=>'button_name',
                -src=>'/source/URL',
                -align=>'MIDDLE');      

    -あるいは-

     print $query->image_button('button_name','/source/URL','MIDDLE');

image_button()はクリッカブルなイメージを作成します。クリックされると、 スクリプトへクリックの位置が"bottun_name.x"と"button_name.y"として 返されます。"button_name"のところはそれに指定した名前です。

JAVASCRIPTING: image_buttonは-onClickパラメータを理解します。 さらなる詳細はcheckbox_group()をご覧下さい。

パラメータ:
1.

最初の引数(-name) は必須で、このフィールドの名前を指定します。

2.

2番目の引数(-src) も必須で、URLを指定します。

3.

3番目のオプション(-align, optional) はアラインメントのタイプで、 TOP, BOTTOMまたはMIDDLEを指定することが出来ます。

このボタンの値は以下のようにして取り出してください: $x = $query->param('button_name.x'); $y = $query->param('button_name.y');

JAVASCRIPTアクション・ボタンの作成

     print $query->button(-name=>'button_name',
              -value=>'user visible label',
              -onClick=>"do_something()");

    -あるいは-

     print $query->button('button_name',"do_something()");

button()はNetscape 2.0のJavaScriptと互換性のあるボタンを作成します。 -onClickパラメータで示されるJavaScriptのコードが実行されます。 Netscapeではないブラウザでは、このフォーム要素は多分表示すら されないでしょう。

HTTPクッキー

Netscapeブラウザ バージョン1.1以上とInternet Explorerのすべての バージョンはブラウザ・セッションでの状態を保持することを助けるように 設計された、いわゆる"クッキー"をサポートしています。CGI.pmはクッキーを サポートするさまざまなメソッドを持っています。

クッキーは、CGI問い合わせ文字列の名前付きパラメータによく似た、 名前=値の組みです。CGIスクリプトは1つまたは複数のクッキーを作り、 HTTPヘッダに入れてブラウザに送信します。ブラウザは特定のWebサーバに 所属するクッキーのリストを保持し、その後の対話の間、CGIスクリプトに 返します。

必須の名前=値の組に加えて、各クッキーはさまざまなオプションの属性を 持っています:

1. 有効期限(expiration time)

これはクッキーの有効期限を示す時刻/日付の文字列(特別なGMTフォーマット による)です。ユーザがブラウザを終了させ、再起動したならば、 この有効期限が来るまで、クッキーは保存され、スクリプトに返されます。 有効期限が指定されなければ、クッキーはユーザがブラウザを終わらせるまで 有効です。

2. ドメイン(domain)

これはクッキーが有効であるドメイン名の全体あるいは一部です。 ブラウザはドメイン名の一部がマッチする、すべてのホストにクッキーを 返します。例えばドメイン名に".capricorn.com"を指定すれば、 ブラウザは"www.capricorn.com", "www2.capricorn.com", "feckless.capricorn.com"などのマシンのすべて実行されているWebサーバに クッキーを返します。".edu"のように最上位のドメインにマッチしようと することを防ぐよう、ドメイン名は少なくとも2つのピリオドが入って いなければなりません。もしドメインが指定されなければ、ブラウザは クッキーが作成されたホストのサーバにだけクッキーを返します。

3. パス(path)

クッキークリプトのURLをpath属性を与えると、ブラウザはクッキーを 返す前にあなたのスクリプトのURLをチェックします。例えばパスを "/cgi-bin"と指定すれば、"/cgi-bin/tally.pl", "/cgi-bin/order.pl", "/cgi-bin/customer_service/complain.pl"のそれぞれのスクリプトには 返されますが、"/cgi-private/site_admin.pl'"には返されません。 デフォルトではパスは"/"で、これはあなたのサイトのすべての CGIスクリプトにクッキーが送信させます。

4. "安全"フラグ("secure" flag)

もし"secure"属性が設定されると、クッキーはCGIリクエストがSSLのような セキュアなチャンネルで発生された場合にのみ送信されます。

HTTPクッキーへのインタフェースはcookie()メソッドです:

    $cookie = $query->cookie(-name=>'sessionID',
                 -value=>'xyzzy',
                 -expires=>'+1h',
                 -path=>'/cgi-bin/database',
                 -domain=>'.capricorn.org',
                 -secure=>1);
    print $query->header(-cookie=>$cookie);

cookie()は新しいクッキーを作成します。そのパラメータには 以下のものがあります:

-name

クッキーの名前(必須)。これにはどんな文字列でも指定できます。 ブラウザは、そのクッキー名を空白が入らない、英数字に限定しますが、 CGI.pmは背後でクッキーをエスケープ、アンエスケープすることにより、 これらの制限を取り払います。

-value

クッキーの値。これにはすべてのスカラ値、配列リファレンス、さらに 連想配列リファレンスさえも指定できます。例えば完全な連想配列を クッキーに以下のようにして格納することが出来ます:

    $cookie=$query->cookie(-name=>'family information',
                   -value=>\%childrens_ages);
-path

オプションで、上記で説明したようにクッキーが有効になるパスの一部。

-domain

オプションで、上記で説明したようにクッキーが有効になるドメインの一部。

-expires

オプションで、このクッキーの有効期限。フォーマットはheader()メソッドに ついてのセクションで説明したのと同じ:

    "+1h"  今から1時間
-secure

trueに設定されれば、このクッキーは安全なSSLセッションでのみ 使われます。

cookie()によって作成されたクッキーは、header()メソッドによって返される 文字列で、HTTPヘッダの中に入れられなければなりません:

    print $query->header(-cookie=>$my_cookie);

複数のクッキーを作成するには、header()に配列リファレンスを指定してください:

    $cookie1 = $query->cookie(-name=>'riddle_name',
                  -value=>"The Sphynx's Question");
    $cookie2 = $query->cookie(-name=>'answers',
                  -value=>\%answers);
    print $query->header(-cookie=>[$cookie1,$cookie2]);

クッキーを取り出すには、cookie()メソッドを-valueパラメータなしで 呼び出すことによって名前で要求します:

    use CGI;
    $query = new CGI;
    $riddle = $query->cookie('riddle_name');
        %answers = $query->cookie('answers');

"riddle_name"クッキーのように、1つのスカラーの値で作成されたクッキーは、 その形で帰されます。配列やハッシュを持っているクッキーも取り出すことが 出来ます。

クッキーとCGI名前空間は分かれています。もし'answers'という名前の パラメータと'answers'という名前のクッキーを持っていれば、param()と cookie()によって取り出される値はそれぞれ独立しています。 しかしながら、CGIパラメータをクッキーにしたり、その逆も簡単です:

   # CGIパラメータをクッキーにする
   $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
   # その逆
   $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);

クッキーをどのように効率よく使うかについての、いくつかのアイデアに ついては、例のスクリプトcookie.cgiをご覧下さい。

フレームの利用

CGI.pmスクリプトではHTML4フレーム機能を使って、たくさんのブラウザ・パネルと ウィンドウに書き込むことができます。プログラム的に新しいフレームを定義する ためには3つのテクニックがあります:ぽ

1. <Frameset>ドキュメントの作成

HTTPヘッダを出力した後、start_html()呼び出しを使って標準の HTMLドキュメントを作成する代りに、ページにフレームを定義する <frameset>ドキュメントを作成します。各フレームのSRCとして スクリプトを(適切なパラメータをつけて)指定します。

CGI.pmには<frameset>セクションを作成するのに特別なサポートは ありません。しかしHTMLはとても簡単に書けます。詳細については ネトスケープのホームページにあるフレームのドキュメントをご覧ください。

  http://home.netscape.com/assist/net_sites/frames.html
2. HTTPヘッダでドキュメントの出力先を指定

header()に-targetを指定することが出来ます:

    print $q->header(-target=>'ResultsWindow');

これはブラウザにスクリプトの出力を"ResultsWindow"という名前の フレームにロードするように伝えます。もしその名前のフレームがなければ、 ブラウザは新しいウィンドウを立ち上げ、それにスクリプトのドキュメントを ロードします。ターゲットに使うことが出来る特別な名前がたくさんあります。 詳細についてはネットスケープのホームページにあるフレームのドキュメントを ご覧ください。

3. <form>タグでドキュメントの出力先を指定

FORMタグそれ自身にロードするフレームを指定することが出来ます。 CGI.pmでは以下のようになります:

    print $q->start_form(-target=>'ResultsWindow');

フォームによりスクリプトが再び呼び出されると、その出力は"ResultsWindow"という 名前のフレームにロードされます。それがまだなければ新しいウィンドウが 作成されます。

examplesディレクトリにあるスクリプト"frameset.cgi"は、フォームと レスポンスが隣り合ったフレームに存在するページを作成する1つの方法を 示しています。

カスケーディング・スタイル・シートの限定サポート

CGI.pm はHTML3のカスケーディング・スタイル・シート(css)を限定付きで サポートします。スタイルシートをドキュメントに組込むためには、 start_html()メソッドに-styleパラメータを渡します。このパラメータの 値にはスカラー、この場合は直接<style>セクションに組込まれます。 あるいはハッシュ・リファレンスを指定することが出来ます。後者の場合は、 1つあるいは複数の-srcまたは-codeを持ったハッシュを指定しなければ いけません。-srcは完全に定義されたスタイルシートを見つけることが 出来るURLを示します。-codeは<style>セクションに組込まれるスカラー値を 示します。-codeでのスタイルの定義は、-srcでの同じ名前のもので 上書きされます。これゆえに名前が"cascading"(滝のように落ちる)なのです。

-styleによって示されるハッシュに、オプションの-typeを加えることにより スタイルシートの種類を指定することも出来ます。もし指定されなければ、 そのスタイルはデフォルトの'text/css'です。

ドキュメントの本体(Body)でスタイルを参照するためには、HTML要素に -classを加えます:

    print h1({-class=>'Fancy'},'Welcome to the Party');

あるいは、その場で-styleパラメータでスタイルを定義します:

    print h1({-style=>'Color: red;'},'Welcome to Hell');

テキストのセクションにスタイルを適用するため、新しいspan()を 使うことも出来ます:

    print span({-style=>'Color: red;'},
           h1('Welcome to Hell'),
           "Where did that handbasket get to?"
           );

span()メソッドを使えるようにするためには":html3"をインポートしなければ いけないことに注意してください。CSS使用の簡単で汚い例を以下に示します。 さらなる詳細はhttp://www.w3.org/pub/WWW/TR/Wd-css-1.html にあるCSSの仕様を ご覧下さい。

    use CGI qw/:standard :html3/;

    #ここはページに直接組込まれるスタイルシートです
    $newStyle=<<END;
    <!-- 
    P.Tip {
    margin-right: 50pt;
    margin-left: 50pt;
        color: red;
    }
    P.Alert {
    font-size: 30pt;
        font-family: sans-serif;
      color: red;
    }
    -->
    END
    print header();
    print start_html( -title=>'CGI with Style',
              -style=>{-src=>'http://www.capricorn.com/style/st1.css',
                       -code=>$newStyle}
                 );
    print h1('CGI with Style'),
          p({-class=>'Tip'},
        "Better read the cascading style sheet spec before playing with this!"),
          span({-style=>'color: magenta'},
           "Look Mom, no hands!",
           p(),
           "Whooo wee!"
           );
    print end_html;

ドキュメントに複数のスタイルシートを組み込むためには-styleに 配列リファレンスを渡してください。

デバッグ方法

コマンドラインからスクリプトを実行するか、perlデバッガのなかで 実行するならば、キーワードのリストやパラメータ=値の組をコマンド行や 標準入力からスクリプトに渡すことが出来ます(環境変数からスクリプトに 読み込むような仕組みについて心配する必要はありません)。キーワードを 以下のようにして渡すことが出来ます:

    your_script.pl keyword1 keyword2 keyword3

あるいは:

   your_script.pl keyword1+keyword2+keyword3

あるいは:

    your_script.pl name1=value1 name2=value2

あるいは:

    your_script.pl name1=value1&name2=value2

この機能を無効にするには、-no_debugプラグマを使ってください。

POSTメソッドをテストするために、-debugプラグマでフルのデバッグを 可能にすることができます。これは改行で区切った名前=値の組み合わせを 標準入力からスクリプトに食わせることができます。

デバッグのとき、よく知っているシェルのマナーで、文字をエスケープする ためにクォートとバックスラッシュを使うことが出来ます。パラメータ=値の組で、 空白や他の変わった文字を置かせるためには以下のようにします:

   your_script.pl "name1='I am a long value'" "name2=two\ words"

すべての名前/値の組み合わせをダンプする方法

Dump()メソッドはすべての問い合わせの名前/組が入った、ネストした リストとしてきれいに整形されたされた文字列を作成します。 こればデバッグの目的には有効です:

    print $query->Dump

これは以下のようなものを作成します:

    <ul>
    <li>name1
    <ul>
    <li>value1
    <li>value2
    </ul>
    <li>name2
    <ul>
    <li>value1
    </ul>
    </ul>

ショートカットとして、完全なCGIオブジェクトを文字列に入れることが 出来ます。そしてそれは上記に示されるきれいなHTMLダンプで置きかえられます:

    $query=new CGI;
    print "<h2>Current Values</h2> $query\n";

環境変数の取り出し

いくつかのより便利な環境変数がこのインターフェースを通して 取り出すことが出来ます。メソッドを以下に示します:

Accept()

リモートのブラウザが受取るMIMEタイプのリストを返します。 $query->Accept('text/html')のように、もしこのメソッドにMIMEタイプに 対応する1つの引数を渡せば、このタイプについてのブラウザの優先順位に 対応する0.0(欲しくありません)から1.0までの浮動小数点値を返します。 ブラウザの受取リストでのGlob型(例えば text/*)は正確に扱われます。

Perlのaccept()関数とぶつかることを避けるために、2.43と2.44の間で 先頭文字が大文字に変更されたことに注意してください。

raw_cookie()

Netscapeブラウザ バージョン1.1以上とInternet Explorerのすべての バージョンによるHTTP拡張であるHTTP_COOKIE変数を返します。クッキーは 特別なフォーマットを持っており、このメソッドは単にそのままの形式を 返します(いわばクッキーのタネ?)。調理されたクッキーを設定し、 取得する方法については、cookie()をご覧下さい。

パラメータなしで呼ばれると、raw_cookie()はパックされたクッキー構造体を 返します。";"の文字並びで分割(split)することにより、ここのクッキーに 分けることが出来ます。クッキーの名前をつけて呼び出すと、クッキーの エスケープされていない形式を取り出します。名前を取得するために、 通常のcookie()メソッドを使ったり、CGI::Cookieモジュールからの raw_fetchメソッドを使うことが出来ます。

user_agent()

HTTP_USER_AGENT 変数を返します。このメソッドに1つの引数を与えると、 それにパターンマッチを試み、 $query->user_agent(netscape); のようなことを おこなうことを可能にします。

path_info()

スクリプトからの追加パス情報を返します。 例えば/cgi-bin/your_script/additional/stuffを取り出すと、 $query->path_info()は結果として"addtional/stuff"を返します。

注意:Microsoft Internet Information Server は追加のパス情報の見方で おかしくなっています。Perl DLLライブラリを使うと、IISサーバは Perlスクリプトとして追加パス情報を実行しようとします。もし通常の ファイル関連マッピングを使えば、パス情報は環境変数に表れますが正しくありません。 これをおこなう一番よいことは、IISで使用するようなCGIでは追加パス情報を使うことを 避けることです。

path_translated()

path_info()と同様、しかし追加パス情報を物理パス情報に変換します。 例えば"/usr/local/etc/httpd/htdocs/addtional/stuff"。

変換されたパスについてもMicrosoft IISはイカレています。

remote_host()

リモート・ホスト名または、もし前者が使えなければIPアドレスの どちらかを返します。

script_name()

自分を参照するスクリプトのため、URLの一部としてスクリプト名を 返します。

referer()

ブラウザがスクリプトを取り出す前に見ていたページのURLを返します。 すべてのブラウザに利用できるわけではありません。

auth_type ()

もしあれば、このスクリプトのために使われた、 authorization/verification (認証/検証)方法を返します。

server_name ()

サーバの名前、通常はマシンのホスト名を返します。

virtual_host ()

バーチャル・ホストを使っているとき、ブラウザがコンタクト しようとしたホストの名前を返します。

server_port ()

サーバ・ソフトウェアとバージョン番号を返します。

server_software ()

サーバ・ソフトウェアとバージョン番号を返します。

remote_user ()

このスクリプトが保護されていれば、ユーザ検証に使われた authorization/verification 名を返します。

user_name ()

さまざまな異なる技術を使ってリモートユーザの名前を取得しようと します。これはMosaicのような古いブラウザでのみ機能します。 新しいブラウザはプライバシーの理由からユーザ名を報告しません!

request_method()

スクリプトにアクセスするために使われたメソッドを返します。 通常は'POST'、'GET'または'HEAD'のどれかです。

content_type()

POSTで送信されてきたデータのcontent_typeを返します。一般には multipart/form-data または application/x-www-form-urlencodedです。

http()

引数なしで呼ばれると、それぞれリクエストでの似たような HTTPヘッダ・フィールドに対応する、HTTP_USER_AGENT、HTTP_ACCEPT_LANGUAGE、 そしてHTTP_ACCEPT_CHARSETのようなものが入った環境変数のリストを返します。 HTTPヘッダ・フィールドの名前付きで呼ばれると、その値を返します。 大文字/小文字、アンダースコアの代わりにハイフンを使うことは区別されません。

例えば、この3つの例はすべて同値です:

   $requested_language = $q->http('Accept-language');
   $requested_language = $q->http('Accept_language');
   $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE');
https()

http()と同じ。しかしSSLプロトコルが有効なときに現れる HTTPS環境変数を扱います。SSLがオンになっているかどうかを判定するためにも 使うことができます。

NPHスクリプトの使い方

NPHまたは"解析されないヘッダ"("no-parsed-header")、では、完全な HTTPヘッダを直接ブラウザに送信することにより、スクリプトはサーバを 完全にバイパスします。これはパフォーマンスの面で少し利点があります。 しかしほとんどは、サーバ・プッシュやPICSヘッダのような、サーバによって 直接にはサポートされていないHTTP拡張の利点を得るために使われます。

CGIスクリプトをNPHとして示すため、さまざまな約束が使われます。 多くのUnixサーバはスクリプトの名前の始まりに接頭辞"nph-"があるかを 見ます。これに対してMacintosh WebSTARサーバと Microsoftの Internet Information Serverは、スクリプト出力の先頭行をチェックする ことによりNPHスクリプトであるかを判定しようとします。

CGI.pmは特別はNPHモードでNPHスクリプトをサポートします。 このモードではCGI.pmはheader()やredirect()メソッドが呼ばれると 必要となる特殊なヘッダ情報を出力します。

Microsoft Internet Information Server はNPHモードを必要とします。 version 2.30では、CGI.pmはIISの元で実行されたとき自動的に検知し、 自分自身でこのモードにします。手動でこのモードにする必要はありません。 しかしそうしたからといって、何も問題はありません。 しかしながら サービスパック6を提供しているのであれば、注意してください。 クッキーが設定されている間、リダイレクトするという機能も含めて、 NPHスクリプトの機能の多くがMicrosoftからの特別なパッチなしには IISではb<まったく機能しません>。このURLをご覧ください http://support.microsoft.com/support/kb/articles/Q280/3/41.ASP: Non-Parsed Headers Stripped From CGI Applications That Have nph- Prefix in Name. (名前がnph-で始まらないCGIアプリケーションからの 解析されないヘッダの除去)

useステートメントで

スクリプトにインポートされるシンボルのリストに単に"-nph"プラグマを 追加してください:

      use CGI qw(:standard -nph)
nph()メソッドの呼出し

CGI.pmをプログラムで使った後のどこかの時点で、非0のパラメータで nph()を呼び出してください。

      CGI->nph(1)
-nphパラメータを使う

header()redirect()ステートメントで:

      print $q->header(-nph=>1);

サーバー・プッシュ

CGI.pmは、サーバ・プッシュを実装するために必要な種類である マルチパート・ドキュメントを作成するために簡単な4つの関数を提供しています。 これらの関数はありがたいことに Ed Jordan <[email protected]>によって 提供されました。これらを名前空間にインポートするためには、":push"セットを インポートしなければいけません。またスクリプトをNPHモードとし、バッファリングの 問題を避けるために$|を1に設定したほうがよいでしょう。

サーバ・プッシュをデモンストレーションする簡単なスクリプトを以下にしめします:

  #!/usr/local/bin/perl
  use CGI qw/:push -nph/;
  $| = 1;
  print multipart_init(-boundary=>'----here we go!');
  foreach (0 .. 4) {
      print multipart_start(-type=>'text/plain'),
            "The current time is ",scalar(localtime),"\n";
      if ($_ < 4) {
              print multipart_end;
      } else {
              print multipart_final;
      }
      sleep 1;
  }

このスクリプトはmultipart_init()を呼ぶことによってサーバ・プッシュを 初期化しています。そしてmultipart_start()を呼ぶことによって新しい マルチパート・セクションを始め、現在のローカル・タイムを出力し、 multipart_end()でマルチパート・セクションを終わらせているループに 入ります。そして1秒スリープした後、再び開始します。最後の繰り返しでは multipart_end()ではなくmultipart_final()でマルチパート・ セクションを終了させています。

multipart_init()
  multipart_init(-boundary=>$boundary);

マルチパート・システムを初期化します。-boundary 引数はドキュメントの 部分を分割するために使われるMIMEバウンダリ文字列を指定します。 指定されなければ、CGI.pmはあなたに代わって合理的なバウンダリを選択します。

multipart_start()
  multipart_start(-type=>$type)

指定されたMIMEタイプを使ってマルチパート・ドキュメントの新しい部分を 開始します。指定されなければ、text/htmlが想定されます。

multipart_end()
  multipart_end()

部分(part)を終わらせます。multipart_end()の代わりにmultipart_final()を 呼ばなければならないマルチパート・ドキュメントの最後の部分の終わりを 除いて、multipart_start()を呼ぶ毎にmultpart_end()を 呼ぶ事を忘れては行けません。

multipart_final()
  multipart_final()

全ての部分を終了させます。マルチパート・ドキュメントの最後の部分の 終了のときにはmultipart_end()ではなく、multipart_final()を呼ばなければ なりません。

サーバ・プッシュ・アプリケーションに興味のあるユーザはCGI::Pushモジュールも 見るべきです。

Netscape Navigatorだけがサーバー・プッシュをサポートしています。 Internet Explorerブラウザはサポートしていません。

サービス不能(DoS)攻撃の回避

CGI.pmでの潜在的な問題は、デフォルトではPOSTされたフォームがどんなに大きくても 処理しようとすることです。ずるがしこいハッカーは数メガバイトの巨大な POSTをCGIスクリプトに送信することにより、あたなのサイトを攻撃することが 出来ます。CGI.pmはPOST全体を変数に読み込もうとし、メモリがなくなるまで、 その大きさは巨大に成長します。スクリプトがメモリを占有しようとする間、 システムは劇的に遅くなるかもしれません。これがサービス不能(DoS)攻撃の形です。

他の可能な攻撃はリモードユーザがCGI.pmに巨大なファイルのアップロードを 受取ることを強要することです。CGI.pmは、例えあなたのスクリプトがアップロード されるファイルを受けることを予想していなくても、アップロードを受けつけ、 それを一時ディレクトリに格納しようとします。CGI.pmはそれが終わったとき、 自動的にファイルを削除します、しかしその間にリモートユーザがサーバの ディスク空間をいっぱいにしてしまうかも知れません。他の問題を起こしながら。

サービス・アタックの拒否を避ける一番よい方法は、CGIスクリプトが使うことが できるメモリ量、CPU時間、ディスク容量を制限することです。いつくかのWebサーバは これを実現する組込み機能を持っています。その他の場合、シェルのlimitまたは ulimitをCGIの資源使用に上限を設定ために使うことが出来ます。

CGI.pmもサービス・アタックの拒否に対するいくかの簡単な組込まれた保護を 持っていますが、使えるようになる前に活性化させなければなりません。 これらはCGI名前空間での2つのグローバル変数の形を取ります:

$CGI::POST_MAX

負でない整数が設定されると、この変数はPOSTされるサイズの上限を バイト数で設定します。CGI.pmは上限よりも大きいPOSTを検知すると、 エラーメッセージとともにすぐにexitします。この値は通常のPOSTと マルチパートPOSTの両方に影響を与えます。つまりファイル・アップロードの 最大の大きさも制限するということです。 これは1メガバイトのように合理的に大きい値を設定しなければいけません。

$CGI::DISABLE_UPLOADS

非0の値が設定されると、これはファイルのアップロードを完全に 不可能にします。他のフォームの値は通常通り機能します。

これらの変数を以下の2つの方法のどちらかで使うことが出来ます:

1. スクリプト毎に

"use"ステートメントのすぐ後に、スクリプトの先頭でその変数を設定します:

    use CGI qw/:standard/;
    use CGI::Carp 'fatalsToBrowser';
    $CGI::POST_MAX=1024 * 100;  # max 100K posts
    $CGI::DISABLE_UPLOADS = 1;  # no uploads
2. すべてのスクリプトでグローバルに

CGI.pmを開き$POST_MAXと$DISABLE_UPLOADSのための定義を見つけ、 それを望んでいる値に設定します。ファイルの先頭の近くinitialize_globals() という名前のサブルーチンの中で見つけるでしょう。

$POST_MAXバイトよりも大きなPOSTを送信しようとするとparam()に 空のCGIパラメータを返させます。このイベントはCGIオブジェクトを 作成した後もしくは関数指向インターフェースを使っていれば最初に <param()>を呼び出した後に、cgi_error()をチェックすることで 調べることができます。もしPOSTが中断されていれば、cgi_error()は "413 POST too large"というメッセージを返します。

このエラーメッセージは実際にはHTTPプロトコルで定義されており、 そしてCGIスクリプトのステータス・コードとしてブラウザに返される ようになっています。例えば:

   $uploaded_file = param('upload');
   if (!$uploaded_file && cgi_error()) {
      print header(-status=>cgi_error());
      exit 0;
   }

しかしながら、すべてのブラウザが現在のところ、このステータスで 何をすべきか分かっているかははっきりしません。問題のユーザに 警告するHTMLページを作るだけの方がよいかもしれません。

CGI-LIB.PLとの互換性

cgi-lib.plを使っている既にあるプログラムの移植を簡単にするため、 互換性ルーチン"ReadParse"が提供されています。移植は簡単です:

旧バージョン require "cgi-lib.pl"; &ReadParse; print "The value of the antique is $in{antique}.\n";

新バージョン use CGI; CGI::ReadParse print "The value of the antique is $in{antique}.\n";

CGI.pmのReadParse()ルーチンは%inという名前のtieされた変数を作成します。 それは問い合わせ変数を取得するためにアクセスされます。 ReadParseのように独自の変数を提供することも出来ます。 @inと$in変数の作成のように、ReadParseのあまり頻繁には使われない 機能はサポートされていません。

一度ReadParseを使えば、以下のように問い合わせオブジェクトそれ自身を 取り出すことが出来ます:

    $q = $in{CGI};
    print $q->textfield(-name=>'wow',
            -value=>'does this really work?');

これにより、古いスクリプトを頭から書きなおすことなく、CGI.pmの より興味深い機能を使い始めることが出来ます。

作者情報(AUTHOR INFORMATION)

Copyright 1995-1998, Lincoln D. Stein. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

バグレポートとコメントはこちらへ:[email protected]。バグレポートを送る ときにはCGI.pmのバージョン、Perlのバージョン、Webサーバの名前と バージョン、そして使用しているオペレーティング・システムの名前と バージョンを教えてください。もし問題が離れた場所にあるブラウザにさえも 依存していれば、影響されるブラウザについての情報を教えてください。

謝辞

以下の方々に感謝します:

Matt Heffron ([email protected])
James Taylor ([email protected])
Scott Anguish <[email protected]>
Mike Jewell ([email protected])
Timothy Shimmin ([email protected])
Joergen Haegg ([email protected])
Laurent Delfosse ([email protected])
Richard Resnick ([email protected])
Craig Bishop ([email protected])
Tony Curtis ([email protected])
Tim Bunce ([email protected])
Tom Christiansen ([email protected])
Andreas Koenig ([email protected])
Tim MacKenzie ([email protected])
Kevin B. Hendricks ([email protected])
Stephen Dahmen ([email protected])
Ed Jordan ([email protected])
David Alan Pisoni ([email protected])
Doug MacEachern ([email protected])
Robin Houston ([email protected])
...そしてさらに多くの本当に多くの人たちに...

提案とバグ・フィックスに対して。

単純なフォーム・ベースのスクリプトの完全な例

    #!/usr/local/bin/perl

    use CGI;

    $query = new CGI;

    print $query->header;
    print $query->start_html("Example CGI.pm Form");
    print "<h1> Example CGI.pm Form</h1>\n";
    &print_prompt($query);
    &do_work($query);
    &print_tail;
    print $query->end_html;

    sub print_prompt {
       my($query) = @_;

       print $query->start_form;
       print "<em>What's your name?</em><br>";
       print $query->textfield('name');
       print $query->checkbox('Not my real name');

       print "<p><em>Where can you find English Sparrows?</em><br>";
       print $query->checkbox_group(
                 -name=>'Sparrow locations',
                 -values=>[England,France,Spain,Asia,Hoboken],
                 -linebreak=>'yes',
                 -defaults=>[England,Asia]);

       print "<p><em>How far can they fly?</em><br>",
        $query->radio_group(
            -name=>'how far',
            -values=>['10 ft','1 mile','10 miles','real far'],
            -default=>'1 mile');

       print "<p><em>What's your favorite color?</em>  ";
       print $query->popup_menu(-name=>'Color',
                    -values=>['black','brown','red','yellow'],
                    -default=>'red');

       print $query->hidden('Reference','Monty Python and the Holy Grail');

       print "<p><em>What have you got there?</em><br>";
       print $query->scrolling_list(
             -name=>'possessions',
             -values=>['A Coconut','A Grail','An Icon',
                   'A Sword','A Ticket'],
             -size=>5,
             -multiple=>'true');

       print "<p><em>Any parting comments?</em><br>";
       print $query->textarea(-name=>'Comments',
                  -rows=>10,
                  -columns=>50);

       print "<p>",$query->reset;
       print $query->submit('Action','Shout');
       print $query->submit('Action','Scream');
       print $query->endform;
       print "<hr>\n";
    }

    sub do_work {
       my($query) = @_;
       my(@values,$key);

       print "<h2>Here are the current settings in this form</h2>";

       foreach $key ($query->param) {
          print "<strong>$key</strong> -> ";
          @values = $query->param($key);
          print join(", ",@values),"<br>\n";
      }
    }

    sub print_tail {
       print <<END;
    <hr>
    <address>Lincoln D. Stein</address><br>
    <a href="/">Home Page</a>
    END
    }

バグ

どうか報告してください。

参考資料

CGI::Carp, CGI::Fast, CGI::Pretty

翻訳者

川合孝典([email protected])

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 1106:

Expected text after =item, not a number

Around line 1110:

Expected text after =item, not a number

Around line 1114:

Expected text after =item, not a number

Around line 1572:

Expected text after =item, not a number

Around line 1576:

Expected text after =item, not a number

Around line 1580:

Expected text after =item, not a number

Around line 1584:

Expected text after =item, not a number

Around line 1676:

Expected text after =item, not a number

Around line 1680:

Expected text after =item, not a number

Around line 1691:

Expected text after =item, not a number

Around line 1696:

Expected text after =item, not a number

Around line 1963:

Expected text after =item, not a number

Around line 1969:

Expected text after =item, not a number

Around line 1977:

Expected text after =item, not a number

Around line 1981:

Expected text after =item, not a number

Around line 1986:

Expected text after =item, not a number

Around line 1992:

Expected text after =item, not a number

Around line 2040:

Expected text after =item, not a number

Around line 2048:

Expected text after =item, not a number

Around line 2055:

Expected text after =item, not a number

Around line 2061:

Expected text after =item, not a number

Around line 2067:

Expected text after =item, not a number

Around line 2076:

Expected text after =item, not a number

Around line 2128:

Expected text after =item, not a number

Around line 2134:

Expected text after =item, not a number

Around line 2140:

Expected text after =item, not a number

Around line 2145:

Expected text after =item, not a number

Around line 2190:

Expected text after =item, not a number

Around line 2194:

Expected text after =item, not a number

Around line 2201:

Expected text after =item, not a number

Around line 2208:

Expected text after =item, not a number

Around line 2213:

Expected text after =item, not a number

Around line 2219:

Expected text after =item, not a number

Around line 2228:

Expected text after =item, not a number

Around line 2276:

Expected text after =item, not a number

Around line 2283:

Expected text after =item, not a number

Around line 2330:

Expected text after =item, not a number

Around line 2334:

Expected text after =item, not a number

Around line 2374:

Expected text after =item, not a number

Around line 2378:

Expected text after =item, not a number

Around line 2382:

Expected text after =item, not a number