さて、CGI出力を決まった形のページにする人はいないだろう。当然パラメータに応じてプログラムが動作し、結果を出力することになる。この時のパラメータとして、まずあげられるのが環境変数に格納されたものである。環境変数にどういうものがあるかということは、WWWブラウザとサーバの間でどういうデータがやり取りされているか、ということに他ならない。環境変数は、一般に、「Environ("NAME")」として得ることができる。ここでは、「多くの場合使うことになる」ものについてのみを紹介する。他のパラメータについては、御自身で確認して頂きたい。
参照ページ、つまり、CGIプログラムのページへ飛んできた元のページのURLは、「Environ("HTTP_REFERER")」で得られる。CGI出力に「参照ページへ戻る」を追加する時にこれを使用すると便利だ。ただし、いきなりブラウザにアドレスを打ち込んだ場合は、少々変なURLになることがあるので、注意した方が良い。ユーザーの使用しているブラウザについては、「Environ("HTTP_USER_AGENT")」で取得する。使用ブラウザによって出力を変えるのであれば、この文字列の値に応じて処理を変更するわけだ。
クエリー文字列は、URLの後ろにクエスチョンマークで区切られて記述される。例えば、「cgi.exe」というプログラムに対するクエリーは「cgi.exe?TEXT1=TEST&TEXT2=OK」というようになる。環境変数の「Environ("QUERY_STRING")」はURL上のクエスチョンマークより後ろの文字列、「TEXT1=TEST&TEXT2=OK」となる。クエリー文字列は、「名前=値」が「&」で区切られて羅列されるので、これらを切り分ける関数を作成しておくと便利だ。HTMLにクエリー文字列を含んだURLを書く場合は、区切り記号として、「&」と書くことが正しいとのこと。もっとも、この場合、サーバ(IIS)がこれを解釈してくれて、環境変数には「&」で入ってくるので気にしなくても良い。
クエリー文字列は、CGIプログラムを呼び出す時のコマンドライン引数でもある。上記のURL例でいくと、コマンドラインは「cgi.exe TEXT1=TEST&TEXT2=OK」というわけだ。どちらを使っても良いのだが、筆者としては環境変数を用いる方を推奨する。恥ずかしながら、プログラムを紹介。
Public Function GET_PARAM(ByVal Q As String, S As String, D As String) As String
Dim I, J, K As Integer
Dim T As String
Dim U As String
GET_PARAM = ""
If InStr(Q, "=") = 0 Then GET_PARAM = "": Exit Function
If Left(Q, 1) <> D Then Q = D & Q
If Right(Q, 1) <> D Then Q = Q & D
I = 1: K = InStr(2, Q, D)
Do
T = Mid(Q, I + 1, K - I - 1)
J = InStr(T, "=")
If J = 0 Then
U = ""
Else
U = DECODE_URL(Left(T, J - 1))
End If
If Trim(UCase(S)) = Trim(UCase(U)) Then
GET_PARAM = DECODE_URL(Mid(T, J + 1))
Exit Function
End If
I = K: K = InStr(I + 1, Q, D)
Loop Until K = 0
End Function
このプログラムは、元の文字列(S)と、指定した文字列(Q)と、パラメータ区切りの文字列(D)をセットして呼び出すことで、対応する値が得られるものだ。先程の例をとると、「GET_PARAM("TEXT1","TEXT1=TEST&TEXT2=OK","&")」とすると、「TEST」が戻ってくる。区切り文字列を指定するようにしているのは、後述の通り、テキストを「POST」した場合にも対応するためである。(決して奇麗なプログラムじゃないけど、目をつぶってもらいたい)
クエリー文字列は、通常のASCII文字であればそのままで良いが、特殊文字や8ビットキャラクタ(漢字など)の場合はURLエンコーディングがなされる。これを復元する必要が発生する。URLエンコーディングでは、特殊キャラクタはキャラクタコードを16進数にしたものを「%」の後ろに付けたものとなり、スペースは「+」となる。例えば、「漢字」は、「%B4%C1%BB%FA」となる。「漢 字」は、「%B4%C1+%BB%FA」となる。URLデコードも関数にしておくと良いだろう。(CGIプログラムを呼び出す際に、特殊文字を絶対使わないのであれば、当然問題は無い)
またまた汚いプログラムで恐縮だが、URLデコードを記述してみた。
Public Function DEESCAPE_URL(S As String) As String
Dim I, J, K As Long
Dim L As Long
Dim T As String
J = InStr(S, "%")
If J = 0 Then
DEESCAPE_URL = S
Exit Function
End If
DEESCAPE_URL = Left(S, J - 1)
For I = J To Len(S)
T = Mid(S, I, 1)
If T = "%" Then
K = CInt("&H" & Mid(S, I + 1, 2))
If K > &H7F Then
If Mid(S, I + 3, 1) = "%" Then
T = Chr(CInt("&H" & Mid(S, I + 1, 2) & Mid(S, I + 4, 2)))
I = I + 5
Else
T = Chr(CInt("&H" & Mid(S, I + 1, 2) & Hex(Asc(Mid(S, I + 3, 1)))))
I = I + 3
End If
Else
T = Chr(K)
I = I + 2
End If
End If
DEESCAPE_URL = DEESCAPE_URL & T
Next I
End Function
Public Function DEPLUS_URL(S As String) As String
Dim I As Integer
DEPLUS_URL = S
I = InStr(DEPLUS_URL, "+")
Do While I <> 0
Mid(DEPLUS_URL, I, 1) = " "
I = InStr(DEPLUS_URL, "+")
Loop
End Function
やれやれ、ここまで来ると、プログラミング下手を露呈する恥曝しだね。ま、これでも動くと言うことだ。これを呼び出すためには、「+」をスペースに変換する方を先に実行しなければならないので注意。また、クエリーからパラメータを切り出した後にデコードするなど、区切り用などの特殊なキャラクタが実際のデータに含まれている場合のことを考えてやらないといけない。
クッキーパラメータは、まさにクエリー文字列と同じように、「Environ("HTTP_COOKIE")」で取得ができる。ただし、クエリー文字列とは異なり、パラメータの区切りは「;(セミコロン)」となる。つまり「TEXT1=TEST;TEXT2=OK」ということだ。これはURLエンコードはされないので、そのまま使える(違ってたら指摘して下さい)。
CGIを呼び出すページも、CGI作者が作るか指定することになるはずである。作成するCGIにとって必要なパラメータを上手に渡すように工夫することが必要だ。