#!/usr/bin/perl require "../jcode.pl"; use CGI; #==================== ユーザー設定 ========== $CHARSET = 'EUC-JP'; # 文字コード $DATAPASS = './schedule/'; # 記事ファイル $MAXLINE = 100; # 最大記事数 $MAXTHREAD = 100; # 最大スレッド数 $PASSWORD = 'kamigoma'; # 管理パスワード $COOKIE_PREFIX = 'schedule'; # クッキープリフィクス $COOKIE_LIFE = 30; # クッキー期限(日) $SESSIONFILE = '../dat/session.dat'; # セッション管理ファイル $USERFILE = '../dat/users.dat'; # ユーザーファイル $EXPIRES = 2; # アクセスログ保存期間 $GEYEAR; $GEMON; $GEMDAY; #==================== メインプログラム ========== $agent = $ENV{'HTTP_USER_AGENT'}; if($agent =~ /DoCoMo/){ printMobile(); } elsif($agent =~ /UP.Browser/){ printMobile(); } elsif($agent =~ /J-PHONE|Vodafone|SoftBank/){ printMobile(); } # パソコンの場合 else { loadFormdata(); # フォーム読み込み loadCookie(); # クッキー読み込み loadSession(); # セッション読み込み $member = checkCode(); # クッキーに暗号が一致したら$memberにIDを入れる deleteold(); # クッキーに暗号が一致 if($member) { loadUserfile(); # ユーザーファイルを読み込み$memberを基に個人のハッシュ%IDの作成 # 何かしらモード指定があった場合 if(exists $FORM{'mode'}) { if($FORM{'month'} eq ""){ $GEYEAR = $FORM{'year'}; $GEMON = $FORM{'mon'}; $GEDAY = $FORM{'day'}; } # 月の指定があった場合 else{ my ($syear, $smonth, $sday) = split(/-/, $FORM{'month'}); $GEYEAR = $syear; $GEMON = $smonth; $GEDAY = $sday; } $month = "$GEYEAR-$GEMON.dat"; $DATAPASS .= $month; loadLogfile(); # 月データを%LOGに代入 if($FORM{'mode'} eq 'write') { if($FORM{'title'} and $FORM{'year'} and $FORM{'mon'} and $FORM{'day'}){ writeArticle(); # 書き込みモード } else { $CGI = new CGI(); print $CGI->redirect("$ENV{'SCRIPT_NAME'}?month=$FORM{'month'}"); } } else { deleteArticle(); # 削除モード } @LOG = sort @LOG; #sortdata(); # 記事データの書き込み open(FILE, ">$DATAPASS") or printErrorPage("openError"); eval{ flock(FILE, 2) }; print FILE @LOG; close(FILE); $CGI = new CGI(); print $CGI->redirect("$ENV{'SCRIPT_NAME'}?month=$GEYEAR-$GEMON-$GEDAY"); } # 通常の場合 else { # 何月のデータを読み込むかの判断 # 月の指定がなかった場合 if($FORM{'month'} eq ""){ # 現在の日時を取得 my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time); $GEYEAR = $year+1900; $GEMON = $mon+1; $GEDAY = $mday; $GE = "nothing"; } # 月の指定があった場合 else{ my ($syear, $smonth, $sday) = split(/-/, $FORM{'month'}); $GEYEAR = $syear; $GEMON = $smonth; $GEDAY = $sday; } $month = "$GEYEAR-$GEMON.dat"; $DATAPASS .= $month; loadLogfile(); # 月データを%LOGに代入 calday(); # カレンダー演算 if($GEDAY eq "" or $GE eq "nothing"){ printPage("month"); } else { printPage("day"); } } } # クッキーに一致しない else { $CGI = new CGI(); print $CGI->redirect("./index.html"); } } exit; #==================== モバイルのプログラム ========== sub printMobile { loadFormdata(); loadCookie(); loadSession(); $member = checkCode(); $mobile = checkMobile(); # クッキーに暗号が一致 if($member or $mobile) { loadUserfile(); # ユーザーファイルの読み込み$memberを基に個人の%IDの作成 loadLogfile(); # スケジュール管理ファイル if(exists $FORM{'newthread'}){ printMobilePage("newthread"); } else{ if($FORM{'thread'} ne ""){ $DATAFILE = "./bbs/$FORM{'thread'}.dat"; } open(FILE, "<$DATAFILE") or printErrorPage("openError"); eval{ flock(FILE, 1) }; @DATA = ; close(FILE); if(exists $FORM{'mode'}) { if($FORM{'mode'} eq 'write') { if($FORM{'title'} and $FORM{'text'}){ writeArticle(); # 書き込みモード sortdata(); loadLogfile(); # 掲示板管理ファイル } } else { deleteArticle(); # 削除モード } # 記事データの書き込み open(FILE, ">$DATAFILE") or printErrorPage("openError"); eval{ flock(FILE, 2) }; print FILE @DATA; close(FILE); } if(exists $FORM{'new'}){ if($FORM{'title'} and $FORM{'text'} and $FORM{'threadtitle'}){ newthread(); # 新スレッドモード $DATAFILE = "./bbs/$FORM{'thread'}.dat"; open(FILE, "<$DATAFILE") or printErrorPage("openError"); eval{ flock(FILE, 1) }; @DATA = ; close(FILE); writeArticle(); # 書き込みモード open(FILE, ">$DATAFILE") or printErrorPage("openError"); eval{ flock(FILE, 2) }; print FILE @DATA; close(FILE); loadLogfile(); # 掲示板管理ファイル } } printMobilePage("bbs"); } } else { $CGI = new CGI(); print $CGI->redirect("./index.html"); } } #==================== (モバイル用)クッキーの暗号が一致したらID、なければ0を返す ========== sub checkMobile { my($name, $pass, %CODEN, $load); open(FILE, "<$SESSIONFILE") or printPage("openError"); eval{ flock(FILE, 1) }; while($ln = ) { chomp $ln; ($name, $pass) = split(/:/, $ln); $CODEN{$pass} = $name; } $load = $FORM{'session'}; close(FILE); if (exists $CODEN{$load}) { return $CODEN{$load}; } else { return 0; } } #==================== (PC用)クッキーの暗号が一致したらID、なければ0を返す ========== sub checkCode { my($name, $pass, %CODEN, $load); open(FILE, "<$SESSIONFILE") or printPage("openError"); eval{ flock(FILE, 1) }; while($ln = ) { chomp $ln; ($name, $pass) = split(/:/, $ln); $CODEN{$pass} = $name; } $load = $SESSION{'id'}; close(FILE); if (exists $CODEN{$load}) { return $CODEN{$load}; } else { return 0; } } #==================== ユーザーファイル読み込み($memberを基に個人のハッシュ"%ID"を作成。IDが一致しなければIDエラーページ出力) ========== sub loadUserfile { my ($ln, $name, $pass, $id, $sex, $birth, $blood, $email, %USERS); open(FILE, "<$USERFILE") or printPage("openError"); eval{ flock(FILE, 1) }; while($ln = ) { chomp $ln; ($name, $pass, $id, $sex, $birth, $blood, $email) = split(/\t/, $ln); if($id eq $member) { %ID = ('name' => $name, 'pass' => $pass, 'id' => $id, 'sex' => $sex, 'birth' => $birth, 'blood' => $blood, 'email' => $email); close(FILE); return 0; } } close(FILE); printPage("IDerror"); exit; } #==================== 月ファイル読み込み(%LOGに代入) ========== sub loadLogfile { my ($ln, $day, $hour1, $min1, $hour2, $min2, $title, $place, $comment); open(FILE, "<$DATAPASS") or printErrorPage($DATAPASS); eval{ flock(FILE, 1) }; @LOG = ; close(FILE); #open(FILE, "<$DATAPASS") # or printPage("openError"); #eval{ flock(FILE, 1) }; #while($ln = ) { # chomp $ln; # ($day, $hour1, $min1, $hour2, $min2, $title, $place, $comment) = split(/\t/, $ln); # $LOG{$file} = $name; #} #close(FILE); } #==================== 月ファイル書き込み時並び替え ========== sub sortdata { my ($ln, $name, $file, $exhibition, %USERS, @DATA); for($i = 0 ; $i < @LOG ; ++$i) { my ($day, $wday, $hour1, $min1, $hour2, $min2, $title, $place, $comment) = split(/\t/, $LOG[$i]); push @DATA, $LOG[$i]; my $k = $i+1; } @DATA = sort @DATA; } #==================== カレンダー ========== sub calday { # 月の末日の指定(左から順に1月、2月・・・) my @days = (31,28,31,30,31,30,31,31,30,31,30,31); my $cellnum = 0; $year = $GEYEAR; $mon = $GEMON; # うるう年の判定(4の倍数ならうるう年、しかし100の倍数ならうるう年でない、また400の倍数ならうるう年) if( (($year%4 ==0)&&($year%100 != 0))||($year%400 == 0) ){ $days[1]=29; } # 月の初日の曜日(ツェラーの公式)、月の末日を取得 $start = getday($year,$mon,1); $lastday=$days[$mon-1]; # 月の初日の前まで、表のセルにスペース(改行)を入れる if($start!=0){ for($i=0;$i<$start;$i++){ $DAY[$cellnum]=" "; $cellnum++; } } # カレンダーのセルを作成 for($i=1;$i<=$lastday;$i++){ my $caltd = $i; # スケジュール一覧の出力 for($j = 0 ; $j < @LOG ; ++$j) { my ($day, $wday, $hour1, $min1, $hour2, $min2, $title, $place, $comment) = split (/\t/, $LOG[$j]); chomp $comment; my $day2 = sprintf("%d",$day); if($day2 eq $i) { $caltd .= "
$title"; last; } } my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time); $year += 1900; $mon++; if($mday eq $i and $mon eq $GEMON and $year eq $GEYEAR){ $DAY[$cellnum] = sprintf("
$caltd
"); } else { $DAY[$cellnum] = sprintf("
$caltd
"); } $cellnum++; } while($cellnum<=42){ $DAY[$cellnum]=" "; $cellnum++; } } sub getday { my ($year,$month,$day)=@_; if($month<3){ $month += 12; $year--; } return ($year+int($year/4)-int($year/100)+int($year/400)+int((13*$month+8)/5)+$day)% 7; } # ==================== 古いログファイルの削除 ========== sub deleteold { my $t1 = time - $EXPIRES * 60 * 60 * 24 * 365; my ($sec, $min, $hour, $mday, $mon, $year) = localtime($t1); $year += 1900; ++$mon; my $delfile = sprintf("./schedule/%d-%d.dat", $year, $mon); if(-e $delfile) { unlink $delfile; } my $t2 = time + $EXPIRES * 60 * 60 * 24 * 365; my ($sec, $min, $hour, $mday, $mon, $year) = localtime($t2); $year += 1900; ++$mon; my $makefile = sprintf("./schedule/%d-%d.dat", $year, $mon); if(not -e $makefile) { open(FILE,">>$makefile") or printErrorPage("openError"); close(FILE); } } #==================== USERファイル読み込み ========== sub loadMemberfile { open(FILE, "<$USERFILE") or printPage("openError"); eval{ flock(FILE, 1) }; @USER = ; close(FILE); } #==================== 記事を書き込む ========== sub writeArticle { my @wdy_str = ('日', '月', '火', '水', '木', '金', '土'); my $wday = getday($FORM{'year'},$FORM{'mon'},$FORM{'day'}); my $GEWDAY = $wdy_str[$wday]; my $day2 = sprintf("%02d",$FORM{'day'}); unshift @LOG, "$day2\t$GEWDAY\t$FORM{'hour1'}\t$FORM{'min1'}\t$FORM{'hour2'}\t$FORM{'min2'}\t$FORM{'title'}\t$FORM{'place'}\t$FORM{'text'}\n"; while(@LOG > $MAXLINE) { pop @LOG; } } #==================== スレッド作成 ========== sub newthread { my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time); my $date = sprintf("%4d%02d%02d%02d%02d%02d", $year + 1900, ++$mon, $mday, $hour, $min, $sec); my $exlist = "admin&"; foreach $key (keys %FORM) { if($key =~ /exhibition_(.+)/) { $exlist .= $1."&"; } } chop $exlist; unshift @LOG, "$FORM{'threadtitle'}\t$date\t$exlist\n"; while(@LOG > $MAXTHREAD) { my $count = @LOG-1; my $ln = $LOG[$count]; chomp $ln; my ($name, $file, $exhibition) = split(/\t/, $ln); if (-e "./bbs/$file.dat") { unlink "./bbs/$file.dat"; } # $LOG{$file} = $name; pop @LOG; } open(FILE, ">$LOGFILE") or printErrorPage("openError"); eval{ flock(FILE, 2) }; print FILE @LOG; close(FILE); open(FILE, ">./bbs/$date.dat") or printErrorPage("openError"); close(FILE); $FORM{'thread'}=$date; } #==================== 記事を削除する ========== sub deleteArticle { my $key; #if($FORM{'pass'} ne $PASSWORD) { # printErrorPage("管理パスワードが違います。"); #} foreach $key (sort {$b cmp $a} keys %FORM) { if($key =~ /del_([0-9]+)/) { splice @LOG, $1, 1; } } } #==================== HTTPヘッダー出力 ========== sub printHttpHeader { # グリニッジ標準時の文字列 my @mon_str = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); my @wdy_str = ( 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime(time + ($COOKIE_LIFE * 24 * 60 * 60)); my $date = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", $wdy_str[$wday], $mday, $mon_str[$mon], $year + 1900, $hour, $min, $sec); # ヘッダーの出力 my ($name, $value); print "Content-type: text/html; charset=$CHARSET\n"; foreach $name (keys %COOKIE) { $value = $COOKIE{$name}; $name = "${COOKIE_PREFIX}_$name"; $value =~ s/(\W)/sprintf("%%%02X", ord($1))/eg; print "Set-Cookie: $name=$value; expires=$date\n"; } print "\n"; } #==================== エラーページ出力 ========== sub printErrorPage { print < error

program error.

reason:$_[0]

END exit; } #==================== クッキーデータ取り込み ========== sub loadCookie { my $pair; foreach $pair (split(/;\s*/, $ENV{'HTTP_COOKIE'})) { my ($name, $value) = split(/=/, $pair); if(not $name =~ /${COOKIE_PREFIX}_(.+)/) { next; } $name = $1; $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; $COOKIE{$name} = $value; } } #==================== クッキー読み込み ========== sub loadSession { my $pair; foreach $pair (split(/;\s*/, $ENV{'HTTP_COOKIE'})) { my ($name, $value) = split(/=/, $pair); $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; $SESSION{$name} = $value; } } #==================== フォームデータ取り込み ========== sub loadFormdata { my ($query, $pair); if($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $query, $ENV{'CONTENT_LENGTH'}); } else { $query = $ENV{'QUERY_STRING'}; } foreach $pair (split(/&/, $query)) { my ($key, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; $value = jcode::euc($value); $value =~ s/&/&/g; $value =~ s//>/g; $value =~ s/\x0D\x0A/
/g; $value =~ tr/\t/ /; $FORM{$key} = $value; } } #==================== 記事ページ出力 ========== sub printPage { my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time); $year += 1900; $mon++; printHttpHeader(); print < スケジュール|埼玉大学軟式庭球同好会
埼玉大学軟式庭球同好会トップページ軟式庭球同好会についてスケジュール試合結果フォトアルバムコミュニティ
スケジュール
END # 振り分け開始 # カレンダー表示の場合 if($_[0] eq "month"){ print < \n"; print "\n"; print "
END if($GEMON>1) { $nextpage = $GEMON - 1; $nextlink = "$ENV{'SCRIPT_NAME'}?month=$GEYEAR-$nextpage"; print "<<\n"; } elsif($year<=$GEYEAR) { $nextpage = $GEYEAR - 1; $nextlink = "$ENV{'SCRIPT_NAME'}?month=$nextpage-12"; print "<<\n"; } else { print " "; } print "$GEYEAR年$GEMON月のカレンダー\n"; if($GEMON<12) { $nextpage = $GEMON + 1; $nextlink = "$ENV{'SCRIPT_NAME'}?month=$GEYEAR-$nextpage"; print ">>\n"; } elsif($GEYEAR<=$year) { $nextpage = $GEYEAR + 1; $nextlink = "$ENV{'SCRIPT_NAME'}?month=$nextpage-1"; print ">>\n"; } else { print " "; } print <
SUN MON TUE WED THU FRI SAT
$DAY[0] $DAY[1] $DAY[2] $DAY[3] $DAY[4] $DAY[5] $DAY[6]
$DAY[7] $DAY[8] $DAY[9] $DAY[10] $DAY[11] $DAY[12] $DAY[13]
$DAY[14] $DAY[15] $DAY[16] $DAY[17] $DAY[18] $DAY[19] $DAY[20]
$DAY[21] $DAY[22] $DAY[23] $DAY[24] $DAY[25] $DAY[26] $DAY[27]
$DAY[28] $DAY[29] $DAY[30] $DAY[31] $DAY[32] $DAY[33] $DAY[34]
$DAY[35] $DAY[36] $DAY[37] $DAY[38] $DAY[39] $DAY[40] $DAY[41]

$GEYEAR年$GEMON月のスケジュール

END # スケジュール一覧の出力 for($i = 0 ; $i < @LOG ; ++$i) { my ($day, $wday, $hour1, $min1, $hour2, $min2, $title, $place, $comment) = split (/\t/, $LOG[$i]); chomp $comment; my $time; if($hour1 eq ""){ $time = " "; } elsif($hour2 eq ""){ if($min1 eq ""){$min1="00"} $time = sprintf("%s:%s 〜",$hour1,$min1); } else { if($min1 eq ""){$min1="00"} if($min2 eq ""){$min2="00"} $time = sprintf("%s:%s 〜 %s:%s",$hour1,$min1,$hour2,$min2); } my $day2 = sprintf("%d",$day); print "\n\n"; print "\n"; print "\n"; print "\n"; } print < END } # 詳細スケジュール表示の場合 elsif ($_[0] eq "day"){ my @wdy_str = ('日', '月', '火', '水', '木', '金', '土'); my $swday = getday($GEYEAR,$GEMON,$GEDAY); $GEWDAY = $wdy_str[$swday]; print <$GEYEAR年$GEMON月$GEDAY日($GEWDAY)のスケジュール
END for($i = 0 ; $i < @LOG ; ++$i) { my ($day, $wday, $hour1, $min1, $hour2, $min2, $title, $place, $comment) = split (/\t/, $LOG[$i]); chomp $comment; my $time; if($hour1 eq ""){ $time = ""; } elsif($hour2 eq ""){ if($min1 eq ""){$min1="00"} $time = sprintf("%s:%s 〜",$hour1,$min1); } else { if($min1 eq ""){$min1="00"} if($min2 eq ""){$min2="00"} $time = sprintf("%s:%s 〜 %s:%s",$hour1,$min1,$hour2,$min2); } my $day2 = sprintf("%d",$day); if($GEDAY eq $day2) { print <$title
$day2日($wday)$title$time→ 詳しくはコチラ
日時 $GEYEAR年$GEMON月$GEDAY日($GEWDAY) $time END printf "", $i; print <
場所 $place
詳細 $comment
END } } print <<< $GEMON月のスケジュールに戻る


END } # 振り分け終わり print <

新しくスケジュールを投稿する

題名:
日付: END for($i=1;$i<13;$i++){ if($i == $GEMON) { print "\n"; } else { print "\n"; } } print <
時間 END for($i=0;$i<60;$i++){ my $allmin = sprintf("%02d",$i); print "\n"; } print < 分 〜  END for($i=0;$i<60;$i++){ my $allmin = sprintf("%02d",$i); print "\n"; } print <
場所:
詳細:
Menu
$GEYEAR年のカレンダー
END if($GEMON==1){ print ">> 1月のカレンダー
"; } else { print "1月のカレンダー
"; } if($GEMON==2){ print ">> 2月のカレンダー
"; } else { print "2月のカレンダー
"; } if($GEMON==3){ print ">> 3月のカレンダー
"; } else { print "3月のカレンダー
"; } if($GEMON==4){ print ">> 4月のカレンダー
"; } else { print "4月のカレンダー
"; } if($GEMON==5){ print ">> 5月のカレンダー
"; } else { print "5月のカレンダー
"; } if($GEMON==6){ print ">> 6月のカレンダー
"; } else { print "6月のカレンダー
"; } if($GEMON==7){ print ">> 7月のカレンダー
"; } else { print "7月のカレンダー
"; } if($GEMON==8){ print ">> 8月のカレンダー
"; } else { print "8月のカレンダー
"; } if($GEMON==9){ print ">> 9月のカレンダー
"; } else { print "9月のカレンダー
"; } if($GEMON==10){ print ">> 10月のカレンダー
"; } else { print "10月のカレンダー
"; } if($GEMON==11){ print ">> 11月のカレンダー
"; } else { print "11月のカレンダー
"; } if($GEMON==12){ print ">> 12月のカレンダー
"; } else { print "12月のカレンダー
"; } if($GEYEAR==$year){ $prevyear = $GEYEAR - 1; $nextyear = $GEYEAR + 1; } elsif ($GEYEAR<$year){ $prevyear = $GEYEAR + 1; $nextyear = $GEYEAR + 2; } elsif ($GEYEAR>$year){ $prevyear = $GEYEAR - 2; $nextyear = $GEYEAR - 1; } print "
\n\"\" $prevyear年のカレンダー
"; print "\"\" $nextyear年のカレンダー
"; print <
 
END } #==================== モバイルページ出力 ========== sub printMobilePage { my $begin = $FORM{'page'} * $MOBILEPAGEVIEW; my $end = $begin + $MOBILEPAGEVIEW; if($end > @DATA) { $end = @DATA; } printHttpHeader(); print < 軟式庭球同好会 軟式庭球同好会

掲示板

END if($FORM{'thread'} eq ""){ print "

全体掲示板

"; } else { my $titlenum = $FORM{'thread'}; print "

$LOG{$titlenum}

"; } print < 題名:

内容:


END # 記事の出力 my ($i, $j, $nextpage, $nextlink); for($i = $begin ; $i < $end ; ++$i) { my ($date, $title, $author, $email, $text) = split(/\t/, $DATA[$i]); $j = $i+1; print "

$title

\n"; if($email) { print ""; print "$j: $author
"; print "
"; } else { print "$j: $author
"; } print " [ $date ] "; print "

$text

"; print "
\n"; } # 前ページへのリンク if($end-5 > 0) { $nextpage = $FORM{'page'} - 1; $nextlink = "$ENV{'SCRIPT_NAME'}?page=$nextpage&thread=$FORM{'thread'}&session=$FORM{'session'}"; print "

前のページ

\n"; } # 次ページへのリンク if($end < @DATA) { $nextpage = $FORM{'page'} + 1; $nextlink = "$ENV{'SCRIPT_NAME'}?page=$nextpage&thread=$FORM{'thread'}&session=$FORM{'session'}"; print "

次のページ

\n"; } print <参加スレッド一覧
全体掲示板
END for($i = 0 ; $i < @LOG ; ++$i) { my ($name, $file, $exhibition) = split (/\t/, $LOG[$i]); chomp $exhibition; foreach $person (split(/&/, $exhibition)){ if ($ID{'id'} eq $person) { print "$name
\n"; } } } print <HOME
┣お知らせ
┣イベント
掲示板
メンバー一覧
┗ML

ログアウト
END }