2012-01-23 84 views
1

CGIのbashでの動作例が見つかりました。私はスクリプト次CGIを使ったシェルスクリプトは、bashではうまく動作しますが、shでは動作しません。

#!/bin/sh 
echo "Content-type: text/html\n\n" 

に最初の2行を変更した場合は動作を停止し、私は、ブラウザでスクリプトを閲覧するときにスクリプトが消えるの「FOO」、「バー」と「foobarには」ボトムで宣言。

shで同じサンプルをどのように動作させることができますか。実際には、私はbashを持っていないが、shのような組み込みデバイス上でこのような例を実行する必要があります。

#!/bin/bash 
echo -e "Content-type: text/html\n\n" 
echo " 
<html> 
<body> 
<form action="http://${HTTP_HOST}:${SERVER_PORT}${SCRIPT_NAME}?foo=1234" method="POST"> 
<input type="text" name="bar"> 
<textarea name="foobar"></textarea> 
<input type="submit"> 
</form>" 


# (internal) routine to store POST data 
cgi_get_POST_vars() 
{ 
    # check content type 
    # FIXME: not sure if we could handle uploads with this.. 
    [ "${CONTENT_TYPE}" != "application/x-www-form-urlencoded" ] && \ 
    echo "Warning: you should probably use MIME type "\ 
     "application/x-www-form-urlencoded!" 1>&2 
    # save POST variables (only first time this is called) 
    [ -z "$QUERY_STRING_POST" \ 
     -a "$REQUEST_METHOD" = "POST" -a ! -z "$CONTENT_LENGTH" ] && \ 
    read -n $CONTENT_LENGTH QUERY_STRING_POST 
    return 
} 

# (internal) routine to decode urlencoded strings 
cgi_decodevar() 
{ 
    [ $# -ne 1 ] && return 
    local v t h 
    # replace all + with whitespace and append %% 
    t="${1//+/ }%%" 
    while [ ${#t} -gt 0 -a "${t}" != "%" ]; do 
    v="${v}${t%%\%*}" # digest up to the first % 
    t="${t#*%}"  # remove digested part 
    # decode if there is anything to decode and if not at end of string 
    if [ ${#t} -gt 0 -a "${t}" != "%" ]; then 
     h=${t:0:2} # save first two chars 
     t="${t:2}" # remove these 
     v="${v}"`echo -e \\\\x${h}` # convert hex to special char 
    fi 
    done 
    # return decoded string 
    echo "${v}" 
    return 
} 

# routine to get variables from http requests 
# usage: cgi_getvars method varname1 [.. varnameN] 
# method is either GET or POST or BOTH 
# the magic varible name ALL gets everything 
cgi_getvars() 
{ 
    [ $# -lt 2 ] && return 
    local q p k v s 
    # get query 
    case $1 in 
    GET) 
     [ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&" 
     ;; 
    POST) 
     cgi_get_POST_vars 
     [ ! -z "${QUERY_STRING_POST}" ] && q="${QUERY_STRING_POST}&" 
     ;; 
    BOTH) 
     [ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&" 
     cgi_get_POST_vars 
     [ ! -z "${QUERY_STRING_POST}" ] && q="${q}${QUERY_STRING_POST}&" 
     ;; 
    esac 
    shift 
    s=" $* " 
    # parse the query data 
    while [ ! -z "$q" ]; do 
    p="${q%%&*}" # get first part of query string 
    k="${p%%=*}" # get the key (variable name) from it 
    v="${p#*=}" # get the value from it 
    q="${q#$p&*}" # strip first part from query string 
    # decode and evaluate var if requested 
    [ "$1" = "ALL" -o "${s/ $k /}" != "$s" ] && \ 
     eval "$k=\"`cgi_decodevar \"$v\"`\"" 
    done 
    return 
} 



# register all GET and POST variables 
cgi_getvars BOTH ALL 

echo "<pre>foo=$foo</pre>" 
echo "<pre>bar=$bar</pre>" 
echo "<pre>foobar=$foobar</pre>" 

echo "</body> 
</html>" 

アップデート1: sh -x scriptは以下返さ:functionキーワードで

+ echo Content-type: text/html\n\n 
Content-type: text/html 


+ echo 
<html> 
<body> 
<form action=http://:?foo=1234 method=POST> 
<input type=text name=bar> 
<textarea name=foobar></textarea> 
<input type=submit> 
</form> 

<html> 
<body> 
<form action=http://:?foo=1234 method=POST> 
<input type=text name=bar> 
<textarea name=foobar></textarea> 
<input type=submit> 
</form> 
+ cgi_getvars BOTH ALL 
+ [ 2 -lt 2 ] 
+ local q p k v s 
+ [ ! -z ] 
+ cgi_get_POST_vars 
+ [ != application/x-www-form-urlencoded ] 
+ echo Warning: you should probably use MIME type application/x-www-form-urlencoded! 
Warning: you should probably use MIME type application/x-www-form-urlencoded! 
+ [ -z -a = POST -a ! -z ] 
+ return 
+ [ ! -z ] 
+ shift 
+ s= ALL 
+ [ ! -z ] 
+ return 
+ echo <pre>foo=</pre> 
<pre>foo=</pre> 
+ echo <pre>bar=</pre> 
<pre>bar=</pre> 
+ echo <pre>foobar=</pre> 
<pre>foobar=</pre> 
+ echo </body> 
</html> 
</body> 
</html> 
+0

'/ bin/sh'はまだ何らかのシェルであり、変更する前に決定する必要があります。 'sh --version'とは何ですか? –

+1

@baltusajスクリプトをデバッグモードで実行しようとしましたか?これを実行するには、 'sh -x scriptname.sh'を実行します。 'sha-bang'行を' Bourne Shell'に変更してデバッグモードで実行してください。それは役に立つかもしれないいくつかの情報を投げるかもしれません。 –

+0

/bin/sh --version、sh --verionが 'sh:不正な操作 - 'エラーを返します。 shシェルで実行すると同じエラーが発生します。デフォルトのbashシェルで/ bin/shを実行してshシェルを実行しました。 – baltoro

答えて

2

であるbashはPOSIX仕様に比べて機能拡張の多くを持っており、あなたのスクリプトは、それらのいくつかを使用しています。あなたの/bin/shは、明らかにbash(灰、ダッシュ、mkshなど)ではなく、それらの拡張子がありません。あなたはスクリプトを通過し、あなたのshの文書またはPOSIX specificationに対して各構成をチェックする必要があります。

Quckly探して:

  • function cgi_get_POST_vars():functionキーワードが存在してはならないと開きブレースは、同じ行に行く必要があります。
  • read -n $CONTENT_LENGTH QUERY_STRING_POST:read(シェル組み込み)にはPOSIXでは-nオプションがありません。
  • t="${1//+/ }%%"h=${t:0:2}:Bourneはこれらの修飾子のいずれもサポートしていません。

しかし、これ以上あることもあります。

編集:

  • echoは、シェル間で最も互換性のないコマンドです。標準では、\の振る舞いは実装定義であるとしか言いません。代わりにprintfを使用する必要があります。
1

関数宣言のBourneスクリプトとの互換性がありません。 shの正しい構文は

cgi_get_POST_vars() { 
    ... 
} 
+0

それを指摘してくれてありがとう。しかし、その問題は主要な問題を解決します。ブラウザはまだ 'foo'、 'bar'、 'foobar'の値を表示していません。 – baltoro

+0

@baltusaj:はい、スクリプトにPOSIX以外の機能がいくつか追加されています。 –

0

また、このようなスクリプトには非常に注意してください。この引数パーサーはシェルインジェクション攻撃の影響を受けやすいです。たとえば、変数が渡された場合:

cgi-bin/myscript.cgi&foo=bar`ls`bar 

は、私が「LS」コマンドは、引数のデコード中に実行されると信じています。そして、あなたは "ls"よりも多くの破壊的なコマンドを想像することができます。また、敵対的なユーザーが引数&PATH=""を渡すとどうなるか考えてみてください。このようなことは難しく、組み込み機器を扱っているのであれば、Webサーバがroot権限で動作していても驚くことはありません。

関連する問題