#!/usr/bin/perl require "../jcode.pl"; use CGI; #============================ ユーザー設定 ==== $CHARSET = 'EUC-JP'; # 文字コード $DATAFILE = './bbs/default.dat'; # 記事ファイル $PAGEVIEW = 10; # ページ記事数 $MOBILEPAGEVIEW= 5; # ページ記事数 $MAXLINE = 100; # 最大記事数 $MAXTHREAD = 100; # 最大スレッド数 $PASSWORD = 'kamigoma'; # 管理パスワード $COOKIE_PREFIX = 'bbs'; # クッキープリフィクス $COOKIE_LIFE = 30; # クッキー期限(日) $SESSIONFILE = '../dat/session.dat'; # セッション管理ファイル $USERFILE = '../dat/users.dat'; # ユーザーファイル $LOGFILE = './bbs/board.dat'; # 掲示板管理ファイル #======================== メインプログラム ==== $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(); if($member) { # クッキーに暗号が一致 loadUserfile(); # ユーザーファイルの読み込み$memberを基に個人の%IDの作成 loadLogfile(); # 掲示板管理ファイル if(exists $FORM{'newthread'}){ printPage("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(); # 掲示板管理ファイル } } elsif($FORM{'mode'} eq 'join'){ joinset(); } else { deleteArticle(); # 削除モード } # 記事データの書き込み open(FILE, ">$DATAFILE") or printErrorPage("openError"); eval{ flock(FILE, 2) }; print FILE @DATA; close(FILE); $CGI = new CGI(); print $CGI->redirect("$ENV{'SCRIPT_NAME'}?thread=$FORM{'thread'}"); } 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); $CGI = new CGI(); print $CGI->redirect("$ENV{'SCRIPT_NAME'}?thread=$FORM{'thread'}"); loadLogfile(); # 掲示板管理ファイル } } printPage("bbs"); } } 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"); } } # ------------------------------------------------モバイルページの出力 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
┣お知らせ
┣イベント
掲示板
┗メンバー一覧

ログアウト
END } # ------------------------------------------------クッキーの暗号が一致したら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; } } #========================== 記事ページ出力 ==== sub printPage { my $begin = $FORM{'page'} * $PAGEVIEW; my $end = $begin + $PAGEVIEW; if($end > @DATA) { $end = @DATA; } printHttpHeader(); print < 掲示板|埼玉大学軟式庭球同好会
埼玉大学軟式庭球同好会トップページ軟式庭球同好会についてスケジュール試合結果フォトアルバムコミュニティ
掲示板
END if ($_[0] eq "bbs"){ if($FORM{'thread'} eq ""){ print "

全体掲示板

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

$LOG{$titlenum}

\n"; } print <
題名:
内容:
   
END if($FORM{'thread'} ne ""){ print "\n"; } print "
"; # 記事の出力 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 ] "; printf "
", $i; print "

$text

"; print "\n"; } print "\n"; print "\n"; print "\n"; print <
END if($FORM{'thread'} ne ""){ my $exhibition; loadMemberfile(); for($j = 0 ; $j < @LOG ; ++$j) { my ($namej, $filej, $exhibitionj) = split (/\t/, $LOG[$j]); if($FORM{'thread'} eq $filej){ chomp $exhibitionj; $exhibition = $exhibitionj; } } print "

掲示板の参加者を編集する

\n
\n"; print "ここでチェックの付いている人はこの掲示板に参加している人です。

\n"; print "2007年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2007年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2006年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2006年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2005年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2005年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2004年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2004年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2003年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2003年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2002年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2002年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2001年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2001年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print "
2000年度以前入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2000年度") { my $check = 0; foreach $personj (split(/&/, $exhibition)){ if ($id eq $personj) { print "$name
\n"; $check = 1; } } if ($check == 0){ print "$name
\n"; } } } print <
END } } elsif ($_[0] eq "newthread"){ print <新しい掲示板を作る
\n"; # 前ページへのリンク if($end-$PAGEVIEW > 0) { $nextpage = $FORM{'page'} - 1; $nextlink = "$ENV{'SCRIPT_NAME'}?page=$nextpage&thread=$FORM{'thread'}"; print "<<前のページ\n"; } print "\n"; # 次ページへのリンク if($end < @DATA) { $nextpage = $FORM{'page'} + 1; $nextlink = "$ENV{'SCRIPT_NAME'}?page=$nextpage&thread=$FORM{'thread'}"; print "次のページ>>\n"; } print "
掲示板名: (10字以内)
投稿題名:
投稿内容:
   

参加者

この掲示板に参加させたい人にチェックを入れてください。
参加者以外にこの掲示板は公開されません。
参加者は後から編集することもできます。


END loadMemberfile(); print "2007年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2007年度") { print "$name
\n"; } } print "
2006年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2006年度") { print "$name
\n"; } } print "
2005年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2005年度") { print "$name
\n"; } } print "
2004年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2004年度") { print "$name
\n"; } } print "
2003年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2003年度") { print "$name
\n"; } } print "
2002年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2002年度") { print "$name
\n"; } } print "
2001年度入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2001年度") { print "$name
\n"; } } print "
2000年度以前入学生
\n"; for($i = 0 ; $i < @USER ; ++$i) { my ($name, $pass, $id, $sex, $birth, $blood, $email, $nickname, $home, $school, $subject, $year, $hobby, $intro) = split (/\t/, $USER[$i]); if ($year eq "2000年度") { print "$name
\n"; } } print <
END } print <
Menu
参加掲示板一覧
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 "\n"; } } } print <>>新しい掲示板を作る
 
END } # ------------------------------------------------クッキーの暗号が一致したら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; } # ------------------------------------------------掲示板管理ファイル読み込み sub loadLogfile { my ($ln, $name, $file, $exhibition, %USERS); open(FILE, "<$LOGFILE") or printPage("openError"); eval{ flock(FILE, 1) }; @LOG = ; close(FILE); open(FILE, "<$LOGFILE") or printPage("openError"); eval{ flock(FILE, 1) }; while($ln = ) { chomp $ln; ($name, $file, $exhibition) = split(/\t/, $ln); $LOG{$file} = $name; } close(FILE); } # ------------------------------------------------掲示板管理ファイル読み込み sub sortdata { my ($ln, $name, $file, $exhibition, %USERS); open(FILE, "+<$LOGFILE") or printErrorPage("openError"); eval{ flock(FILE, 2) }; @LOG = ; for($i = 0 ; $i < @LOG ; ++$i) { my ($name, $file, $exhibition) = split(/\t/, $LOG[$i]); if ($file eq $FORM{'thread'}) { unshift @LOG, $LOG[$i]; my $k = $i+1; splice @LOG, $k, 1; } } seek( FILE, 0, 0); print FILE @LOG; close(FILE); } # ------------------------------------------------USERファイル読み込み sub loadMemberfile { open(FILE, "<$USERFILE") or printPage("openError"); eval{ flock(FILE, 1) }; @USER = ; close(FILE); } #========================== 記事を書き込む ==== sub writeArticle { my @wdy_str = ('日', '月', '火', '水', '木', '金', '土'); my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime(time); my $date = sprintf("%4d年%02d月%02d日(%s) %02d:%02d", $year + 1900, ++$mon, $mday, $wdy_str[$wday], $hour, $min); unshift @DATA, "$date\t$FORM{'title'}\t$ID{'name'}\t$ID{'id'}\t$FORM{'text'}\n"; while(@DATA > $MAXLINE) { pop @DATA; } } #========================== スレッド作成 ==== 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 = ""; 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 joinset { my $exlist = ""; foreach $key (keys %FORM) { if($key =~ /exhibition_(.+)/) { $exlist .= $1."&"; } } chop $exlist; for($l = 0 ; $l < @LOG ; ++$l) { my ($name, $file, $exhibition) = split (/\t/, $LOG[$l]); if($FORM{'thread'} eq $file){ $LOG[$l] = "$name\t$file"; $LOG[$l] .= "\t$exlist\n"; } } open(FILE, ">$LOGFILE") or printErrorPage("openError"); eval{ flock(FILE, 2) }; print FILE @LOG; close(FILE); } #========================== 記事を削除する ==== sub deleteArticle { my $key; #if($FORM{'pass'} ne $PASSWORD) { # printErrorPage("管理パスワードが違います。"); #} foreach $key (sort {$b cmp $a} keys %FORM) { if($key =~ /del_([0-9]+)/) { splice @DATA, $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 < けいじばん

エラー

$_[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/ /; $value =~ s/<a href=\"(.+)\">//g; $value =~ s/<\/a>/<\/a>/g; $FORM{$key} = $value; } }