top
Loading...
用VB編寫標準CGI程序(下)
font size=2>

三、CGI編程實例

本節將用VB編寫一個處理主頁客戶留言簿的CGI程序。除了要調用本文前面所介紹的Win32API函數外,程序中還調用了Win32API函數GetTempFileName()來獲得一個唯一的臨時文件名。程序中的函數UrlDecode()用來對客戶端的輸入進行URL譯碼。函數GetCgiValue()則用來分解字符串,根據表單元素的NAME屬性獲取其VALUE值,并調用UrlDecode()函數對其進行URL譯碼。

本程序要求在留言簿文件guests.html中使用一個定位串“$#@60;! ENDHEAD $#@62;”,將文件的開始部分和具體的客戶留言部分分開。CGI程序將在“$#@60;! ENDHEAD $#@62;”所在的位置插入客戶新的留言。guests.html應具有如下所示的樣式:

$#@60;html$#@62;

$#@60;head$#@62;$#@60;title$#@62;DHTML Zone $#@60;/title$#@62;$#@60;/head$#@62;

$#@60;body bgcolor="#FFFFFF" text="#00000" vlink="#990000" link="#333399"$#@62;

$#@60;! ENDHEAD $#@62;

$#@60;!---客戶的留言部分從這開始--$#@62;

$#@60;P$#@62;……………………….

$#@60;!---客戶的留言部分結束于此--$#@62;

$#@60;/body$#@62;$#@60;/html$#@62;

這種樣式將保證最后的留言出現在留言簿的最前面。如果要想使最后的留言出現在留言簿的最后面,則只需將留言簿文件中的定位字符串“$#@60;! ENDHEAD $#@62;”移到留言簿文件中客戶留言部分和HTML文件結尾部分之間的位置就行了。整個程序的完整代碼如下所示:

guestbook.bas

Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long

Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any,ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long

Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long,ByVal lpBuffer As String, ByVal nNumberOfBytesToWrite As Long,lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long

Declare Function GetTempFileName Lib "kernel32" Alias "GetTempFileNameA"(ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long

Public Const ST NPUT_HANDLE = -10&

Public Const STD_OUTPUT_HANDLE = -11&

Public Const FILE_BEGIN = 0&

Public hStdIn As Long 標準輸入文件句柄

Public hStdOut As Long 標準輸出文件句柄

Public sFormData As String 用于存儲沒有經過URL譯碼的用戶輸入數據

Public lContentLength As Long

Public CGI_RequestMethod As String

Sub Main()

Dim CGI_ContentLength As String, CGI_QueryString As String, sBuff As String, chinesetail As String

Dim lBytesRead As Long, rc As Long,I As Long

Dim sEmail As String, sName As String, sURL As String, sfrom As String, tempstring As String

Dim sComment As String, tempFileName As String, guestbook As String

CGI程序的初始化工作

hStdIn = GetStdHandle(STD_INPUT_HANDLE)

hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)

CGI_RequestMethod = Environ("REQUEST_METHOD")

CGI_QueryString = Environ("QUERY_STRING")

CGI_ContentLength = Environ("CONTENT_LENGTH")

lContentLength = Val(CGI_ContentLength)

sBuff = String(lContentLength, Chr$(0))

OutPut "Content-type: text/html" & vbCrLf 輸出MIME類型

OutPut "$#@60;FONT SIZE=""+2""$#@62;"

If CGI_RequestMethod = "POST" Then

sBuff = String(lContentLength, Chr$(0))

rc = ReadFile(hStdIn, ByVal sBuff, lContentLength, lBytesRead, ByVal 0&)

sFormData = Left$(sBuff, lBytesRead)

ElseIf CGI_RequestMethod = "GET" Then

sFormData = CGI_QueryString

Else

OutPut "Unknow Form Method !"

End If

chinesetail = String(400, " ")

為了在頁面上正確顯示中文,生成一個空格串以獲取客戶端用戶的輸入

sName = GetCgiValue("name")

sEmail = GetCgiValue("email")

sURL = GetCgiValue("URL")

sfrom = GetCgiValue("from")

sComment = GetCgiValue("URL_Comment")

對客戶端用戶的輸入進行檢查

If Len(sName) = 0 Then

OutPut "$#@60;P$#@62;非常抱歉!您還沒有填寫姓名!" & chinesetail

Exit Sub

End If

If Len(sComment) = 0 Then

OutPut "$#@60;P$#@62;非常抱歉!您還沒有提出建議!" & chinesetail

Exit Sub

End If

獲取唯一的臨時文件名和留言簿文件并打開它們

tempFileName = TempFile("c:windowsemp", "gbk")

guestbook = "e:etscapeserverdocsguests.html"

Open tempFileName For Output As #1

Open guestbook For Input As #2

Do 本循環體用于將留言簿中字符串"$#@60;! ENDHEAD $#@62;"前面的內容寫入臨時文件

Line Input #2, tempstring

Print #1, tempstring

Loop While tempstring $#@60;$#@62; "$#@60;! ENDHEAD $#@62;" And Not EOF(2)

向臨時文件中插入客戶端用戶的留言

Print #1, "$#@60;hr$#@62;" & vbCrLf

Print #1, "$#@60;ul$#@62;" & vbCrLf

Print #1, "$#@60;li$#@62;$#@60;b$#@62;留言時間$#@60;/b$#@62;:" & Date$ & " " & Time$ & vbCrLf

Print #1, "$#@60;li$#@62;$#@60;b$#@62;姓名: $#@60;/b$#@62;" & sName & vbCrLf

If Len(sEmail) $#@60;$#@62; 0 Then

Print #1, "$#@60;li$#@62;$#@60;b$#@62;E-mail: $#@60;/b$#@62;$#@60;a href=""mailto:" & sEmail & """ $#@62;" & sEmail & "$#@60;/a$#@62;" & vbCrLf

End If

If Len(sURL) $#@60;$#@62; 0 Then

Print #1, "$#@60;li$#@62;$#@60;b$#@62;我的主頁: $#@60;/b$#@62; $#@60;a href=""" & sURL & """ $#@62;" & sURL & "$#@60;/a$#@62;" & vbCrLf

End If

If Len(sfrom) $#@60;$#@62; 0 Then

Print #1, "$#@60;li$#@62;$#@60;b$#@62;我來自: $#@60;/b$#@62;" & sfrom & vbCrLf

End If

Print #1, "$#@60;li$#@62;$#@60;b$#@62;我的建議: $#@60;/b$#@62;" & vbCrLf

Print #1, sComment & vbCrLf

Print #1, "$#@60;/ul$#@62;" & vbCrLf

Do 本循環體用于將留言簿剩余的東西寫入留言簿

Line Input #2, tempstring

Print #1, tempstring

Loop While Not EOF(2)

Close #1

Close #2

Kill guestbook 刪除舊的留言簿

Name tempFileName As guestbook 將臨時文件改成新的留言簿

OutPut "$#@60;P$#@62;非常感謝您的留言!" & chinesetail

OutPut "$#@60;P$#@62;歡迎您經常光顧本主頁!" & chinesetail

OutPut "$#@60;/FONT$#@62;"

End Sub

Sub OutPut(s As String) 本子程序用于向標準輸出寫信息

Dim lBytesWritten As Long

s = s & vbCrLf

WriteFile hStdOut, s, Len(s), lBytesWritten, ByVal 0&

End Sub

Public Function GetCgiValue(cgiName As String) As String

本子程序可以獲取表單上某一元素的數據

Dim delim2 As Long position of "="

Dim delim1 As Long position of "&"

Dim n As Integer

Dim pointer1 As Long,pointer2 As Long,length As Long,length1 As Long

Dim tmpstring1 As String,tmpstring2 As String

pointer1 = 1

pointer2 = 1

delim2 = InStr(pointer2, sFormData, "=")

pointer2 = delim2 + 1

Do

length = delim2 - pointer1

tmpstring1 = Mid(sFormData, pointer1, length)

delim1 = InStr(pointer1, sFormData, "&")

pointer1 = delim1 + 1

length1 = delim1 - pointer2

If delim1 = 0 Then length1 = lContentLength + 1 - pointer2

If tmpstring1 = cgiName Then

tmpstring2 = Mid$(sFormData, pointer2, length1)

GetCgiValue = UrlDecode(tmpstring2)

Exit Do

End If

If delim1 = 0 Then

Exit Do

End If

delim2 = InStr(pointer2, sFormData, "=")

pointer2 = delim2 + 1

Loop

End Function

Public Function UrlDecode(ByVal sEncoded As String) As String

本函數可以對用戶輸入的數據進行URL解碼

Dim pointer As Long sEncoded position pointer

Dim pos As Long position of InStr target

Dim temp As String

If sEncoded = "" Then Exit Function

pointer = 1

Do 本循環體用于將"+"轉換成空格

pos = InStr(pointer, sEncoded, "+")

If pos = 0 Then Exit Do

Mid$(sEncoded, pos, 1) = " "

pointer = pos + 1

Loop

pointer = 1

Do

本循環體用于將%XX轉換成字符。對于兩個連續的%XX,如果第一個%XX不是某些特指的Web系統保留字符,將把它們轉換成漢字

pos = InStr(pointer, sEncoded, "%")

If pos = 0 Then Exit Do

temp = Chr$("&H" & (Mid$(sEncoded, pos + 1, 2)))

If Mid(sEncoded, pos + 3, 1) = "%" And (temp $#@60;$#@62; ":") And (temp $#@60;$#@62; "/") _

And (temp $#@60;$#@62; "(") And (temp $#@60;$#@62; ")") And (temp $#@60;$#@62; ".") And (temp $#@60;$#@62; ",") _

And (temp $#@60;$#@62; ";") And (temp $#@60;$#@62; "%") Then

Mid$(sEncoded, pos, 2) = Chr$("&H" & (Mid$(sEncoded, pos + 1, 2)) _

& (Mid$(sEncoded, pos + 4, 2)))

sEncoded = Left$(sEncoded, pos) & Mid$(sEncoded, pos + 6)

pointer = pos + 1

Else

Mid$(sEncoded, pos, 1) = temp

sEncoded = Left$(sEncoded, pos) & Mid$(sEncoded, pos + 3)

pointer = pos + 1

End If

Loop

UrlDecode = sEncoded

Exit Function

End Function

Public Function TempFile(sPath As String, sPrefix As String) As String

本函數可以獲得一個唯一的臨時文件名

Dim x As Long,rc As Long

TempFile = String(127, Chr$(0))

rc = GetTempFileName(sPath, sPrefix, ByVal 0&, TempFile)

x = InStr(TempFile, Chr$(0))

If x $#@62; 0 Then TempFile = Left$(TempFile, x - 1)

End Function

CGI程序guestbook.bas所要處理的表單如下所示:

$#@60;html$#@62;$#@60;head$#@62;$#@60;title$#@62;貴賓留言簿$#@60;/title$#@62;$#@60;/head$#@62;

$#@60;body$#@62;

$#@60;h3$#@62;貴賓留言簿測試$#@60;/h3$#@62;

$#@60;form action="/cgi-bin/guest.exe" method="post"$#@62;

您的姓名: $#@60;input type="text" name="name"$#@62;$#@60;br$#@62;

您的Email信箱: $#@60;input type="text" name="email"$#@62;$#@60;br$#@62;

您的主頁的URL: $#@60;input type="text" name="URL"$#@62;$#@60;br$#@62;

您的建議:$#@60;br$#@62; $#@60;textarea name="URL_Comment" rows=4 cols=30$#@62;$#@60;/textarea$#@62;$#@60;br$#@62;

您來自: $#@60;input type="text" name="from"$#@62;$#@60;br$#@62;

$#@60;input type="submit" value=" 留言 "$#@62;

$#@60;/form$#@62;

$#@60;/body$#@62;$#@60;/html$#@62;

雖然目前已經有很多可以取代CGI且其性能較CGI要高的技術(例如ASP、ISAPI、NSAPI等),但使用它們時需要用到專門的知識和工具,并且利用這些技術所編制的程序只適用于特定的Web服務器或系統平臺。考慮到CGI編程具有易用易學性、跨服務器平臺特性等優點,因此,CGI程序還將在WWW上占有一席之地。

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗