程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB綜合教程 >> 用VB編寫標准CGI程序(下)

用VB編寫標准CGI程序(下)

編輯:VB綜合教程

  三、CGI編程實例

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

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

  

  <html>
          <head><title>DHTML Zone </title></head>
          <body bgcolor="#FFFFFF" text="#00000" vlink="#990000" link="#333399">
          <! ENDHEAD >
          <!---客戶的留言部分從這開始-->
          <P>……………………….
          <!---客戶的留言部分結束於此-->
          </body></html>
  
        這種樣式將保證最後的留言出現在留言簿的最前面。如果要想使最後的留言出現在留言簿的最後面,則只需將留言簿文件中的定位字符串“<! ENDHEAD >”移到留言簿文件中客戶留言部分和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 STD_INPUT_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 "<FONT SIZE=""+2"">"
  
        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 "<P>非常抱歉!您還沒有填寫姓名!" & chinesetail
   
        Exit Sub
  
        End If
  
        If Len(sComment) = 0 Then
   
        OutPut "<P>非常抱歉!您還沒有提出建議!" & chinesetail
   
        Exit Sub
  
        End If
  
        注釋:獲取唯一的臨時文件名和留言簿文件並打開它們
  
        tempFileName = TempFile("c:windowstemp", "gbk")
  
        guestbook = "e:netscapeserverdocsguests.html"
  
        Open tempFileName For Output As #1
  
        Open guestbook For Input As #2
  
        Do 注釋:本循環體用於將留言簿中字符串"<! ENDHEAD >"前面的內容寫入臨時文件
  
        Line Input #2, tempstring
  
        Print #1, tempstring
  
        Loop While tempstring <> "<! ENDHEAD >" And Not EOF(2)
  
        注釋:向臨時文件中插入客戶端用戶的留言
  
        Print #1, "<hr>" & vbCrLf
  
        Print #1, "<ul>" & vbCrLf
  
        Print #1, "<li><b>留言時間</b>:" & Date$ & " " & Time$ & vbCrLf
  
        Print #1, "<li><b>姓名: </b>" & sName & vbCrLf
  
        If Len(sEmail) <> 0 Then
   
        Print #1, "<li><b>E-mail: </b><a href=""mailto:" & sEmail & """ >" & sEmail & "</a>" & vbCrLf
  
        End If
  
        If Len(sURL) <> 0 Then
   
        Print #1, "<li><b>我的主頁: </b> <a href=""" & sURL & """ >" & sURL & "</a>" & vbCrLf
  
        End If
  
        If Len(sfrom) <> 0 Then
   
        Print #1, "<li><b>我來自: </b>" & sfrom & vbCrLf
  
        End If
  
        Print #1, "<li><b>我的建議: </b>" & vbCrLf
  
        Print #1, sComment & vbCrLf
  
        Print #1, "</ul>" & 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 "<P>非常感謝您的留言!" & chinesetail
  
        OutPut "<P>歡迎您經常光顧本主頁!" & chinesetail
  
        OutPut "</FONT>"
  
        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 <> ":") And (temp <> "/") _
   
        And (temp <> "(") And (temp <> ")") And (temp <> ".") And (temp <> ",") _
   
        And (temp <> ";") And (temp <> "%") 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 > 0 Then TempFile = Left$(TempFile, x - 1)
  
        End Function
  
  
        CGI程序guestbook.bas所要處理的表單如下所示:
          <html><head><title>貴賓留言簿</title></head>
          <body>
          <h3>貴賓留言簿測試</h3>
          <form action="/cgi-bin/guest.exe" method="post">
  
        您的姓名: <input type="text" name="name"><br>
  
        您的Email信箱: <input type="text" name="email"><br>
  
        您的主頁的URL: <input type="text" name="URL"><br>
  
        您的建議:<br> <textarea name="URL_Comment" rows=4 cols=30></textarea><br>
  
        您來自: <input type="text" name="from"><br>
          <input type="submit" value=" 留言 ">
          </form>
          </body></html>

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved