期中過後,Linux 作業又來了,這次是關於 Web Server 的架設,此部分元素的元素比以往多了許多,有關連線、防火牆、SElinux,甚至還多了一項過去沒接觸過的 CGI 設計,所謂的 CGI 便是一個提供 Browser 與 Server 溝通的程式,常見大多是使用 Python 來做 CGI 主要設計的語言,但這部分依作業要求使用 C 語言來進行 CGI 的設計。
目錄
前言
其實這次的作業有個很嚴重且麻煩的問題,就是網頁表單透過 CGI 傳輸 POST 資訊時,會自動以 Unicode(UTF8)的編碼形式來呈現中文字,作業部分要求透過輸入姓名、年紀,以及一個選項參數,這部分老實說有點懶得做,想像其他同學一樣以輸入英文來代替中文,其實我想老師應該沒有料想到 Unicode 編碼問題,所以就把它視為一個失誤作業吧,不過不知道為什麼就是有點想把這份作業弄得趨近完美。
作業內容
請根據上課CGI範例,設計一個網頁
網頁中可以輸入姓名(type=text),年齡(type=text)姓名:<INPUT TYPE =text NAME =name >如無更新將以這個值送出<br>年齡:<INPUT TYPE =text NAME =age >必須輸入,輸入值即為VALUE的值<br>及嗜好:<SELECT NAME =menu1><OPTION VALUE=”0”>讀書<OPTION VALUE=”1”>運動<OPTION VALUE=”2”>郊遊<OPTION VALUE=”3”>聽音樂</SELECT ><br>以及<INPUT TYPE =reset VALUE=”重新輸入”><INPUT TYPE =submit VALUE=”送出資料”><br>並設計一個 CGI 程式,可以根據 submit 資料回傳一個包含姓名、年齡跟嗜好的網頁,例如:輸入 張三,18歲,嗜好:聽音樂 (送出)網頁會顯示張三您好,您18歲,嗜好:聽音樂。
解題
這份作業看起來是份簡單到不能再簡單的一份作業,但卻暗藏了一堆麻煩,當然只是需要多花點時間處理,老實說我有點後悔C++ 程式作業出的是 Base64 的解法,應該出 Unicode 編解碼的,這樣這一題就可以更省時的來完成。
先前準備
首先先將 Apache、C/C++ 編譯器安裝到 Fedora 中吧,透過 Fedora 方便的 yum 指令來進行安裝。
sudo yum install httpd -y //Apache sudo yum install gcc -y //C sudo yum install gcc-c++ -y //C++
啟動與關閉
指令: “systemctl [command] [Service].service”
systemctl start httpd.service //啟動服務 systemctl enable httpd.service //自動啟動 systemctl stop firewared.service //關閉防火牆 systemctl disable firewared.service //開機不自動啟動防火牆
關閉防火牆是為了讓非本機用戶來進行連線,例如站長所使用的是實體機器來連接虛擬機(VMware)設備,如果防火牆預設開啟,實體機器則會無法建立連線,上圖中由於防火牆早就被關閉了,所以顯示 “Failed to issue method call: Unit firewared.service not loaded.”。
簡易測試
可以打開 Browser 網址列輸入:127.0.0.1 || localhost || 自己的 IP 位址,基本上可以連到 Apache 的預設網頁。
建立網頁
Apache 預設的 Linux 網頁路徑為 “/var/www/html”,CGI 預設位置則是 “/var/www/cgi-bin/”,稍後將網頁以及 CGI 編譯完成之後,請放入到正確的位置,當然 CGI 與 html 網頁中的 “action” 互相對應,所以檔名也不要設置錯誤。
網頁架構
CGI
用 C 語言來撰寫 CGI,由於是第一次接觸 CGI,也藉由網路尋找許多網路上的資源,可惜大多人都是選用 Python 來撰寫 CGI,C 部分的資源就變得有點缺乏,在 CGI程式入門 一文中有詳細的參數介紹可以參考,此外在 Fedora 中編譯程式使用指令如下。
gcc -o post.cgi post.c g++ -o post.cgi post.cpp
在 Linux 的 Apache 預設的 CGI 路徑為,/var/www/cgi-bin/ 中,記得與 html 網頁 action 相對應。
範例
在老師給的範例中,可以確定是使用 C 語言來進行撰寫,其中下兩行,先是宣告一個指標字串,再來將 URL 上 “?” 之後的字串存入變數之中。
char *data; data = getenv("QUERY_STRING");
運用這一點就可以用來判斷表單填寫的內容,進階再由 CGI 控制來改變輸出或做資料收集等。
Unicode 編碼問題
聰明的各位一定會發現中文字的部分會變成亂碼,事實上這稱為 Unicode 編碼,至於怎麼將 Unicode 編碼解成我們熟悉的中文字,這部分有興趣的朋友們可能要大家運用網路資源,站長在此部分也想快速交差,所以找了人家現成的 Unicode 解碼程式來進行套用,並加上幾段擷取字串重要資訊的程式碼。
Unicode 解碼 C:傳送門
程式我已經改成作業相對應的程式碼了,有需要的自行 Key 吧,但沒有副程式的部分,請自行到 “陳鍾誠的網站” 自行 copy 並在此感謝作者。
以上是我用 C++ 寫的簡易字串擷取程式,邏輯不複雜,雖然算是個笨方法,程式先假設擷取到的 Unicode 為 “name=%E5%8A%89%E5%A4%A7%E5%B8%A5&age=19&menu1=%E2%80%9D0%E2%80%9D”。
資料送出前
送出資料
結論及提醒
在撰寫 CGI 以及測試的過程中要非常小心,在本文章第一張圖片正是站長 VMware 下的 Fedora,其因為 CGI 程式撰寫有嚴重的 Bug 造成了 CPU full Loading,在過去 Ms-dos 中可能會因此死當,但在 Linux 系統中卻是吃盡了資源,這是很可怕的,所以在 Debug 時需要細心一些,否則可能會造成一去不回的結果,在此提醒大家,請不要壓秒交作業!!