プログラムを覚える上で一番大切なのは、プログラムは難解だという先入観を捨てることかもしれません。もともと人間が理解しやすいように考えられたコンピュータ言語なので、コツをつかめば簡単です。とにかく、たくさんのプログラムを書いてみるのが重要です。
1.CGI プログラムの実行
プログラマの心構え
CGI プログラマがプログラムを作成するときは、だいたい次のことを考慮しておく必要があります。
- 多くのプラットフォームで動作すること
- 後から修正、追加が簡単にできること
- サーバに余分な負荷をかけないこと
- サーバダウン、ユーザに迷惑をかけるようなバグを防ぐこと!!
一番簡単なCGIプログラム
CGI プログラム実行までの手順は次のとおりです。
CGI プログラムを実行させる手順
- サーバ情報を調べる
- 必要なソフトウエアを揃える
- perlのディレクトリパスを調べる
- CGI プログラムを作成する
- .htaccessを設定する
- CGIスクリプトを転送する
- CGIのパーミッションを変更する
- CGIを呼び出す
1.サーバ情報を調べる
CGIプログラムを動かすためには、最低限知っておかなければならない情報があります。ほとんどがサーバ管理者に聞かなければわからない情報ですので、下記のことをあらかじめ聞いておくか、マニュアルが用意されていればよく読んでおきましょう。
- プログラムファイル用のディレクトリ・URL情報
CGI ファイルを作成したら、FTPでサーバにアップします。ですから、CGI
ファイルのアップロード用ディレクトリを知っておく必要があります。また、CGI
用ディレクトリパスのURLも重要です。このURLがわからないと、ブラウザからアクセスできません。【例】
CGI 用ディレクトリパス: /home/httpd/cgi-bin
CGI 用ディレクトリパスのURL: http://www.rfs.jp/cgi-bin
- 「.htaccess」ファイルが必要かどうか
CGI を正常に動かすには、「.htaccess」ファイルが必要となる場合があります。
- Perlのディレクトリパス情報
CGI プログラムは、その1行目に Perlのディレクトリを記入しなければなりません。【例】
/usr/local/bin/perl
/usr/bin/perl
Perlのディレクトリパスを調べる
perlのディレクトリパスはコマンドラインから調べることができます。
> which perl
2.必要なソフトウエアを揃える
最低限必要なのは、プログラム製作用にテキストエディタ、ファイルのアップロード用にFTPクライアントです。そのほか、プログラムのデバッグ用にTELNETクライアントも用意しておくとよいでしょう。
- テキストエディタ
秀丸エディタ(4000円) - FTPクライアント
FFFTP
1.79a - TELNETクライアント
Tera
Term Pro
フリーソフトは次のサイトから手に入れることができます。
- テキストエディタ
- テキストファイルを編集するためのアプリケーション
- FTPクライアント
- FTPクライアント(File Transfer Protol Client):ファイルを他のマシンに転送するためのアプリケーション
3.CGI プログラムを作成する
一番簡単なCGIプログラムを作成しましょう。テキストエディタで次のようなテキストファイルを作成し、「04_01.cgi」というファイル名で保存してください。
HTMLを出力する単純なプログラム
#!/usr/local/bin/perl # レスポンスヘッダの出力 print "Content-type: text/html", "\n\n"; # HTMLの出力 print "<HTML>\n"; print "<BODY>\n"; print "ようこそCGIの世界へ!<BR>\n"; print "</BODY>\n"; print "</HTML>\n";
Perlインタプリタのディレクトリパス指定
プログラムの最初の行には #! の後ろにPerlがインストールされている場所を指定します。#! の前に空行やスペースを入れてはいけません。Perlのインストール場所は、「Perlのディレクトリパスを調べる」で調べてから、お使いの環境に合わせて書き換えてください。
#!/usr/local/bin/perl -w
-wスイッチを使うと、エラーほどではないにしても、プログラミング作法としてあまり好ましくないと判断された箇所の警告を出してくれるようになる。これは省略することもで
きますが、特別な理由がない限り-w スイッチを使うことをお勧めします。
コメント
コメントは、プログラムの実行に影響を与えずに埋め込むことができる説明文です。
# この行はコメントです print "Hello World."; #ここからコメントです
シャープ( # )以降から改行までの文字列がコメントになります。
ヘッダとHTMLの出力
Perl でメッセージをブラウザに表示するには、print 関数を使います。
print "文字列", "\n";
print 関数はダブルコーテーション( " )で囲んだ文字列を出力します。カンマ( , )で複数の文字列を分けることができます。
ブラウザに表示させる内容を出力させる前に、HTTP ヘッダ情報を出力します。このヘッダはこれから送ろうとするデータ形式をクライアントのブラウザに伝えるもので、これでブラウザはPerlの出力が HTML 形式であることを理解します。
print "Content-type: text/html", "\n\n";
"\n"は、改行を出力します。ヘッダ情報の後に"\n\n"と改行を2回続けて空行を出力していますが、これは
HTTPヘッダ情報ブロックがここで終わりであることを示しています。空行がないと、どこまでもヘッダ情報として認識されてしまい、ブラウザにはエラーメッセージが表示されることになります。
ところで、"\n"はドキュメントの改行であって、ブラウザ上での改行ではありません。ブラウザ上で改行させたい場合は<BR>タグを使います。
print "文字列<BR>", "\n";
4..htaccessを設定する
ウェブサーバの設定で、CGIを動作させるために CGI プログラムと同じディレクトリに .htaccess ファイルを用意しなくてはならない場合があります。このファイルが必要かどうかわからない場合は、サーバ管理者に問い合わせましょう。
AddType application/x-httpd-cgi .cgi
「.htaccess」の最後の行の後ろで改行しておくのを忘れてはなりません。この改行を忘れると、「.htaccess」ファイルが正常に機能しません。
5.CGIスクリプトを転送する
CGI プログラムを、FTPクライアントでサーバーに転送します。
6.パーミッションを変更する
サーバーがUNIXの場合は、CGI プログラムに実行権をつける必要があるので、パーミッションを755(rwxr-xr-x) に変更します。通常、パーミッションの変更はFTPかTELNETで行います。
TELNETでパーミッション変更
> chmod 755 *.cgi
FTPソフトの「FFFTP」でパーミッション変更
- アップロードしたファイルを右クリックし、ポップアップメニューから[属性変更(A)]をクリック
- 属性を755にして[OK]ボタンを押す
主なパーミッションは以下のとおりです。
パーミッション | 意味 | 解説 |
---|---|---|
644 | 読み出し専用 | 普通のHTMLファイルはパーミッションが644になっています。 |
755 | 実行 | CGI ファイルは実行ファイルですので、パーミッションを実行権のある755にします。 |
666 | 書き込み用 | CGIファイルから書き込みを行うためのファイルのパーミッションです。例えば、掲示板の投稿記事を保存するテキストファイルや、カウンターの数字を記録するファイルなどです。 |
777 | 書き込み用ディレクトリ |
CGIファイルからファイルの作成を行う場合、作成元のディレクトリのパーミッション設定は 777 にしておく必要があります。 |
7.CGIを呼び出す
サーバーに転送したCGI プログラムを、例えば次のようなURLを指定してブラウザから呼び出してください。
http://****.jp/cgi-bin/lesson/01/04_01.cgi
ブラウザからファイルを呼び出すと、次のように表示されます。
ようこそCGIの世界へ!
プログラマーの仕事の大半はプログラムを組むことに費やされ、とにかく一心不乱にパソコンのキーを叩きまくる。パソコンの操作で四苦八苦している人からすると、なんとなく敷居が高い印象を受けるかもしれないけど、作業自体はメールを打っているのとさほど変わらないんだ。むしろ、尊敬語や丁寧語のないプログラミングのほうが簡単だとも言えるんじゃないかな。だって、パソコンが理解できる言語を使って、決まった規則で文章を書いていくだけのことなんだからね。
2.CGI プログラムでダイナミックページを出力する!
******
3.クエリを受け取るいろんな方法
HTMLから CGI プログラムを呼び出す一番簡単な方法はリンクを使うこと。
クエリ文字列
POSTデータ
フォームデータを CGI プログラムへ送る1つの方法として、クエスチョン( ? )の後でフォーム情報をURLに追加する方法があります。そのクエスチョン( ? )より後の文字列データはQUERY_STRING という環境変数に入ります。URL は下記のようになります。
http://www.domain.com/cgi-bin/script.cgi?query=1
ここで注目なのはプログラム名の後にあるクエスチョン( ? )です。クエスチョン( ? )の後の情報がクエリ文字列になり、環境変数 QUERY_STRING
から参照できます。
HTMLのリンクから CGI にデータを渡すには次のようにします。
<a href="/cgi-bin/query.cgi?post_data=1">...</a>
クライアントから送られてきたクエリを出力する
#!/usr/bin/perl print "Content-Type:text/html", "\n\n"; print "query_string: ", $ENV{'QUERY_STRING'}, "\n";
エキストラパス情報
CGIプログラムの名前に続いて追加の情報を記し、CGIプログラムに追加のデータを渡すことができます。この情報は『エキストラパス情報』と呼ばれています。エキストラパス情報は環境変数PATH_INFO から参照することができます。
<A HREF="/cgi-bin/query.cgi/extra-path-info">...</A>
具体的には、CGIプログラム名の直後からhref文字列の中で最初にあらわれるクエスチョン( ? )
マークの直前までの間の文字列となります。
実行
ここまでの説明の例題として、以下のようなCGIプログラムへのリンクを作ったとしましょう。
<a href="script.cgi/extra-path-info?post_data=1">...</a>
このCGIプログラムのリンクがクリックされると、「script.cgi」という名前のCGIプログラムが起動されます。そして、環境変数
PATH_INFO は「extra-path-info」に、環境変数 QUERY_STRING
は「post_data=1」に設定されます。
4.フォームのデータの受信
ホームページでアンケート集計や、メールを受け取るときななどに使われるのがフォームです。フォームには、テキストボックスやドロップダウンメニューなど多くの種類が用意されていて、ユーザからの入力や選択を受けつけることができるようになっています。CGIプログラムはフォームのデータを丸ごと受け取ることができます。
そこで、フォームの作り方から、そのデータの受け取り方までを試してみましょう。
フォームの記述・利用法は超初心者もOKのHTML講座を参照
下記のフィールドの例で、各フィールドの特徴と動作を確認してください。
テキストボックス
1行分の入力データが必要な場合に使用します。
書式
メールアドレス :<input size="28"
name="email"
value="user@rfs.jp">
表示結果
メールアドレス :
テキストエリア
複数行にわたるテキストが必要な場合に使用します。このフィールドは、テキストの量に応じてスクロールします。
書式
コメント :<br>
<textarea name="comment"
cols="40"
rows="4">この仕事のためにシアトルから離れることを恋人のレイニーはあまり喜ばなかったわ。ま、それはともかく、ウールズて男に付きまとわれて、ちょっとうっとうしい気分。男はトラブルのタネ、深入りは絶対禁止ね。キスキスキス、ラブ・ローリン。
</textarea>
表示結果
コメント :
チェックボックス
オン・オフを選択させたい場合に使用します。
書式
<input type="checkbox"
name="mailling_list" value="ON"
checked>メールによる最新情報を受ける
表示結果
メールによる最新情報を受ける
ラジオボタン
複数の選択肢から項目を1つだけ選択させたい場合は、ラジオボタンを使用します。
書式
<input type="radio"
name="sex" value="men">男性
<input type="radio"
name="sex" value="women"
checked>女性
表示結果
男性
女性
ドロップダウンメニュー
選択肢の一覧を表示する場合は、ドロップダウンメニューを使用します。一度に選択できる項目の数は、1つまたは複数に設定できます。
書式
住所 :
<select name="address"
size="1">
<option value="1">都道府県を選択してください
<option value="2">北海道
...
<option value="48">沖縄県</option>
</select>
表示結果
住所 :
プッシュボタン
フォームのデータを送信させるために使用します。そのほか、フィールド内に入力されたり選択された情報を消去することもできます。
プッシュボタンの種類は「button」、「submit」、「reset」の3種類です。
- button
通常のボタンを表示 - submit
フォームデータを送信するためのボタン - reset
フォームに入力された内容をリセットするためのボタン
書式
<input type="button"
value="ボタン">
<input type="submit"
value="送信">
<input type="reset"
value="リセット">
表示結果
インプット画像
プッシュボタンのSUBMITオプションと同じ効果があります。
書式
<input type="image"
src="button_ok.gif"
border="0">
表示結果
隠しインプット
このタイプはブラウザに表示されませんが、データとしてはGETやPOSTによって送られます。
書式
<input type="hidden"
name="post_data"
value="1">
フォームを使ったプログラムの作成
<FORM> タグで指定しているフォームの属性は METHOD と ACTION
です。METHOD 属性には CGI と交信する手段、ACTION
属性には呼び出すプログラム名を指定できます。上記の FORM タグを訳すと、「POSTという方法でquery.cgiプログラムと交信する」といった意味になります。
INPUTタグはTYPE
属性でフォームの部品を指定することができます。たとえば、次の例ではテキストフィールド2つとサブミットボタンを表示させています。
<FORM METHOD=GET
ACTION="/cgi-bin/query.cgi">
名前:<INPUT
TYPE="text"
NAME="NAME"
SIZE=10>
E-Mail:<INPUT
TYPE="text"
NAME="MAIL"
SIZE=10>
<INPUT TYPE="submit"
VALUE="送信">
</FORM>
上記のHTMLタグが読み込まれると、下記のようにブラウザに表示されます。
表示結果
名前:
E-Mail:
テキストボックスやプルダウンなどのフォームフィールドを記述するタグには NAME
属性があります。NAME 属性には個々のフォームフィールドを区別するためのフィールド名を指定することができます。
<INPUT TYPE="text"
NAME="MAIL">
NAME 属性に「MAIL」というフィールド名を指定しています。
[送信]ボタンを押すと、テキストフィールドに入力されたデータがPOSTを使ってプログラムに渡されます。プログラムに渡されるデータは「<フィールド名>=<値>」という文字列になります。
たとえば、フィールド名が「MAIL」のテキストボックスに「user@rfs.jp」と入力された場合は、「MAIL=user@rfs.jp」という文字列が送信されます。
入力フィールドが複数あるときは「<CGI
プログラム名>?<フィールド名>=<値>&<フィールド名>=<値>...」と、それぞれのフィールドがアンパサンド(
& )で連結されます。
GETメソッド/POSTメソッドからデータの受け取り
フォームデータを送る手法としては、GET と POSTという2つのメソッドがあります。両メソッドは「HTTPヘッダ」の章で詳しく説明していますが、その使い方を軽くおさらいしておきましょう。
GET
GETの一般的な使い方は、URLにクエリを追加します。
<a href="/cgi-bin/query.cgi?post_data=1">...</a>
クエスチョン( ? )以降の「post_data=1」がクエリデータとして環境変数
QUERY_STRINGに格納されます。ただし、渡されるデータがリミットを越えると、超えた分の値が切り捨てられます。
環境変数QUERY_STRINGを使用すれば、このクエリ情報にアクセスすることができます。環境変数を参照するには、下記のように%ENV変数を使って呼び出します。
# 環境変数 QUERY_STRING の値を $query_string に代入 $query_string = $ENV{'QUERY_STRING'};
POST
POSTはHTTPヘッダのボディ部でデータを送信します。パラメータは標準入力で渡されます。データの長さ(バイト数)は環境変数
CONTENT_LENGTH に格納されています。
POSTの主な特徴は、クエリのサイズに制限がないことです。したがって、クライアントやサーバがデータを切り捨ててしまうことはありません。POSTによって送られたデータは、標準出力から取得することができます。
GETとPOSTで処理を振り分ける
フォームのMETHOD属性をPOSTに指定する場合は以下のとおりです。
<form method="POST"
action="/cgi-bin/query.cgi">
....
</form>
METHOD属性をGETに指定するときは、たとえば上記の場合でしたら、METHOD属性をGETに変更するだけです。
GET、もしくはPOSTで送られたデータを読み込むための汎用的なプログラムを作ってみましょう。
GET/POSTデータを読み込む
#!/usr/local/bin/perl # GETメソッドの場合 if( $ENV{'REQUEST_METHOD'} eq "GET" ) { $buffer = $ENV{'QUERY_STRING'}; # POSTメソッドの場合 } else { read( STDIN, $buffer, $ENV{'CONTENT_LENGTH'} ); } print "Content-Type: text/html\n\n\n"; print "<b>Method</b> ", $ENV{'REQUEST_METHOD'},"<br>\n"; print "<b>Data</b> ", $buffer, "\n";
GETの場合は単純に環境変数QUERY_STRINGの内容を取り出すだけです。POSTの場合はreadを使って標準入力からデータを読み込みます。
実行テスト
GET
POST
フォームのデータをデコードする
クライアントが GET と POST のどちらのメソッドで送られたかは、環境変数 REQUEST_METHOD を使います。この値がGETリクエストを示していると、クエリ文字列または エキストラパス情報
から環境変数から入手しなければなりません。一方、これがPOSTリクエストなら、環境変数CONTENT_LENGTHによって指定されたバイト数を標準入力から読み込む必要があります。
フォームデータをデコード
- REQUEST_METHOD をチェックしてリクエストプロトコル(GET or POST)を判断する。
- GETであれば、QUERY_STRING からクエリを読み込む。
(PATH_INFOからエキストラパス情報を読み込む方法もある) - POSTであれば、CONTENT_LENGTH
を使用してリクエストのサイズを調べ、標準入力からクエリを読み込む。 - クエリをアンパサンド( & )で分割。
- イコール( = )で連結されたキーと値を分割(kye=value)
- プラス( + )をスペースに変換。
- 16進数にエンコードされた文字列をデコード
エンコードされたデータをデコードする
#!/usr/local/bin/perl # 1.REQUEST_METHODをチェックしてリクエストプロトコル(GET or POST)を判断する if( $ENV{'REQUEST_METHOD'} eq "GET" ) { # 2.GETであれば、QUERY_STRINGからクエリを読み込む $buffer = $ENV{'QUERY_STRING'}; } else { # 3.POSTであれば、CONTENT_LENGTHを使用してリクエストのサイズを調べ、 # 標準入力からクエリを読み込む read( STDIN, $buffer, $ENV{'CONTENT_LENGTH'} ); } print "Content-Type: text/html", "\n\n"; print "<b>Data</b> ", $buffer, "<br>\n"; print "<b>Split Data</b><br> ", "\n"; # 4.クエリをアンパサンド( & )で分割 my @pairs = split(/&/,$buffer); foreach $pair (@pairs){ # 5.イコール( = )で連結されたキーと値を分割(kye=value) my($name, $value) = split(/=/, $pair); # 6.プラス( + )をスペース( )に変換 $value =~ tr/+/ /; # 7.16進数にエンコードされた文字列をデコード $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; print "$name : $value<br>"; }
このコードを実行すると QUERY_STRING の内容をフィールドごとに分割し、空白や記号、漢字といった文字列を戻した状態にしてから出力します。
注意したいのは、POST や GET で送られてくるデータは『エンコード』されているということです。エンコードされたデータは、英数字はそのままですが、空白はプラス( + )に、特殊記号や漢字などはパーセント( % )を先頭に付けた『16進数』に変換してから格納します。
用語
- 基数
- 数値を表現する際に、各桁の重み付けの基本となる数を基数といいます。社会一般で使用されている10進数は、10倍ごとに桁が上がるので基数は10です。
- 16進数
- 16進数は基数が16の数値です。16進数は、「0」から「9」までの10種類の数字に加え、「A」から「F」までの6種類の文字を数字とします。「A」が10進数で言う「10」に、Bが11にというように対応します。
次の例は、上記のようにデコードしたあとにドキュメントを表示するものです。テキストボックスに値を入力してボタンを押してみてください。