#!/usr/local/bin/perl
#----------------------------------------------------------------------------
# TODO リスト version 0.1
#
# Copyright (C) 2000 WackyFactory / WAKI Toshihito
#
# このスクリプトは、ネットサーフレスキュー[Web裏技]で配布されている
# 電子掲示板 MiniBBS を改造したものです。利用条件などについては WackyFactory
# http://www2b.biglobe.ne.jp/~wakit/SOFTWARE/ をご参照ください。
#
#----------------------------------------------------------------------------
# Original Copyright:
;# 簡易BBS version 10.31
;#
;# This is Freeware.
;# Script written by Kazu.Y
;# Created on: 02/05/96
;# I can be reached at: resq@rescue.ne.jp
;# Scripts Found at: http://www.rescue.ne.jp/
# [基本仕様]
#
# ※ METHOD=POST専用です.
# ※ S-JIS設置専用です.
# ※ 西暦2000年対応.
# [基本構成] ( )内は設定する必要があるパーミッション値
#
# /public_html/(ホームページディレクトリ)
# |
# |-- /cgi-bin/(任意のディレクトリ)
# |
# |-- jcode.pl
# |-- todo.cgi (755)
# |
# |-- /data/ (777)
# |
# |-- data.cgi
# [履歴]
#
# v1.0 02/MAY/96 初版
# v8.90 11/AUG/98 v8.8にロック機能を付加
# v9.00 12/AUG/98 タグ処理を制限してセキュリティアップ
# v9.01 24/AUG/98 未入力処理(クッキー消去)時にリストされな不具合を修正
# v9.02 03/SEP/98 改行の扱いを3種類に変更
# v9.03 18/SEP/98 Eメール自動リンクの廃止
# v9.04 19/OCT/98 タブコードの取り扱い修正
# v9.05 26/OCT/98 記録データ制限の解除処理
# v9.06 22/NOV/98 エラー処理を改善
# v10.00 24/NOV/98 検索機能の追加および構造変更
# v10.01 02/DEC/98 クッキー機能の修正ほか
# v10.02 08/DEC/98 D系トラブルの修正
# v10.10 08/DEC/98 2重(連続)投稿防止処理
# v10.11 08/DEC/98 削除キー削除が出来なくなったバグの修正
# v10.12 15/DEC/98 パスワード強化
# v10.13 17/DEC/98 全角文字マッチの不具合の訂正
# v10.14 21/DEC/98 ファイルを閉じていない個所の修正,メールアドレス形式チェック方法の変更
# v10.15 14/FEB/99 記事最後案内の修正
# v10.20 19/FEB/99 新着記事のマーキング
# v10.21 20/FEB/99 通算日数計算のバグ修正
# v10.30 08/JUL/99 ロック処理のバグ修正,ロック処理方法の変更,暗号処理のベリファイ機能付加
# v10.31 04/SEP/99 暗号処理部分の修正
# ==============================================================
# v0.1 31/OCT/00 TODOリストとして改造初版
# [データ形式]
#
# ※ 各記事は1件1行とし、各項目はタブ区切りとする.
# ※ 各項目の並びは次の通り.
#
# 通番 識別番号 担当者 e-mail 登録日 題名 記録タイプ リンクの有無 詳細内容 進捗状況 締切日 完了日 2重投稿チェック用文字列
#----------------#
# 初期設定 #
#----------------#
#--- 必ずあなたの環境に合わせて書き替える項目 --------------------------------------------#
#◆掲示板の名前
$title = 'TODO リスト';
#◆このスクリプトをURLで設定
$reload = 'todo.cgi';
#◆画面の「終了」リンク先をURLで設定
$modoru = './';
#--- 必要に応じて設定する項目 ------------------------------------------------------------#
#◆画面の色や背景の設定 (HTML書式)
$body = '
';
#◆列見出しの背景色
$TitleBack = 'BGCOLOR=#7777FF';
#◆記事内容の色
$body_color = '#000000';
#◆記事(通常時)内容の文字サイズ(CSS設定)
$span_size = 'small';
#◆記事(図表モード時)内容の文字サイズ(CSS設定)
$pre_size = 'small';
#◆2重(連続)投稿チェックの対象にする行数
$njmax = 5;
#◆$reloadで設定した設置URL以外のフォームからの投稿を禁止する処置 する:1 しない:0
# 悪戯の防止用ですが、利用サーバやブラウザによっては正規投稿もできなくなる場合もあります.
$ref_axs = 0;
#◆1画面に表示する件数
$def = 10;
#◆新着マーク(New画像)を表示する日数
$update = 3;
#◆書き込み件数の最大登録数の設定です。この件数を超えると、古いものから削除されていきます.
# ページ処理機能が付きましたので、この件数を大きくしても一度に表示される記事数は限定されます.
# サーバの負担を考慮し、できるだけ500以下程度に設定しましょう。
$max = '300';
#◆日本語コード変換ライブラリ
# minibbs.cgiと同じ場所に設置する場合はこのままでよい.
require 'jcode.pl';
#◆内容が書き込まれる記録ファイルの名前(パスの設定ではない!)
$file = 'data.cgi';
#◆データディレクトリのパスの設定(処理の都合上 / で閉じない)
$tmp_dir = './data';
#◆海外サーバ等で時差が生じる場合は修正
# +9時間する場合 = localtime(time + 9*60*60);
# −9時間する場合 = localtime(time - 9*60*60);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
#◆クッキーの消化設定
# 最終書き込みから 30日後 30*24*60*60
# 1日後 24*60*60
# 10時間後 10*60*60
($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = gmtime(time + 30*24*60*60);
#------------------
$cmd = $ENV{'QUERY_STRING'};
if ($cmd eq 'copyright') { ©right; exit; }
elsif ($cmd eq 'new') { &new; exit; }
@wday_array = ('日','月','火','水','木','金','土');
$date_now = sprintf("%04d年%01d月%01d日(%s)%02d時%02d分",$year +1900,$mon +1,$mday,$wday_array[$wday],$hour,$min);
$date_num = sprintf("%04d%02d%02d%02d%02d%02d",$year +1900,$mon +1,$mday,$hour,$min,$sec);
$date_today = sprintf("%04d年%01d月%01d日(%s)",$year +1900,$mon +1,$mday,$wday_array[$wday]);
$days[4] = $days[6] = $days[9] = $days[11] = 30;
$days[1] = $days[3] = $days[5] = $days[7] = $days[8] = $days[10] = $days[12] = 31;
$days_now = &Days($year +1900,$mon +1,$mday);
$ps = $$;
if ($ps eq '') { $ps = $date_num; }
$tmp_file = "$ps\.tmp";
$ls = "$tmp_dir\/*.*";
read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
@pairs = split(/&/,$buffer);
foreach $pair (@pairs) {
($name,$value) = split(/=/,$pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
&jcode'convert(*value,'sjis');
$value =~ s/\&/&/g;
$value =~ s/\"/"/g;
$value =~ s/</g;
$value =~ s/>/>/g;
$value =~ s/\t//g;
$value =~ s/\r\n/\r/g;
$value =~ s/\n/\r/g;
$FORM{$name} = $value;
}
$cookies = $ENV{'HTTP_COOKIE'};
@pairs = split(/;/,$cookies);
foreach $pair (@pairs) {
($name,$value) = split(/=/,$pair);
$name =~ s/ //g;
$DUMMY{$name} = $value;
}
@pairs = split(/,/,$DUMMY{$reload});
foreach $pair (@pairs) {
($name,$value) = split(/:/,$pair);
$COOKIE{$name} = $value;
}
if (-z "$tmp_dir\/$file") { $first = 1; }
if ($first) { &setmaster; }
elsif ($FORM{'action'} eq 'remove') { &remove; }
elsif ($FORM{'action'} eq 'regist') { ®ist; }
elsif ($FORM{'action'} eq 'edit') { &edit; exit; }
elsif ($FORM{'action'} eq 'newreg') { &newreg; exit; }
elsif ($FORM{'action'} eq 'rereg') { &rereg; }
elsif ($FORM{'action'} eq 'complete') { &complete; }
elsif ($FORM{'action'} eq 'sortlist') { &sortlist; }
elsif ($FORM{'action'} eq 'exit') { &exit; }
&search;
&html;
exit;
#------------------
sub search {
if ($FORM{'search'} ne '') {
$i = $FORM{'search'};
$i =~ s/ / /g;
$keys = $i;
&jcode'convert(*i,'euc');
$i =~ s/(\W)/\\$1/g;
$target = $i;
@keys = split(/\\\s+/,$target);
}
if (!open(READ,"$tmp_dir\/$file")) { &error('エラー','データが読み出せません.'); }
$master = ;
unless ($master =~ /^TODOList:(.*)$/) { &error('エラー','データの形式が違います.'); }
if ($FORM{'page'} eq '') { $page = 1; } else { $page = $FORM{'page'}; }
$page_control = $hit = $allhits = $all = 0;
if ($FORM{'action'} ne 'remove') { $start = (times)[0]; }
while () {
$string = $string_s = $_;
$page_control++;
if ($page > $page_control) { next; }
if ($FORM{'search'} ne '') {
if ($FORM{'page'} eq '') { $all++; }
&jcode'convert(*string,'euc');
if ($FORM{'mode'} eq 'or') {
$match = 1;
foreach $term (@keys) {
if ($string =~ /^([\x00-\x7F]|[\x8E\xA1-\xFE][\xA1-\xFE]|\x8F[\xA1-\xFE]{2})*$term/i) { $match = 0; }
}
}
else {
$match = 0;
foreach $term (@keys) {
if (!($string =~ /^([\x00-\x7F]|[\x8E\xA1-\xFE][\xA1-\xFE]|\x8F[\xA1-\xFE]{2})*$term/i)) { $match = 1; }
}
}
if ($match) { next; }
if ($FORM{'page'} ne '') {
$allhits = $FORM{'allhits'};
if ($hit == $def) { $next_num = $page_control; last; }
else { push(@PICKUP,$string_s); $hit++; }
}
else {
if ($end != 1 && $hit == $def) { $end = 1; $next_num = $page_control; $allhits++; }
elsif ($hit >= $def) { $allhits++; }
else { push(@PICKUP,$string_s); $hit++; $allhits++; }
}
}
else {
$hit++;
if ($hit > $def) { $next_num = $page_control; last; }
else { push(@PICKUP,$string_s); }
}
}
if ($FORM{'action'} ne 'remove') { $end = (times)[0]; }
$cpu = sprintf("%.3f",$end - $start);
close(READ);
}
sub html {
if (!@PICKUP && $page != 0) { $FORM{'page'} = $page - 1; &search; }
$nj = '';
@char = ('a'..'z','A'..'Z','0'..'9');
srand(time|$$);
foreach (0..9) {
{
local(@temp);
push(@temp,splice(@char,rand(@char),1)) while @char;
@char = @temp;
}
$nj = $char[($_)] . $nj;
}
print "Content-type: text/html\n\n";
print "$title\n";
print "\n";
print "\n";
print "\n";
print "\n";
print "$body\n";
print "$title
\n";
if ($FORM{'mode'} eq 'or') { $OR = 'checked'; $MODE = '(または)'; }
elsif ($FORM{'mode'} eq 'and' || $FORM{'mode'} eq '') { $AND = 'checked'; $MODE = '(かつ)'; }
unless ($keys =~ / /) { $MODE = ''; }
if ($next_num ne '') { $page_end = $page + $hit - 2; }
else { $page_end = $page + $hit - 1; }
print "";
print "| ";
print " | ";
print " | ";
print " | ";
print " | ";
print "";
print " |
\n";
print "
\n";
if ($page_end <= 0) {
if ($FORM{'search'} ne '') { print "指定の文字列を含む記事はありません. (検索時間 $cpu CPU秒)
\n"; }
else { print "記事はありません.
\n"; }
}
elsif ($page <= $page_end && $FORM{'search'} eq '' && !$next_num) {
print "最大 $max 件まで記録可能\です。現在" . &getmaxnumber . "件が登録されています。
\n";
print "No:" . sprintf("%03d", $page) . " → 最終";
}
else {
if ($FORM{'search'} ne '') {
if ($all == 0) { $all = $FORM{'all'}; }
print "《検索モード》 文字列 "$keys" $MODE ";
if ($FORM{'action'} ne 'remove') {
print "抽出数 $allhits ";
print "抽出位置 $page/総数$all〜 ";
print "検索時間 $cpu CPU秒
\n";
}
else { print "
\n"; }
}
else {
print "最大 $max 件まで記録可能\です。現在" . &getmaxnumber . "件が登録されています。
\n";
print "No:" . sprintf("%03d", $page) . " → No:" . sprintf("%03d", $page_end);
print "";
}
}
print "(
は$update日以内の記事)
\n";
if ($page_end > 0) {
print "\n";
print "\n";
print "| TODO | \n";
print "詳細 | \n";
print "進捗状況 | \n";
print "
\n";
foreach (@PICKUP) {
($id,$number,$name,$email,$date,$subject,$how,$link,$value,$value2,$shimekiribi,$kanryoubi,$nj) = split(/\t/);
if ($number =~ /^(\d\d\d\d)(\d\d)(\d\d)/) {
$y = $1;
$m = sprintf("%d",$2);
$d = sprintf("%d",$3);
}
$days = &Days($y,$m,$d);
$upd = $days_now - $days;
if ($upd <= $update) { $new = "
"; } else { $new = ""; }
$value =~ s/"/\"/g;
$value =~ s/&/\&/g;
if ($link == 1) { $value =~ s/(https?|ftp|gopher|telnet|whois|news)\:([\w|\:\!\#\$\%\=\&\-\^\`\\\|\@\~\[\{\]\}\;\+\*\,\.\?\/]+)/$1\:$2<\/a>/ig; }
if (length($value) == 0) { $value = " "; }
$value2 =~ s/"/\"/g;
$value2 =~ s/&/\&/g;
if ($link == 1) { $value2 =~ s/(https?|ftp|gopher|telnet|whois|news)\:([\w|\:\!\#\$\%\=\&\-\^\`\\\|\@\~\[\{\]\}\;\+\*\,\.\?\/]+)/$1\:$2<\/a>/ig; }
if (length($value2) == 0) { $value2 = " "; }
$border++;
if ($border % 2 != 0) { $bgcolor = "bgcolor=#eeeeff"; } else { $bgcolor = ""; }
print "\n";
print "| No.$id:$subject $new | \n";
if ($how == 1) {
print "$value | \n";
print "$value2 | \n";
} elsif ($how == 2) {
$value =~ s/\r/
\r/g;
$value2 =~ s/\r/
\r/g;
print "$value | \n";
print "$value2 | \n";
} else {
print "$value | \n";
print "$value2 | \n";
}
print "
\n";
print "\n";
print "| 担当者:";
if ($email ne '') {
print "$name | \n";
} else {
print "$name\n";
}
print "
\n";
print "\n";
print "| 登録日:$date | \n";
print "
\n";
print "\n";
print "| 締切日:$shimekiribi | \n";
print "
\n";
print "\n";
print "| 完了日:$kanryoubi | \n";
print "
\n";
print "\n";
print "\n";
print "| ";
print "表\示順:";
print " | ";
print "";
print " ";
print " | ";
print "
\n";
print "\n";
print "\n";
print "";
print "";
print "";
print "| ";
print " 担当者を:";
print " | ";
print "";
print " \n";
print " |
\n";
}
}
print "
\n";
print "\n";
if (($page >= 2) && ($page <= $page_end) && ($FORM{'search'} eq '')) {
$prev_num = $page - $def;
print " | \n";
}
if (($next_num ne '') && ($FORM{'search'} eq '')) {
print " | \n";
}
print "
\n";
print "
\nページのトップへ
";
# このスクリプトの著作権表示(かならず表示してください)
print "\n";
print "Original:

\n";
print "Remodeled by
WackyFactory\n";
print "
\n";
print "\n";
}
sub complete {
&lock1;
if (!open(READ,"$tmp_dir\/$file")) { &error('エラー','データが読み出せません.'); }
$master = ;
if (!open(WRITE,"> $tmp_dir\/$tmp_file")) { &error('エラー','テンポラリーファイルが作成できません.'); }
print WRITE $master;
$max_control = 0;
while ( $line = ) {
$max_control++;
($id,$num,$name,$email,$date,$subject,$how,$link,$value,$value2,$shimekiribi,$kanryoubi,$nj) = split(/\t/, $line);
if ($num =~ /$FORM{'number'}/) {
print WRITE "$id\t$num\t$name\t$email\t$date\t$subject\t$how\t$link\t$value\t$value2\t$shimekiribi\t$date_today\t$nj";
} else {
print WRITE $line;
}
if ($max_control == $max - 1) { last; }
}
close(WRITE);
close(READ);
&lock2;
}
sub exit {
print "Location: $modoru\n\n";
}
sub edit {
if (!open(READ,"$tmp_dir\/$file")) { &error('エラー','データが読み出せません.'); }
$master = ;
while ( ) {
($id,$number,$name,$email,$date,$subject,$how,$link,$value,$value2,$shimekiribi,$kanryoubi,$nj) = split(/\t/);
if ($number =~ /$FORM{'number'}/) {
print "Content-type: text/html\n\n";
print "$title\n";
print "\n";
print "\n";
print "\n";
print "$body\n";
print "$title 編集\モード
\n";
print "\n";
print "[戻る]\n";
print "