HTML
,
CSS
,
JavaScript
,
CGI
の紹介
稲元 勉
2016
年 4 月 13 日
1
はじめに
情報システム開発演習では,構築するソフトウェアを Webアプリケーションに限定している.この理由,および HTML (Hyper-Text Markup Language)[1],CSS (Cas-cading Style Sheets)[2, 3],JavaScript ([4]),CGI (Com-mon Gateway Interface)[5]の概要を紹介する.ここで,“紹介” としていることから分かるように,本 資料の目的は,それらの技術の詳細を述べることにはな い.HTML などの解説資料は,書店にも Web 上にも大 量に存在する.系統だった知識を得たいならば書籍(手 軽には中古本)の購入を,とりあえず言葉の意味を知り たいならば Web 上で検索しいくつかのページを見るこ とを,それぞれ推奨する.
2
Web
アプリケーションに限定する
理由
近年では,ほぼすべてのアプリケーションソフトウェ アが,マウスで操作する GUI を備えている.そうでは ない,CUI しか備えないソフトウェアも存在するが,一 般のエンドユーザ向けとはいいがたいと思われる1.GUI を備えるアプリケーションソフトウェアを作るためには, それが実行される OS 用の適切な GUI ライブラリが必要 であり,かつそのライブラリに含まれる関数などの使い 方を覚える必要がある.ライブラリを使うための学習は, 有益ではあるものの,アプリケーションソフトウェア開 発にあたっての周辺に過ぎず,本質ではない場合が多い. そのような GUI ライブラリの学習コストを避ける方途 の一つとして,Web ブラウザ(以降,たんにブラウザ) の利用があげられる.ブラウザ上にボタンやメニューを 表示し,操作できるようにすれば,GUI ライブラリを使 用する必要はなくなる.さらに,高度/最先端の機能を 有するものでなければ,どのような OS にもブラウザは 提供されており,OS ごとの差異に注意を払う必要はない といえる.以上の理由から,本演習では,構築するアプ リケーションは Web アプリケーションに限定する. 1使い難いが,使いこなせると生産性が飛躍的に向上する.3
HTML
の紹介
3.1
HTML
の役割
パソコンを含む多くの機器が接続して形成している巨 大なネットワークであるインターネット内に,ある情報 がべつのある情報と関係することを表すハイパーリンク により,多種多様な文書・画像・音楽などを結びつけた ネットワークが存在する.これが WWW (World Wide Web, Web) であり,その基本的構成要素である文書は Webページと呼ばれ,Web ページを記述するための代表 的形式が HTML である.本資料では,HTML 形式で記 述された Web ページを,HTML ページあるいは HTML ファイルと呼ぶ. HTMLの正式勧告バージョンは,長らく 4 であったが, 2014年 10 月 28 日に HTML5[6] が勧告された.HTML5 は,動画や音声といったリッチコンテンツの取り扱いや, グラフィックの描画,大量データの保存・通信といった点 で機能が拡張されており,機械語のネイティブアプリケー ションと同程度の機能を有する Web アプリケーションの 開発を可能にすると期待できる.このように HTML5 は 興味深いものの,“紹介” を目的とする本稿では,歴史が 長く枯れている(安定して使用できる)バージョン 4 の みを念頭におく.3.2
タグと属性
HTMLファイルは,“タグ” と呼ばれるマークで囲まれ た部分から構成される.タグの役割は,それが含む部品 の,文書内での役割や体裁2を指定することにある.タ グは階層構造をとることができ,図 1 に例示するように, あるタグの中身が別のタグをもつことが一般的である.ま た,タグは “属性” と呼ばれるパラメータを持っており, その値を指定することで,振る舞いや体裁を変更するこ とができる. 2文字の大きさ,色,線の太さ,スペースといった体裁は,CSS[3] を用いて指定することが推奨されており,かつ一般的となっている.</tag1>
</tag4>
図 1: タグが形成する階層構造のイメージ 3.2.1 タグ タグは,それが囲む内容の,HTML ファイル全体に おける役割を指定するためのマークである.文章など の前に置かれるタグは “開始タグ” と呼ばれ,タグ名を tag_name とすれば “<tag_name>” と記述される.文 章などの後に置かれるタグは “終了タグ” と呼ばれ,タ グ名を tag_name とすれば “</tag_name>” と,開始 タグに “/” を挿入した文字列として記述される.そして, タグおよびタグに囲まれた部分は “要素” と呼ばれる. タグの種類は HTML の仕様 [1] により定められており, 中身が存在すべきものと,そうでない(中身がなくてよ い)ものに大別される.前者のタグのうち代表的なもの として以下があげられる. • html: Web ページ全体を囲み,当該文書が HTML ページであることを表す. • head: HTML ページのタイトルといった情報を含む. • body: HTML ページの,タイトルといった情報を除 いた,本質的内容を含む. • title: HTML ページのタイトルを表す. • p: 段落 (paragraph) を表す.字下げや空白の挿入な ど,見易くなるための体裁の調節をともなう. • a: ここに含まれる中身からハイパーリンクを張る. リンク先は,後述する href 属性を用いて指定する. • div: 複数行にわたる領域を作成する3.当該領域に 含まれる部品に対し一括して体裁などを指定できる. • span: 単一行の領域を作成する4.当該領域に含まれ る部品(多くの場合,単純な文字列)に対して,一 括して体裁などを指定できる. • h1, ..., h6: 見出し (heading) を表す.数字の小さい ほうがより大きな単位の見出しである.例えば,通 常の設定では,h1 タグで囲まれた文字列は h2 タグ で囲まれた文字列よりも大きな文字で表示される. • table: 表を作成する.表中の行は,table タグの中 身のうち tr (table row) タグにより囲まれた部分と なる.行中のセルは,tr タグの中身のうち td (table data)タグにより囲まれた部分となる.• ol, ul: それぞれ順序つき (ordered),順序なし
(un-ordered)リストを表す. • li: ol タグや ul タグの内部で,リストの要素を表す. • form: CGI プログラムへデータを渡す際に使用する. formタグの中身では,渡すデータの種類におうじて, つぎのようなタグを使用する. – input: 一行ほどの文字列や選ばれた選択肢など を渡す.また,CGI プログラムへのデータ送信 を行う. – textarea: 複数行の文字列を渡す. – select: 複数の選択肢の中の一つを選んで渡す. 中身を持たないタグのうちでは,以下が代表的と考え られる. • img: 画像 (image) を表す.画像ファイルは,後述す る src 属性を用いて指定する. • br: 改行 (break line) を表す.p タグとは異なり,空 白を挿入するといった調節は行われない. • hr: 水平 (horizontal) 線を表す. • meta: head 要素に含まれ,HTML ページの情報(メ タデータ)を指定する. タ グ 名 は ,大 文 字・小 文 字 が 区 別 さ れ ず,例 え ば “<HTML> ... </HTML>”と “<html> ... </html>” は同じである.しかし,XHTML との親和性から,本資 料では小文字を使うこととする. 多くのタグは,その中身にほかのタグを含むという階 層構造をとったり,一つの文書内に複数存在することが できる.このようなことが許されないタグとして,html 3ブロック要素と呼ばれる. 4インライン要素と呼ばれる.
リスト 1: 単純な HTML ページ
1 <html> <head>
3 < t i t l e>s i m p l e web page</ t i t l e> </head> 5 <body> <h1>c h a p t e r 1</h1> 7 <h2> s e c t i o n 1</h2> <p>p a r a g r a p h 1 .</p> 9 <p>p a r a g r a p h 2 : b e f o r e b r .<br> a f t e r b r .</p> 11 <h2> s e c t i o n 2</h2> <p>f o o b a r .</p> 13 <hr> 15 <h1>c h a p t e r 2</h1> 17 <h2> s e c t i o n 1</h2> <h2> s e c t i o n 2</h2> 19 </body> </html> や body があげられる.その禁則は,例えば以下のよう に記述できる. • 一つのファイルが複数の HTML ページに対応するこ とはないため,html タグは一つだけである. • html タグは,ほかのすべてのタグを含む最大のタグ であり,ほかのタグに含まれることはない. • head タグ,body タグは,HTML ページの情報,中 身を伝えるものであるので,html タグの直下に,ど ちらも一つずつ,含まれる.また,これらのタグが htmlタグ以外のタグの中身に含まれることはない. このようなルールに従う,きわめて単純な HTML ペー ジをリスト 1 に示す.このファイルを Firefox で開くと, 図 2 に示すように表示される. 3.2.2 属性 あるタグで指定可能な属性は,HTML の仕様 [1] で規 定されており,タグごとに異なる.とくに重要な属性と しては,以下があげられる. • id: 文書内で一意である ID(通し名)を振る.ID は, ハイパーリンクのリンク先として使用できる. • name: id 属性と同様に文書内の ID を振ったり,form タグ内で使われるデータ送信用のタグにおいては,個 別データと紐づけられる変数名を指定する. • href: a タグにおいて,ハイパーリンク先を指定する. リンク元は,a タグの中身となる. • src: img タグにおいて,表示する画像ファイルを指 定する. 図 2: 単純な HTML ページの表示画面 • action: form タグにおいて,渡すデータを処理する CGIプログラムを指定する. • method: form タグにおいて,データの送信方法を指 定する. • http-equiv: meta タグにより指定するメタデータの 種類を指定する. • content: meta タグにより指定するメタデータの中 身を指定する. • style: CSS の書式によって体裁などを指定する.
3.3
HTML
ページの例
リスト 1 に示した HTML ページは,単純であること を優先して作成したものであり,HTML-lint[7] でチェッ クすれば分かるように,HTML 仕様への準拠は不十分で ある.また,ページ内で使われる文字の文字コードを指 定していないため,日本語などを使った場合には文字化 けし,適切に読めない可能性が高い.仕様への準拠や日 本語などの使用に留意した単純な HTML ページの一例 を,リスト 2 に示す.このファイルを Firefox で開いた イメージは,図 3 のようになる.4
CSS
の紹介
CSS[2] は,Cascading Style Sheets の頭字語であり, HTMLページの体裁を調節するための仕組みである.近
リスト 2: 仕様に準拠する単純な HTML ページ
< !DOCTYPE HTML PUBLIC
2 "−//W3C//DTD␣HTML␣ 4 . 0 1 ␣ T r a n s i t i o n a l //EN"> <html lang=" j a ">
4 <head>
<meta h t t p−equiv=" Content−type "
6 content=" t e x t / html ; ␣ c h a r s e t=UTF−8"> < t i t l e>仕様に準拠する単純な HTML ページ</ t i t l e> 8 </head> 10 <body> <div id="TOC"> 12 <o l>
< l i><a href="#C1 ">第 1 章</a> 14 <ul>
< l i><a href="#C1 . S1 ">1 . 1 節</a></ l i> 16 < l i><a href="#C1 . S2 ">1 . 2 節</a></ l i>
</ ul> 18 </ l i>
< l i><a href="#C2 ">第 2 章</a> 20 <ul>
< l i><a href="#C2 . S1 ">2 . 1 節</a></ l i> 22 < l i><a href="#C2 . S2 ">2 . 2 節</a></ l i>
</ ul> 24 </ l i> </ o l> 26 </ div> 28 <hr> 30 <div> <h1 id=" C1 ">第 1 章</h1> 32 <h2 id=" C1 . S1 ">1 . 1 節</h2> <p>第 1 段落.</p> 34 <p>第 2 段落.改行前<br>改行後 </p> 36 <h2 id=" C1 . S2 ">1 . 2 節</h2> 38 <p>ほげ</p> </ div> 40 <hr> 42 <div> 44 <h1 id=" C2 ">第 2 章</h1> <h2 id=" C2 . S1 ">2 . 1 節</h2> 46 <h2 id=" C2 . S2 ">2 . 2 節</h2> </ div> 48 </body> 50 </html> 年の HTML ページのほとんどでは,論理構成を含む真に 価値のある中身は HTML で記述され,体裁は別添の CSS ファイルで指定されている.CSS ファイルを切り替える ことで,同一の HTML ページを,スマートフォンでは縦 長,パソコンでは横長などと,環境におうじて見やすく 表示できる.この際,CSS の指定を単一の CSS ファイル で行うのであっては,CSS ファイルの作成・管理が難し くなる.この困難を避けるために,CSS は,HTML ペー ジの一部の要素の体裁を指定する多数の CSS ファイルを, 明確な優先順序のもと連結(カスケード)して使えると いう仕様になっている.この結果,高度な体裁を少ない 手間で指定することが可能となっている. CSSの基本は,“セレクタ” で指定される要素の “プロ 図 3: 仕様に準拠する単純な HTML ページの表示画面 パティ” の値を指定するルールを記述することである.“ セレクタ” で選ばれる要素は,基本的にタグである.例え ば,セレクタを「h1」とすれば,そのルールが効果を持 つすべての h1 タグが選ばれる.このようにしていては選 択範囲が広すぎるため,実際には,HTML の class 属性 や id 属性を用いるなどして,適切な要素だけを選べるよ う,ルールを記述する.“プロパティ” は,対応する要素 の位置や色などを指定する変数であり,top, left, color など無数に規定されている.なお,昔ほどではないが,ブ ラウザごとに CSS への準拠状況が異なり,あるブラウザ では機能するがべつのブラウザでは機能しないというこ とがある点に注意する. 近年では,CSS3[3] と呼ばれる,HTML ページの閲覧 環境(どのようなサイズの画面で見ているのかなど)を 調べたり,セレクタへの適合ルールをより高度・適応的 に記述できるバージョンが策定されつつある.このよう な特長が,さまざまな機器や画面サイズへ単一のファイ ルで対応するという,レスポンシブデザインと呼ばれる 効率の高い Web デザインを可能としている.
5
JavaScript
の紹介
JavaScriptは,さまざまなプラットフォームで動く,オ ブジェクト指向のスクリプト言語である [4].関数自体も オブジェクトとして,例えばある変数へ関数(へのリファ レンス)を代入することができる.また,スクリプト言 語であり,C 言語などでは必要となる事前コンパイルを, JavaScriptは必要としない. JavaScriptは,クライアントサイドで(HTML ブラウ ザ上で),HTML ページの中身を動的に(ユーザの操作 や環境におうじて)切り替えるために多用される.ユー ザの操作を検知するために,HTML の onclick 属性など が仕様される.この属性の値として,その属性が付与さ れたタグをユーザがクリックしたときに起動するイベン トハンドラ(イベントを処理する関数)を設定する.イ ベントハンドラ内では,タグをオブジェクトとして取得 し,そのオブジェクトを innerText メソッドなどを用い て変更することにより,タグ,ひいては HTML ページを 変更する.オブジェクトとしてのタグを取得する方法の 例としては,イベントハンドラに変更対象のタグの id 属 性を引数として与え,このデータおよび WebAPI として 提供されている document.getElementById 関数を用い ることが挙げられる. JavaScript の 生 産 性 を 高 め る た め に ,jQuery.js[8], Prototype[9]といったライブラリが開発されており,多 くの Web サイトで活用されている.また,上述のような クライアントサイドでの用途以外にも,Node.js[10] など, サーバサイドで JavaScript を活用する環境も開発されて いる.6
CGI
の紹介
6.1
CGI
の役割
基本的な Web ページは静的・一方向的である.そのよう なページを閲覧する際,ユーザは同一の内容を Web サー バから受け取ることになる.近年では,JavaScript が広 く利用されるようになり,ユーザの操作におうじて内容 の変化する動的 Web ページが膾炙している.また,Ajax と呼ばれる一連の技術を利用することで,ユーザが入力 したデータにおうじて即時に変化する双方向的動的 Web ページも一般的になりつつある. CGIは,このような現況において,ユーザが入力した データにおうじてサーバの振る舞いを変えるという,双 方向的やり取りを支えている技術である.検索サービス などを提供する企業により,Ajax を用いて検索を行いや すくするためのスクリプト・ライブラリなどが無償で配 布されており,そのようなライブラリを使うだけならば CGIについての知識はあまり必要ない.しかし,新奇な 図 4: Google のトップページのソース(抜粋) サービスを考案・開始するなど,ライブラリを使うだけ ではなく作ることができるためには,CGI に関する知識 は必須と考えられる.具体的には,Ajax により即時に変 化する Web ページが存在するとき,その内部では form タグが使用され,どこかのサーバと CGI によりデータを やり取りしている.例えば,Google[11] のトップページ の HTML ソースを見ると,図 4 に示すように,form タ グを使っていることが分かる.6.2
Web
ページと CGI プログラム間のやり
取り
CGIが提供する機能は,大きく三つに整理できる. 1. ブラウザを介して,ユーザが Web サーバ上でプログ ラム(CGI プログラムと呼ぶ)を実行すること. 2. ブラウザを介してユーザが与えたデータを,CGI プ ログラムが受け取ること.3. Webサーバが,CGI プログラムの出力を,Web ペー ジとしてブラウザへ返すこと.
CGIプログラムと(Ajax を用いない)Web ページと のやり取りは,つぎのようになる. 1. ユーザがブラウザを用いて Web ページへアクセス する. 2. 当該 Web ページ上でユーザが適宜操作することで, ユーザが入力/選択したデータを処理せよという指 示が,ブラウザから Web サーバへ送られる.
user browser Web server(httpd) (CGI program)Web server time 1. 2. 3. 4. 5. 6. 7. 図 5: CGI を用いる Web ページとのやり取りのイメージ 3. Webサーバは,ブラウザから送られた指示に基づき, CGIプログラムを実行し,ユーザにより入力/選択 されたデータを渡す. 4. CGIプログラムは,ユーザにより入力/選択された データを適宜処理し,何らかの結果を出力する. 5. Webサーバは,CGI プログラムからの出力を受け 取る. 6. Webサーバは,CGI プログラムの出力をブラウザへ 返す. 7. ブラウザは,Web サーバから返された内容を Web ページとして表示する. このやり取りのイメージを図 5 に示す.
6.3
データの送信
ある HTML ページから CGI プログラムへデータを送 信するためには,form タグを用いる.form タグの action 属性により実行する CGI プログラムを指定し,method 属性によりデータの送信方法を指定する.なお,本資料 では,ユーザが入力/選択したデータが,HTML ページ 内で表示される際に問題とならないよう適宜符号化され た(URL 符号化 [12])ものを,フォームデータと呼ぶこ とにする.ユーザが入力/選択したデータは,form タグ 経由で CGI プログラムが受け取るフォームデータとは異 なる点に注意する. 6.3.1 method属性による送信方法の指定 データの送信方法は,form タグの method 属性により 指定する.method 属性の値は GET, POST5のいずれかである.それらのおもな違いを表 1 に示す. GETメソッドは, • フォームデータのサイズが小さく, 5小文字でもよい. • 同じフォームデータが与えられれば,同じ結果が返 され, • パスワードなどの機密情報を,フォームデータが含 んでいない6 場合に用いられる.キーワードを与えて検索サービスを 提供するサーバの CGI プログラムが,GET メソッドの 使われる典型例であるといえる.GET メソッドが使われ ない場合には,POST メソッドが使われる. 6.3.2 タグによるデータ送信 デ ー タ の 入 力 / 選 択 に は ,form タ グ に 含 ま れ る , textareaタグ,input タグ,または select タグを用いる. これらのタグは,文字列といった一連のデータを CGI プ ログラムへ送る.それら 3 種類のタグには name という 属性があり,この属性はタグで渡される変数の名前を指 定しているといえる.textarea タグは複数行の文字列を 入力するために,select タグは複数の選択肢をリスト状に 表示し,そのなかから選択肢 (option) を選ぶために,そ れぞれ用いる.input タグは type という属性を持ち,そ の値を指定することで,表 2 に示すようにさまざまな機 能を発揮できる. 変数の値は,つぎのようにして指定する. • textarea タグ: その中身.
• select タグ: このタグが含む option タグの value 属
性の値.
• input タグ: type 属性の値が radio, checkbox, hidden
のいずれかならば value 属性の値.そうでなければ, 基本的に,その中身. 変数の名前および値は,基本的に, 1. URLとして扱えるように,名前と値のどちらも URL 符号化 [12] されたあと, 2. 変数名とその値をイコール (=) で連結し, 3. このペアを全変数にわたってアンパサンド (&) で連 結したうえで, CGIプログラムへ送信される.例えば,「3」という値を 持つ変数 hoge,「fuga」という値を持つ変数 bar の 2 つを CGIプログラムへ渡す際の形式は,「hoge=3&bar=fuga」 となる.
6あるブラウザでアクセスしている Web ページの URL は,フィッ
シングを避けるといったセキュリティ上の配慮から,ブラウザのアドレ ス欄に表示される点に注意する.
表 1: GET と POST のおもな違い method フォームデー タのサイズ フォームデータの渡され方 リクエスト時の URL 結果へのリンク (&キャッシュ) GET 限定的 環境変数を介して フォームデータが含まれる 可能 POST 多い 標準入力を介して フォームデータが含まれない 不可能 表 2: input タグが発揮できるおもな機能 type属性の値 機能 text 一行の文字列を入力. password ブラウザ上では読めないように表示される一行の文字列を入力.暗号化されているわけではないの で注意. radio 複数の選択肢のうちの一つを選択. checkbox 各選択肢を個別に選択.複数選ぶことも,まったく選ばないことも可能. file アップロードするファイルを選択. hidden ブラウザ上に表示されないため,ユーザからは見えず,通常は変更できない変数を保持.少し工夫 すれば,ユーザが見ることも変更することもできるので注意.
submit formタグが含むデータを CGI プログラムへ送信する. reset formタグ内で入力/選択されたデータをクリアする.
6.4
CGI
プログラムの例
CGIプログラムは,フォームデータを適切に処理でき るのであれば,どのような言語で実装してもよい.フォー ムデータは基本的に文字列であるため,高度な文字列処 理を手軽に行える Perl, PHP, Python, Ruby といった言 語の使われることが多い.本演習では,それらの言語の 学習に時間を割くことを避け,またそれらの言語のあり がたさを体感するためにも,これまでに習ってきた C 言 語により実装することとする. 6.4.1 フォームデータを用いないプログラム フォームデータを用いないプログラムは,CGI プログ ラムとしてはあまり意味がないが,動的に HTML ページ が生成される様子を眺める点では意味があると思われる. 実行するたびにサイコロの目を返すプログラムソースの 一例を,リスト 3 に示す.また,このプログラムを CGI プログラムとして動かすための HTML ページの一例を, リスト 4 に示す. 6.4.2 フォームデータをたんに出力するプログラム CGIプログラムは,環境変数を介してさまざまな情報 を得る [5].例えば,REQUEST_METHOD という環境 変数を調べることで,フォームデータの送信方法(POST であるか,GET であるか)を判定することができる.こ のような主要な環境変数を表 3 に示す. 環境変数の値は,(stdlib.h でプロトタイプが宣言され ている)標準関数に含まれる,getenv という関数を用い て取得することができる.また,フォームデータの取得手 続きは,環境変数 REQUEST_METHOD の値によって 異なる.この環境変数の値におうじて取得したフォーム データをそのまま(URL 符号化を元に戻したりせずに) 出力する CGI プログラムのソースの一例を,リスト 5 に 示す. 6.4.3 cgilibを用いてフォームデータを出力する例 現実的な CGI プログラムでは, 1. &をデリミタとしてフォームデータを分割し, 2. 分割後のデータの「=」より左を変数名,右をその 値とし, 3. それぞれ URL 符号化の反対の処理(復号化)を行う ことで,もとの入力データを復元・使用する.このよう な処理は広く使用される定型的なものであり,そのため の多くのライブラリが作成・配布されている.本資料で は,そのようなライブラリの一例として,cgilib[13] を用 いたプログラムを例示する.なお,cgilib は GPL[14] と いうライセンスのもとで頒布されており,cgilib にもとも と含まれているファイル群に手を加えないとしても, • 2 次派生プログラムのソースにおいて GPL を明記 する; • 2 次派生プログラムの利用ライセンスも GPL とする;
リスト 3: サイコロを振る CGI プログラムのソース /∗ 実行するたびに 1−6 の数字を表示するプログラム ∗/ 2 #include < s t d i o . h> 4 #include <t i m e . h> #include < s t d l i b . h> 6 #de f i n e HTML_HEADER(CHAR_SET) \
8 " Content−type : ␣ t e x t /html ; ␣ c h a r s e t=" CHAR_SET " \n\n " 10 i n t main ( void )
{
12 const time_t now = t i m e (NULL ) ; /∗ 時刻を取得 ( c f . man −a time ) ∗/
i n t num ; 14 s r a n d ( ( unsigned ) now ) ; /∗ 擬似乱数系列の初期値を設定 ∗/ 16 num = rand ( ) % 6 + 1 ; /∗ サイコロを振る ∗/ 18 /∗ ページの文字コードは UTF−8 とする ∗/ 20 p u t s (HTML_HEADER( "UTF−8" ) ) ; p u t s ( "<html><body>" ) ; 22 /∗ HTML による記述を出力 ∗/ 24 p r i n t f ( "<p>s e e d ␣=␣%l d ; ␣ d i c e ␣=␣%d</p>\n " , now , num ) ;
26 p u t s ( "<form ␣ a c t i o n =\"/~ inamoto / c g i−bin /CGI−d i c e . c g i \" ␣method=\"GET\">\n " " ␣<i n p u t ␣ t y p e =\" s u b m i t \ " ␣ v a l u e =\" ␣もう一度振る␣ \">\n " 28 "</form>" "</html></body>" ) ; 30 return 0 ; 32 } リスト 4: サイコロを振る CGI プログラムを用いる HTML ページ <html> 2 <head>
<meta h t t p−equiv=" Content−type " c o n t e n t s=" t e x t /html ; ␣ c h a r s e t=UTF−8"> 4 < t i t l e>サイコロを振る CGI プログラム</ t i t l e>
</head> 6
<body>
8 <form action=" /~ inamoto / c g i−bin /CGI−d i c e . c g i " method="GET"> <input type=" s u b m i t " value="サイコロを振る ">
10 </form> </body> 12 </html> • 複製・頒布する際には cgilib のみならず 2 次派生プ ログラムのソースも提供する,あるいは提供手段を 提供する; といった対応が必要と考えられる点に注意する.このよ うに,GPL にしたがうプログラムを利用する際にはきわ めて高度な注意が必要であり,例えば GPL にしたがう プログラムソースの一部を社内で開発したプログラムの ソースに含めると,そのプログラム全体のソースの公表 を可能とする,あるは社内で開発したプログラムの複製・ 頒布を中止することが求められる. cgilibを用いて CGI 経由で与えられたデータを変数ご とに表示するプログラムのソースをリスト 6 に示す.この ソースをコンパイルするための手続きは,付録 A に示す. また,このプログラムの動作をテストするための HTML ページの一例を,リスト 7 に示す. な お ,本 小 節 で 説 明 し た プ ロ グ ラ ム は ,フォー ム デ ー タ を 復 号 化 し て い る た め ,HTML ペ ー ジ 内 で 使 用 す る と 危 険 な 文 字 列 も そ の ま ま 出 力 さ れ る 点 に 注 意 す る .例 え ば ,textarea タ グ に「<form action="http://somewhere/virus.cgi" method="GET"><input type="submit" value=" 押 さ な い で"></form>」な ど と 入 力 す れ ば , CGI プ ロ グ ラ ム を 実 行 し て 得 ら れ た 出 力 の 中 に , http://somewhere/virus.cgi と い う 怪 し い 外 部 の CGIプログラムを呼び出す form タグが含まれてしまう. CGIプログラムからの出力はブラウザに表示されるが, 好奇心などで怪しいフォームの送信ボタンを押下すると, ページに含まれるフォームデータが外部へ送信されてし
表 3: CGI プログラムから参照できる主要な環境変数
環境変数 保持している情報
REQUEST_METHOD formタグの method 属性で指定されたフォームデータ送信方法 QUERY_STRING 送信方法が GET である場合のフォームデータ
CONTENT_LENGTH 送信方法が POST である場合に,標準入力から読み取れるフォームデータのバイト数 PATH_INFO URLにおける,CGIプログラム名以降(送信方法がGETである場合には?までの)の部分
まう.
6.4.4 cgilibを用いて変数を保持する例
ある CGI プログラムに入力したデータを,その CGI プ ログラムあるいはほかの CGI プログラムで利用するため には,type 属性が hidden である input タグを用いて対 応する変数を保持することが典型的である.例えば,リ スト 8 にソースを示す CGI プログラムは,ある空でない 文字列を,空でない文字列が新たに指定されれば置き換 えながら,保持し続けるものである. なお,type 属性が hidden である変数の値は,ブラウ ザ上に表示されないだけであり,HTML で書かれたソー スを見れば確認できる.CGI プログラム間で機密情報を, このようにして渡してはいけない.
7
おわりに
本資料では,HTML などについて簡単に説明した.詳 細は,例えば Web 上で検索すると見つかるホームページ [15]など,ほかの資料を参考されたい.また,C 言語で CGIプログラムを作成するためのライブラリとして cgilib を紹介し,その使用例を示した.このライブラリを含め, 多くの有用なライブラリやプログラムが GPL のもと公 開されているが,GPL 汚染 [16] という言葉が生じている ように,それらの利用の際には十分な注意が必要がある.A
cgilib
を用いて
CGI
プログラムを
作成する手続き
ここで説明する手続きでは,以下を前提する. • 作業するユーザのホームディレクトリは,~user で ある. • プログラムのソースは,~user/workspace/cgi/src というディレクトリの下に,sample.c という名前 で置かれている. • sample.c の中では,cgilib の一部であるヘッダファイル cgi.h が,「#include <cgi.h>」という書式で インクルードされている. • CGI プログラムは,~user/public_html/cgi-bin というディレクトリの下に,sample.cgi という名 前で設置する. これらの前提における設定(例えば CGI プログラム名な ど)は,実際の状況におうじて異なる点に注意する. cgilibを用いるソースから CGI プログラムを作成する 手続きは,つぎのようになる. 1. cgilib のソースを配布元のホームページ [13] から 取 得 し ,~user/workspace/cgi/src と い う ディ レクトリに保存する.この結果,本資料作成時点 での cgilib の最新バージョンは 0.7 であるため, ~user/workspace/cgi/src/cgilib-0.7.tar.gz という(アーカイブ)ファイルが作成される. 2. 端末を開いてつぎのように入力することで,アーカ イブファイルを伸張する. (a) cd ~user/workspace/cgi/src (b) tar zxvf cgilib-0.7.tar.gz この結果,~user/workspace/cgi/src/cgilib-0.7 というディレクトリが作成される. 3. プログラムソースをコンパイルする.cgilib 内で必 要なソースファイルは cgi.c, aux.c, cookies.c の三つであるため,コンパイルのために端末へ入力 するコマンドは以下のようになる. (a) gcc -I cgilib-0.7 -o ~user/public_html/cgi-bin/sample.cgi sample.c cgilib-0.7/cgi.c cgilib-0.7/aux.c cgilib-0.7/cookies.c なお,このコマンドは,資料の上では改行されてい るが,端末上では改行せず一行で入力する.
参考文献
[1] HTML 4.01 Specification: http://www.w3.org/TR/ html401/(2014 年 3 月 21 日閲覧).[2] Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification: https://www.w3.org/TR/CSS2/ (2016 年 4 月 12 日閲覧).
リスト 5: フォームデータを出力する単純な CGI プログラムのソース /∗ フォームデータをたんに出力するプログラム ∗/ 2 #include < s t d i o . h> 4 #include < s t d l i b . h> #include < s t r i n g . h> 6 #include <e r r n o . h> #include < a s s e r t . h> 8 #de f i n e HTML_HEADER(CHAR_SET) \
10 " Content−type : ␣ t e x t /html ; ␣ c h a r s e t=" CHAR_SET " \n\n " 12 i n t main ( void )
{
14 i n t d a t a _ s i z e ; /∗ フォームデータのデータサイズ ∗/
char ∗ buf = NULL; /∗ フォームデータを保持しておくところ ∗/
16 char ∗cp ;
18 p u t s (HTML_HEADER( "UTF−8" ) ) ; /∗ Web ページの文字コードは UTF−8 が一般的 ∗/ p u t s ( "<html><body>" ) ;
20
/∗ 送信方法は POST .標準入力から読み取る ∗/
22 i f ( ( cp = g e t e n v ( "REQUEST_METHOD" ) ) && ( ! s t r c m p ( cp , "POST" ) ) ) { cp = g e t e n v ( "CONTENT_LENGTH" ) ; /∗ データサイズを取得 ∗/
24 a s s e r t ( cp ) ;
d a t a _ s i z e = a t o i ( cp ) ; /∗ 数字を,数値へ変換 ∗/
26 b u f = ( char∗) malloc ( data_size + 1 ) ; /∗ メモリを確保.\0 用に +1 ∗/ cp = f g e t s ( buf , d a t a _ s i z e + 1 , s t d i n ) ; /∗ データを取得 ∗/ 28 b u f [ d a t a _ s i z e ] = ’ \0 ’ ; } e l s e i f ( cp && ( ! s t r c m p ( cp , "GET" ) ) ) { 30 /∗ 送信方法は GET .環境変数から読み取る ∗/ cp = g e t e n v ( "QUERY_STRING" ) ; 32 a s s e r t ( cp ) ; d a t a _ s i z e = s t r l e n ( cp ) ; /∗ サイズを取得 ∗/
34 b u f = ( char∗) malloc ( data_size + 1 ) ; /∗ メモリを確保.\0 用に +1 ∗/ memcpy ( buf , cp , d a t a _ s i z e + 1 ) ; /∗ データを取得 ∗/ 36 } e l s e { f p r i n t f ( s t d e r r , " i n v a l i d ␣ method : ␣%s \n " , cp ) ; 38 e x i t (EXIT_FAILURE ) ; } 40 /∗ フォームデータを処理.今回はそのまま出力 ∗/ 42 p r i n t f ( " form ␣ d a t a ␣ f o l l o w s :< br >\n " ) ; f p u t s ( buf , s t d o u t ) ; 44 p u t s ( " \n</body></html>" ) ; 46 f r e e ( b u f ) ; /∗ メモリを解放 ∗/ 48 return 0 ; 50 }
[3] Cascading Style Sheets home page: https://www. w3.org/Style/CSS/(2016 年 4 月 12 日閲覧). [4] JavaScript | Mozilla Developer Network:
https://developer.mozilla.org/ja/docs/ Web/JavaScript(2016 年 4 月 12 日閲覧). [5] The WWW Common Gateway
Inter-face 1.1: http://tools.ietf.org/html/ draft-robinson-www-interface-00(2014 年 3月 27 日閲覧).
[6] HTML5: https://www.w3.org/TR/html5/(2016 年 4 月 12 日閲覧).
[7] 石野恵一郎: Another HTML-lint gateway, http: //cetus.sakura.ne.jp/htmllint/htmllint.html (2014 年 3 月 21 日閲覧). [8] jQuery: http://jquery.com/(2016 年 4 月 12 日閲 覧). [9] Prototype: http://prototypejs.org/(2016 年 4 月 12 日閲覧). [10] Node.js : https://nodejs.org/en/(2016 年 4 月 12日閲覧).
[11] Google, Inc.: http://www.google.co.jp/(2014 年 3 月 26 日閲覧).
[12] URL Character Encoding Issues: http://tools. ietf.org/html/rfc1738#section-2.2(2014 年 3 月 21 日閲覧).
[13] Lightweight CGI Library: http://www.infodrom. org/projects/cgilib/(2014 年 4 月 2 日閲覧). [14] GNU 一般公衆利用許諾契約書(非公式翻訳版): http://sourceforge.jp/projects/opensource/ wiki/licenses\%2FGNU_General_Public_License (2014 年 4 月 2 日閲覧). [15] とほほの WWW 入門: http://www.tohoho-web. com/www.htm(2014 年 4 月 3 日閲覧). [16] 「気にしていますか? オープンソースのソース コ ー ド 混 入 」: http://itpro.nikkeibp.co.jp/ article/OPINION/20061124/254769/?ST=network (2014 年 4 月 3 日閲覧).
リスト 6: cgilib を用いてデータを変数ごとに表示する CGI プログラムのソース
/∗∗∗
2 C o p y r i g h t (C) INAMOTO Tsutomu & Ehime U n i v e r s i t y
4 This program i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and/ or m o d i f y i t under t h e te r m s o f t h e GNU G e n e r a l P u b l i c L i c e n s e
6 a s p u b l i s h e d by t h e Free S o f t w a r e Foundation ; e i t h e r v e r s i o n 2 o f t h e L i c e n s e , or ( a t your o p t i o n ) any l a t e r v e r s i o n .
8
This program i s d i s t r i b u t e d i n t h e hope t h a t i t w i l l b e u s e f u l ,
10 b u t WITHOUT ANY WARRANTY; w i t h o u t even t h e i m p l i e d w a r r a n t y o f MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See t h e
12 GNU G e n e r a l P u b l i c L i c e n s e f o r more d e t a i l s .
14 You s h o u l d have r e c e i v e d a copy o f t h e GNU G e n e r a l P u b l i c L i c e n s e a l o n g w i t h t h i s program ; i f not , w r i t e t o t h e Free S o f t w a r e
16 Foundation , I n c . , 59 Temple P l a c e − S u i t e 330 , Boston , MA 02111−1307, USA. ∗∗∗/ 18 /∗ ↑ GPL ∗/ 20 #i n c l u d e < s t d l i b . h> 22 #i n c l u d e < s t d i o . h> #i n c l u d e < s t r i n g . h> 24 #i n c l u d e <e r r n o . h> 26 #i n c l u d e < c g i . h>
28 i n t main ( i n t a r g c , char ∗∗ argv )
{ 30 s _ c g i ∗ c g i ; char ∗∗ vars , ∗∗ f i l e s ; 32 i n t i ; 34 c g i = c g i I n i t ( ) ; /∗ c g i l i b の初期化 ∗/ c g i S e t T y p e ( " t e x t / html ; ␣ c h a r s e t=UTF−8" ) ; /∗ 文字コードを UTF−8 に ∗/ 36 c g i H e a d e r ( ) ; /∗ HTTP ヘッダを出力 ∗/ 38 p u t s ( "<html><body>" ) ; 40 v a r s = c g i G e t V a r i a b l e s ( c g i ) ; /∗ 変数名の一覧を取得 ∗/ i f ( v a r s ) { 42 p u t s ( "<p>␣変数一覧␣</p>\n<d l >" ) ; f o r ( i = 0 ; v a r s [ i ] ; i ++) { 44 /∗ 変数名と復号化された値を出力 ∗/ p r i n t f ( "<dt>%s </dt >\n<dd>%s </dd>\n " , v a r s [ i ] , c g i G e t V a l u e ( c g i , v a r s [ i ] ) ) ; 46 } p u t s ( "</d l >" ) ; 48 c g i F r e e L i s t ( v a r s ) ; /∗ メモリを解放 ∗/ 50 } 52 f i l e s = c g i G e t F i l e s ( c g i ) ; /∗ アップロードされたファイルの一覧を取得 ∗/ i f ( f i l e s ) { 54 p u t s ( "<p>␣ファイル一覧␣</p>\n<d l >" ) ; f o r ( i = 0 ; f i l e s [ i ] ; i ++) { 56 s _ f i l e ∗ f i l e v a r ; char b u f f e r [ 1 0 2 4 ] ; 58 FILE ∗ fp ; char ∗e1 , ∗ e2 ; 60 f i l e v a r = c g i G e t F i l e ( c g i , f i l e s [ i ] ) ; 62 p r i n t f ( "<dt>␣クライアント側のファイル名␣ : ␣%s ; ␣サーバ側のファイル名␣ : ␣%s </dt >\n<dd>" , ( e 1 = c g i E s c a p e ( f i l e v a r−>f i l e n a m e ) ) , ( e 2 = c g i E s c a p e ( f i l e v a r−>t m p f i l e ) ) ) ; 64 f r e e ( e 1 ) ; f r e e ( e 2 ) ; /∗ cgiEscape 内部で確保したメモリを解放 ∗/ 66 i f ( ! ( f p = f o p e n ( f i l e v a r−>t m p f i l e , " r " ) ) ) { /∗ ファイルを開く ∗/ p r i n t f ( " f a i l e d ␣ i n ␣ o p e n i n g ␣ f i l e : ␣%s<br >\n " , s t r e r r o r ( e r r n o ) ) ; 68 e x i t (EXIT_FAILURE ) ; } 70 while ( f g e t s ( b u f f e r , s i z e o f ( b u f f e r ) , f p ) ) { /∗ ファイルの中身を出力 ∗/ p r i n t f ( "%s " , b u f f e r ) ; /∗ \n はスペースと同じように解釈され,そこでは改行されない ∗/ 72 } f c l o s e ( f p ) ; 74 p u t s ( "</dd></d l >" ) ; } 76 c g i F r e e L i s t ( f i l e s ) ; } 78 p u t s ( "</body></html>" ) ; 80 c g i F r e e ( c g i ) ; /∗ メモリを解放 ∗/ 82 return EXIT_SUCCESS ; 84 }
リスト 7: データ表示用 CGI プログラムを使用する HTML ページの例
<html> 2 <head>
<meta h t t p−equiv=" Content−type " c o n t e n t s=" t e x t / html ; ␣ c h a r s e t=UTF−8"> 4 < t i t l e>c g i−dump</ t i t l e>
</head> 6
<body>
8 <h1>送信方法がGET</h1>
<form a c t i o n=" /~ i n a m o t o / c g i−bin /CGI−decoded−dump . c g i " method="GET"> 10 <h2>i n p u t</h2>
<u l>
12 < l i>t y p e 属性が t e x t <input type=" t e x t " value=" i n p u t ␣ p l z . " name="GET−t e x t "> </ l i>
14 < l i>t y p e 属性が p a s s w o r d <input type=" p a s s w o r d " value=" p a s s w o r d ␣ p l z . " name="GET−password "> </ l i>
16 < l i>t y p e 属性が r a d i o <input type=" r a d i o " value=" y e s " name=" レディオ ">y e s <input type=" r a d i o " checked value="いいえ " name=" レディオ ">いいえ 18 </ l i>
< l i>t y p e 属性が c h e c k b o x
20 <input type=" c h e c k b o x " value=" a p p l e " name="GET−checkbox ">apple <input type=" checkbox " value=" みかん " name="GET−checkbox ">みかん <input type=" checkbox " value="いちご" name="GET−checkbox ">いちご
</ l i>
22 < l i>t y p e 属性が h i d d e n <input type=" h i d d e n " value=" h i d d e n ␣ v a l u e " name="GET−hidden "> </ l i>
24 </ u l>
26 <h2>t e x t a r e a</h2>
<text ar ea name="GET−t e x t a r e a ">テキストエリア</ textarea> 28
<h2> s e l e c t</h2>
30 <s e l e c t name="GET−s e l e c t ">
<option value="選 択 肢1 ">選 択 肢1</ option> <option value=" o p t i o n ␣ 2 ">o p t i o n 2</ option> <option value=" 選択肢3 ">選択肢3</ option>
32 </ s e l e c t> <br>
34 <input type=" s u b m i t " value="送信 "> <input type=" r e s e t " value=" リセット "> </form>
36
<hr> 38
<h1>送信方法がPOST</h1>
40 <form a c t i o n=" /~ i n a m o t o / c g i−bin /CGI−decoded−dump . c g i " method="POST"> <h2>i n p u t</h2>
42 <u l>
< l i>t y p e 属性が p a s s w o r d
44 <input type=" p a s s w o r d " value=" p a s s w o r d ␣ p l z . " name="POST−password "> </ l i>
46 </ u l>
48 <h2>t e x t a r e a</h2>
<text ar ea name="POST−t e x t a r e a ">テキストエリア</ textarea> 50 <br>
<input type=" s u b m i t " value="送信 "> <input type=" r e s e t " value=" リセット "> 52 </form>
54 <hr>
56 <h2>ファイルをアップロードする場合</h2>
<form a c t i o n=" /~ i n a m o t o / c g i−bin /CGI−decoded−dump . c g i " method="POST" enctype=" m u l t i p a r t /form−data "> 58 <h2>i n p u t</h2>
<u l>
60 < l i>t y p e 属性が t e x t <input type=" t e x t " value=" i n p u t ␣ p l z . " name=" form−t e x t "> </ l i>
62 < l i>t y p e 属性が p a s s w o r d <input type=" p a s s w o r d " value=" p a s s w o r d ␣ p l z . " name=" form−password "> </ l i>
64 < l i>t y p e 属性が r a d i o <input type=" r a d i o " value=" y e s " name=" レディオ ">y e s <input type=" r a d i o " checked value="いいえ " name=" レディオ ">いいえ 66 </ l i>
< l i>t y p e 属性が c h e c k b o x <input type=" c h e c k b o x " value=" a p p l e " name=" form−checkbox ">apple
68 <input type=" c h e c k b o x " value="みかん " name=" form−checkbox ">みかん
<input type=" c h e c k b o x " value="いちご " name=" form−checkbox ">いちご
70 </ l i>
< l i>t y p e 属性が h i d d e n <input type=" h i d d e n " value=" h i d d e n ␣ v a l u e " name=" form−hidden "> 72 </ l i>
< l i s t y l e=" f o n t−weight : ␣ bold ">type 属性が f i l e <input type=" f i l e " name=" form− f i l e ">
74 </ l i> </ u l> 76 <br>
<input type=" s u b m i t " value="送信 "> <input type=" r e s e t " value=" リセット "> 78 </form>
</body> 80 </html>
リスト 8: 文字列を保持し続ける CGI プログラムのソース /∗ ∗∗
2 C o p y r i g h t (C) INAMOTO Tsutomu & Ehime U n i v e r s i t y
4 T h i s program i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and / o r m o d i f y i t under t h e t e r m s o f t h e GNU G e n e r a l P u b l i c L i c e n s e
6 a s p u b l i s h e d by t h e Free S o f t w a r e F o u n d a t i o n ; e i t h e r v e r s i o n 2 o f t h e L i c e n s e , o r ( a t y o u r o p t i o n ) any l a t e r v e r s i o n .
8
T h i s program i s d i s t r i b u t e d i n t h e hope t h a t i t w i l l b e u s e f u l ,
10 b u t WITHOUT ANY WARRANTY; w i t h o u t e v e n t h e i m p l i e d w a r r a n t y o f MERCHANTABILITY o r FITNESS FOR A PARTICULAR PURPOSE. See t h e
12 GNU G e n e r a l P u b l i c L i c e n s e f o r more d e t a i l s .
14 You s h o u l d h a v e r e c e i v e d a copy o f t h e GNU G e n e r a l P u b l i c L i c e n s e a l o n g w i t h t h i s program ; i f not , w r i t e t o t h e Free S o f t w a r e
16 Foundation , I n c . , 59 Temple P l a c e − S u i t e 330 , Boston , MA 02111 −1307 , USA. ∗∗ ∗/
18
/∗ 変数を保持し続ける ∗/
20
#de f i n e VAR_NAME " r e m a i n i n g " 22 #de f i n e NEW_NAME " new_name " 24 #include < s t d i o . h> #include < s t d l i b . h> 26 #include < s t r i n g . h> #include < c g i . h> 28 i n t main ( void ) 30 { s _ c g i ∗ c g i ; 32 char ∗∗ vars , ∗cp ; char v a r _ v a l u e [ 1 0 2 4 ] = " " ; /∗ サイズ固定 ∗/ 34 i n t i ; 36 c g i = c g i I n i t ( ) ; /∗ c g i l i b の初期化 ∗/ c g i S e t T y p e ( " t e x t / html ; ␣ c h a r s e t=UTF−8" ) ; /∗ 文字コードを UTF−8 に ∗/ 38 c g i H e a d e r ( ) ; /∗ HTTP ヘッダを出力 ∗/ 40 v a r s = c g i G e t V a r i a b l e s ( c g i ) ; /∗ 変数名の一覧を取得 ∗/ i f ( v a r s ) { 42 f o r ( i = 0 ; v a r s [ i ] ; i ++) { i f ( ! s t r c m p ( v a r s [ i ] , VAR_NAME) ) { 44 s t r n c p y ( v a r _ v a l u e , c g i G e t V a l u e ( c g i , VAR_NAME) , s i z e o f ( v a r _ v a l u e ) ) ; /∗ 変数の値をコピー ∗/ break ; 46 } } 48 c g i F r e e L i s t ( v a r s ) ; /∗ メモリを解放 ∗/ } 50 i f ( ( cp = c g i G e t V a l u e ( c g i , NEW_NAME) ) && s t r c m p ( cp , " " ) ) { /∗ べつの所定の変数が空でなければ ∗/ 52 s t r n c p y ( v a r _ v a l u e , cp , s i z e o f ( v a r _ v a l u e ) ) ; /∗ 変数の値を変更 ∗/ } 54 p r i n t f ( "<html><body><p>␣%s ␣=␣%s </p>" , VAR_NAME, v a r _ v a l u e ) ; /∗ 値を参考までに表示 ∗/
56 p r i n t f ( "<form ␣ a c t i o n =\"/~ inamoto / c g i−bin /CGI−hidden . c g i \" ␣method=\"POST\"> " ) ; p r i n t f ( "新しい値␣ : ␣<i n p u t ␣ t y p e =\" t e x t \ " ␣ v a l u e =\"\" ␣name=\"%s \"> " , NEW_NAME) ; 58 i f ( s t r c m p ( v a r _ v a l u e , " " ) ) { p r i n t f ( "<i n p u t ␣ t y p e =\" h i d d e n \ " ␣name=\"% s \ " ␣ v a l u e =\"% s \"> " , 60 VAR_NAME, v a r _ v a l u e ) ; /∗ hidden 変数として保持 ∗/ } 62 p u t s ( "<i n p u t ␣ t y p e =\" s u b m i t \ " ␣ v a l u e =\" ␣実行␣\"></form></body></html>" ) ; 64 c g i F r e e ( c g i ) ; /∗ メモリを解放 ∗/ 66 return EXIT_SUCCESS ; }