2007年11月16日 星期五

使用 Bash Shell 撰寫 Web CGI 程式

Standard
使用系統的 Bash Shell 來寫 CGI,這是以前做嵌入式系統時的一個 Web 應用程式解決方案,構想很酷、很有趣。當時考慮到,如果用 C 語言寫 CGI,程式會既複雜又不易維護﹝研發嵌入式系統時 Cross Compile 和繁瑣的 Debug 可是很討厭的!!﹞;若是讓 Web Server 其支援 PHP、Perl,其程式架構會太過龐大。種種因素讓我決定用 Bash 完成需要的 CGI 網站應用程式,畢竟 Bash 從面市到現在,功能越來越齊全強大了,我想應該能勝任 Web Scripts 的工作!:P

當時我先上網搜尋是否有人試過使用 Bash Shell 開發過 CGI 程式,果然有個老兄寫了一些 Bash Functions 來支援些 Web 上的操作,讓我們可以輕易使用 Bash 來寫 CGI。有興趣的人可以到 bashlib(http://bashlib.sourceforge.net/) 抓回來玩玩看。

如果你看過了這個 Bashlib ,一定發現其實它功能很陽春,只有取得 GET 傳值、表單傳值、轉向、Cookies等幾種功能。嘿嘿,這時候當然要開始惡搞這個 bashlib,我改寫並加入了一些功能,像是 Session 的支援。

自己額外亂搞新增支援 Session 的 Functions:
function init_session {
if [ ! -d /tmp/.xcdmgrsess ]; then
mkdir /tmp/.xcdmgrsess &> /dev/null
fi

SESS_ID=`cookie SESS_ID`
if [ A$SESS_ID = A"" ]; then
SESS_ID=`mkcode 30`
set_cookie SESS_ID $SESS_ID
touch /tmp/.xcdmgrsess/$SESS_ID
else
if [ -f /tmp/.xcdmgrsess/$SESS_ID ]; then
while read SESSLINE; do
eval "export 'SESSION_${SESSLINE}'"
done < /tmp/.xcdmgrsess/$SESS_ID
else
touch /tmp/.xcdmgrsess/$SESS_ID
fi
fi
}

function uninit_session {
SESS_ID=`cookie SESS_ID`
if [ ! A$SESS_ID = A"" ]; then
set_cookie SESS_ID ""
if [ -f /tmp/.xcdmgrsess/$SESS_ID ]; then
rm -f /tmp/.xcdmgrsess/$SESS_ID
fi
fi
}

# session function. Same explanation as param
function session {
local name
local value

SESS_ID=`cookie SESS_ID`
while read SESSLINE; do
eval "export 'SESSION_${SESSLINE}'"
done < /tmp/.xcdmgrsess/$SESS_ID

if [ $# -eq 1 ]; then
name=$1
name=$(echo ${name} | /bin/sed -e 's/SESSION_//')
value=$(/usr/bin/env | /bin/grep "^SESSION_${name}" | /bin/sed -e 's/SESSION_//' | /usr/bin/cut -d= -f2-)
echo ${value}
elif [ $# -gt 1 ]; then
name=$1
shift
eval "export 'SESSION_${name}=$*'"
/usr/bin/env | /bin/grep '^SESSION_' | /bin/sed -e 's/SESSION_//' > /tmp/.xcdmgrsess/$SESS_ID
else
value=$(/usr/bin/env | /bin/grep '^SESSION_' | /bin/sed -e 's/SESSION_//' | /usr/bin/cut -d= -f1)
echo ${value}
fi
unset name
unset value
}


function set_session {
local name=$1
shift
local value=$*

session $name $value &> /dev/null
}


使用方法:
  1. 使用前先呼叫:
    • init_session
  2. 設自訂的 Session 變數:
    • set_session NAME "Fred"
  3. 取得 Session 變數值:
    • SESSION_NAME=`session NAME`


後記:

其實,用 Bash 這種系統 shell 來寫 CGI 本來就不是什麼新構想,因為常在開發 Web Server 的 CGI 支援時,就會用這種 Shell 寫簡單的 CGI 做測試。只是這次瘋狂了點,利用 Bash 達成更多 CGI 的功能。

另外,使用 Bash 當 CGI 的 Scripts Language 要注意的是 Injection 的攻擊,因為每一行都被當成系統命令在執行,所以當用戶透過 Web 執行 Bash CGI 時,就相當於用戶在你的 Console 下執行命令。想要避免這些問題,需要詳細了解 Bash 雙引號和單引號的使用和差別。