環境変数

戻る

さて、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にとって必要なパラメータを上手に渡すように工夫することが必要だ。