ただ画像を表示するだけのCGI

 今回は実践的なプログラミングを紹介しましょう。もちろんC言語で。

「ただ画像を表示すること」が重要なワケ
 今回紹介する「ただ画像を表示するだけのCGI」はヒジョーに応用範囲の広いプログラムです。このプログラムと組み合わせることでバックグラウンド型CGIを簡単に作動させることができるようになります。
 あるページが読み込まれたときに、CGIを実行させたい。このとき取りうる選択肢はひとつ。<IMG>タグを使うことです。例えば

	
<IMG
	SRC="ACLog.cgi" 
	WIDTH="1" 
	HEIGHT="1" 
	ALT="アクセスログです" 
	BORDER="0">
	
	

 とすることによって、読者にストレスを与えることなくCGIを実行できます。実際、これ以外の方法で、ホームページの読み込み時にCGIを実行することは不可能と言って間違いないでしょう。テキストのインライン挿入はSSIを使用する必要がありますし、フレームではページごとに違うCGIを実行するのが難しくなります。CGIを使ってホームページごと表示する方法もありますが、この方法は管理が難しく、また読者にストレスを与える可能性もあります。将来的にはJAVAスクリプトやDHTMLなどでサポートされる可能性もありますが、それでは現在多くの方が使用されているブラウザで機能しなくなってしまいます。

 というわけで、画像を表示することがページの裏でCGIを実行するときに必要不可欠な機能となるわけです。が、実は画像を表示できなくても、CGIは実行できます
 <IMG>タグを使うことでCGIは実行できます。その結果としてCGIがイメージを出力しなくても、CGIそのものはちゃんと実行されます。問題は、ブラウザが「イメージがないよー」と文句を言うことです

 イメージが存在しなかった場合、ブラウザは「壊れたファイル」のグラフィックを出力します。このイメージは<IMG>タグWIDTHとHEIGHTのふたつのプロパティにを入れることでたった1ドットにすることができるため、たいがいは無効化できます。ところが、これは次のふたつの点で問題が出てきます。
 ひとつはブラウザ依存です。ネットスケープ3.0以下では、壊れたファイルの場合にはWIDTHとHEIGHTのプロパティは無視されます。そのため、美しいページも見事なほどぐちゃぐちゃになります。
 また背景が黒だと目立つという問題もあります。壊れたファイルの表示は多くの場合白や灰色の絵になっています。そのため、黒地だと見事に目立ちます。

うそイメージ

 上の例を見れば一目瞭然でしょう。ねすけ3以下なら壊れたイメージが表示され、ねすけ4なら小さな白い点が表示されていることでしょう。イメージのサイズをゼロにできたらなんの問題もなかったんですけどねぇ。
 ちなみにこの問題はIEでは発生しません。「壊れたイメージ」がすこし違う形で表示されるため、1ドットの場合にはきれいに隠れてしまうからです。これは逆に危険なことだと思います。
 もちろんJAVAスクリプトでブラウザを識別したり、画面の端に表示させたりといったこともできますが、それよりは普通に透明1ドットのイメージを表示させるのがいちばんでしょう。
 というわけで、ただイメージを表示することがとても重要なのです

実は無茶苦茶簡単
 ただイメージを表示する、それはとーっても簡単だったりします。次のCGIを使えばあっさりと実現します。

#!/usr/bin/sh
echo 'Content-type: image/gif'
echo
cat ./L01.gif
	

 これはシェルスクリプトと言って、UNIXのコマンドを自動的に実行してくれるプログラムです。DOSで言うところのバッチファイルのようなものです。

 まず1行目は、このスクリプトを実行するshコマンドを書きます。これはCGIを実行するサーバーごとにパスが異なるので、whichコマンドで場所を調べて、直接のパスを書き込んでください。

 2行目はコンテンツタイプを表示しています。echoコマンドただ文字を表示するコマンドです。このコマンドから、ブラウザはただ出力された文字をそのまま受け取っていることが分かります。
 で、このとき表示される「コンテンツタイプ」とは、これから渡すデータがなんなのかを示しています。ここではGIFイメージだということを示しています。HTMLファイルであればContent-type: text/htmlというコンテンツタイプになります。

 3行目ではただの空行を出力しています。コンテンツタイプと実際のデータの間には1行間を空けて、どこからがデータなのか明確に分かるようにしなければならないためです。

 さて4行目、このたった1行でイメージを出力しています。
 catコマンドファイルの中身をそのまま出力するコマンドです。例えばcat test.txtと入れれば、test.txtの中の文字列が表示されるというわけです。
 じゃあGIFファイルを出力したらどうなるのか? かなり支離滅裂な文章がずらーっと出てきます。一度くらいTelnetで入ったときに試してみてください。かろうじて最初の数バイトは「GIFのバージョン」がテキスト形式で入っているのでそれが表示されますが、そのあとは無茶苦茶になります。
 ところが!! ブラウザはこれを読みとってイメージとして表示してしまうのです!! 一体何考えてるんでしょーねー。

 でも、これである程度分かったと思います。普通に文字を出力するのはC言語でも簡単にできます。問題のイメージ表示の部分は要するにcatコマンドと同じ物を作ればいいということです。これで、プログラムの方針みたいなものができあがったと思います。
 では、ようやくですがプログラムの解説に移りたい思います。

プログラムについて
 実際のプログラムはこちらです。
 このリンクは新しいブラウザウィンドウを開きます
 このプログラムは著作権フリーとします。
 このプログラムを使用することによるいかなる損害にも関知しません
 動作確認はリムネットだけです。他のプロバイダでは確認してません。
 このプログラムを使用するときには拡張子をcにしてください

関数の形式
 関数の形が変だと思うかもしれません。どうやらリムネットのCコンパイラは古い形式らしく、昔のK&R形式の引数しか受け付けません。引数の型宣言はすぐ下の行で行ってください。またconstも使えないみたいなので、文字列を渡すときには十分注意してください。もちろん他のプロバイダでコンパイルする場合には大丈夫かもしれません。
 あと、引数の命名形式を変に感じるかもしれませんが気にしないでください(汗)。

コマンド引数の渡され方
 main関数の引数はコマンドラインが入っています。例えばcat test.txt img.cというコマンドであればargv[0]にはcatargv[1]にはtest.txt、そしてargv[2]にはimg.cが入っています。また、argcにはコマンド引数の数が入っています。この例ならが入っていることになります。

 さて、これはフツーにコマンドを入力した場合の話です。では、HTMLで呼び出すときにはどう引数を渡せばいいのでしょう
 <IMG>タグでCGIを呼び出すときに引数を加えるには、?と+を使います。具体的には次のような形です。

	
<IMG
	SRC="ACLog.cgi?ACLog.txt+test.html" 
	WIDTH="1" 
	HEIGHT="1" 
	ALT="アクセスログです" 
	BORDER="0">
	
	

 ?のあとが引数とみなされ、ひとつひとつの引数が+で継ながれています。この例ならargv[0]にはACLog.cgiargv[1]にはACLog.txt、そしてargv[2]にはtest.htmlが入っています。また、argcにはが入っていることと思います。

 今回のプログラムでは第1引数表示するイメージファイルの名前を渡しているものと見なします。そこで、まず引数の数をチェックして2未満ならデフォルトのイメージを表示するようにしています。
 前述したように、壊れたファイルが表示されるのはできるだけ避けたい場合が多いと思われます。そのため、間違った使用方法がなされたときのために「確実に表示される」イメージを置いておき、それを代わりに表示するようなシステムにするのがいいでしょう。

イメージの表示
 さて、肝心のイメージの表示部分です。この機能はWriteImg()で行っています。渡されてくるファイル名を元に、イメージを表示します。

 この関数ではまず、コンテンツタイプを表示しています。最後が\n\nになっていることを確認してください。コンテンツタイプとデータの間に空行を入れる必要があるのは、Cのプログラムでも同じです。
 次にファイルをオープンします。イメージを表示するだけなので当然「読み込み専用」です。また、テキストファイルではないので「バイナリーモード」で開きます。失敗したらデフォルトのファイルを開きます。
 開いたら念のためファイルの先頭にファイルポインタを持っておきます。これは多分必要ないと思います。
 で、ここからが実際のイメージ表示。fgetc()でファイルから1文字データを取得したら、それをputchar()で出力する。これをファイルの最後まで続けます。ただこれだけ。難しいところはないですねー。
 で、最後にファイルをクローズ。これを忘れないように。

 ここで使っている関数はすべてANSI準拠のものですから、本屋で売っている本を見たり、VCに付いているヘルプを見たりすればすぐ分かるでしょう。
 で、プログラムはこれで終わり。結構あっさりできちゃいましたね。

デバッグしましょ
 筆者なんかはそうなんですが、ウィンドウズプログラミングでの統合環境を使っていると、UNIXのコマンド形式のコンパイルなどは非常にめんどくさくなってしまいます。それはデバッグでも同じで、ちゃんとデバッグ用のコマンドとかがあるんですが、筆者は使い方を知りません
 じゃぁどーやってデバッグするのか、といえば昔ながらのprintf()をばらまいてチェックするとゆーのが一番楽でしょう。

 ところがここで問題が出てきます。デバッグを終了してprintf()を削除しようというときに、あまりにもばらまきすぎて削除が大変だったりすると、ひとつくらい忘れちゃうことがあります。そうなると、もちろんイメージ表示が壊れます。たったひとつのprintf()で、CGIは目的を達成できなくなってしまいます。

 それを防ぐため、デバッグ用のマクロを使ってみましょう。冒頭のMODE_DEBUGをセットしてください。そうすると「デバッグモード」に入ります。
 次に、ここまでprintf()でデバッグしていたところをTRACE( "Error" );とかTRACE( argv[1] );とかすればOK。
 見れば分かりますが、このマクロは単にprintf()を使っているだけです。で、MODE_DEBUGを0にセットしたときにはマクロを引数ごと削除してしまいます。これで安心してデバッグできますね。

これだけじゃなーんの役にも立ちませーん
 基本的に、このプログラム単独では役に立ちません。「引数に渡すんだったら直接読み込みゃえーやん」って感じです。
 でも、これをベースにありとあらゆるプログラムを組むことができます。アクセスカウンターはもちろん、アクセスログやリンクログも作れますし、普通アクセス数をチェックできない画像ファイルも、どれくらい人気があるのかチェックできたりするプログラムだって組めます。
 あとは皆さんのアイディア次第、といったところです。突拍子もないCGIを作ってみましょう!

(C)KAB-studio 1998 ALL RIGHTS RESERVED.