#!/usr/bin/perl

###################################################
#
#  雀悟狼−ｊ アプレット機能補完 CGI "JANPLUS.CGI"
#
#          http://jan.kalin.to/
#
#  Ver.1.03 Programmed by 「たく」 06/06/10
#
###################################################
#
#　！！！　重要　！！！
#　このバージョンは、前バージョンの Ver.1.01 において、jangoro.jar の最新バージョンを
#　正しく取得できないサーバー(主にホームページに広告が入るフリーのwebサーバー）を利用
#　されている方向けのものです。前 Version において不具合がない場合は、前バージョンを
#　そのままご利用いただいても問題ありません。
#
#  このプログラムは、雀悟狼−ｊアプレットの機能をより充実させるための付随アプリケーションです。
#　このファイルが無くても雀悟狼−ｊの設置および公開は可能ですが、現在及び今後の機能拡張に
#　際してこのプログラムがあるとより便利になるので是非導入してください。
#
#--------------------------------------------------
#【このプログラムは何？】
#　このプログラムは、雀悟狼−ｊアプレットの機能をより充実させるためのプログラムで、クライアント
#　マシンにダウンロードされた雀悟狼−ｊアプレットと、雀悟狼−ｊ公式サーバーとの通信経路を確立
#　させるためのプログラムです。
#　通常、Java アプレットはアプレットをダウンロードしたサーバー(＝ＨＰサーバー)との間でしか
#　通信ができないという制限があります。このプログラムを導入する事によって、ネットワーク
#　のセキュリティー強度を落とす事なく、比較的簡単にアプレット本体と公式サーバーとの間に通信経路を
#　確立し情報のやりとりができるようになります。それによって、今後様々なサービスを提供できる
#　ようになります。
#
#--------------------------------------------------
#【設置方法】
#
#　このファイルは CGI プログラムです。一般的な掲示板などの設置経験のある方は、3.の動作確認
#　からお読みください。CGI 設置経験の無い方は 1.から順を追って設置してください。
#
#1.このプログラムを、雀悟狼−ｊアプレットと同じサーバー内の、CGI プログラムの動作可能な場所
#　にアスキーモードでアップロードします。多くのサーバーの場合は、/cgi-bin/ 内になると
#　思われます。詳しくはサーバー管理人の方にお尋ねください。
#
#2.アップロードしたプログラムに実行属性をつけます。ftp クライアント等を使って、janplus.cgi
#　の属性(パーミッション)を 755 に変更してください。具体的な設定方法は、お使いの ftp クライアントの
#　マニュアル・ヘルプ等を参照してください。
#
#3.設定した cgi プログラムを呼び出して動作確認をします。ブラウザなどを使って、URL 入力欄に
#　http://(janplus.cgiのURLパス)/janplus.cgi?cmd=gif/banner_jgj.gif
#　と入力してください。雀悟狼−Ｊのバナーが表示されれば正常に動作しています。
#
#4.先ほどの3.で入力した URL の文字列の先頭 http://　から、janplus.cgi の直前の / 部分までを
#　記録し、アプレットを呼び出す html ファイル内のパラメータ　"cgiurl" に記述します。
#　先ほどの例で具体的に　http://www.kalin.to/cgi-bin/janplus.cgi?………
#　と入力していた場合には、html 内の設定は
#　<param name = "cgiurl" value = "http://www.kalin.to/cgi-bin/">
#　と記述します。
#
#5.上記設定を施した html ファイルからアプレットを立ち上げてください。正常に設定が反映されて
#　いればゲーム開始前の画面でアナウンスが表示されます。
#
#--------------------------------------------------
#
#【トラブルシュート】
#　上記のように設置したのに動作しない場合は、公式ＨＰのＦＡＱを参考にしたり、掲示板などで
#　質問したりしてみてください。
#　
#--------------------------------------------------
#
#【セキュリティーポリシー】
#　このプログラムによって雀悟狼−ｊ公式サーバーに送信される情報は、アプレット内部だけで
#　使用されているゲームのデータ（得点や牌情報など）および、ゲームプレー中の IP アドレス、
#　サーバーアドレス、クライアントマシンの JavaVM の種類、エラー情報等です。
#　このプログラムを導入する事によって、あなたの個人情報(お名前やメールアドレス等)が
#　雀悟狼−ｊ公式サーバーに送信される事はありません。
#　なお、セキュリティーポリシーを変更した場合には公式ＨＰにおいて報告致します。
#　
#--------------------------------------------------
#
#【更新履歴】
# Ver.1.01　リリース版
# Ver.1.02　oab.sytes.net などの、ホームページに広告が入るサーバーへの暫定対策版
# Ver.1.03　空引数で呼ばれた場合は gif 偽装ヘッダをキャンセル
#
###################################################
#
#　以下プログラム本体です。いじらないでください。
#
###################################################

$host = "jan.kalin.to" ;
$default_cmd = "banner/banner.cgi" ;
&Parse() ;
$opt = "" ;
# cgi の引数を再構築する
foreach $key (sort keys %name) {
  if ($key eq "cmd" || $key eq "host") {	# 
    ${$key} = $name{$key} ;		# cmd、host は特殊引数
  } else {
    $opt .= $key ;		# それ以外は引き継ぐ引数
    $opt .= "=" ;
    $opt .= $name{$key} ;
    $opt .= "\&" ;
  }
}
if ($opt ne "") {		# 引数が空文字でない場合は
  $opt = "\?".$opt ;	# 行頭に ? を追加
  chop $opt ;		  	# 文末の & を削除
}
if ($cmd eq "") {		# 呼び出す cgi の名前が無い場合は
  $cmd = $default_cmd ;	# デフォルトコマンドを設定
}

#########################
# socket モジュールを使う(Perl5以降は標準装備)
use Socket ;

# 接続ポートも完全固定
$port = getservbyname('http','tcp') || 80 ;

# 接続準備
if (!($iaddr = inet_aton($host))) {
  &HTTPError ("$host は存在しません") ;
}
$sock_addr = sockaddr_in($port, $iaddr) ;

# 接続
binmode(SOCKET) ;		# バイナリモード
socket(SOCKET, PF_INET, SOCK_STREAM, 0) or &HTTPError ("SOCKETに失敗: $!\n") ;
connect(SOCKET, $sock_addr) or &HTTPError("$hostのポート$portに接続できません: $!\n") ;
select(SOCKET); $|=1; select(STDOUT);	# socket データをバッファに溜めない設定

# HTTP ヘッダーを送信する
send(SOCKET, "GET \/${cmd}${opt} HTTP/1.1\r\n",0) ;
send(SOCKET, "Host: $host\r\n",0) ;
send(SOCKET, "Connection: close\r\n",0) ;
send(SOCKET, "User-Agent: janplus.cgi Ver.1.02(playerIP:".$ENV{'REMOTE_ADDR'}.")\r\n",0) ;
send(SOCKET, "Accept: */*\r\n",0) ;
send(SOCKET, "\r\n", 0) ;

# リクエスト先から送られてきたデータをバイナリデータとして $in に取得
# ヘッダを含めたデータが欲しい場合は $header=1 とする。

@header = () ;			# 親サーバーからヘッダを取得
while (<SOCKET>){
  if ($_ eq "\r\n") {
    last ;
  }
  if ($_ =~ /^Content-Type: Text/i) {					# 親サーバーから送られてきたコンテンツがText系の場合
  	if ($opt eq "") {									# オプションがなかった場合
	    push @header , "Content-Type: text\/html\n" ;
  	} else {
	    push @header , "Content-Type: image\/gif\n" ;		# gif に偽装 (ver.1.02)
	}
  } elsif ($_ =~ /^HTTP/ || $_ =~ /^Content-Length:/ ) {	# HTTP レスポンス及びコンテントレングスは消去
    ;
  } else {
    push @header , $_ ;
  }
}

$in='';					# 本体を取得
while (<SOCKET>){ $in.=$_; }
$cln = length($in) ;

# socket 切断
shutdown(SOCKET,2) ;
close(SOCKET);	#ソケットの解消。


print @header ;
print "Content-Length: $cln\n\n" ;
print $in ;
exit ;


##################################################
###             Parse Programm                  ##
##################################################

sub Parse {
	local ($_, @_) ;
	local ($key, $value) ;
	if ($ENV{'REQUEST_METHOD'} eq "GET") {			# get method
		$_ = $ENV{'QUERY_STRING'} ;
	} elsif ($ENV{'REQUEST_METHOD'} eq "POST") {	# post method
		read(STDIN, $_, $ENV{'CONTENT_LENGTH'}) ;
	} else {
		unless (open(FILE, "<perlpar.txt")) {
			while (<STDIN>) {						# keybord input
				chop;
				last ;
			}
		} else {
			while (<FILE>) {						# file read
				chop;
				last ;
			}
		}
	}
	$arg_str =  $_ ;				# to error report
	split(/&/) ;

	foreach(@_) {
		if (index($_, "=") == $[ - 1) {
			push(name, '', $_) ;
		} else {
			push(name, split(/=/, $_, 2)) ;
		}
	}
	foreach(@name) {
		s/\+/ /g;
		s/%(..)/pack("c", hex($1))/ge;
	}
	%name = @name ;
}

sub HTTPError {
	print "Content-Type: text/html\n\nError.\n@_" ;
	exit ;
}
