cgi

cgi學習簡明教程
閱覽次數:
文章來源: CP整理
原文作者: 不詳
整理日期: 2006-10-05
發表評論
字體大小: 小
 中
 大
 
第一章:基礎的基礎CGI/PERL學習

    1.1 爲什麼使用CGI?

    我沒有把什麼是CGI放在基礎篇的第一段,是因爲實在很難說明白到底什麼是CGI.

    而如果你先知道CGI有什麼作用,將會很好的理解CGI是什麼這個概念。 CGI可以爲我們

    提供許多HTML無法做到的功能。比如a.一個記數器; b.顧客信息表格的提交以及統計;

    c.搜索程序;d.WEB數據庫等等。

    用Html是沒有辦法記住客戶的任何信息的,就算用戶願意讓你知道。用Html也是無法

    把信息記錄到某一個特定文件裏的。要把客戶段的信息記錄在服務器的硬盤上,就要用到

    CGI. 這是CGI最重要的作用,它補充了Html的不足。是的,僅僅是補充,不是替代。

    1.2 CGI是什麼?

    好了,現在我們來說到底什麼是CGI.Common Gate Intergace聽起來讓人有些專業,

    我們就管它叫CGI好了。在物理上,CGI是一段程序,它運行在Server上,提供同客戶段

    Html頁面的接口。這樣說大概還不好理解。那麼我們看一個實際例子: 現在的個人主頁

    上大部分都有一個留言本。留言本的工作是這樣的:先由用戶在客戶段輸入一些信息,

    如名字之類的東西。接着用戶按一下“留言”(到目前爲止工作都在客戶端),瀏覽器把

    這些信息傳送到服務器的cgi目錄下特定的cgi程序中,於是cgi程序在服務器上按照預定

    的方法進行處理。在本例中就是把用戶提交的信息存入指定的文件中。然後cgi程序給客

    戶端發送一個信息,表示請求的任務已經結束。此時用戶在瀏覽器裏將看到“留言結束”

    的字樣。整個過程結束。

    1.3 選擇你熟悉的編程語言

    既然CGI是一種程序,自然需要用編程語言來寫。你可以用任何一種你熟悉的高級語言,

    C,C++,C shell和VB.值得特別指出的,有一種叫Perl的語言。其前身是屬於Unix專用的

    高級語言,其具有強大的字符串處理能力而成爲現在寫CGI,特別是表單類程序的首選。最

    近它已經有了Window95,和winnt版本。你可以在搜索程序裏找到在那裏下載它。 VB是Ms

    的殺手鐗,從目前的情況看,微軟公司正試圖使VB無所不能。自然也包括在Internet 請各

    位注意,VB開發的程序只能在windows平臺上被執行,所以它有一定侷限。 C Shell,經典

    的語言。可惜能做的事情不多,而且必須在Unix平臺下。 C,C++,正真的無所不能。可是

    在寫CGI的時候顯得非常難以掌握。特別是缺乏可以靈活使用的字符串處理函數。對程序員

    的要求也比較高,維護複雜。 最後要提醒各位,因爲CGI是Server和Clinet的接口,所以

    對於不同的Server,CGI程序的移值是一個很複雜的問題。一般對於不同的Server,決沒有

    兩個可以互相通用的CGI.實際上 這就是CGI程序最複雜的地方。

    1.4 安全

    我想各位敏感的朋友又要問我關於安全性能的問題了。實際上CGI是比較安全的,至少

    比那些沒有數字簽名的ActiveX控件要安全的多。除非你有意在程序里加入了破壞Server的

    命令, 否則一般不會有什麼嚴重的後果。而個人網站不向大衆開放CGI目錄,則因爲怕各位

    學習不精,無端增加服務器的負擔,所以一般不提供。

    小結:本章講述了CGI基本概念,也說明了各種編程語言的優缺點,同時解釋了爲什麼個人

    網站不提供CGI的原因。接下來我們開始正式學習。


第二章 Html的表單基礎知識

    組成Cgi程序的是兩部分,一部分是html頁面,就是用戶看到的東西。另一部分則是運

    行在服務器上的程序。一般來說,我們先寫html頁面,再寫程序。所以我們的學習頁是這樣,

    先看看錶單的寫法,再去學習CGI程序。

    對於html的表單,有比較複雜和詳細的規定。但由於它們是屬於html標準裏的東西,所

    以我不打算詳細講解。最好是你自己找本書看看。

    Html表單

    <Form></Form>標記把輸入域組合起來,並且說明了表單提交的方式和地點。Form標籤有許

    多屬性,比如NAME等等。具體的屬性,將在使用的時候說明。

    在FORM裏還有許多不同的標籤,正是它們組成了表單的各種成分。

    <INPUT [TYPE=TEXT] NAME="TEXT-ID" [SIZE=NN] [MAXLENGTH=NN]

    [VALUE='DEFAULT TEXT']>

    該語句在HTML裏產生一個文本標籤,[]裏表示該屬性是可選的。

    <INPUT TYPE=SUBMIT [NAME='BUTTON-ID'][VALUE="BUTTON LABLE TEXT"]>

    該語句產生一個提交按鍵,用於表單的提交。它提供一個發送表單的按紐,信息發向<FORM>

    標記裏ACTION屬性裏給出的URL.根據表單方法(METHOD)指定的HTTP請求類型 提交信息。

    在以後我將詳細講解。

    <INPUT TYPE=RESET[VALUE='BUTTON LABEL TEXT']>

    具有TYPE=RESET屬性的INPUT將產生一個按鈕,它能重置表單各個域 的內容到初始狀態。

    <INPUT TYPE=RADIO NAME="RADIO-SET -ID" vALUE="CHOICE-ID" [CHECKED]>

    表單可以用此標記提示用戶從幾個選擇項裏作出選擇。麼個選擇項目都是一個單選按鈕它們

    具有相同的NAME值。在任何時候只要有一個被選中。此標記有一個VALUE屬性,如果它被選

    中,則發送表單時將以"RADIO-SET-ID=CHOICE-ID"的形式發送。

    <INPUT TYPE=CHECKBOX NAME='BOX-SET-ID' VALUE='CHOICE-ID' [CHECKED]>

    此標籤將產生一個'OFF'或'ON'的開關。它同RADIO相似,但是可以多選。當提交表單的時候如

    果一個複選框是選中的餓,那麼它的VALUE屬性作爲BOX-SET-ID表單數據的值被提交。幾個

    擁有同樣NAME屬性的複選框爲一組。它們用','分開的列表。




第三章:傳送方式 CGI/PERL學習

    傳送方法:

    所謂方法是指調用CGI程序的途徑。事實上,要執行程序時,你用一種方法向服務器提

    出請求,此請求定義了程序如何接受數據。 下面介紹最常用的兩種方法:get和post

    1.GET 當使用這種方法時,CGI程序從環境變量QUERY_STRING獲取數據。QUERY_STRING被

    稱爲環境變量,就是這種環境變量把客戶端的數據傳給服務器。爲了解釋和執行程序,CGI

    必須要分析(處理)此字符串。當你想從服務器獲得數據並且不改變服務器上的數據時,

    你應該選用GET.但如果你的字符串長度超過了一定長度,那麼還是選用POST方法。

    2.POST 使用POST方法時,WEB服務器通過stdin(標準輸入),向CGI程序傳送數據。服務

    器在數據的最後沒有使用EOF字符標記,因此程序爲了正確的讀取stdin,必須使用

    CONTENT_LENGTH .當你發送的數據將改變Web服務器端的數據或者你想給CGI程序傳送的數

    據超過了1024 字節,這是url的極限長度,你應該使用post方法。

    3.實現方法:

    上次講過html中的<Form>標籤,對於傳送數據方法的定義也在這個標籤裏定義。 如下:

    <form name="guyi's form" action=http://www.yourname.com/cgi/your.cgi method=GET>

    定義了一個以get方法傳送數據的form,它的服務端程序是http://www.yourname.com/cgi/your.cgi.

    同樣的如下的定義將使用post方法。

    <form method=post>




第四章:基本調試環境的建立

    基本調試環境的建立:

    我想不是每個閱讀教程的朋友有機會接觸到服務器之類的東西的。所以在接下去的閱

    讀過程中沒有調試環境的朋友將會非常吃力。爲了解決這個問題,我特別介紹一種在

    win95或nt上建立WEB SITE的方法,以便各位能很好的閱讀程序。不過本方法內使用的軟

    件都比較大,如果你不是一個真正的網絡發燒友,或許你會放棄這個教程。這個我也沒

    有辦法,要知道喜歡一樣東西總是要付出代價的。

    1.win95&winnt的Server軟件:

    首先我要各位弄清楚一個概念,所謂Sever只是指在一臺電腦上安裝了一個特別的軟件。

    該軟件可以提供internet web site服務。這臺電腦不一定要是什麼特別好的機器,只要它

    能夠很好的運行Server軟件就可以了。比如我們的個人電腦就可以承擔這個任務。 在

    Windows95下運行的server軟件不是很多,而且是屬於“業餘”的。就是說離真正的商業使

    用有很大的距離。這主要是windows95平臺的侷限,比如很差的安全性,不穩定的內存分配

    系統,混亂的文件系統以及最差的進程管理。不過這些不影響我們使用CGI程序,特別是一

    個人調試自己的程序,而不是放在internet給數萬個人訪問。其代表是MS在windows OSR離

    提供的pws(person web server)。你可以通過控制面版——>網絡——>服務——>Ms——>個人WEB服

    務器安裝它。不過我希望你們最好還是不要使用這個東西,因爲它對我們下面的課程沒有什

    麼幫助。我曾試驗過用它來和我的perl程序相連,但很顯然不支持perl.雖然有消息說修改

    註冊表可以解決這個問題,但我到現在還是沒有找到方法。相對而言,Windows NT因爲其定

    位的不同而可以提供較理想的操作平臺。而且NT自帶有IIS(Internet Information Server)。

    不過是2.0版的,如果你有IIS3.0就更好了。到本文寫成的時候,IIS已經有了4.0版本。當

    然我相信不是所有人會去下載這個東西,因爲有 104M.

    上面講了這麼多,實際上我要給各位推薦的是WebSite for win95&NT.就是說兩個操作

    系統都可以使用它。現在的版本是2.1,有17M.顯然是一個很大的軟件,不過正如我說的,

    喜歡一樣東西是有代價的。你可以在http://www.windows95.com 裏找到這個程序。 WebSite

    支持winCGI,也支持perl寫的CGI程序。顯然這是一個好東西,可以滿足我們的要求。雖然

    大了些,不過要是你能找到website 1.1的話也不錯,它大概有4M左右。不過我在網上從沒

    發現有下載的地方。

    2.Perl for win32

    Perl,讓人激動的名字。我想再也找不到一個編程語言可以如此出色的完成基本CGI程序

    的開發了。我感謝那些爲perl移植做出貢獻的朋友們,是他們讓我們可以在win平臺上使用如

    此如此強大的Unix工具。 你可以在perl的主頁上找到perl for win32版本,當前版本是5.02.

    你也可以在 http://download.ihw.com.cn 裏找到perl for win32版本。大概是2.5M.

    3.VB

    VB是我們寫WinCGI程序最好的選擇。我推薦各位使用vb4.不是因爲vb5不好,只是在

    Internet上支持它的文檔和免費代碼太少了。

    4.C&C++

    這個教程裏幾乎沒有用C&C++寫的代碼,因爲它更適合高級程序員而不是我們這些業餘

    選手。不過你要是一定使用它我也沒有意見。

    5.安裝。

    好了,我們開始建立基本環境。就是說我們要在自己的機器上建立一個WEB SITE! 首

    先安裝Website.按照它標準的安裝界面,你可以輕鬆的完成這個工作。缺省情況下它將

    被安裝到c:website下。我提醒各位注意這幾個目錄:

    cgi-shl:這個是基本的cgi目錄,也就是各位朝思暮想的地方!

    cgi-win:這個cgi目錄裏放的是WinCgi程序。 其他的各位自己研究吧。

    好了,在裝完Website後請確認它已經運行。在狀態攔地右下角會有一個齒輪地圖標,

    它表示website正在運行。接下去請打開你地瀏覽器,在url輸入你機器的ip地址,如果沒

    有 ip,請輸入:127.0.0.1.注意,做這些動作的時候,最好請你使用netscape,而且你

    不必連上網絡! 如果一切順利的話,你將看到website的標記,那證明你已經成功了!

    接下去我們安裝perl. 下載後的perl是一個自解開文件,它會問你安裝到哪個目錄。缺省

    是c:perl,接着它展開併產生幾個自目錄。在安裝結束的時候,它會修改autoexec.bat,

    把c:perlbin加如 path,請一定要這麼做,道理我會在下面解釋。最後請隨便寫一個以

    。cgi或。pl結尾的文本文件。直接雙擊它,併爲它加上關聯。。pl或 .cgi的關聯文件是

    c:perlbinperl.exe.這步很重要,不然你無法完成接下去的學習。 那麼爲什麼我們

    要加路徑呢?因爲perl是一種文本解釋型語言,就是說它沒有編譯的過程, 只有在運行

    的時候解釋。解釋一句運行一句。所以我們必須讓系統知道perl.exe在哪裏。

    6.測試

    最後我們進行一個測試。請把下面的兩個程序下載並運行它們:

    1.html文件:這是測試程序的客戶端內容,請以test.htm保存它。並把它放在

    c:websitehotdocs 下,那是你的website缺省的根目錄。

    test.htm:

    <html> <title>你的第一個perl測試程序</title> <body> <h1>你的第一個perl測試程序<h1><br> <h2>win 平臺的環境變量測試</h2><br> <form method="get" acton="http://127.0.0.1/cgi-shl/env.pl "> <input type=submit value="查看CGI環境變量"> </form> </body> </html>

    2.Perl文件:請使用任意一個文本編輯器,輸入後以env.pl保存到c:websitecgi-shl下。

    #! perl

    print"Content-type:text/htmlnn";print"<title>Windows環境變量</title>";print"<body>恭喜你的website已經成功<br>";foreach $key(sort keys %ENV){ print"$key=$ENV{$key}<br>"; } PRINT"</BODY>";

    在完成上面的工作後,請打開瀏覽器,輸入http://127.0.0.1/test.htm.當然如果你的

    機器是以tcp/ip方式 連在局域網上,請把127.0.0.1改成你的ip地址(還有test.htm裏的。)

    然後按下那個鍵,當你的瀏覽器去向另一個 頁面的時候,今天的任務就算是完成了。





第五章:第一個程序--環境變量CGI/PERL學習

   服務器與CGI程序交換信息的協作方式是通過環境變量實現的。無論什麼請求,CGI程序總能在特定位置找到某些信息。無論環境變量怎樣定義,總有一些變量有着特定含義。環境變量是一個保存用戶信息的內存區。例如,所有的機器都有一個PATH環境變量,當在當前目錄找佈道文件時就要查找PATH變量。當服務器收到一個請求後,它首先要收集它能得到的所有相關信息,並把它放入內存。那麼,服務器要收集什麼信息呢?

    關於服務器自身的詳細信息

    關於用戶的信息信息

    關於用戶請求的信息

    服務器不知道CGI程序到底需要那些信息,所以它把這些信息一起收集,那麼如果有什麼重要的東西就不會遺漏了。爲了向你展示服務器收集那些環境變量,在上一期的教程裏我已經爲各位寫了一個程序,該程序將幾乎所有的信息都反映在了瀏覽器裏。所以在進一步學習變量的時候,請首先把程序調試好。

    環境變量

    1.與服務器相關的環境變量

GATEWAY_INTERFACE 服務器遵守的CGI版本
SERVER_NAME 服務器的IP或名字
SERVER_PORT 主機的端口號
SERVER_SOFTWARE 服務器軟件的名字


    2.與客戶機相關的環境變量

    服務器瞭解你的CGI程序,但它一定不知道你的客戶機環境。正因爲如此,同客戶機有

    關的變量纔是最重要的。因爲它涉及到你的瀏覽器等等。

ACCEPT 例出能被次請求接受的應答方式
ACCEPT_ENCODING 列出客戶機支持的編碼方式
ACCEPT_LANGUAGE 表明客戶機可接受語言的ISO代碼
AUTORIZATION 表明被證實了的用戶
FORM 列出客戶機的EMAIL地址
IF_MODIFIED_SINGCE 當用get方式請求並且只有當文檔比指定日期更早時才返回數據
PRAGMA 設定將來要用到的服務器代理
REFFERER 指出連接到當前文檔的文檔的URL
USER_AGENT 標明客戶使用的軟件


    3.與請求相關的環境變量

    每次服務器受到的請求都不可能是一樣的。這意味着有許多CGI程序必須注意的信息。這些與請求相關的信息包含有用戶調用的信息,用戶如何發送請求,以及作爲請求的一部分傳送了多少(什麼)信息。這些對你的程序來說是非常重要的,因此我們將化些時間詳細地討論一下其中的一些變量。特別是下面寫出的三個變量。這三個變量相當重要。

    REQUEST_METHOD

    QUERY_STRING

    CONTENT_LENGTH

    你必須熟悉這三個變量,因爲它們用來表示數據是如何送到CGI程序的;然後你所要要做的事情就是在這三個變量裏取出數據,進行下一步的編程。其他的一些變量的用處很多,

    你可以瞭解你的競爭對手正在調用你的程序,你可以辨別用戶是否註冊,或者你可以設置連接到你的CGI程序以便要求附加路徑信息包含在請求之中——因此你不必猜測你的用戶正在你的服務器的哪個頁面上。

AUTH_TYPE 服務器用的確認模式
CONTENT_FILE 含有CGI程序的數據文件
CONTENT_LENGTH POST請求中向標準輸入(STDIN)發送的字節數
CONTENT_TYPE 被髮送數據的類型
PATH_INFO CGI程序的附加路徑
PATH_TRANSLATED PATH_INFO對應的絕對路徑
QUERY_STRING 傳送給CGI程序的URL的問號(?)之後的那一部分
REMOTE_ADDR 最終用戶的IP或主機名
REMOTE_USER 如果用戶合法,則是用戶的組名
REQUEST_LINE 發送給服務器的完整URL請求
REQUEST_METHOD 作爲HTTP的一部分請求而傳送數據的方法,比如get。
SCRPT_NAME 運行的腳本名字





第六章: 調查表CGI/PERL學習

    對於本章的程序——選票程序,我不想多說什麼。我只是想在本程序內教給大家如何

    使用perl語言或C語言如何處理字符串的實例。讓我們先看看代碼:

    頁面文件——pote.html

    <HTML>

    <TITLE>投票程序</TITLE>

    <h1>投票程序</h1>

    <FORM METHOD="post" ACTION="/cgi-bin/vote.pl">

    一。你喜歡誰?<br>

    <input type="radio" name="idol" value="A" checked>張德陪<br>

    <input type="radio" name="idol" value="B">阿加西<br>

    <input type="radio" name="idol" value="C">桑普拉斯<br>

    <input type="radio" name="idol" value="D">貝克<br>

    <input type="radio" name="idol" value="D">顧懿<br>

    <input type="submit" value="執行">

    <input type="reset" value="取消">

    </form>

    查詢<a href="/cgi-bin/vote.pl?command=view">選舉投票結果</a>

    </html>

    CGI程序:——vote.pl

    #!perl

    print"Content-type:text/htmlnn";

    print"<titel>投票系統</title>";

    if($ENV{'REQUEST_METHOD'}eq"POST"){

    read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});

    }elsif($ENV{'REQUEST_METHOD'}eq"GET"){

    $buffer=$ENV{'QUERY_STIRNG'};

    }

    @pairs=split(/&/,$buffer);

    foreach $pair(@pairs){

    ($name,$value)=split(/=/,$pair);

    $value=~tr/+//;

    $value=~s/%([a-f A-F 0-9][a-f A-f 0-9])/pack("C",hex($1))/eg;

    $FORM{$name}=$value;}

    $filename="/vote.dat";

    %NAME=("A","張德陪","B","阿加西","C","桑普拉斯","D","貝克","E","顧懿");

    if($ENV{'REQUEST_METHOD'}eq"POST"){

    print"Content-type:text/htmlnn";

    print"<titel>投票系統</title>";

    print"<h1>投票系統的例子</h1>";

    open(FILE,"<$filename")||die"不能打開文件,請和管理員聯繫n";

    for($i=0;$i<2;$i++){

    $file[$i]=<FILE>;

    $file[$i]=~s/n$//;

    }

    close(FILE);

    @item=split(/:/,$file[0]);

    @vote=split(/:/,$file[1]);

    for($i=0;$i<@item;$i++){

    if($FORM{'idol'}eq$item[$i]){

    $vote[$i]++;

    last;

    }

    }

    open(FILE,">filename")||die"Can't Open the file";

    $item=join(":",@item);

    $vote=join(":",@vote);

    pirnt FILE "$itemn";

    print FILE "$voten";

    close (FILE);

    print"<h2>您是投票給$NAME{$FORM{'idol'}},謝謝您的選票!<h2>";

    print"查詢<a href="/cgi-bin/vote.pl?command=viem">投票結果系統</a>";

    }

    if($FORM{'command'}eq"view"){

    print "HTTP/1.0 200n";

    print "Content-type:text/htmlnn";

    print"<title>投票結果</title>";

    print"<h1>投票結果</h1>";

    open (FILE,"$filename")||die"文件打開錯誤";

    for($i=0;$i<2;$i++){

    $file[$i]=<FILE>;

    $file[$i]=~s/n$//;

    }

    close(FILE);

    @item=split(/:/,$file[0]);

    @vote=split(/:/,$file[1]);

    print"<table border=1>";

    for($i=0;$i<@item;$i++){

    print"<tr><td>姓名</td><td>$NAME{$item[$i]}</td><td>票數</td>,td>$vote[$i]

    </td><tr>";

    }

    print "</table>";

    }

    這個程序是要各位學習Perl的分解字符串的功能。在Perl中,字符串操作

    是非常簡單的。

    我對幾句重要語句做一個分析:

    if($ENV{'REQUEST_METHOD'}eq"POST"){

    read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});

    }elsif($ENV{'REQUEST_METHOD'}eq"GET"){

    $buffer=$ENV{'QUERY_STIRNG'};

    }

    這是一個非常常見的功能塊,幾乎所有的CGI程序都會用到它。它判斷

    頁面使用何種方式提交變量。如果是post,就從STDIN裏把變量讀出,存到

    變量buffer裏。注意在perl裏,變量是用$開頭的。而$ENV{'CONTENT_LENGTH'}

    則是讀出該變量的長度,請注意CONTENT_LENGTH是一個環境變量。第二個if則

    處理get情況,在get情況下,頁面提交的信息是存放在環境變量QUERY_STIRNG中

    的。所以$buffer也就是頁面提交的信息。環境變量REQUEST_METHOD表示方式,

    它的值是一個字符串,前面加上$ENV則表示讀出該變量的值。

    @pairs=split(/&/,$buffer);

    foreach $pair(@pairs){

    ($name,$value)=split(/=/,$pair);

    $value=~tr/+//;

    $value=~s/%([a-f A-F 0-9][a-f A-f 0-9])/pack("C",hex($1))/eg;

    $FORM{$name}=$value;}

    以上功能塊是一個分解過程。頁面信息的提交往往是以“名稱=值”的形式,

    比如本例子中就是以“idol=顧懿”這樣的形式提交的,所以我們要去掉字符串中

    的"="等等信息,但同時要保留“idol”和"顧懿"之間的對應關係。$FORM{$name}

    =$value做到這一點,這是一個關聯數組。具體其中的語法,請各位自行查書。接

    下來的就是文件的操作,但那已經不是本課的重點。所以就不多說了。




第七章:上傳文件

   上傳文件是建立交互式網站的一個重要手段。一般來說,考慮到CGI程序的安全和一些敏感問題,服務器是不會輕易開放文件上傳權利的。

    今天的程序是由WEBSITE1.1附帶的一個upload.exe程序,由VB編寫而成。所以我要講的也就是VB寫WIN-CGI時候的一些問題。

    VB寫Win-CGI:

    在Windows環境下,WEB服務器和一個Windows CGI之間是通過臨時文件來傳送數據的。這個

    過程如下:

    1.Web服務器接受一個客戶機對Windows CGI程序的請求,這個請求也稱爲Windows CGI請求。

    2.Web服務器把要傳送給Windows CGI程序的數據放在一個叫CGI profile的主輸入文件。在某些情況下,還會增加一個文件。

    3.Web服務器執行CGI程序,把CGI profile作爲它的第一個參數。

    4.Windows CGI開始執行,服務器等待Windows CGI進程結束。在等待過程中,服務器還可以處理其他請求,比如另一個新的CGI進程或HTTP請求。

    5.Windows CGI程序讀取作爲命令行參數的profile文件並完成必要的處理,CGI程序也許要使用porfile文件中的數據和其他相關的輔助文件中的數據。

    6.在Windows CGI程序結束前,把它的應答寫在profile文件指定的輸出文件中。

    7.得到CGI程序處理結果後,WEB服務器讀取輸出文件,看看輸出數據是否要打包,並把最後數據發給客戶機。

    8.WEB服務器隨後就刪除處理這個請求時產生的臨時文件。如果在服務器管理器註冊時,不刪除臨時文件,則保留這些臨時文件。總的說,基於文件的傳輸過程是比較古老的。但它是最常用的通訊方式。

    CGI32.BAS

    CGI32.BAS是給windows系列的使用者在VB4.0或更高的環境下開發Windows-cgi而寫的一

    個程序接口。本文假設你已經對VB編程非常熟悉,所以對於使用VB的過程我就省略不說了。

    在寫Win-CGI程序的時候,請將VB環境中的有效對象全部關掉(Custom controls),並將

    CGI32.bas加入project中。隨後創建一個子程序

    CGI_Main()

    Sub CGI-Main()

    'Win-CGI程序內容end sub

    對於CGI32.bas,如果你還沒有,請在這裏下載。

    Sub Main()

    On Error GoTo ErrorHandler

    If Trim$(Command$) = "" Then ' Interactive start Inter_Main ' Call interactive main Exit Sub ' Exit the program End If

    InitializeCGI ' Create the CGI environment

    '=========== CGI_Main ' Execute the actual "script" '===========

    Cleanup:Close #CGI_OutputFN Exit Sub ' End the program '——ErrorHandler:Select Case Err ' Decode our "user defined" errors Case ERR_NO_FIELD:ErrorString = "Unknown form field" Case Else:ErrorString = Error$ ' Must be VB error End Select

    ErrorString = ErrorString & " (error #" & Err & ")" On Error GoTo 0 ' Prevent recursion ErrorHandler (Err) ' Generate HTTP error result Resume Cleanup '——End Sub

    上面是一個Win-cgi的例子。




第八章:Form to MailCGI/PERL學習

    Form to Mail

    所謂Form to Mail的功能,就是在頁面上建立一個表單(form),該表單內記錄着用戶的信息,當用戶提交了此表單,程序自動將表單內容發送的管理員所設定的信箱裏。聽起來這非常簡單,根本用CGI就可以寫這樣的功能。其實當然沒有這麼簡單,實際上許多公司網頁還要求此表單在提交時存如另一個數據庫,這樣就需要寫CGI程序了。

    爲了便於解說form to mail的功能,我們這裏不考慮複雜情況,只考慮最簡單的情況。就是唯一的form to mail功能,其他的功能只要在程序內加入相應的程序塊就可以了。

    在Unix中,我們最多使用的就是Email網關,因爲是CGI開發環境中少數幾個標準unix工具之一。在CGI程序中發送e-mail的命令是mail和Sendmail.我比較喜歡sendmail,因爲它功能更強,Sendmail從STDIN接受數據,遇到Eof或只包含。的一行信息就將信息發送出去。

    Perl中使用Sendmail的一個方式是將mail內容寫入一個臨時文件,然後使用Cat,同時把輸出管道與Sendmail命令相聯繫起來。

    如:

    open(EMAIL,“>tempfile $ $,txt”);

    print(EMAIL,“stuff to be emailed …… la la la ……n”);

    close(EMAIL);

    system(“cat tempfile $ $,txt | /usr/sbin/sendmail $tokens(‘email’)”);

    system(“rm tempfile $ $,txt”);

    名字tempfile $$,txt中的$ $是Perl中的一個特殊變量,即進程號(PID)。之所以使用是爲了避免兩個用戶同時啓動這個程序會覆蓋tempfile文件,使用這種方法每個tempfile都是唯一的。(由pid表示)。這種好的思想可以用在許多程序中。

    Sendmail命令從關聯數組元素$token(‘email’)中找到e-mail目標地址,你可以假設這個變量的值在用戶提交的表單由用戶輸入。如果沒有安全措施,這樣做是很危險的,設想有惡意的用戶在Web表單中給你如下地址:[email protected] ;cd/;rm-R *分號是表示unix命令結束的符號並將命令提交unix命令解釋器。精通web的人誰也不會在根目錄運行httpd,這個例子將刪除整個文件系統。所以在設計整個系統的時候,必須考慮到這種用戶直接到達Shell的情況。

    Windows 下的Form to Mail

    很不幸,Windows沒有類似於Unix的mail網關,不管是WinNt和Windows都無法做到類似的功能。當然也有些非常熱心的程序員寫過Dos接口的mail程序,但是相當不幸,此類程序直到現在也沒有很成功的例子。它們的問題是過於佔用系統資源,並非常容易被黑客攻擊。所以這裏我就不提供程序了。




第九章:Guest book

    Guest-book在網頁設計中佔有相當重要的地位,以至於可以和記數器相提並論。留言本可以用許多編程語言來設計,當然使用最多的還是perl和vb兩種。本次cgi教程我們將談談在編寫Guest-book中最應該注意的問題,並將給出一個不算很完整的程序代碼。同時提供一個C語言的win-cgi程序供大家下載。

    就現在的情況來看,一個標準的guest-book程序一般包括三個文件。提交表單文件(form.html)、cgi處理文件(guest-book.cgi)和最後的輸出文件(book.html)。有些vb程序以access數據庫爲後臺存儲格式,以方便用戶查找留言。下圖給出了guest-book的工作流程。

    form.html首先我們來看看form.html的文件內容:<html> <title>guest-book.html</title> <h1>留言本</h1> <form method="post" action="/cgi-shl/guest-book.cgi"> <p>名字:<input name="name" size="20"> <p>email:<input name="email" size="30"> <p>意見:<textarea name="suggest" cols=30 rows=4></textarea> </textarea><p> <input type="submit" value="提交"> <input type="reset" value="取消"> </form></html>

    <form method="post" action="/cgi-shl/guest-book.cgi">將此表單的提交後的動作交給guest-book.cgi程序。

    guest-book.cgi #! perl

    print"Content-type:text/htmlnn";read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});@pairs=split(/&/,$buffer);foreach $pair(@pairs){($name,$value)=split(/=/,$pair);$value=~tr/+//;$value=~s/%([a-f A-F 0-9][a-f A-F 0-9])/pack("C",hex($1))/eg;$FORM{$name}=$value;} print"<title>留言本</title>";print"<h1>留言本</h1>";

    foreach $check(values%FORM){ if($check eq""){ print"<hr size=3>";print"<h2>請不要留空";exit(0);}

    $FORM{'suggest'}=~s/cMn/<br>n/g;

    $filename="c:/website/htdocs/book.html";

    open(FILE,">> $filename");print FILE "名字:$FORM{'name'}<br>n";print FILE "Email:<a href="mailto:$FORM{'email'}>$FORM{'email'}</a><br>n"}";print FILE "留言:$FORM{'suggest'}";close{FILE};

    print "<h2>謝謝留言</h2>";

    print"<a href="book.html">請觀看留言本</a>";

    exit(0);

    這個程序相當簡陋,但它具有了所有的CGI-Guest程序的特點,我們一一分析如下:首先,read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});@pairs=split(/&/,$buffer);foreach $pair(@pairs){($name,$value)=split(/=/,$pair);$value=~tr/+//;$value=~s/%([a-f A-F 0-9][a-f A-F 0-9])/pack("C",hex($1))/eg;$FORM{$name}=$value;}這是一段表單分析的語句,在前面的程序裏,估計大家也都見過了。

    其次:foreach $check(values%FORM){ if($check eq""){ print"<hr size=3>";print"<h2>請不要留空";exit(0);}做輸入字段的檢查,看看是否有留空的現象。從前這種任務都是要CGI程序來驗證的,比如

    email是否輸入的是mail地址等檢查。不過現在我們可以通過javascript來做這樣的檢查,

    這樣服務器的負擔將大大減輕。

    最後:$filename="c:/website/htdocs/book.html";

    open(FILE,">> $filename");print FILE "名字:$FORM{'name'}<br>n";print FILE "Email:<a href="mailto:$FORM{'email'}>$FORM{'email'}</a><br>n"}";print FILE "留言:$FORM{'suggest'}";close{FILE};

    print "<h2>謝謝留言</h2>";

    print"<a href="book.html">請觀看留言本</a>";

    exit(0);輸出內容到文件和屏幕上。完成留言的程序。

    book.html:這個程序中book.html沒有什麼特別的要求,可以不用寫,就讓程序自動生成。

    現在有的cgi程序,對book.html也有設定,比如在<head></head>之間就寫上註釋<!——這是流言開始——!> <!——這是流言結束——!>這樣,在程序對留言數據操作的時候,就可以忽略掉文件內的其他內容。

    最後,我爲各位找到一個用C寫的guestbook程序,它是在win平臺上運行的,具有非常好的兼容性。同時它採用了臨時文件的方式來傳遞信息。所以你需要設定。ini文件。好了,這課到此爲止。




第十章:一個數據庫的例子

   毫無疑問,當今Web程序設計中最吸引人而且最複雜的當然就是web數據庫程序了。平心而論,其複雜高深的程度決不是你們可以想象得到的。我們先來看看其中涉及到的幾個方面的問題:

    1.最基本的html設計

    2.CGI程序編寫調試

    3.網絡管理和客戶協調

    4.數據庫編寫

    5.客戶/服務體系程序編寫

    另外你還得不時地同你的客戶進行鬥爭,以取得他們對你工作的認同。因此編寫一個大型WEB數據庫,是綜合素質的考驗。

    筆者自問尚不完全具備以上的能力,但有幸曾參加過幾個web數據庫的開發,算是具備了初步的經驗吧。這裏給大家分享,也算是感謝各位對這個斷斷續續的教程的總結吧。

    一 數據庫選擇

    從一般情況來看,使用web數據庫往往是要解決數據的歸納、索引和維護的問題。我們一般選擇最流行的關係型數據庫,比如NT下的sql,win95和nt下的Access,NT下的sybase,unix下的msql等等。當然還有Oracle、FileMaker PRO、Paradox等等。這些都是很流行的Sql數據庫。Sql給數據管理提供了一個標準而堅實的接口,它對數據庫操作餓所有函數必需在數據庫語言中實現。這種函數包括:數據對象的創建、插入數據和數據修改等。對於數據量不大的小型數據庫,一般使用access。

    二 接口程序CGI/PERL學習

    雖然我們可以直接編寫WEB的CGI接口,但是那是工作量巨大且麻煩異常的工作。爲了減輕開發者的負擔,數據庫程序員爲我們編寫了許多可以直接使用的接口程序,配合不同的數據庫。下面就是一些十分常用的接口程序:

    1. DB2WWW

    http://www.software.ibm.com/data/db2/db2wfac2.html

    這是一個用於和IBM DB2數據庫進行連接的工具。在HTTP服務器中,這種工具將HTML文件和SQL命令作爲宏文件存儲,然後,DB2WWW在接受到瀏覽器請求後就處理這些宏文件。

    2. dbCGI

    http://www.progress.com/webtools.html

    這個工具通過在html文件中內置SQL語句來實現和數據庫的連接。適用於Progress,Sybase,Oracle,Informix,Ingres和ODBC。下面是一個典型的dbCGI程序代碼:

<title>dbCGI test</title>
<sql init>
INFORMIXDIR=/usr/informixdir
SQLEXEC=/usr/informix/sqlturbo
TBCONFIG=tbconfig
</sql>
<sql connect connl>
<DATABASE=stores>
<sql>
<sql format>
% [! 8:<h1>%8d</h1>%]
....
</sql>
<sql query connl>
selet *
from customer
order by date,city,zipcode
</sql>
<sql disconect connl>
</sql>
<sql uninit>
</sql>
    這個工具通過<sql>標籤和%轉意字符來把sql語句放置在html語句內。

    3 Genera

    http://gdbdoc.gdb.org/letovsky/genera/general.html

    這個是sybase數據庫系統的網關。它通過在文本文件中加入特定的語句來和數據庫進行連接。

    4 WebDBC

    http://www.ndev.com

    以windows NT爲平臺,可以訪問所有對odbc兼容的數據庫。

    5 A-Xorion

    http://www.clark.net/infouser/endidc.html

    他是一個CGI網關,它可以訪問大多數的PC機數據庫。它以Windows3.1/95/NT爲平臺。數據庫爲Ms Access2.0。

    三 編程語言CGI/PERL學習

    上面介紹的是一些常用的接口程序,它們需要Server的配合才能正常工作。當然如果是很小的數據庫程序,不需要使用如此複雜的數據庫接口程序。用C,Perl,VB等等,寫成CGI程序,在CGI程序內調用數據庫。雖然速度方面不是很快,但絕對是非常簡單的。

    最後的例子:

    最後,我準備以一個例子來結束這個教程。

    環境:

    這是一個非常簡單的WEB應用程序。如果你要運行這個程序,也許你得化些時間來配置自己的系統。在這個例子裏,CGI程序由Perl5來編寫,後臺數據庫使用sybase system 10,Sybperl用於建立腳本和數據庫之間的通信,用其他的CGI後臺數據庫接口程序也可以。

CGI程序:

<head>
<title>會議登記程序</title>
</head>
<body>
<h2>會議登記系統</h2>
please fill out the following form. A registration packet will be sent to you immediatel you.Note that all <b>bolad-faced</b>fields muse be complected.
<hr>
<form method="post" action="cgi-bin/resgister.pl">
<b>first name:</b><input type="text" name="c_fname" size=30>
<p>
<b>Last name:</b><input type="text" name="c_lname" size=30>
<p>
<b>address 1:</b><input type="text" name="c_add1" size=30>
<p>
<b>address 2:</b><input type="text" name="c_add2" size=30>
<p>
<b>city:</b><input type="text" name="c_city" size=30>
<p>
<b>State:</b><input type="text" name="c_state" size=2>
<p>
<b>Zip:</b><input type="text" name="c_zip" size=15>
<p>
<b>phone:</b><input type="text" name="c_phone" size=15>
<p>
<b>Fax:</b><input type="text" name="c_fax" size=15>
<p>
<b>Email:</b><input type="text" name="c_email" size=15>
<p>
Packge:
<ul>
<li><input type="radio" name="c_packge" valuge="a">Package A
<li><input type="radio" name="c_packge" valuge="b">Package B
<li><input type="radio" name="c_packge" valuge="c">Package C
</ul>
How did you hear about the conference:
<ul>
<li><input type="radio" name="c_ad" value="a">Direct Mail
<li><input type="radio" name="c_ad" value="b">Associate
<li><input type="radio" name="c_ad" value="c">Journal
<li><input type="radio" name="c_ad" value="d">Other
</ul>
<p>
<input type="reset" value="clear"><input type="submit" value="Register"><p>
</form>

<hr>
</body>

Perl腳本:
#!/usr/local/bin/perl
require"cgi-lib.pl";
&ReadParse(* input);
$mc_fname=$input{'c_fname'};
$mc_lname=$input{'c_lname'};
$mc_add1=$input{'c_add1'};
$mc_add2=$input{'c_add2'};
$mc_city=$input{'c_city'};
$mc_state=$input{'c_state'};
$mc_zip=$input{'c_zip'};
$mc_phone=$input{'c_phone'};
$mc_fax=$input{'c_fax'};
$mc_email=$input{'c_email'};
$mc_package=$input{'c_package'};
$mc_ad=$input{'c_ad'};

print &PrintHeader;

if (($mc_fname eq"")||(mc_lname eq "")||(mc_add1  eq "")||($mc_add2  eq "")||(
mc_city eq "")||(mc_state eq "")||(mc_zip  eq "")){
printf ("<br>");
printf(",strong>Your registration cannot be processed as is.Pleae make sure all the requied fields are filled properly.</strong>");
print"<p>";
print"Pleae use the <i>Back</i>button to complete the form.n";
}
else{# data is OK

use Sybase::DBlib;

$dbh=Sybase::DBlib->dblogin('conf_user','123','DB-SERVER','REG');
$dbh->dbuse('conference');

$sqlcmd="insert into reg(c_fname,c_lanme,c_add1,c_add2,c_city,c_state,c_zip, c_phone,c_fax,c_email,c_package,c_ad)";

$sqlcmd=$sqlcmd."values("
$sqlcmd=$sqlcmd.'"".$mc_fname."",";
$sqlcmd=$sqlcmd.'"".$mc_flame."",";
$sqlcmd=$sqlcmd.'"".$mc_add1."",";
$sqlcmd=$sqlcmd.'"".$mc_add2."",";
$sqlcmd=$sqlcmd.'"".$mc_city."",";
$sqlcmd=$sqlcmd.'"".$mc_state."",";
$sqlcmd=$sqlcmd.'"".$mc_zip."",";
$sqlcmd=$sqlcmd.'"".$mc_phone."",";
$sqlcmd=$sqlcmd.'"".$mc_fax."",";
$sqlcmd=$sqlcmd.'"".$mc_email."",";
$sqlcmd=$sqlcmd.'"".$mc_package."",";
$sqlcmd=$sqlcmd.'"".$mc_ad."",";
$sqlcmd=$sqlcmd.'"".$mc_fax."",";
$dbh->dbcmd($sqlcmd."n");
$dbh->dbsqlexec;

print"<strong>Thank you.</strong>Your registration has been submitted.You should receive you packet shourtly in the mail.";

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章