#!/usr/local/bin/perl
#
# 1997.9.14製作
# すくりぷと ばい ゆいちゃっと
# Since 1996
#------------------message from Y.K-----------------------------
#!このスクリプトはY.K作のsubupload.cgiと連動して動くように改造されています。
#!よってどちらか片方だけでは動きません。
#このスクリプトはsubupload.cgi Ver0.5以降に対応しています。
#↓消したら動かなくなりますよw?
$modified = "+Y.K(Ver 0.51)";
#改造したことで非常に初期設定が面倒になってしまいました。
#僕のHPのサポート文を参考にして設置してみて下さい。
#しばカウンタの部分をファイル保護処理に差し替えた為、しばカウンタは使用できません。
#--------------------------------------------------------------
# ■改造版■
$copyright = 'ずるぼん+擬古描 2001年10月27日版';
# 連絡先:zurubon@lycos.ne.jp
# 2001年10月27日版変更点
# ・記事の開始番号を必ず001からではなく、任意の数字から開始できるようにした
# ・記事の連番を3桁表示から4桁表示に変更(ex. 001.jpg -> 0001.jpg)
# ・画像閲覧モードの外観を変更
# ・サーバディスク使用量の概算を表示(FTPモードには非対応)
# ・アクセス集中によるアップロードミス防止処理を若干改良
# ・その他細かいところ・ソースコードのダイエット等
# ずるぼんあぷろだサポートページ
# 過去の改造版ソース等もここに置いておきます。
# http://zurubon.strange-x.com/uploader/
# *無保証
# このスクリプトを使用することによって生じたいかなる
# 損害・事件について、私ずるぼんは引責・補償できません。
# *2次配布条件
# ゆいちゃっとさんの配布条件に準ずるものとします。
# *「FTPモード」使用に関する注意事項
# 2000年3月17日改修版から保存先にFTPホストを指定できるようになっています。
# このFTPモードは十分にテストされているわけではありません。
# したがって安定・高速な動作を希望される場合には使用しないようにしてください。
# また、セキュリティーの面でも問題がありますので保存先のFTPホストに
# クラックされて困るようなサーバーを指定しないでください。
# *バグレポートは歓迎します
# ロクにテストもせずに公開していますのでおそらくバグがあると思います。
# もしお気づきの点がありましたら、私に直接メールを送るか、
# @プログラマのアンチダウソコーダー掲示板にでも書き込んでください。
# ただし、私のスキル、余暇にも限界がありますので必ず対処できるとは限らないことをご承知置き下さい。
# *注意
# @プログラマ、及びアンチダウソコーダー掲示板はあやしいわーるどの一部です。
# 書き込みの際は、あやしいわーるどに相応しい書き込みをお願いします。
# ※特に2ちゃんねるネタやそれに類似する書き込みはご遠慮ください。
# ***************************
# ***以上のことを了承される方のみご利用ください***
# ***************************
# *謝辞
# みらいあぷろだ管理人様 2000/09/07
# HTMLタグの間違い等、鋭い指摘に感謝
#
# 改竄 by 擬古描 - Sat, Apr 15, 2000 - gkJVMgleaMcTQ
#
# ∧ ∧
# 〜′ ̄(´ー`)<コメントにタグが複数入ってると上手く<等に変換されないのを修正
# UU ̄ U U MIME typeからの拡張子判定の強化
# MIME typeの記録/表示
# アプされたファイルの末尾にゴミがついてウゼェのを解消
#
# 改竄 by 擬古描 - Thu, May 11, 2000 - gkwWZ40tgKf5I
#
# 拡張子の自動判定の強化
# 誤認識の多かったlzh等の対応を強化
#
# 改竄 by 擬古描 - Fri, Jun 30, 2000 - gkHcafwBNEY86
#
# MIME typeが送信されない場合への対応の修正
# MIME typesを少し修正
# ################################
# 初期設定 ※必ず設定/変更
# ################################
# このスクリプトのURL(HTTP)
# 解説:このままの設定で動作しない場合は正確なURL(URI)を入力してください。
$url = "http://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}";
# アップロードデータの格納先ディレクトリ
# 推奨パーミッション:700->777
# 解説:FTPモードの場合も作業用に使うので必ず設定してください。
$storedir = './source/';
# アップロードデータの格納先ディレクトリURL
# 解説:URLリスト作成・画像閲覧モードで使います。
# FTPモード使用の場合は正しく設定しておかないと
# 訪問者がファイルをダウンロードできなくなります。
$storeurl = 'http://isweb41.infoseek.co.jp/feminine/uzafwyd/cgi-bin/source/';
#HTML用ログファイル
#拡張子を付けないでおいて下さい。
#サーバに置く時には"sourcelog0.txt"というように名前をつけて下さい。
$source = './sourcelog/sourcelog';
#カウント用ログファイル
$countsource = './sourcelog/count.txt';
# 投稿処理時の排他制御用lockファイル
# 解説:空のファイルを用意してください。
# 推奨パーミッション:600->604 (要するにCGIから読めるだけでOKです。)
$up_lockfile = './upload.lock';
# 表示するタイトル
$title = 'Y.K.Studio.Uploader';
# タイトルの下に表示するお知らせ
$info = '
あんまり変なファイルはあげないでくださいねw
';
#subupload.cgiの名前を変更したらここも変更が必要
$subupload = 'subupload.cgi';
# ########################################
# もう少し細かい設定
# ########################################
# HTMLのBODY設定
$body = '
';
# HTMLのスタイルシート設定
$css = '
A {text-decoration: none;}
A:link {text-decoration: none;}
A:hover {text-decoration: none; background-color: none; color: none;}
select {background-color: none; color:none;}
.button {background-color:none; color:none; border-color:none;}
';
# HTMLの広告バナー設定
# 解説:設置するサーバーに応じて書き換えてください。
$ban = '';
# リンクバー
# 各自の都合・環境に合わせて適宜修正してください。
$links = '
| Y.K.Studio
';
# タイトルの入るオビの色
$obi = 'white';
# 保存ファイル名の接頭辞
# 解説:'up0001.jpg'のようなファイル名で保存されます。なにも書かなくてもOKです。
#注:数字と"?"と"."を使わないで下さい。
$prefix = 'test';
# 記事の開始番号
# 解説:記事の開始番号を任意の数字に変更できます。
$start_num = '0001';
# コメントのオートリンク
# 1:する 0:しない
$autolink = 1;
# コメントの長さ制限
# 解説:単位はバイトです。
$comment_max = 256;
# デフォルトでの1ページにおける表示件数
$lmaxdef = 5;
# ログの最大件数
$max = 10;
# ファイルサイズ制限(キロバイト単位)
$limitk = 300;
# URLリスト出力フォーム
# 1:表示する 0:表示しない
$listform_enable = 0;
#ファイル保護の強度設定。必ずsubupload.cgiと同じにする事。
#0以下の数字は不可。数字をあげるほどファイル保護が強固になる。
$guard = 3;
# 過去ログ検索用jcode.pl
# 解説:過去ログ検索にjcode.plを使いたい場合は、jcode.plへのサーバーパスを書いてください。
# 以下はあぷろだ本体と同じディレクトリに置く場合の設定です。
# ※必ず設置する必要はありません。設置しなくてもエラーにはなりません。
$jcode = './jcode.pl';
# ロックファイル
# 1:使用する 0:使用しない
$lock = 0;
# ロックファイルのディレクトリ+ファイル名
# 解説:ロック用ディレクトリ 推奨パーミッション700->777
$lockfile = './lock/lock-file.lock';
# 対応ファイル形式
# 解説:半角カンマで区切って特別に対応させたいファイル形式を入力
$support = '';
# ########################################
# ちょっとむずかしい設定
# ########################################
# 投稿ファイル削除
# 1:使用する 0:使用しない
# 解説:投稿者がパスワードを設定して自分の投稿データを削除できるようになります。
# このオプションを有効にしてもパスワードが何も設定されなかった場合は
# 管理者以外削除できなくなります。
$del_enable = 0;
# 投稿ファイル削除パス生成時の'種'
# 解説:設定文字列を'種'として削除パスワードを生成します。
$del_seed = 'z8';
# 投稿ファイルの管理者削除
# 1:使用する 0:使用しない
# 解説:全ての投稿ファイルを削除できる管理者パスワードを設定します。
# 上記の"投稿ファイル削除"を有効にする必要があります。
$admindel_enable = 0;
# 管理者パスワードの'種'
# 解説:上記の投稿制限用パスワードを生成するときに用いた種です。
$adminseed = 'z8';
# 管理者パスワード
# 解説:平文のパスワードではなく暗号化されたものが必要です。
#
# まずhttp://zurubon.strange-x.com/crypt.txtを自分の利用するサーバーに設置して、
# 平文のパスワードと管理者パスワードの種を入力、生成された暗号化パスワード
# をここに設定してください。
$adminpass = 'z8aGslNZD.HSm6';
# gzip圧縮転送を許可する
# 解説:HTMLページをgzipで圧縮転送できるようになります。
# サーバーにかかる負担が多少上昇します。
# 1:許可する 0:許可しない
$gzipenc_enable = 0;
# gzip圧縮転送を許可した場合、
# 解説:gzip圧縮転送をデフォルトとするか
# 1:デフォルトとする 0:デフォルトとしない
$gzipenc_def = 0;
# crcチェックサム算出
# 1:使用する 0:使用しない
# 解説:大炸裂氏作のdcrc、またはcrc.plを利用してファイルのチェックサムを記録します。
# dcrcはhttp://daisakuretsu.hypermart.net/dcrc.htmlから入手できます。
# ソースファイルを入手後、telnetクライアントやtelnet.cgiを使ってコンパイルしてください。
# crc.plはhttp://zurubon.strange-x.com/uploader/crc_pl.txtから入手できます。
#
$dcrc_enable = 0;
# dcrcの場所
$dcrc_path = './dcrc';
# Perlでcrcチェックサム算出
# 解説:拙作のcrc.plを使ってCRCチェックサムを算出します。
# ※dcrcで計算した場合に比べて処理スピードがかなり落ちます。
#
# crc.plを使ってCRC計算をする場合はcrc.plへのパスを設定してください。
$crc_pl = './crc.pl';
# md5チェックサム算出
# 1:使用する 0:使用しない
# 解説:サーバー側のmd5コマンドまたはmd5.plを利用してファイルのチェックサムを記録します。
# md5.plはhttp://zurubon.strange-x.com/uploader/md5_pl.txtから入手できます。
# ※アップロード時に記録
$md5_enable = 0;
# md5コマンドのサーバーパス
$md5_path = '/sbin/md5';
# md5.plへのサーバーパス
# なるべくサーバー側のmd5コマンドが使えない場合の代替処置としてmd5.plを使うようにしてください。
# ※md5コマンドで計算した場合に比べてかなり処理速度が落ちます。
#
# md5.plを使ってMD5計算をする場合はmd5.plへのパスを設定してください。
$md5_pl = './md5.pl';
# upftp.plへのサーバーパス
# 解説:upftp.plはhttp://zurubon.strange-x.com/uploader/upftp_pl.txtから入手できます。
# FTPモードを使用しない場合はupftp.plを設置する必要はありません。
$upftp_pl = './upftp.pl';
# FTP転送先ホスト
$ftp_host = 'ftp.strange-world.co.jp';
# FTPユーザー名
$ftp_user = 'nyasu_daisensei';
# FTPパスワード
$ftp_pass = 'daisensei_password';
# FTP保存先ディレクトリ
# 解説:FTP転送先ホストにログイン後指定されたディレクトリに
# 移動してそこにデータをアップロードします。
$ftp_dir = '.';
# 「環境設定」で発行されるcookieの有効期限日数
# 解説:デフォルトは90日間(およそ3ヶ月)
# ※あまりに日数を多くしてもブラウザー側で処理不能となりますのでほどほどに。
$cookie_limit_day = 90;
# ########################################
# セキュリティーに関する設定
# ########################################
# HTMLファイルは拡張子を*.txtに変更する(※イタズラ防止)
# 1:変更する 0:変更しない
$htmlext = 0;
# 投稿者IPのログファイルへの記録
# 1:記録する 0:記録しない
$getip = 1;
# 投稿制限用パスワード
# 解説:投稿者は全て管理者が設定したパスワードを入力しないと
# 投稿できなくなります。
$postpass_enable = 0;
# 投稿制限用パスワードの'種'
# 解説:上記の投稿制限用パスワードを生成するときに用いた種です。
$postseed = 'z8';
# 投稿制限用パスワード
# 解説:平文のパスワードではなく暗号化されたものが必要です。
#
# まずhttp://zurubon.strange-x.com/crypt.txtを自分の利用するサーバーに設置して、
# 平文のパスワードと投稿制限用パスワードの種を入力、生成されたパスワード
# をここに設定してください。
$postpass = 'z8SwWsin2UzxM';
# 連続投稿間隔の制限
# 1:制限する 0:制限しない
$continue_limit = 0;
# 連続投稿制限用データファイル
# 推奨パーミッション:600->666
$continue_file = './continue.cgi';
# 連続投稿を許可する間隔
# 解説:デフォルトは30分。
# 「以前の"同じIP"の投稿から30分経ったら再度投稿してもOK」ということです。
# ◆記述例◆
# 2時間「200」
# 1時間半「130」
# 30分「030」
# 1分「001」
$contine_time = '030';
# アクセス制限
# 1:使用する 0:使用しない
$access_ctl = 0;
# アクセス制限用データファイル
# 解説:このファイルにはアクセスを禁止したいホストを
# 「1行1ホスト名・FQDN(またはIPアドレス)」で記述します。
# ※正規表現も使えます。
$denylist = './deny.cgi';
# MIME types
%MIME =
(
# テキスト
c => "text/c",
css => "text/css",
csv => "text/comma-separated-values",
htm => "text/html",
js => "text/(js|javascript)",
rtf => "text/rtf|application/rtf",
smi => "text/smil-basic|application/smil",
txt => "text/plain",
vbs => "text/vbscript",
xml => "text/xml|application/xml",
# イメージ
bmp => "image/(bmp|x-bmp|x-MS-bmp)",
gif => "image/gif",
ico => "image/x-icon",
jpg => "image/.*jpeg",
png => "image/(png|x-png)",
psd => "image/x-photoshop",
tif => "image/(tiff|x-tiff)",
xbm => "image/(x-xbm|x-xbitmap)",
# ビデオ
asf => "video/(x-ms-asf|x-ms-asf-plugin)|application/x-mplayer2",
avi => "video/(avi|msvideo|x-msvideo)",
mov => "video/quicktime",
mpg => "video/(mpg|mpeg|x-mpeg)",
# オーディオ
aif => "audio/(aiff|x-aiff|x-pn-aiff)",
au => "audio/(basic|x-pn-au)",
m3u => "audio/(mpegurl|x-scpls|x-mpegurl)",
mid => "audio/(mid|midi|x-mid|x-midi)|application/x-midi|music/crescendo|x-music/x-midi",
mod => "audio/x-mod",
mp3 => "audio/(mp3|mpg|mpeg|x-mp3|x-mpg)",
ra => "audio/(x-realaudio|vnd\\.rn-realaudio)",
ram => "audio/x-pn-realaudio",
rm => "application/vnd\\.rn-realmedia",
rpm => "audio/x-pn-realaudio-plugin",
vqe => "audio/x-twinvq-plugin",
vqf => "audio/x-twinvq|application/x-twinvq",
wav => "audio/(wav|x-wav|x-pn-wav|x-pn-windows-acm|x-pn-windows-pcm)",
wma => "audio/x-ms-wma",
# 他
arj => "application/arj",
bin => "application/(octet-stream|x-macbinary)",
dcr => "application/x-director",
exe => "application/(x-exe|x-msdownload)",
gz => "gzip",
hlp => "application/(winhlp|x-winhelp)",
jar => "application/java-archive",
js => "application/x-javascript",
lzh => "lha|lzh|LhasaArchive|LHMelt",
pac => "application/x-ns-proxy-autoconfig",
pdf => "application/pdf",
rar => "application/x-rar-compressed",
sit => "application/x-stuffit",
swf => "application/x-shockwave-flash",
tar => "application/x-tar",
uue => "application/x-uuencode",
wmf => "application/x-msmetafile",
wri => "application/application/x-mswrite",
yz1 => "application/x-yz1",
Z => "application/x-compress",
zip => "zip",
wrl => "model/vrml|x-world/x-vrml",
);
%EMIM =
(
"zip" => "gzip",
);
# ############################################################################
# 以下はスクリプトのエンジン部分。無闇にいじくると動かなくなるかも(ワラ
# ############################################################################
$subupload = "$storedir$subupload"."/";
# アクセス制限
$host = $ENV{REMOTE_ADDR};
if($access_ctl){
open(DB,"$denylist") || die &error('アクセス制限ファイルがオープンできません','');
@lines = ;
close(DB);
foreach $line (@lines) {
next if(length($line)<4);
chop $line;
if( $host=~/$line/ ){&error('アクセス制限','あなたにはアクセス権限がありません。');}
}
$lines = 0;
}
@sup = split(/,/, $support);
@MEXT = sort keys(%MIME);
%sup = ();
grep($sup{$_} = 1, @sup, @MEXT);
if($htmlext != 0)
{
delete $sup{"htm"} if exists $sup{"htm"};
delete $sup{"html"} if exists $sup{"html"};
delete $MIME{"htm"} if exists $MIME{"htm"};
delete $MIME{"html"} if exists $MIME{"html"};
}
@sup = sort keys(%sup);
if($lock){
$retry = 5;
while (!symlink(".", $lockfile)) {
if (--$retry <= 0){unlink($lockfile); exit;}
sleep(1);
}
}
# ログ読み込み
&readlog;
# アップロード処理とログへの追加書込み
if ($ENV{REQUEST_METHOD} eq "POST") {
# $dateに現在時刻を入れる
$ENV{TZ} = 'JST-9';
$times = time;
($sec,$min,$hour,$mday,$month,$year,$wday,undef,undef) = localtime($times);
$month++;
$youbi = ('日','月','火','水','木','金','土') [$wday];
$year = 1900 + $year;
$date = sprintf("%d年%02d/%02d(%s)%02d:%02d", $year, $month, $mday, $youbi, $hour, $min);
# 連続投稿制限
if($continue_limit){
$cont_val = &continue_check('check');
&error('連続投稿制限中','時間を置いてやり直してください') if(!$cont_val);
}
srand(time^$$);
$uniq_name = time . int(rand(time)) . '.temp'; # temporaryにuniqueな名前を付ける
unlink <$storedir*.temp>; # ディレクトリにゴミが残っている場合には掃除する
&decode;
open (UPLOCK, "$up_lockfile");
flock (UPLOCK, 2); # 排他処理の始まり
&readlog; # uploadが終わってからログを読む
# 正式な$idを決める
if((-s "$getsource")==0){
$id = $start_num;
}else{
@Dlines = reverse(sort(@lines));
($id) = split(/\t/, $Dlines[0]);
$id = sprintf("%04d",++$id);
}
rename ("$storedir$uniq_name", "$storedir$prefix$id.$type"); # temporaryな名前から正式な名前へrename
chmod 0604, "$storedir$prefix$id.$type";
if($ftp_enable){
if(-f $upftp_pl){
require $upftp_pl;
use Cwd; my $olddir = cwd;
chdir $storedir || die error('エラー', "$storedirが開けません");
&upftp::login($ftp_host, 21, $ftp_user, $ftp_pass);
&upftp::cd($ftp_dir);
&upftp::upload("$prefix$id.$type");
&upftp::logout;
chdir $olddir;
}
else{
&error('エラー','upftp.plが見つかりません。
設定を見直してください。');
}
unlink("$storedir$prefix$id.$type");
}
&write if($comment);
close (UPLOCK); # 排他処理の終わり
&readlog;
}
# フォームデータのデコード(GET)
$buffer = $ENV{QUERY_STRING};
@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;
$FORM{$name} = $value;
}
# 環境設定モード
if($ENV{QUERY_STRING} eq 'env'){
&env_form;
}
# 過去ログ検索
elsif($FORM{search} ne "" || $ENV{QUERY_STRING} eq "search"){
if($FORM{search}){
@search_ary = &search_log($FORM{search});
$search_hit = @search_ary;
}
&search_result;
}
# 画像閲覧モード
elsif($ENV{QUERY_STRING} eq "image" || $FORM{image} ne ""){
&image_view($FORM{image});
}
# URLリスト作成
elsif($FORM{lstart} ne "" && $FORM{lend} ne ""){
&list;
}
# 投稿データ削除フォーム
elsif($FORM{del} ne "" && $del_enable){
&del_form($FORM{del});
}
# 投稿データの削除
elsif($FORM{delid} && $FORM{delpass} ne ""){
&del($FORM{delid},$FORM{delpass});
&readlog;
&html;
}
# md5表示
elsif($md5_enable && $FORM{md5} ne ""){
&md5_disp($FORM{md5});
}
# dcrc
elsif($dcrc_enable && $FORM{dcrc} ne ""){
&dcrc_disp($FORM{dcrc});
}
# ヘルプ
elsif($FORM{help} ne ""){
&help($FORM{help});
}
# トップページ表示
else{
&html;
}
# ロックファイル削除
unlink($lockfile) if($lock);
# 終了
exit;
# ############################################################################
# 以下関数定義&実装
# ############################################################################
# ログ読み込み
sub readlog{
if(!open(DB,"$countsource")){&error('カウント用のログファイルがオープンできません','スクリプトの設定を見直してください。');}
seek(DB,0,0);
$no = ;
close(DB);
$getno = $no % $guard;
$getsource = "$source"."$getno"."\.txt";
if(!open(DB,"$getsource")){&error('HTML用のログファイルがオープンできません','スクリプトの設定を見直してください。');}
seek(DB,0,0);
@lines = ;
$end_num = (split(/\t/,$lines[0]))[0];
close(DB);
}
# ログ書き込み
sub write{
$size = $ENV{CONTENT_LENGTH}/1024;
$size = 1 if($ENV{CONTENT_LENGTH} < 1024);
$size = sprintf("%d", $size);
$host = 'anonymous' if(!$getip);
$pass = '*' if(!$del_enable);
$value = &tjoin($id, $type, $comment, $host, $ENV{HTTP_USER_AGENT}, $date, $size, $ctype, $pass, $md5, $dcrc,'0');
$value .= "\n";
#$valueを@linesに加えたのち、書き込む
if(@lines > $max-1){#最大を超えたら削除します。
$del= pop(@lines);
($id, $type) = split(/\t/, $del);
if($ftp_enable){
if(-f $upftp_pl){
require $upftp_pl;
&upftp::login($ftp_host, 21, $ftp_user, $ftp_pass);
&upftp::cd($ftp_dir);
&upftp::del("$prefix$id.$type");
&upftp::logout;
}
else{
&error('エラー','upftp.plが見つかりません。
設定を見直してください。');
}
}
else{unlink("$storedir$prefix$id.$type");}
}
unshift(@lines,$value);
open(DB,">$getsource");
eval { flock(DB,2); };
seek(DB,0,0);
print DB @lines;
eval { flock(DB,8); };
close(DB);
}
# POSTされたデータのMIMEタイプ決定、CRC・MD5算出、
# コメント長計算・パスワード照合処理
sub decode{
my $size, $expfile;
return if($ENV{CONTENT_LENGTH} > $limitk*1024);
return unless($ENV{HTTP_REFERER} =~/$url/);
binmode(STDIN);
while(){
last if(/^\r\n/);
$bound = $_ if(/^--/);
$rext = $1 if(/^Content-Disposition:.*filename="(.*)"/i);
$ctype = $1 if(/^Content-Type:(.*)/i);
}
$rext =~ s/.*\.//go;
$ctype =~ s/(^\s|\s$)//go;
$bound=~s/\r\n//;
foreach $mext (@MEXT)
{
if($ctype =~ /$MIME{$mext}/)
{
next if (defined($EMIM{$mext}) && $ctype =~ /$EMIM{$mext}/);
$type = $mext;
}
}
if($rext ne "")
{
$rextl = "\L$rext\E";
foreach $ext (@sup)
{
if("\L$ext\E" eq $rextl)
{
$type = $ext;
last;
}
}
}
$type = 'xxx' if($type eq '');
$ctype = "www/none" unless $ctype;
$ctype = &htmlenc($ctype);
open(DB,">$storedir$uniq_name");
binmode(DB);
$dbuf = "";
while(){
last if($_=~/^$bound/);
print DB $dbuf;
$dbuf = $_;
}
$dbuf =~ s/\r\n$//;
print DB $dbuf;
close (DB);
$size = -s "$storedir$uniq_name";
&reload if(!$size); #sizeが0ならリロード
$ext = &post_decode;
if($ext ne 'ext'){
if(!grep($ext eq $_, @sup)){
unlink("$storedir$uniq_name");
&error('投稿データエラー', '許可されていない拡張子です。');
}
$type = $ext;
}
if($dcrc_enable){ # CRC計算
if(-f $crc_pl){
require $crc_pl;
$dcrc = &crc::crc16("$storedir$uniq_name");
}
else{
$dcrc = &dcrc("$storedir$uniq_name");
}
}
if($md5_enable){ # MD5計算
if(-f $md5_pl){
require $md5_pl;
$md5 = &md5::from_file("$storedir$uniq_name");
}
else{
$md5 = &md5("$storedir$uniq_name");
}
}
$comment = &post_decode;
&reload if(!$comment); # コメントが書かれていない場合はReload
&error('投稿エラー','コメントが長すぎます') if(length($comment) > $comment_max);
$comment = &htmlenc($comment);
$comment =~ s/(https?|ftp|news)(:.*)([a-z]|[A-Z]|[0-9]|\/)/$1$2$3<\/a>/g if($autolink);
if($del_enable){
$input_pass = &post_decode;
$pass = crypt($input_pass, $del_seed);
$pass = '*' if($input_pass eq '');
&error('投稿エラー','パスワードが長すぎます') if(length($input_pass) > 10);
if($postpass_enable){
&error('投稿用パスワードが違います','投稿用パスワードを管理者から入手してください。') if(!&postpass);
}
}
elsif($postpass_enable){
&error('投稿用パスワードが違います','投稿用パスワードを管理者から入手してください。') if(!&postpass);
}
&continue_check('add') if($continue_limit);
}#decode END
# POSTデータを文字列に変換して返す
sub post_decode{
my $post_str;
while(){
last if(/^$bound/);
next if(/^\r\n/);
next if(/^Content/);
$post_str .=$_; $post_str=~s/\r\n//;
}
return $post_str;
}
# トップページ表示
sub html{
$page = $FORM{page};
$page=0 unless($page);
$lmax = $FORM{lm};
$lmax=$lmaxdef unless($lmax);# 一ページにどれだけ表示するか?
$page2 = $page*$lmax;
&print_header;
print <<"_HTML_";
\n";
print "\n" if($listform_enable);
&print_footer;
}#html END
# HTMLのヘッダ部分
sub print_header{
my $subtitle = shift;
my $title_h;
if(!$subtitle){$title_h = $title}
else{$title_h = "$title -$subtitle-";}
# 環境設定cookie取得
&get_cookie;
print "Content-type: text/html\n";
if($FORM{mode} eq 'envset'){
&send_cookie; # cookie送信
# 新しく設定された環境設定を有効化する
$crce=$FORM{crce}; $md5e=$FORM{md5e}; $acte=$FORM{acte}; $commente=$FORM{commente};
$sizee=$FORM{sizee}; $mimee=$FORM{mimee}; $datee=$FORM{datee}; $anothere=$FORM{anothere};
$gzipence=$FORM{gzipence};
}
if($gzipenc_enable && $gzipence){&gzip_encode;}
else{print "\n";}
print <<"HEADER";
$title_h
$body
$info
HEADER
}
# HTMLのフッタ部分
sub print_footer{
print "
\n$ban
\n\n";
close(STDOUT) if($gzipenc_enable && $gzipence);
}
# 投稿記事部分のHTML
sub print_postdata{
my @matrix = @_;
my $id, $type, $comment, $host, $brauza, $date, $size, $ctype, $pass, $md5, $dcrc;
print "\n";
print "| ACT | \n" if($acte);
print "NAME | \n";
print "COMMENT | \n" if($commente);
print "SIZE(KB) | \n" if($sizee);
print "MIME | \n" if($mimee);
print "DATE | \n" if($datee);
print "MD5 | \n" if($md5e && $md5_enable);
print "CRC | \n" if($crce && $dcrc_enable);
print "DL | \n";
print "
\n";
foreach (@matrix){
s/\n//g;
($id, $type,$comment,$host,$brauza,$date,$size,$ctype,$pass,,$md5,$dcrc,$readcount) = split(/\t/);
next unless($id);
print "\n";
if($acte){
print "| \n";
print "D\n" if($del_enable);
print " C\n" if($dcrc_enable && !$crce);
print " 5\n" if($md5_enable && !$md5e);
print " | \n";
}
print "[$prefix$id.$type] | \n";
print "$comment | \n" if($commente);
print "$size | \n" if($sizee);
print "$ctype | \n" if($mimee);
print "$date | \n" if($datee);
print "$md5 | \n" if($md5e && $md5_enable);
print "$dcrc | \n" if($crce && $dcrc_enable);
print "$readcount | \n";
print "
\n";
}
print "
\n";
}
#gzip圧縮転送
sub gzip_encode{
if($ENV{HTTP_ACCEPT_ENCODING}=~/gzip/){
if($ENV{HTTP_ACCEPT_ENCODING}=~/x-gzip/ ){
print "Content-encoding: x-gzip\n\n";
}else{
print "Content-encoding: gzip\n\n";
}
open(STDOUT,"| gzip -1 -c");
print "\n";
}
}
#URLリスト出力
sub list{
my $id, $type, $comment, $host, $brauza, $date, $size, $ctype, $pass, $md5, $dcrc;
my $start = $FORM{lstart};
my $end = $FORM{lend};
my $ext = $FORM{extlist} if($FORM{extlist});
print "Content-type: text/plain\n\n";
foreach(@lines){
s/\n//g;
($id,$type,$comment,$host,$brauza,$date,$size,$ctype,$pass,$md5,$dcrc) = split(/\t/);
next if($ext && ($type ne $ext));
if($id <= $end){
print "$storeurl$prefix$id.$type";
print "\t$md5" if($FORM{md5list} eq "checked");
print "\t$dcrc" if($FORM{dcrclist} eq "checked");
print "\n";
}
last if($id eq $start);
}
}
# 投稿データ削除フォーム
sub del_form{
my $target_id = shift;
&print_header('投稿データ削除');
print <<"DEL";
ID:$target_idを削除します
DEL
&print_footer;
}
# 投稿ファイル削除処理
sub del{
my ($target_id, $target_pass) = @_;
my $id, $type, $pass, $target_type;
foreach (@lines){
chop;
($id, $type, undef, undef, undef, undef, undef, undef, $pass, undef, undef) = split(/\t/);
if($id eq $target_id){$target_type=$type; $org_pass=$pass; last;}
}
&error('削除エラー','該当ファイル無し') if(!$target_type);
if(!$admindel_enable || ($admindel_enable && $adminpass ne (crypt($target_pass, $adminseed)))){
&error('削除エラー','削除禁止ファイルです') if($org_pass eq '*');
&error('削除エラー','パスワードが違います') if($org_pass ne (crypt($target_pass, $del_seed)));
}
if($ftp_enable){
if(-f $upftp_pl){
require $upftp_pl;
&upftp::login($ftp_host, 21, $ftp_user, $ftp_pass);
&upftp::cd($ftp_dir);
&upftp::del("$prefix$id.$type");
&upftp::logout;
}
else{
&error('エラー','upftp.plが見つかりません。
設定を見直してください。');
}
}
else{unlink("$storedir$prefix$target_id.$target_type");}
open(DB,">$getsource");
eval { flock DB, 2; };
foreach (@lines){
next if($target_id eq (split(/\t/))[0]);
s/\n//g;
print DB "$_\n";
}
eval { flock DB, 8; };
close(DB);
}
# エラー出力
sub error{
&print_header('Notice!');
print <<"ERROR";
$_[0]
$_[1]
Return
ERROR
&print_footer;
exit;
}
# 引数の配列を分解してタブで区切られた文字列を返す
sub tjoin
{
my @data = @_;
foreach (@data)
{
next if(!$_);
s/\s/ /go;
}
return join("\t", @data);
}
# 文字列中のHTMLタグを無効にする
sub htmlenc
{
my $str = shift;
$str =~ s/\&/&/go;
$str =~ s/\</go;
$str =~ s/\>/>/go;
$str =~ s/\"/"/go;
$str =~ s/\t/ /go;
return $str;
}
# md5コマンドからmd5 CRCを得る
sub md5{
open MD5, "$md5_path $_[0] |";
my $val = ;
close MD5;
$val =~ s/ //g;
$val = (split(/\=/,$val))[1];
return $val;
}
# md5表示
sub md5_disp{
my $target_id = $_[0];
my $ans, $id, $md5;
foreach (@lines){
chop;
($id, undef, undef, undef, undef, undef, undef, undef, undef, $md5, undef) = split(/\t/);
if($id eq $target_id){$ans = $md5; last;}
}
&error('エラー','該当ファイルが存在しないか、md5チェックサムが記録されていません。') if(!$ans);
&error("$target_idのmd5チェックサム","$ans");
}
# ログファイルを検索して結果を収納した配列を返す
sub search_log{
my $search_str = $_[0];
my $count = 0;
my $id, $type, $comment, $host, $brauza, $date, $size, $ctype;
my $start, $end, $ext;
my @ans;
$start = $FORM{sstart};
$end = $FORM{send};
$ext = $FORM{extlist};
$min = $FORM{size_min};
$max = $FORM{size_max};
if(-f $jcode){
require $jcode;
&jcode'convert(*search_str,'sjis') if(!$FORM{nojcode});
}
$search_str = quotemeta($search_str);
foreach (@lines){
s/\n//g;
($id,$type,$comment,$host,$brauza,$date,$size,$ctype) = split(/\t/);
if($id >= $start && $id <= $end){
if($ext ne '' && $ext ne $type){next;}
else{
if($size >= $min){
if($size <= $max || !$max){
if(/$search_str/){$ans[$count] = $_; $count++;}
}
}
}
}
}
return @ans;
}
# 過去ログ検索のトップページ/結果 表示
sub search_result{
if($FORM{sstart}){$sstart = $FORM{sstart};}else{$sstart = $start_num;}
if($FORM{send}){$send = $FORM{send};}else{$send = $end_num;}
if($FORM{size_min}){$size_min = $FORM{size_min};}else{$size_min = 1;}
if($FORM{size_max}){$size_max = $FORM{size_max};}else{$size_max = '';}
if($FORM{extlist}){$ext = $FORM{extlist}; $extv = $FORM{extlist};}
else{$ext = '拡張子'; $extv = '';}
&print_header('過去ログ検索');
print <<"FORM";
\n";
print ' D:投稿記事削除' if($del_enable);
print ' C:CRC表示' if($dcrc_enable);
print ' 5:md5表示' if($md5_enable);
print "\n";
print '
';
if($search_hit){&print_postdata(@search_ary);}
if($search_str){
print "\"$search_str\"は$search_hit件見つかりました。
" if($search_hit);
print "\"$search_str\"は見つかりませんでした。
" if(!$search_hit);
}
&print_footer;
}
# dcrcからターゲットファイルのCRCを得る
sub dcrc{
my $target = shift;
open DCRC, "$dcrc_path $target |";
my $val = ;
close DCRC;
$val = (split(/ /,$val))[1];
return $val;
}
# CRC表示
sub dcrc_disp{
my $target_id, $ans, $id, $dcrc;
$target_id = $_[0];
foreach (@lines){
chop;
($id, undef, undef, undef, undef, undef, undef, undef, undef, undef, $dcrc) = split(/\t/);
if($id eq $target_id){$ans = $dcrc; last;}
}
&error('エラー','該当ファイルが存在しないか、CRCチェックサムが記録されていません。') if(!$ans);
&error("$target_idのCRCチェックサム","$ans");
}
# 投稿制限用パスチェック
sub postpass{
my $input_postpass = &post_decode;
if($postpass ne crypt($input_postpass, $postseed)){
unlink "$storedir$uniq_name";
return 0;
}
return 1;
}
# 画像閲覧モード
sub image_view{
my $page = $_[0];
my $total, $page_max, $id, $type, $comment, $date, $size, $i;
my @images;
foreach (@lines){
if((split(/\t/))[1] =~ /(jpg|png|gif)/){
$images[$count] = $_; $count++;
}
}
$total = @images;
$page_max = int($total/5);
$page_max++ if((split(/\./, $total/5))[1]);
$page = 1 if(!$page || $page > $page_max);
&print_header('画像閲覧');
print "
| 過去ログ検索\n",
" | 画像閲覧 | 環境設定 $links\n";
print "
\n", "ページ: ";
for($i=1; $i<=$page_max; $i++){
if($i==$page){ print "[$i]\n"; }
else { print "[$i]\n"; }
}
print "
\n\n";
if($page == 1){ print "[Prev] \n"; }
else { print sprintf("[Prev] \n", ($page-1)); }
print "[戻る]\n";
if($page == $page_max){ print " [Next]\n"; }
else { print sprintf(" [Next]\n", ($page+1)); }
print "\n";
for($i=($page*5-5); $i<=($page*5-1); $i++){
last if(($i+1) > $total);
($id, $type, $comment, undef, undef, $date, $size, undef, undef, undef, undef) = split(/\t/, $images[$i]);
print "
\n";
print "$prefix$id.$type
\n",
"$comment $date
\n";
}
&print_footer;
}
# Reload
sub reload{
unlink "$storedir$prefix$id.$type";
&readlog;
&html;
exit;
}
# 連続投稿制限ファイルの読み書き、連続投稿チェック
sub continue_check{
my $mode = shift;
my $date_id, $post_ip, $line_c, $line_num, $ans, $ip, $id;
$date_id = sprintf("%d%02d%02d%02d%02d", $year, $month, $mday, $hour, $min);
$post_ip = $ENV{REMOTE_ADDR};
if(!open(DB, "$continue_file")){&error('連続投稿制限ファイルがオープンできません');}
@line_c = ;
close(DB);
if($mode eq 'check'){ # 投稿者情報のチェック
foreach (reverse(@line_c)){
chop;
($ip,$id) = split(/:/);
if($post_ip eq $ip){
$ans = $date_id - $id;
return 0 if($ans < $contine_time);
}
}
}
if($mode eq 'add'){ # 連続投稿制限ファイルに投稿者情報を追加
$line_num = @line_c;
push(@line_c, "$post_ip:$date_id");
pop(@line_c) if($line_num > $max-1);
if(!open(DB,">$continue_file")){
&error('連続投稿制限ファイルを書込みモードで開けません','ファイルのパーミッションを見直してください');}
eval { flock DB, 2; };
foreach (@line_c){print DB "$_\n";}
eval { flock DB, 8; };
close (DB);
}
return 1;
}
# 環境設定フォーム
sub env_form{
&print_header('環境設定');
print <<"ENV";
環境設定
戻る
ENV
&print_footer;
}
# cookie送信
sub send_cookie{
my $cookie = "crce:$FORM{crce}<>md5e:$FORM{md5e}<>acte:$FORM{acte}<>";
$cookie .= "commente:$FORM{commente}<>sizee:$FORM{sizee}<>mimee:$FORM{mimee}<>";
$cookie .= "datee:$FORM{datee}<>anothere:$FORM{anothere}<>gzipence:$FORM{gzipence}";
# cookieの有効期限の計算
my($sec, $min, $hour, $mday, $month, $year, $wday) = gmtime(time + $cookie_limit_day * 24 * 60 * 60);
my $youbi = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday') [$wday];
my $tuki = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') [$month];
my $year = 1900 + $year;
my $expire = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", $youbi, $mday, $tuki, $year, $hour, $min, $sec);
print "Set-Cookie: env=$cookie; expires=$expire\n";
}
# cookie取得
sub get_cookie{
my $key, $value, $db, $db2, $env;
foreach (split(/; /,$ENV{HTTP_COOKIE})){
($key, $value) = split(/=/);
$db{$key} = $value;
}
$env = $db{env};
foreach (split(/<>/,$env)){
($key, $value) = split(/:/);
$db2{$key} = $value;
}
$crce = $db2{crce}; $md5e = $db2{md5e};
$acte = $db2{acte}; $commente = $db2{commente};
$sizee = $db2{sizee}; $mimee = $db2{mimee};
$datee = $db2{datee}; $anothere = $db2{anothere};
$gzipence = $db2{gzipence};
if(!$env){ # cookieが取得できなかった場合
$acte=1; $commente=1; $sizee=1;
$datee=1; $gzipence=$gzipenc_def;
}
}
# HELPページ表示
sub help{
my $target = shift;
&print_header('HELP');
if($target eq 'del'){
print <<"DEL";
投稿記事削除パスについて
投稿者が後々自分の投稿記事を削除したい場合に入力します。
パスワードが入力されないまま投稿された記事は管理者にしか削除できなくなります。
パスワードには10文字未満の英数記号を指定できます。
DEL
}
elsif($target eq 'post'){
print <<"POST";
投稿用パスワードについて
全ての投稿者は、管理者があらかじめ設定した投稿用パスワードを、"postpass"
フィールドに入力する必要があります。投稿用パスワードは、サイトの管理者から
入手してください。
POST
}
else{
print "その項目についてのヘルプはありません。";
}
print "戻る\n";
&print_footer;
exit;
}
# サーバディスク使用量を計算
sub calc_disk_usage{
my $sum = 0;
opendir DIR, "$storedir";
foreach (readdir DIR){
next if(/^\.$|^\.\.$/);
$sum += -s "$storedir/$_";
}
closedir DIR;
return int($sum/1024);
}