package friends; #----------------------------------------------------------------------------- #使用方法 # require "friends.pl"; # &friends'RegistFriend(name, mail, url); #----------------------------------------------------------------------------- #初期設定 $DataFile = "friendsup.dat"; #保存ファイル名 # 新規DataFileは、最初に0を記述しておいてください。 # Data構造 # KEY=n [TAB] DATE=yyyy/mmm/dd hh:mm(w) [TAB] NAME=xxxx [TAB] MAIL=xxxx [TAB] URL=xxxx,xx [TAB] \n $LockFile = "./friends.lock"; #ロックファイル名 $LockMode = 1; #0-ロックしない 1-ロックする #----------------------------------------------------------------------------- sub initRtn{ $Name = undef; $Mail = undef; $URL = undef; } sub RegistFriend{ local(@Data, %LOG, $Flag, $Mode, @Url, $No, $i, @New, $NewData); &initRtn; ($Name, $Mail, $URL) = ($_[0], $_[1], $_[2]); if($Name eq ""){ return; } if(!&FileLock){ return; } if($URL =~ /http\:\/\/(.*)/){ $URL = $1; } if(!open(IN, "$DataFile")){ &FileUnLock; return;} @Data = ; close(IN); $No = shift(@Data); $Mode = 0; $i = 0; while($i < @Data){ %LOG = &SplitLog($Data[$i]); @Url = split(/\,/, $LOG{'URL'}); if(($LOG{'NAME'} eq $Name) && ($LOG{'MAIL'} eq $Mail)){ #HN MAIL一致 $Mode = 1; if($URL eq ""){ &FileUnLock; return; } else{ if(@Url == 0){ last; } $Flag = 0; foreach(@Url){ if($URL ne $_){ $Flag = 1; last; }} if($Flag){ last; }else{ &FileUnLock; return; } } } if($LOG{'NAME'} eq $Name){ #HN一致 $Mode = 1; if(($Mail eq "") && ($URL eq "")){ &FileUnLock; return; } last; } if($LOG{'MAIL'} eq $Mail){ $Mode = 1; if($URL eq ""){ &FileUnLock; return; } $Name = $LOG{'NAME'}; last; } undef @Url; $i++; } push(@Url, $URL); if($Mode){ $No = $LOG{'KEY'}; } else{ $No++; } push(@New, "KEY=" . $No); push(@New, "DATE=" . &GetDateTime); push(@New, "NAME=" . $Name); push(@New, "MAIL=" . $Mail); push(@New, "URL=" . join("\,", @Url)); push(@New, "\n"); $NewData = join("\t", @New); if($Mode){ $Data[$i] = $NewData; } else{ push(@Data, $NewData); } @Data = ($No . "\n", @Data); if(!open(OUT, ">$DataFile")){ &FileUnLock; return;} print OUT @Data; close(OUT); &FileUnLock; } sub SplitLog{ # [TAB] で分割→ = で分割 →連想配列LOGに代入 local(@ARR, $N, $Value, %LOG); @ARR = split(/\t/, $_[0]); foreach(@ARR){ ($N, $Value) = split(/=/, $_); $LOG{$N} = $Value; } return %LOG; } sub GetFriendDataName{ return $DataFile; } sub GetDateTime{ local(@WeekName) = ("(Sun)","(Mon)","(Tue)","(Wed)","(Tur)","(Fri)","(Sut)"); local($sec, $min, $hour, $day, $mon, $year, $wday) = localtime(time); $year += 1900; $mon++; if ($mon < 10) {$mon = "0$mon";} if ($day < 10) {$day = "0$day";} if ($hour < 10) {$hour = "0$hour";} if ($min < 10) {$min = "0$min";} if ($sec < 10) {$sec = "0$sec";} return "$year/$mon/$day $hour:$min$WeekName[$wday]"; } #ロック sub FileLock{ local($Retry) = 5; if(! $LockMode){ return; } foreach(1..$Retry){ if(-e "$LockFile"){ local($mtime) = (stat($LockFile))[9]; if ($mtime < time() - 600){ unlink($LockFile); } else{ sleep(1); } }else{ open(LOCK,">$LockFile") || &cgi_error; close(LOCK); return 1; } } return 0; } #ロック解除 sub FileUnLock{ if(-e "$LockFile"){ unlink($LockFile); } } 1;