#! /usr/bin/perl # # attlist3.cgi # # 5.007 : 2/2/07 : 参加者ファイルを使わないように修正 # 5.006 : 1/24/07 : 名前欄の半角カンマのバグを修正 # 5.005 : 8/5/06 : パスワード無効モードを追加 # 5.004 : 4/23/06 : パスワードがマッチすると更新日を更新するように修正 # 5.003 : 4/16/06 : 変更なしでも更新者、更新日が更新されるのを修正 # 5.002 : 3/19/06 : 参加人数制限、更新締め切り機能を追加 # 5.001 : 3/6/06 : 追加時に更新情報が正しく表示されるように修正 # 5.0 : 3/5/06 : Upgread from attlist2.cgi # # http://www.hidekik.com/ # # $Id: attlist3.cgi,v 1.9 2007/02/02 02:07:49 Hideki Kanayama Exp $ # Copyright(c) 1997-2006, Hideki Kanayama, All rights reserved. use CGI qw(:cgi-lib); use strict; use CGI::Carp qw(fatalsToBrowser); use File::Basename; use Time::Local; my $version = "5.007"; my $lastupdatedyear = "2007"; my $admindat = "adminpwd.dat"; my $setupfile = "attlist3_setup.pl"; my $script = basename($0); my $lang = 0; my $charset = ("Shift_JIS","ISO-8859-1")[$lang]; ########## 環境設定 ここから ########################### our $datafile = "attend.dat"; # lockfile our $lockfile = "lockfile.dat"; # Title our $title = '出欠表 '; # Background our $bgimage_en = 0; our $bgimage_file = ''; our $bgcolor = "#ffffff"; # Back link our $backlink_en = 1; our $backlink = '..'; our $backlink_name = '戻る'; # Body width our $body_width = '100'; # option cell back ground color our $option_bg_color = "#ffcc33"; # option cell font color our $option_font_color = "black"; # item cell back ground color our $item_bg_color = "#66ff99"; # item cell font color our $item_font_color = "black"; #表示テーブルのカラム数 our $table_colms = 1; #参加者設定の初期登録可能人数 our $default_max = 15; #管理用リンク表示 1:有効 0:無効 our $setup_en = 1; #変更日表示 1:有効 0:無効 our $update_en = 1; #削除チェック 1:有効 0:無効 our $delcheck_en = 1; #定員設定 1:有効 0:無効 our $att_limit_en = 0; our $att_limit_num = 10; #締め切り 1:有効 0:無効 our $deadline_en = 0; our $deadline_year = 2006; our $deadline_month = 3; our $deadline_day = 25; our $deadline_hour = 0; our $deadline_min = 0; #パスワード保護 1:有効 0:無効 our $password_en = 1; #カウント 1:有効 0:無効 our $count_en = 0; #管理人オンリーモード 1:有効 0:無効 our $adminonly_en = 0; #オプション オプション名,背景色 our $options = '出席,red 欠席,blue 未定,green '; # body_head our $body_head = '

出欠表

'; # body_tail our $body_tail = ' '; # Style Sheet our $style_sheet_en = 0; our $style_sheet = ' '; # Head insert our $head_insert_en = 0; our $head_insert = ' '; #時間設定 1:localtime, 0:offset from GMT our $localtime_en = 1; our $offset_from_gmt = 9; #予備のアップデートファイル # 1: on, 0: off our $update1_file_en = 0; our $update2_file_en = 0; our $update1_file = "update1.log"; our $update2_file = "update2.log"; ########## 環境設定 ここまで ########################### require "$setupfile" if (-e "$setupfile"); my $q = CGI->new; my $cgierror = $q->cgi_error; &error($cgierror) if ($cgierror); my %in = &postprocess($q->Vars); if (! -e "$admindat"){ if ($in{mode} ne 'wradminpwd'){ &setadminpwd; } else { &wradminpwd($in{pwd}); } } my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)= $localtime_en ? localtime(time) : gmtime(time + 3600 * $offset_from_gmt); my $update = sprintf("%s_%s_%s_%02s_%02s",$year+1900,$mon+1,$mday,$hour,$min); my $deadline_time = timelocal(0,$deadline_min,$deadline_hour,$deadline_day,$deadline_month-1,$deadline_year); my $now = timelocal(localtime); my @items = &get_items; my ($maxnum, $date, $lastname, $name, $status, $count, $eachpwd, $eachmod) = &get_data; my (@name, @status, @count, @eachpwd, @eachmod); @name = @{$name}; @status = @{$status}; @count = @{$count}; @eachpwd = @{$eachpwd}; @eachmod = @{$eachmod}; my @valid_list = grep /^0$/, @status; my $attnum = $#valid_list + 1; my $hit_limit = 0; my $update_button = 1; if ($in{mode} eq 'atwrite'){ &atwrite; } elsif ($in{mode} eq 'setup'){ &setup; } elsif ($in{mode} eq 'setup_update'){ &setup_update; } else { &display; } ###################### 書き込み ############################ sub atwrite { &error('管理用パスワードが違います。') if (!&checkadmin($in{pwd}) and $adminonly_en == 1); if ($deadline_en and $now > $deadline_time){ &error('締め切り日時を過ぎているので追加、変更できません。'); } if ($in{add} ne ''){ &newregister; } else { &update; } &extraupdate; print "Location: $script\n\n"; } sub newregister { &error('名前は必ず入れてください')if ($in{newname} eq ""); &error('パスワードは必ず入れてください')if ($in{newpwd} eq "" and $password_en); if ($att_limit_en and $attnum >= $att_limit_num){ &error('締め切り人数に達しているので追加できません。。'); } &lockfile; my ($maxnum, @dummy) = &get_data; open (TMPFILE, "> tmp.$$") or &error("tempfileを作成できません。"); print TMPFILE "0,$in{newname},$update\n"; if (open(DAT,"< $datafile")) { my $i = 0; while (){ print TMPFILE "$_" if ($i != 0); $i++; } close(DAT); } $maxnum++; $in{newoption} = 0 if ($in{newoption} eq ''); my $encpwd = $password_en ? &makecrypt($in{newpwd}) : ''; print TMPFILE "$maxnum,$in{newname},$in{newoption},$in{newcount},$update,$encpwd\n"; close(TMPFILE); rename "tmp.$$", $datafile; &unlockfile; } sub update { &lockfile; my $tmpfile = "tmp.$$"; open(WRDAT,">$tmpfile") or &error("$tmpfileが開けません。"); my $endatt = $#items + 1; my $i; for ($i=1;$i<=$endatt;$i=$i+1){ my $btni = "btn_$i"; if ($in{$btni} ne ''){ $lastname = $name[$i]; last; } } print WRDAT "0,$lastname,$update,\n"; my $newstatus; my $newcount; my $modified = 0; for ($i=1;$i<=$endatt;$i=$i+1){ my $pwdi = "pwd_$i"; my $btni = "btn_$i"; $newstatus = $status[$i]; $newcount = $count[$i]; chomp($items[$i-1]); if ($in{$btni} ne '' and ($password_en == 1 && &checkcrypt("$in{$pwdi}","$eachpwd[$i]"))) { $eachmod[$i] = "$update"; $modified = 1; } if (($in{$i} ne $status[$i] or ($in{"count_$i"} != $count[$i] and $count_en)) and $in{$btni} ne ''){ $eachmod[$i] = "$update"; $modified = 1; if ($password_en == 1 && "$eachpwd[$i]" ne '' && !&checkcrypt("$in{$pwdi}","$eachpwd[$i]")) { close(WRDAT); unlink("$tmpfile"); &error("$name[$i]を変更しようとしましたが、そのパスワードが違います。"); } $newstatus = $in{$i}; $newcount = $in{"count_$i"}; if ($att_limit_en and $attnum >= $att_limit_num and $newstatus eq '0'){ close(WRDAT); unlink("$tmpfile"); &error('締め切り人数に達しているので追加、変更できません。'); } } if ($password_en == 1 && ("$in{$pwdi}" ne '' && "$eachpwd[$i]" eq '')){ $eachpwd[$i] = &makecrypt("$in{$pwdi}"); } print WRDAT "$i,$items[$i-1],$newstatus,$newcount,$eachmod[$i],$eachpwd[$i]\n"; } close(WRDAT); if ($modified){ rename("$tmpfile","$datafile"); } else { unlink "$tmpfile"; } chmod(0666,"$datafile"); &unlockfile; } ###################### 表示 ############################ sub display { &htmlhead($title); if ($att_limit_en and $attnum >= $att_limit_num){ $hit_limit = 1; } if ($deadline_en and $now >= $deadline_time){ $delcheck_en = 0; $password_en = 0; $update_button = 0; } print "$body_head"; print "

\n"; print "\n"; if ($date =~ /(\d+)_(\d+)_(\d+)_(\d+)_(\d+)/) { $date = sprintf("%s年%s月%s日%s時%s分",$1,$2,$3,$4,$5); } else { $date = " "; } print "$backlink_name

\n" if ($backlink_en); if ($deadline_en == 1){ printf("更新締め切り:%4d年%02d月%02d日%02d時%02d分
\n",$deadline_year,$deadline_month,$deadline_day,$deadline_hour,$deadline_min); } if ($att_limit_en){ print "参加者上限:$att_limit_num人
\n"; } print "最終更新日:"; print "$date
"; print "最終更新者:"; print "$lastname

"; my @option_list = grep !/^\s*$/, split /[\r\n]/, $options; my $select_items = $#option_list + 2 + $delcheck_en + $update_en + $count_en + $password_en + $update_button; my $cols = $table_colms * $select_items; print "\n"; print "\n"; my $i; for ($i=1;$i<=$table_colms;$i=$i+1){ print "\n"; my $j; for ($j=0;$j<=$#option_list;$j++) { my ($option,$color) = split /,/, $option_list[$j]; print "\n"; } print "\n" if ($delcheck_en == 1); print "\n" if ($count_en == 1); print "\n" if ($update_en == 1); print "\n" if ($password_en == 1); print "\n" if ($update_button); } print "\n"; my $i = 1; my $totalattlist3; my @total; while ($#items >= 0){ if ($status[$i] eq 'deleted'){ shift @items; $i++; next; } print "\n"; my $j; my @checked; for ($j=1;$j<=$table_colms;$j=$j+1){ if ($#items < 0) { my $h; for ($h=0;$h<$select_items;$h=$h+1){ print "\n"; } last; } print "\n"; $checked[$status[$i]] = 'checked'; my $k; for ($k=0;$k<=$#option_list;$k++) { my ($item,$color) = split /,/, $option_list[$k]; if ($checked[$k] eq 'checked') { print "\n"; } if ($delcheck_en == 1){ print "\n"; } if ($count_en == 1){ $count[$i] = 0 if (!$count[$i]); print "\n"; } if ($update_en == 1){ print "\n"; } if ($password_en == 1){ print "\n"; } else { print "\n"; } if ($update_button){ print "\n"; } $totalattlist3 = $totalattlist3 + $count[$i]; shift(@items); $i = $i + 1; } print "\n"; } print ""; print "\n"; my $rightcolspan = $delcheck_en + $update_en + $count_en + $password_en + $update_button; my $leftcol = $cols - $rightcolspan - 2; for ($i=0;$i<=$leftcol;$i++){ if ($total[$i] ne '') { print "\n"; } else { print "\n"; } } if ($count_en == 1){ print "\n"; } else { for ($i=1;$i<=$rightcolspan;$i++){ print "\n"; } } print "\n"; # Display when # time limit is not reached or # $udpate_button = 0 when time limit is reached # attend limit is not reached # $hit_limit = 1 when attend limit is reached if (($update_button == 1 and $deadline_en) or ($hit_limit == 0 and $att_limit_en) or (($att_limit_en == 0) and ($deadline_en == 0))){ print "\n"; print ""; my $k; for ($k=0;$k<=$#option_list;$k++) { my ($item,$color) = split /,/, $option_list[$k]; print "\n"; } if ($delcheck_en == 1){ print "\n"; } if ($count_en == 1){ print "\n"; } if ($update_en == 1){ print "\n"; } if ($password_en == 1){ print "\n"; } else { print "\n"; } print "\n"; print "\n"; } print "
名前$option削除人数更新日パスワード 
 "; chomp($items[0]); print "$items[0]"; print ""; $total[$k]++; } else { print ""; } print ""; print ""; print ""; print ""; print ""; if ($eachmod[$i] =~ /(\d+)_(\d+)_(\d+)_(\d+)_(\d+)/) { print "$1年$2月$3日$4時$5分"; } else { print " "; } print ""; if ($hit_limit and $status[$i] eq '0' or $hit_limit == 0) { print ""; } else { print " "; } print ""; if ($hit_limit and $status[$i] eq '0' or $hit_limit == 0) { print ""; } else { print " "; } print "
合計$total[$i]0合計 $totalattlist3 
"; print qq(\n); print ""; print ""; print " "; print ""; print ""; print ""; print " "; print ""; print ""; print ""; print ""; print "
\n"; ©right; if ($setup_en == 1){ print "
管理用
\n"; } print "

"; print "$body_tail"; &htmltail; } ###################### セットアップ ############################ sub setup { &setadminpwd if ($in{pwd} eq ''); &error('管理用パスワードが違います。') unless &checkadmin($in{pwd}); &htmlhead('管理用セットアップ'); print "
\n"; print "\n"; print "\n"; print "\n"; my @setup_check; my @update_check; my @password_check; my @count_check; my @update1_file_check; my @update2_file_check; my @localtime_check; my @adminonly_check; my @att_limit_check; my @deadline_check; $setup_check[$setup_en] = "checked"; $update_check[$update_en] = "checked"; $password_check[$password_en] = "checked"; $count_check[$count_en] = "checked"; $update1_file_check[$update1_file_en] = "checked"; $update2_file_check[$update2_file_en] = "checked"; $localtime_check[$localtime_en] = "checked"; $adminonly_check[$adminonly_en] = "checked"; $att_limit_check[$att_limit_en] = "checked"; $deadline_check[$deadline_en] = "checked"; my %check; $check{bgimage}[$bgimage_en] = "checked"; $check{backlink}[$backlink_en] = "checked"; $check{style_sheet}[$style_sheet_en] = "checked"; $check{head_insert}[$head_insert_en] = "checked"; print <
  • 管理人パスワードを変更するには、$admindatを削除して、$scriptを実行しなおしてパスワードを再入力してください。
  • これらの設定は$setupfileに保存されます。また、$setupfileをエディタ等で変更してもこの設定ページに反映されます。
  • $scriptがバージョンアップされた場合、単純に$scriptだけを置き換えるだけで設定はそのまま使えます。
  • $admindatと$setupfileのファイル名はこの設定ページでは変更できません。変更したい場合は$scriptの中で変更してください。
  • 管理用リンクを非表\示にしている場合にこのページにアクセスするには、$script?mode=setupを実行するとアクセスできます。
  • 数字やカラー指定は必ず半角で指定してください。全角やブランクだとCGIが起動しなくなります。万一間違って全角で書いてしまった場合は、$setupfileをエディタで開きその場所を半角に正しく修正してください。それで直ります。
データファイル
ロックファイル
タイトル
ブラウザのタイトルバーに表\示されるタイトルです。ページのタイトルは「ページ上部」で自由にタイトル表\示させることができます。
バックグランド 画像を使う カラー設定にする
画像を使う場合の画像ファイル
カラー設定の場合のカラー番号(白:\#ffffff 又は white)
トップへのリンク 表\示 非表\示
リンク名
URL
表\示幅 ブラウザ全体の
ヘッダーセルの色 オプションセルの背景色
オプションセルのフォント色
項目セルの背景色
項目セルのフォント色
オプション設定 選択可能\なオプションを「オプション名,背景色」で並べてください。
例)
参加,red
不参加,#ff0000
未定,green
管理用リンク表\示 表\示 非表\示
数量 有効 無効
参加人数設定 有効 無効
参加人数上限
締め切り時間 有効にすると締め切り日時以降に更新できなくなります。
有効 無効
締め切り
パスワード保護 有効 無効
ページ上部 ページ上部に表\示させるものをHTML表\記

ページ下部 ページ下部に表\示させるものをHTML表\記

スタイルシート 有効 無効

<head>内挿入文 有効 無効
HTML書式
ポップアップ広告やJavascript、<META>を挿入したい場合にここに記述する。
以下の記述が<head>〜</head>内に挿入される。

時間設定 GMTからのオフセット ローカルタイム
GMTからのオフセットに設定した場合、GMTより時間(日本:+9時間)
予\備のアップデートファイル 使用 非使用 ファイル名
使用 非使用 ファイル名
END_SETUP print "

"; print "

\n"; print "

"; ©right; print "
"; &htmltail; } ###################### セットアップ作成 ############################ sub wrsetup { &error('パスワードが違います。') unless (&checkadmin($in{pwd})); open(SETUP,"> $setupfile") || &error('セットアップファイルが作成できません。
CGIを置いてあるディレクトリが書き込み可能\か確認してください。'); foreach (keys(%in)){ $in{$_} =~ s/
/\n/g if (!/body_head/ and !/body_tail/); $in{$_} =~ s/,/,/g; $in{$_} =~ s/<//g; $in{$_} =~ s/\s*$//; } print SETUP <header(-charset=>$charset); print "\n"; print "\n"; print "\n"; print "$title\n"; if ($head_insert_en == 1){ print "$head_insert\n"; } if ($style_sheet_en == 1){ print "\n"; } print "\n"; print "\n"; print "
\n"; } sub copyright { my $mysite = ('http://www.hidekik.com/','http://www.hidekik.com/en/')[$lang]; print "$script Ver. $version\n"; print "Copyright(C) 1997-$lastupdatedyear, hidekik.com\n"; } sub htmltail { print "
\n"; exit; } sub error { my ($msg) = shift; &unlockfile; &htmlhead($msg); print "
$msg
\n"; print "
"; ©right; print "
"; &htmltail; exit; } sub makecrypt { my $plain = shift; my $salt = join "", ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]; my $result = crypt($plain,$salt) or crypt($plain,'$1$'.$salt.'$'); return $result; } sub setadminpwd { my $subname = 'setadminpwd'; &htmlhead('管理者用パスワードを入力してください'); print "
\n"; if ($in{mode} eq 'setup'){ print "
管理者用パスワードを入力してください。
\n"; print "\n"; print "\n"; print "\n"; } else { print "
管理者用パスワードを設定してください。
\n"; print "\n"; print "\n"; print "\n"; } print "

"; ©right; print "
"; &htmltail; exit; } sub wradminpwd { my $plain = shift; my $passwd = &makecrypt($plain); if (open(FILE,"> $admindat")){ print FILE "$passwd"; close(FILE); } else { &error('パスワードファイル作成に失敗しました'); } print "Location: $script\n\n"; } sub checkadmin { my $pwd = shift; if (open(ADMINFILE,"< $admindat")){ my $filepwd = ; close(ADMINFILE); my $inpwd = crypt($pwd,$filepwd); return ("$inpwd" eq "$filepwd"); } else { &error('パスワードファイルが存在しません'); } } sub lockfile { while(-e "$lockfile"){ sleep(1); } open(LOCK,"> $lockfile"); close(LOCK); } sub unlockfile { unlink("tmp.$$") if (-e "tmp.$$"); unlink("$lockfile") if (-e $lockfile); } sub get_items { my @items_list; if (open(ITEM,"< $datafile")){ flock ITEM, 1; while (){ push @items_list, (split /,/)[1]; } close(ITEM); shift @items_list; } return (@items_list); } sub get_data { my ($date, $lastname); my (@name, @status, @count, @eachpwd, @eachmod); my ($key,$name,$value,$count,$moddate,$pwd); if (open(ATTLIST3,"< $datafile")) { foreach (){ chomp; ($key,$name,$value,$count,$moddate,$pwd)=split(/,/); if ($key == 0){ $date = $value;; $lastname = $name; } else { $name[$key] = "$name"; if ($value eq '') { $status[$key] = "0"; } else { $status[$key] = "$value"; } $count[$key] = "$count"; $eachpwd[$key] = "$pwd"; $eachmod[$key] = "$moddate"; } } close(ATTLIST3); } return ($key, $date, $lastname, \@name, \@status, \@count, \@eachpwd, \@eachmod); } sub extraupdate { if ($update1_file_en == 1){ open(UPDATE,">$update1_file"); print UPDATE "dummy file1\n"; close(UPDATE); chmod(0666,"$update1_file"); } if ($update2_file_en == 1){ open(UPDATE,">$update2_file"); print UPDATE "dummy file2\n"; close(UPDATE); chmod(0666,"$update2_file"); } } sub postprocess { my (%in) = @_; my ($key, $value); while (($key,$value)=each %in){ $value =~ s//>/g; $value =~ s/,/&\#44;/g; $in{"$key"}=$value; } return(%in); }