#!/usr/bin/perl

use strict;

# ソフトウェア情報
# 
# BS Psssword Jump Ver2.2
#  パスワードによって、ジャンプ先が変るCGIです。
# 
# 著作権
#  CGI-Store.JP
#  http://cgi-store.jp/
# 
# 公開日
#  2007/09/07
# 
# 取扱説明書
#  Cookieの使用の可否が設定できます。
#   使用する設定の時でも携帯端末と判断した場合、一部の端末では使用しません。
#   （USER AGENTにDoCoMo・J-PHONE・UP.Browserが存在した場合、Cookie使用不可携帯端末と判断します。）
#   Cookieにパスワードが保存されていない場合はフォームを表示します。
#  Cookieを削除したい場合は、
#   「PssswordJump.cgi?act=clear」とアクセスすればCookieが削除されフォームが表示されます。
#  エラー画面はSJISで出力されます。
#  Locationヘッダが使用できないブラウザが携帯端末の一部にあるようです。
#   その場合は正常に動作しません。ご了承ください。
#  フォーム用HTMLファイル内にはフォームを記述する必要があります。
#   携帯端末はGETメソッドしか対応していない端末が数多くあります。
#   記述例：
#    <FORM method="GET" action="PssswordJump.cgi">
#    <INPUT type="hidden" name="act" value="jump">
#    <INPUT type="password" name="password" value="">
#    <INPUT type="submit" value="Enter">
#    </FORM>
#  標準ではフォーム用HTMLは、データディレクトリ内のformディレクトリにあるdefault.htmlが使用されます。
#   任意のフォームを複数用意する場合には、formディレクトリに違う名称の拡張子がhtmlを設置します。
#   そして、任意のフォームを利用するには、「sample.html」を呼び出すには「PssswordJump.cgi?page=sample」へリンクします。
#   任意のHTMLを利用する時のCookie削除は「PssswordJump.cgi?act=clear&page=sample」です。
# 
# 

# 初期設定ここから

# データ用ディレクトリ
my $DataDir = './data';

# パスワード保存用ファイル
# 　「パスワード文字列<TAB>URL文字列」を各行毎に記述しておく。
my $PwdFile = $DataDir . '/password.txt';

# Cookieを使用するか。
# 　1 -> 使用する。0 -> 使用しない。
my $UseCookie = 0;

# 初期設定ここまで


# フォームデコード
my($buffer, @pairs, $pair, $name, $value, %FORM);
%FORM = ();
if ($ENV{'REQUEST_METHOD'} eq "POST"){
	read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
else{
	$buffer = $ENV{'QUERY_STRING'};
}
@pairs = split(/&/,$buffer);
foreach $pair (@pairs) {
	($name, $value) = split(/=/, $pair);
	$name =~ tr/+/ /;
	$name =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
	$value =~ tr/+/ /;
	$value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
	$FORM{$name} = $value;
}

# USER AGENTのチェック
my($CType, %COOKIE);
%COOKIE = ();
if ($ENV{'HTTP_USER_AGENT'} =~ /DoCoMo/) {
	$CType = 'imode';
}
elsif ($ENV{'HTTP_USER_AGENT'} =~ /J-PHONE/) {
	$CType = 'jsky';
}
elsif ($ENV{'HTTP_USER_AGENT'} =~ /UP\.Browser/) {
	$CType = 'ezweb';
}
else {
	$CType = 'other';
	if ($UseCookie == 1) {
		&getCookie(\%COOKIE);
	}
}

# フォーム用HTMLを決定する
my $FormFile = $DataDir . '/form/default.html';
if ($FORM{'page'} ne '') {
	$FormFile = $DataDir . '/form/' . $FORM{'page'} . '.html';
}
unless (-e $FormFile) {
	&error('Error', 'form file not found');
	exit;
}

if ($FORM{'act'} eq '') {
	if ($UseCookie == 0) {
		&Form($FormFile);
	}
	elsif ($COOKIE{'PASSWORD'} eq '') {
		&Form($FormFile);
	}
	else {
		$FORM{'password'} = $COOKIE{'PASSWORD'};
		&Jump;
	}
}
elsif ($FORM{'act'} eq 'jump') {
	&Jump;
}
elsif ($FORM{'act'} eq 'clear') {
	if ($CType eq 'other') {
		if ($UseCookie == 1) {
			print &clearCookie('PASSWORD');
		}
	}
	&Form($FormFile);
}
else {
	&error('Error', 'End of Prpgram');
}

exit;


# form.cgiの出力
sub Form {
	print "Content-type: text/html; charset=Shift_JIS\n\n";
	open FILE, $_[0];
	while (<FILE>) {
		$_ =~ s/\x0D?\x0A?$//;
		print $_ . "\n";
	}
	close FILE;
}

# リダイレクト処理
sub Jump {
	my($seko, $data, $pwd, $url);
	# パスワード照合
	$seko = 0;
	open FILE, $PwdFile;
	while ($data = <FILE>) {
		$data =~ s/\x0D?\x0A?$//;
		($pwd, $url) = split(/\t/, $data, 2);
		if ($FORM{'password'} eq $pwd) {
			$seko = 1;
			last;
		}
	}
	close FILE;
	# リダイレクト処理
	if ($seko == 1) {
		if ($CType eq 'other') {
			if ($UseCookie == 1) {
				print &setCookie('PASSWORD',$FORM{'password'});
			}
		}
		print "Location: $url\n\n";
	}
	else {
		&error('Error', 'Password Error');
	}
}

# エラーメッセージ出力
sub error {
	print "Content-type: text/html; charset=Shift_JIS\n\n";
	print '<HTML>' . "\n";
	print '<HEAD>' . "\n";
	print '<TITLE>' . $_[0] . '</TITLE>' . "\n";
	print '</HEAD>' . "\n";
	print '<BODY>' . "\n";
	print $_[0] . ':<BR>' . "\n";
	print $_[1] . "\n";
	print '</BODY>' . "\n";
	print '</HTML>' . "\n";
}

sub getCookie {
	my($ref, $tmp, $name, $value);
	$ref = $_[0];
	for $tmp (split(/; */, $ENV{'HTTP_COOKIE'})) {
		($name, $value) = split(/=/, $tmp);
		$value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('C', hex($1))/eg;
		$ref->{$name} = $value;
	}
}

sub setCookie {
	my $val = $_[1];
	$val =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg;
	my $tmp = 'Set-Cookie: ' . $_[0] . '=' . $val . '; ';
	$tmp .= 'expires=Thu, 1-Jan-2030 00:00:00 GMT;' . "\n";
	return $tmp;
}

sub clearCookie {
	my $tmp = 'Set-Cookie: ' . $_[0] . '=xx; ';
	$tmp .= 'expires=Thu, 1-Jan-1980 00:00:00 GMT;' . "\n";
	return $tmp;
}

