通販:注文書(CGI)

前のページ

CGI用フォームの解説

前項で完成したフォームの仕組みを改めて確認しておきましょう。
CGIファイル(プログラム)にデータを送るには、URLの後ろにデータを付けて送る方法と、URLとは別にデータを送信する方法があります。

実例:p8.html(注文フォーム)

CGIにデータを送る方法(検索文字列)

URLにデータを付けるとは、URLの後ろに「?」を使って検索文字列というテキストを送る方法です。
例えば、order.cgiにデータを送るとして以下のようなURLをリンクから呼び出します。

http://www.shurey.com/data/order.cgi?mode=1&set=5&get=10

ファイル名の後にそのファイルに送信する検索文字列が付いています。
この方法では、常にURLに送信するデータが見えるため、CGIの動作を分析することが容易にできてしまいます。また、URLをブックマークしたり、リンクとして用意するだけで同じデータを送ることができます。
このデータがCGIを動かす命令にもなるため、不正な命令を送信されるという問題が発生しやすくなります。単純にデータを表示する程度であれば問題は少ないと思われますが、自由に検索結果を操作したり、データを削除されてしまったら大変なことになります。

この方法は次のフォームからデータを送る場合にも使うことができます。

CGIにデータを送る方法(フォーム)

次はフォームからデータを送る方法を見てみましょう。
p8.htmlのフォームを下記に抜粋します。

	<form name="order" action="order.cgi" method="post" onSubmit="return check_order2()">
<input type="hidden" name="mode" value="add"> <textarea name="order_text" cols="90" rows="10" readonly id="order_text"></textarea>
<input name="name" type="text" id="name" size="50" onChange="check_order2()"> <input name="add1" type="text" id="add1" size="50" onChange="check_order2()">
<input name="add2" type="text" id="add2" size="50">
<input name="tel" type="text" id="tel" size="50" onChange="check_order2()">
<input name="mail" type="text" id="mail" size="50" onChange="check_order2()">
<input name="sonota" type="text" id="sonota" size="50">
<input type="submit" value="送信" id="b_submit" disabled>
</form>

まず、<form>タグにaction属性「order.cgi」が指定されています。これがフォームの送信先のファイル(URL)を示しています。

次にmethod属性に「post」が指示されています。ここに「get」を指示すると、URLに検索文字列を使ってデータを送信します。前項と同じことが起こります。
ここでは「post」を使っているので、URLにはデータを表示せず、見えないようにデータを送信してくれます。また、この方法では、テキストだけでなく画像などのバイナリファイルも送信することができます。

<input>タグや<textarea>タグなどフォームの構成要素となるタグには、必ずname属性が必要です。それが付いていないタグがあると、そのデータは送信されません。また、送信ボタンについても、name属性があるとデータとしてvalueの内容が送信されます。
上記のフォーム内では、9個のname属性がありますが、<form>タグ内には送信するデータがないので、<input>タグと<textarea>タグから8つのデータが送信されます。

送信されるデータはname属性とvalue属性が自動的に一組となります。タグ内にvalue属性がない場合、その項目にデータを入力するとそれがvalue属性の値となります。もちろん、value属性はフォームの初期値なので、項目を書き換えた時点で上書きされます。
一組のデータは「name属性の値=value属性の値」という形で送信されます。複数のデータは「&」でくくられます。例えば「name=山田&add1=滋賀県&add2=&tel=077」のようになります。

命令の送信

先ほどのフォームの中に1つだけデータではなく命令文があります。
<input>タグの一つ目、type属性がhidden(隠す)になっているところです。このタグはフォーム内には表示されません。value属性にはaddとあります。この部分から「mode=add」というデータが送られることになります。
CGI側では、これを受け取ると「mode」を探して命令を受け取ります。「add」が命令ということになります。今回はデータを追加しなさいという命令になっており、これに続くデータの組を追加データとしてログに保存することになります。
このような命令はCGI側で作ります。どんなキーワードを受け取ったら、どのような処理をするか、それはCGIを作った人が全て決めることができます。
フォームとCGIは常に連動していますので、フォームの項目を変更した場合、CGI側も受け取るデータをどう処理するから作り直さなければなりません。

CGIファイルの解説

実際に利用しているCGIファイルの仕組みを見ていきましょう。
実例のorder.cgiへのリンクは、実際に稼働してるCGIによる画面が表示されます。ソースファイルを見る場合は、order.txtをダウンロードしてテキストエディタを使います。
通常、CGIファイルはサーバに置いて使いますので、編集時は拡張子をtxtにしておき、サーバに転送後、拡張子をcgiに変更する必要があります。CGIファイルを直接編集できるエディタもあります。

実例:order.cgi(注文の管理プログラム) order.txt(ソースファイル)

プログラムへのパス設定

CGIファイルでは、最初の1行目にそのファイルをどのプログラムで使用するかを指定します。
ソースファイルの1行目を見てみましょう。

#!/usr/local/bin/perl

このCGIファイルはPerlという言語の書式か書かれてます。
「#」はPerlではコメントアウトを表してます。
そして、「#!」の後に、このCGIファイルを読み込んで処理するプログラムのパスが書かれています。
ここでは、フォルダ名の後に、perlというプログラム名が記述されています。
このような記述はサーバによって違いがありますので、サーバ管理者指定のパスを記述します。

CGIの基本設定

CGIファイルをテキストエディタで開いて、サーバや使用環境に合わせた変更を行います。
order.cgiはPerlという言語で書かれているため、サーバにPerlのプログラムが必要になっています。Perlの使えないサーバや、Perl以外のCGI環境もあります。

それでは、order.cgiの基本設定を見てみましょう。関連するファイルに関する設定です。

##### 基本設定 #####

#ページタイトル
$title = "受注処理";

#カウントファイル
$count_file = "count.txt";

#ログファイル
$log_file = "order.csv";

#フォーム
$back_form = "p8.html";
ページタイトル HTMLファイルを出力したときのタイトルになります。<title>タグの文字列として利用されます。
カウントファイル 受信した回数を記録するテキストファイルの名前です。
ログファイル 受信したデータそのものを記録するテキストファイルの名前です。
フォーム CGIからフォームのページに戻るときのファイル名です。<a>タグでリンクして使います。

「$taitle」のように頭に「$」とあるのが変数です。配列変数の場合「@」で表します。

CGIのユーザー設定

次は利用者がページの利用形態に合わせて調節するシステム内の設定です。

##### ユーザー設定 #####

#管理人パスワード(管理画面の呼出に必要)
$kanri_pass = "0000";

#ログの最大行数(0:無制限)
$max = 1000;

#ログファイルの表示順(0:古い順/1:最新順/2:ランダム)
$log_sort = 1;

#多重登録の禁止(0:許可/1:禁止)
$taju = 0;

#入力項目の名称(省略可。入力フォームに合わせて記入)
@form_name = ("注文内容","お名前","ご住所(1)","ご住所(2)","電話番号","メール","連絡事項");
#備考欄を自動的に追加
$form_name[@form_name] = "備考";
#あわせて「データの変換処理」で一覧表示用のテーブルを作成してください。
管理人パスワード CGIの管理者が書き込みされたデータを見るときに利用します。個人情報を預かるため、パスワードがないと記録内容を見ることはできません。
ログの最大行数 注文の記録件数。最大数を超えるとデータは自動的に削除されます。無制限にすることも可能です。
ログファイルの表示順 ログファイルをどのような順番に表示するか選択できます。
多重登録の禁止 フォームを送信したときに、日付とIPアドレスを調べて、同じであれば同一人物からの送信として書き込みを禁止します。これは悪戯を防止する役割もあります。
入力項目の名称 受け取ったデータのラベル名を用意します。これによって、データを表示するときのデータの名前とします。
備考欄を自動的に追加 受信したデータの最後に項目を1つ付け足して、備考というラベル名の項目にします。

フォームから送信されるデータの数に合わせて「@form_name」を作ります。このとき、表示用のテーブルも変更が必要です。

システム設定

画面の表示に使う設定で、特に変更が必要ない部分です。

##### システム設定 #####
#テーブルフォーム
$table_color = "#FFFFFF";
$header_color = "#FF9999";
$light_color = "#FFFF99";
$dark_color = "#999999";
テーブルフォーム 管理者用のテーブルを表示する際の色設定です。

これ以降はプログラムの処理になります。

一覧表示用のテーブル

order.cgiのログイン画面からパスワードを入力すると、一覧表示の画面に入ります。
ブラウザで見てる画面はHTMLで作られています。CGIファイルは、サーバで処理した後、HTMLファイルをブラウザに送っているのです。
では、どのように処理が行われているのか少し見てみましょう。同時に、どの部分が手を加えられるのかも確認します。

Perlでは、JavaScriptのユーザー関数のように、プログラムを1つのセットにまとめた部分をサブルーチンと呼びます。
「一覧表示画面」の見出しのある「view_list」というサブルーチンを見てみましょう。

### 一覧表示画面 ###
sub view_list ($kanri,$kanri_text,$ON,$OFF) {

サブルーチンは「sub」で始まっています。ルーチン名の後にあるのはローカル変数です。

そこから少し下に行くと、<form>タグや<table>タグが見つかります。ここで画面に出力するHTMLが作られています。
その出力の手前には、「print」という命令があり、これがブラウザへ出力を返す指示をしています。

テーブルについては、HTMLで記述されているため、変更も用意です。
Perlの変数をそのまま記述するとprintされたときには変数内の文字列や数値に置き換えられてから、HTMLとして出力されることになります。

<table bgcolor="$table_color">
<tr bgcolor="$header_color"><th>注文番号</th><th>日付</th><th>時刻</th><th>お名前</th><th>メール</th><th>ステータス</th><th>修正</th></tr>

上記は、テーブル内には、「$table_color」と「$header_color」という2つの変数が使われてます。どちらもシステム設定で準備された色番号が入ります。

テーブルの一行目には7列の項目が<th>タグで記述されています。これが一覧表の見出し行となります。

この後のテーブルはログファイルの1行(1レコード)ごとに繰り返し出力されます。ログファイルの1行とは、発注データ1件分ということです。

ログファイルの書き出しの前に、データの変換処理の部分を見てみましょう。メールアドレスをリンク付きのデータに変更しています。

		#データの変換処理

		#以下の部分はデータの内容に合わせて表示内容を変える処理です。
		#(データの順番や内容に合わせて修正が必要)
		if ($_[5] ne "") {$_[5] = "<a href='mailto:$_[5]'>$_[5]</a>";}

ここで「$_[5]」という特殊な変数を使っています。これはログから取りだしたデータのうち、受信したときの順番を表しています。配列変数と同じ扱いなので、「5」は6番目の要素を表しています。
6番目に送信されたデータはメールアドレスです。if文でアドレスがある場合、HTML表示用にリンクを付けています。
フォームの項目を変更したときに、メールアドレスの順番に変更があれば、ここも変更が必要です。

次に、1件分のデータをHTMLとして出力する部分です。

	#表示許可・未許可によって表示を切り替え
	if ($status eq "ON") {
		#表示許可の場合のテーブル
		print <<E_O_F;
<tr bgcolor="$light_color"><td align=right>$count</td><td>$date</td><td>$time</td><td>$_[1]</td><td>$_[5]</td><th>$stat</th><th><a href="$SN?edit=$kanri_pass&count=$count">修正</a></th></tr>
<tr><td colspan="3">$_[0]</td><td colspan="4">$_[2]<br>$_[3]<br>$_[4]<br>$_[6]</td></tr>
<tr><td>備考:$_[7]</td></tr>
E_O_F
	} else {
		#表示未許可の場合のテーブル
 		print <<E_O_F;
<tr bgcolor="$dark_color"><td align=right>$count</td><td>$date</td><td>$time</td><td>$_[1]</td><td>非表示</td><th>$stat</th><th><a href="$SN?edit=$kanri_pass&count=$count">修正</a></th></tr>
E_O_F
 	}

if文によって分岐があります。
ステータスが「表示」か「非表示」かによって、データの表示方法を切り換えています。処理が終わったデータは非表示にしたり、削除することができます。

「print <<E_O_F;」から「E_O_F」の間にHTMLを書きます。「E_O_F」は任意に指定する終わりの位置を示すキーワードです。このキーワードは必ず行の先頭に各必要があるため、HTMLとともに、タブで行揃えをせずに表記しています。

この中で注目するのはやはり「$_」で始まる変数です。これらはデータの順番と一致しているので、「$_[0]」が注文内容、「$_[1]」が名前となっています。
一覧画面では全てのデータを表示する必要はありません。別途修正画面があるので、そちらには全データが表示されます。

修正画面について

修正画面では、テーブルのレイアウトを自動的に作っています。
ここで、@form_nameで指定したラベル名が使われます。

データのステータスを表示、非表示、削除の変更ができます。
非表示にすると一覧画面では省略表示されます。
削除にするとログからデータを消してしまいますので、注意が必要です。

一覧画面や修正画面には管理画面からしか入ることはできません。

管理画面について

CGIファイルをそのままのURLで呼び出すと管理画面の入口が現れます。
そこでパスワードを入力すると管理画面に入ります。

管理画面の中には一覧画面と修正画面があります。

管理画面はパスワードをURLにそのまま記述しても開くことができます。これはパスワードを一緒にブックマークするためです。

order.cgi?kanri=0000

もちろん、このようなリンクは誰かに知られてはいけませんので、WEB上には置かないことが原則です。

order.csvの管理について

ログファイルであるorder.csvはテキストファイルですが、中身は1行ごとにログが記録され、データごとに「,」で区切られています。
拡張子をcsvにしてあるので、Windowsではエクセルでファイルを開こうとします。ブラウザからリンクで開く場合も同様です。

このファイルも管理パスワードと同様に一般に見せられないデータです。
管理画面にはデータのダウンロード用にリンクを用意してあります。FTPでダウンロードしてもかまいません。

アップロードやダウンロード時には、必要な注文内容を消してしまわないように細心の注意が必要です。
ダウンロード時に名前を変更して保存して置くと経過が分かって良いかも知れません。サーバ上のデータは適時削除して、手元のパソコン内にダウンロードしたログファイルを残して置くのが、個人情報の取扱上も安全です。

セキュリティ対策について

CGIを利用する場合、セキュリティ対策も必要になります。

例えば、掲示板であれば怪しげな情報を書き込まれたり、不正なリンクを張られたり、写真を表示する場合にはプライバシーや法律に違反したものが紛れ込まないように気をつけねばなりません。
誹謗中傷や違法な画像は目で見なければ、それが不正なものか判断できません。しかし、名前の欄にURLを書かれるなど不正な広告目的の書き込みなどは一定の方法で防ぐことができます。

今回使ったCGIでは次のような対策をしています。

不正行為 対策
多重登録の禁止 ホストアドレスを記録して、同じ日に同じアドレスからの書き込みを禁止します
不正なURLの書き込み 書き込み内容をチェックして、「http」または「https」が含まれていたらログに記録しません
不正なタグの記入 タグで使う「<」と「>」を「&lt;」「&gt;」に置き換えます。これでタグとして機能しなくなります

パーミッションの設定

実際にCGIを使うには、サーバ側の設定も必要になります。
サーバに置いたファイルに対し、誰が何をすることができるのか。その範囲を指定する必要があります。このようなファイルに指定する権限をパーミッションと呼びます。

サーバを利用する場合、登録されたユーザーとそうでないユーザーがあります。原則的に登録されたユーザーでないとサーバにアクセスすることはできません。
ログイン時にアカウントとパスワードが必要なのは登録ユーザーであることをサーバに認識させるためです。
誰でもがファイルをサーバに置いたりされては困りますので、サーバの管理者や管理者に許された人だけにファイルの書き込みを許可するのが普通でしょう。
しかし、ブラウザでサーバ内のファイルを見に来るのは一般の多くの人々ですから、HTMLファイルには全ての人がアクセスして読み込みできるように許可を与えます。
このような設定を各ファイル(フォルダ)毎にするのが、パーミッションの設定です。

フォルダを作った場合、またファイルを転送した後には、目的に応じたパーミッションを設定します。サーバによっては規定の設定方法がありますので注意が必要です。
CGIファイルの場合は、実行許可というパーミッションがありますので、ブラウザから使えるようにするには必ず全ての人に許可を与えないといけません。

パーミッションは、利用者の種類と3つの権限をそれぞれ設定します。
利用者には、オーナー、グループ、その他の人がいます。オーナーというのはファイルを作った人のこと。グループはサーバに登録されたユーザーです。その他の人は、それ以外の人です。
権限には「読込」「書込」「実行」があります。これら3つの許可からどれを与えるか決めます。
例えば、オーナーにはファイルを自由に読み書きする許可が必要です。CGIファイルであれば実行許可も必要です。結局3つの許可の全てを与えることになります。
その他の人とは、外からブラウザでアクセスしてくる一般の人を指しますので、HTMLファイルに読込許可を与えないとページを見てもらうことはできません。また、CGIファイルの場合、実行許可がなければエラーが表示されます。

  読込(r) 書込(w) 実行(x)
オーナー(Owner) on/off on/off on/off
グループ(Group) on/off on/off on/off
その他の人(Other) on/off on/off on/off

これらを略号で表記すると「rwxr-xr-x」のようになります。これはオーナーに3つの権限と、グループやその他には読込(r)と実行(x)の権限を与えていることを示します。

また、この略号を数字で表記することもあります。「rwx」を一つの数字で表します。これを8進数表記にして「111」(許可なら1、不可なら0)とし、10進数に直して「7」と表します。「rwxr-xr-x」を3文字で区切って「755」と表記します。


サーバを借りた場合、シェルコマンドを使ってサーバに直接ログインしたり、telnetを使ってログインすることは少ないでしょう。レンタルサーバにファイルを転送する場合にはFTPアプリが利用されます。
FTPアプリによってはパーミッションの設定ができないものもあります。CGIを利用する場合は、必ずパーミッションの設定ができるアプリが必要になります。

終わりに

今回作成したCGIは、基本的にデータをそのまま受け取って表示するだけのものです。
レンタルCGIやレンタルサーバのCGIでは、売上管理や在庫管理、商品の発送なども管理できるものもあります。またクレジットカード決済やページを渡り歩くためのカート機能などもあります。
用途や受注の仕方によってサービスを選択する必要があります。

このサンプルは、掲示板のプログラムを転用して学習用の受注システムにしましたので、多機能にはなっていません。
また、初期設定では簡単なパスワードになっていますし、パスワードも公開しています。

CGIの運営ではセキュリティ対策が重要になります。データを見られたり、消されたりという危険性もあります。また、いたずらにデータを送信されることもあります。
使わないCGIファイルはパーミッションで実行をOFFにしておくと安全です。

戻る