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.";
}
cgi
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.