情報工学実験II WWW


メールでのレポート提出は、平文で行なってください。
作成したプログラムソースと, 図のファイルなどは,nirai からアクセスできる状態にし,URL 等を含めてレポート中に場所を明記して下さい.またプログラムは第三者が実行確認できるように簡単なREADMEファイルを付加すること.

プログラムソースを印刷して添付することはしないこと.LaTeX のソースを付けた大馬鹿者が一グループありましたが,そういう水増しはやめよう
 

○Webサービスを行うデーモン
デーモン(daemon)とは、UNIX上でさまざまなサービスをする偉いやつです。通常使われている telnet や ftp を受け付けるときもそれぞれデーモンによってその機能が提供されており、それぞれ telnetd 、 ftpd というデーモンが動作することによって通信ができるようになってます。
当然WWWサービスもデーモンで提供されており、httpd というデーモンで行われています。

WWWサービスを提供するプログラムはたくさんありますが、pw機には apache というパッケージがインストールされています。

○httpd のたちあげ
rootになって
% /usr/var/www/bin/start-apache
をします。

これでhttp://pw???.st.ie.u-ryukyu.ac.jp/にアクセスすることができます。

WWWサービスを停止するときは、
% kill -9 /var/run/http.pid
とします。

■課題1
rootになって httpd を起動し、http://pw???.st.ie.u-ryukyu.ac.jp/にアクセスしてみよう。プロセスが httpd を起動する前とした後ではどうかわるでしょうか?

○httpdサービスの設定
apacheの設定ファイルは /usr/local/etc/httpd/conf/httpd.conf にあります。このファイルには同時にアクセスできる人数や公開するroot directory 、使用 port が設定されています。

このファイルのパラメタを変えることで、httpd の詳細な設定ができます。

<例>
ServerType standalone
standalone か inetd を記述します。 boot からデーモンとして立ち上げ るか、inetdの管理下で リクエストがあってから立ち上げるかの違いです。 inetd は、TCP wrapper のセキュリティ機能が適用されます。

HostnameLookups off
サーバにアクセスして来たホストの DNS を参照するかどうかの設定です。 外部かアクセスを把握したいときには、on を記述します。

ServerAdmin webmaster@hogenet.jp
WEB サーバ管理者のメールアドレスを指定します。エラーがあった場合に、サーバが表示するメッセージとともに表示するメールアドレスです。
 

また、バーチャルホストネームの設定とかできます。
さらにいろいろな設定ができますが、http.confの説明書きを読めばわかるでしょう。

/usr/local/etc/httpd/conf/srm.conf サーバリソースマップと呼ばれ、
各種ファイルのディレクトリの位置やインデックス化に関する情報等を設定 できます。WEB サーバは、ここで指定されたディレクトリ以外へのアクセスは出 来ない様になっています。

<例>
DocumentRoot /home/httpd/html
アクセスしたときの、サーバの最上位のドキュメントディレクトリを指定します。
http://www.hoge.jp/
とアクセスしたときに表示される HTML を置くディレクトリです。

UserDir public_html
ユーザホームページのディレクトリの指定です。ユーザ foo ディレクトリの下に public_html ディレクトリを作れば、http://hoge.hoge.jp/~foo/ で アクセスできます。

FancyIndexing on
ディレクトリに対する自動インデックス化の設定です。ファイル名の無い URL のリクエストが来た時、index.html が無かった場合に、そのディレクトリをインデインデックス化してファイルリストを表示します。
※最近はセキュリティを高めるために off にすることが多いようです。

AccessFileName .htaccess
ここで設定したファイルがディレクトリにあると、その中で設定された内容を優先的に適用します。

AddHandler cgi-script .cgi
AddHandler は、特定の拡張子を持つファイルの挙動を設定します。 拡張子 .cgi のCGIスクリプトを実行出来るようにします。

server-parsed .shtml
SSI のコール名と拡張子です。


○CGI(Common Gateway Interface) と SSI(Server Side Include)
WWWを使用すると、掲示板やカウンタなどを見たことがあると思います。こ れはCGIと呼ばれる機能です。主にPerlで書かれています。C でも実現可 能です。また、 HomePage 内に日付や他のファイルを読み込ませる機能を SSI と呼びます。これはサーバに「○○してね」とコマンドを渡します。
これらは http.conf と srm.conf を調整することで使用可能となります。
 

■課題2
http://pw???.st.ie.u-ryukyu.ac.jp/cgi-bin/bsdi-man/
にはBSD/OSのマニュアルを参照できるようになCGIがある。ここにアクセスし、使用してみよう。このとき HomePage のソースを参照し、「場所ツールバー」にどういう表示がされるか考 察してみよう。また、http.conf 、 srm.conf を変更し、WWWサービスがどう変化するか試してみよう。
 

○CGIスクリプトの作成
では、実際にCGIスクリプトを作成しましょう。
ここでは Perl を使用します。Perl は非常に柔軟な言語ですので、覚えておいて損はないです(管理者は必須)。

オンラインマニュアルは
http://rananim.ie.u-ryukyu.ac.jp/~kono/perl/index.html
にあります。

が、これでたりないと思うので
「初めてのPerl - Learning Perl」 O'Reilly シリーズ
の購入を薦めます(通称リャマ本)。もちろんWeb上のCGIサイトで勉強しても構いません。

では、簡単な cgi スクリプトを作成しましょう。
 
-  hello.cgi  -
1 #!/usr/bin/perl5
2 print "Content-type: text/html\n\n";
3 print "<HTML>\n";
4 print "<TITLE>Simple cgi Script</TITLE>\n";
5 print "<HR>Welcome cgi sample<P>\n";

7 print "hello world!\n";
8 print "</HTML>\n";

■説明■
1行目 perl コマンドがどこにあるかフルパスで記述します。(おまじないです)
2〜8行目 print コマンドで"(ダブルクォーテーション)で囲まれたテキストを表示
します。

perlコマンドで実行すると、
pw008: {6} % perl hello.cgi
Content-type: text/html

<HTML>
<TITLE>Simple cgi Script</TITLE>
<HR>Welcome cgi sample<P>
hello world!
</HTML>

と表示されますね。hello.cgi はperlで実行されるとHTML言語を出力します。

これを ~/public_html に移動させて、ブラウザから実行させましょう。
% mv hello.cgi ~/public_html
% chmod +x ~/public_html/hello.cgi
として、ユーザ以外の実行権限を追加します。
※置くところは任意です。パスに応じて場所は変えてください。

http://pw???.st.ie.u-ryukyu.ac.jp/~j98????/hello.cgi
にアクセスして実行させましょう。

■課題3
hello.cgiを作成してブラウザからアクセスし、実行させてみよう。
また、なぜユーザ以外の実行権限を追加するのかhttpサーバとperlの連係を考察
してみよう。図で示すとよいです。

○SSIの使用
SSIはHTMLの途中で使用することにより、別のファイルを呼び出したり、コマンドを
実行させることができます。

※慣習的に SSI を利用できるサーバーでは,拡張子 shtml を SSI が利用で きる html ファイル(MIME type: text/x-server-parsed-html) としている場合が多い。このような利用環境では拡張子を html から shtml にすることで SSI が記述可能になります。また、public_html ディレクトリに .htaccess ファイルを設置することでhtmlファイルでSSIが利用可能になります。

SSIの基本構文は

<!--#element attribute = value ... -->

で成り立っています。

※注意点

  • "<!--" と "#" の間にはスペースを入れない。
  • "-->" の前にはスペースを入れた方がよい。

  •  

     
     

    elementとattributeは対になっていて、
    <!--#config errmsg = "エラーなのさ" -->
    <!--#echo var = "REMOTE_HOST" -->
    <!--#include file="hoge.html" -->

    など、
    config には errmsg
    echo には var
    include には file
    といった使用になります。それぞれ他にいろいろなattributeが使用できます。

    #exec cmd は特別で UNIX コマンドを実行させることができます。
    <!--#exec cmd = "/usr/bin/cal" -->
    だと、cal コマンドを実行してブラウザに表示させることができます。

    例えば次のようなSSI構文を ssi.shtml として作成します。
     
    -  ssi.html -
    <HTML>
    <BODY>
    <!--#config timefmt="%Y年%m月%d日%p %I時 %M分 %S秒" -->
    <!--この#config timefmtはタイムフォーマットの指定-->
    あなたのマシン名:<!--#echo var = "REMOTE_HOST" --><BR>
    現在のサーバの時刻:<!--#exec cmd = "date" --><BR>
    このファイルの最終更新日時:<!--#flastmod file = "ssi.shtml" --><BR>
    カレンダー:<BR>
    <!--#exec cmd = "/usr/bin/cal" --><BR>
    </BODY>
    </HTML>

    そのファイルにアクセスしてみましょう。SSIが実行されて、ブラウザには
    あなたのマシン名:133.13.48.203
    現在のサーバの時刻:Sun Oct 24 19:42:55 JST 1999 
    このファイルの最終更新日:1999年10月24日PM 07時 59分 09秒
    カレンダー
     

    October 1999
    S M Tu W Th F S
    1 2
    3 4 5 6 7 8 9
    10 11 12 13 14 15 16
    17 18 19 20 21 22 23
    24 25 26 27 28 29 30
    31

    と表示されます。
     

    ○共通(Common)の環境変数
    ssi.shtml で、
    <!--#echo var = "REMOTE_HOST" -->
    を使ってみましたが、REMOTE_HOSTというのは環境変数と呼ばれます。これは ssi.shtml を見た人がもつ情報を取り出したものです。tcsh で setenv コマンドを実行するとシェルでの環境変数が見えますね? それに似たものです。

    ※環境変数の種類
    AUTH_TYPE ユーザ認証するためのもの
    CONTENT_LENGTH HTML の form タグから POST によって CGIプログラムへ送るデータのサイズ
    CONTENT_TYPE CGI によって扱われるデータの種類
    GATEWAY_INTERFACE サーバで使っている CGI のバージョン
    HTTP_ACCEPT 訪問者の使っているブラウザがヘルパーソフト無しで表示できるファイル形式
    HTTP_REFERER CGI スクリプトがどこから呼び出されたか
    HTTP_USER_AGENT 訪問者の使っているブラウザやコンピュータの種類
    PATH_INFO HTML タグから CGI プログラムへパス情報を送る際に使う
    PATH_TRANSLATED HTML タグから CGI プログラムへフルパス情報を送る際に使う
    QUERY_STRING HTML タグから GET によって CGI プログラムへ情報を送る際に使う
    REMOTE_ADDR 訪問者の IP アドレス
    REMOTE_HOST 訪問者のマシン名
    REQUEST_METHOD HTML タグから CGI プログラムへ情報を送った手段(POST または GET)
    SCRIPT_NAME 実行した CGI プログラムのファイル名
    SERVER_NAME 実行した CGI プログラムの置いてあるサーバ名
    SERVER_PORT 実行した CGI プログラムの置いてあるサーバのポート番号
    SERVER_PROTOCOL WWW サーバのプロトコルバージョン
    SERVER_SOFTWARE httpd のバージョン

    ■課題4
    環境変数を表示するSSI(またはCGI)スクリプトを作ってブラウザからアクセスし、環境変数を確認してみよう。
     

    ○カウンタを作る
    CGIとSSIについてはわかりましたね。次はカウンタを作ってみましょう。

    まずは public_html/counter/ のようなディレクトリを作り、
    countdata カウンタのデータを入れるファイル
    count.cgi カウンタ動作するCGIスクリプト
    を作ります。
    countdata ファイルの中身は 0 に、パーミッションは 666 に設定します。
     
    -  countdata  -
    0
    -  count.cgi  -
    1 #!/usr/bin/perl5
    2 $data_file=countdata;
    3 open(KAZU,"<$data_file")||die "CounterReadError.......\n";
    4 flock(KAZU,2);
    5 $counter=<KAZU>;
    6 $counter_new=($counter+1);
    7 close(KAZU);
    8 flock($data_file,8);
    9 open(KZ,">$date_file")||die "CounterWriteError.......\n";
    10 flock(KZ,2);
    11 print KZ "$counter_new\n";
    12 #print "$counter_new\n"; #これは端末からの確認用。
    13 close(KZ);
    14 flock($data_file,8);
    15 #------- 実行確認の表示 -------
    16 print "Content-type:text/html\n\n";
    17 print "<HTML><HEAD><TITLE>OK</TITLE></HEAD>\n";
    18 print "<BODYBGCOLOR=\#ffbbaa\>\n";
    19 print "<CENTER>\n";
    20 print "<H1>ThankYou.</H1>\n";
    21 print "<H2>---Counter---</H2>\n";
    22 #カウンターの新しい数値の表示。
    23 print "$counter_new\n";
    24 print "</CENTER>\n";
    25 print "</BODY></HTML>\n";

    1行目:おまじない
    2行目:$data_file に countdata をプリセット
    3行目:$data_file を KAZU として開く。失敗したら die 以下のメッセージを出力
    4行目:flock で $data_file をロック
    5行目:KAZU の1行目を $counter に読み込む
    6行目:$counter_new に $counter+1 を入れる
    7行目:KAZU を閉じる
    8行目:$data_file を開放
    9行目:$data_file を KZ として開く。失敗したら die 以下のメッセージを出力
    10行目:flock で $data_file をロック
    11行目:print で KZ に $counter_new を書き込む
    13行目:KZ を閉じる
    14行目:$data_file を開放
    16〜24行目:HTMLを出力

    ■課題5
    perl コマンドで count.cgi を実行し正しく動くかチェックしてみよう。
    ブラウザからアクセスし、なんどかリロードしてカウンタを増やしてみよう。
    また、ファイルをロックするのは何故でしょうか?

    ■課題6
    このプログラムには重大な欠陥があります。実際に複数の count.cgi を同時に動作させる(バックグラウンドでね)とわかります。異常が起きるとどうなるでしょうか?
    ファイルのロックに着目してこのプログラムのフローチャートを描き、まずい点を指摘してみよう。

    ■課題7
    読み書き可能でファイルを開くには
    open(HOGE,"+<hogefile")
    を使用します。課題6での欠点を補うようにcount.cgiを改良しましょう。
     

    ○formからテキストを受け取る。
    count.cgiはプログラムを実行してHTMLを吐くものでした。では、HTMLのformから
    テキストを受けてみましょう。
     
    -  form.html  -
    <HTML>
    <HEAD>
    <TITLE> form get </TITEL>
    </HEAD>
    <BODY>
    <H2>GETでformのデータをCGIプログラムに渡す。</H2>
    <HR>
    <FORM METHOD="GET" ACTION="formget.cgi">
    データ1:<INPUT TYPE="TEXT" NAME="data1" SIZE=30><BR>
    データ2:<INPUT TYPE="TEXT" NAME="data2" SIZE=60><BR>
    URL:<INPUT TYPE="TEXT" NAME="url" VALUE="http://" SIZE=60><BR>
    好きな色:<SELECT NAME="color" SIZE=1>
    <OPTION VALUE="red">あか
    <OPTION VALUE="blue">あお
    <OPTION VALUE="yellow">きいろ
    </SELECT>
    <INPUT TYPE="submit" VALUE="submit"><INPUT TYPE="reset" VALUE="reset">
    </FORM>
    <HR>
    </BODY>
    </HTML>
    -  formget.cgi  -
    #!/usr/bin/perl5
    $data=$ENV{'QUERY_STRING'};
    print "Content-type:text/html\n\n";
    print "<HTML><HEAD><TITLE>formget.cgi</TITLE></HEAD>\n";
    print "<BODY>\n";
    print "<H2>form.htmlから submit で受け取ったデータ</H2>\n";
    print "$data\n";
    print "</BODY></HTML>\n";

    form.html 内の <FORM> タグで囲まれたところで <INPUT> タグ内のものをGETメソッドで formget.cgi に送っています。送る際に、 QUERY_STRING という環境変数で渡しているのです。

    ■課題8
    form.html formget.cgi を作成して情報を受けてみよう。
     
     

    これだと日本語や特殊文字が使えん!





    ということでこれを decode するために、 jcode.pl を利用します。
    日本語を表現するコードには、 EUC 、 SJIS 、 JIS の3種あり、これらのコードが混在するとブラウザではうまく表示できません(俗にいう文字化け)。
    例えば Windows 、 MacOS はデータを SJIS で扱い、 UNIX 系 OS では EUC を使っています。 jcode.pl はこのようなコードの違いを簡単な操作で変換してくれます。また、 cgi-lib.pl は <FORM> タグ内で NAME で受けた各パラメタを切り出す機能があります。
     
    -  formdecode.html  -
    <HTML>
    <HEAD>
    <TITLE>formdecode.html</TITLE>
    </HEAD>
    <BODY>
    <H2>GETでfromのデータをCGIプログラムに渡す</H2>
    <HR>
    <FORM METHOD="GET" ACTION="formgetdecode.cgi">
    データ1:<INPUT TYPE="TEXT" NAME="data1" SIZE=30><BR>
    データ2:<INPUT TYPE="TEXT" NAME="data2" SIZE=60><BR>
    URL:<INPUT TYPE="TEXT" NAME="url" VALUE="http://" SIZE=60><BR>
    好きな色:<SELECT NAME="color" SIZE=1>
    <OPTION VALUE="red">あか
    <OPTION VALUE="blue">あお
    <OPTION VALUE="yellow">きいろ
    </SELECT>
    <INPUT TYPE="submit" VALUE="submit"><INPUT TYPE="reset" VALUE="reset">
    </FORM>
    </BODY>
    </HTML>
    -  formgetdecode.cgi  -
    #!/usr/bin/perl5
    require "cgi-lib.pl";
    require "jcode.pl";
    &ReadParse;   #cgi-lib.pl の機能。

    $data=$ENV{'QUERY_STRING'};
    $data1=$in{'data1'};
    $data2=$in{'data2'};
    $url=$in{'url'};
    $color=$in{'color'};
    $colorstring;
    if($color eq "red"){$colorstring='あか';}
    elsif($color eq "blue"){$colorstring='あお';}
    elsif($color eq "yellow"){$colorstring='きいろ';}
    esle{;}

    print "Content-type:text/html\n\n";
    print "<HTML><HEAD><TITLE>formgetdecode.cgi</TITLE></HEAD>\n";
    print "<BODY>\n";
    print "<H2>decode前</H2>$data<BR></HR>\n";
    print "<H2>切り出し</H2>\n";
    print "$data1<BR>";
    print "$data2<BR>";
    print "$url<BR>";
    print "好きな色:<FONT COLOR=\"$color\">$colorstring</FONT><HR>";

    &jcode'convert(*data1,"euc");
    &jcode'convert(*data2,"euc");
    &jcode'convert(*url,"euc");
    &jcode'convert(*colorstring,"euc");

    print "<H2>これはEUCコード</H2>";
    print "$data1<BR>";
    print "$data2<BR>";
    print "$url<BR>";
    print "好きな色:<FONT COLOR=\"$color\">$colorstring</FONT><HR>";

    &jcode'convert(*data1,"sjis");
    &jcode'convert(*data2,"sjis");
    &jcode'convert(*url,"sjis");
    &jcode'convert(*colorstring,"sjis");

    print "<H2>これはsjisコード</H2>";
    print "$data1<BR>";
    print "$data2<BR>";
    print "$url<BR>";
    print "好きな色:<FONT COLOR=\"$color\">$colorstring</FONT><HR>";

    &jcode'convert(*data1,"jis");
    &jcode'convert(*data2,"jis");
    &jcode'convert(*url,"jis");

    print "<H2>これはjisコード</H2>";
    print "$data1<BR>";
    print "$data2<BR>";
    print "$url<BR>";
    print "好きな色:<FONT COLOR=\"$color\">$colorstring</FONT><HR>";

    print "</BODY></HTML>\n";

    ■課題9
    コードを統一し、一言掲示板を作ってみよう。

    ※HTMLファイルの<META>タグ内を適切に処理すればコードの統一は気にしなくてもよいかもしれない。

    ○さまざまなブラウザ
    ブラウザにはいろいろなものがあります。

    Netscape Navigator、Netscape Communicator
    米Netscape社が開発したブラウザ。その前身は大学生が作った Mosaic だった。今年AOL(American On Line)に買収された。ブラウザのソースが公開されているので、改変可能となっている。中核にGeckoエンジンをもち、自由にインタフェースを変えられるようになるらしい。

    InternetExploror
    米Microsoft社がNetscapeに対抗して作った。Windowsとの親和性は高い。

    lynx
    UNIX tty 端末で実行する文字ベースのブラウザ。
    % lynx とすると実行できる。

    i-mode
    携帯電話で Web file を閲覧することができる。今年デビュー。
     

    ■課題10
    http://www.nttdocomo.co.jp/mc-user/i/tag/index.html
    を参照して 自分のページの i-mode 対応pageを書いてみよう。

    ○plug-in と Helper-Application
    NN(Netscape Navigator)、IE(Internet Exploror)には plug-in 機能があり、特別
    なページを参照することができる。helper-applicationとは、ブラウザで補えない
    機能を別のソフトで実現することです。
    それぞれ [option] -> [general Preferences ...]でApplicationがわかります。

    ■課題11
    telnet を起動するhtmlを書いてみよう。
     

    ○インタレースGIF、アニメーションGIF
    Webページには背景が透けて見える画像、動く画像があります。これはInterlace GIFAnimation GIFと呼ばれ、画像フォーマットとして規格化されています。Interlace GIF は背景が透けて見えるもの、Animation GIF はぱらぱら漫画の要領で次々とGIF画像を入れ換えていく画像です。
    UNIXには gimp という素晴らしいアプリケーションがあります。Windows や MacOS での Photoshop と同等の機能があります。さらにこれがオープンソースとは!
    ※Windows版の gimp はあります。

    使い方:
    端末から
    % gimp
    として gimp を起動します。ダイアログを見ながら先へ進みましょう。
    起動したら[File]-[Open] や [File]-[New] などでパレットを表示します。

    ある程度できるようになったらAnimationGIFを作ってみましょう。
    パレット内で右クリックし、下の画像のような Layer ウィンドウを開きます。
    gimp1.jpg

    Layerを表示させたい順に並べて階層化します。

    これをセーブするときに、 Animated GIF Options の Loop をチェックします。

    OKを押し、名前を付けて保存します。

    ■課題12
    gimp を使ってインターレースGIFとアニメーションGIFを作成してみましょう。
    がんばれば
    http://www6.big.or.jp/~monga/
    をつくれます。