#!/usr/bin/perl
;# -------------------------------------------------------------------
;# Copyright
;#
;# Script : Mini Thread
;# Homepage : Flash CGI
;# URL : http://www.flashcgi.net/
;# Mail : webmaster@flashcgi.net
;# Type : Free Ware(May Convert)
;# -------------------------------------------------------------------
;#
;# 設定ファイル名
;; require 'config.cgi';
;#
;# -------------------------------------------------------------------
;# 書式
;#
;# q=検索ワード(&tr=対象スレッド&st=開始位置&no=表示数&op=and/or&tg=検索対象)
;# -------------------------------------------------------------------
;#
;; &main;
;#
;#
;# 検索画面
;#
sub main {
#
# 引数を受け取ります
#
my $QUERY_DATA = $ENV{'QUERY_STRING'};
#
# サイズチェック
#
&error(__LINE__,'検索ワードが長すぎです') if (length($QUERY_DATA) > $sobig);
#
# デコード
#
my @pairs = split(/&/,$QUERY_DATA);
my $hold;
foreach $pair (@pairs) {
my ($name, $value) = split(/=/, $pair);
$hold = $value if ($name eq 'q');
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/[\x00-\x0d\x10-\x1a\x1c-\x1f]+//g;
$FORM{$name} = $value;
}
#
# 変数取得
#
my $bbs = $FORM{'b'};
my $no = $FORM{'no'};
my $q = $FORM{'q'};
my $tg = $FORM{'tg'};
#
# 検索対象の引継ぎ
#
if (&checkBbs($bbs)) {
&readsubset($pluspath.$bbs.'/'.$subsetcgi);
} elsif (!$allboard) {
&error(__LINE__,'板が見つかりません');
}
#
# 圧縮
#
&encode();
#
# HTML
#
print '';
print '
';
print '検索画面';
print '';
print $search_style;
print '';
print '';
print '■掲示板に戻る■';
print '';
#
# 検索処理
#
if ($FORM{'ac'} eq '') {
©right;
} else {
&search(\%FORM,$bbs,$hold);
}
#
# 著作と終端
#
©right;
}
;#
;# 検索
;#
sub search {
#
# 受信
#
my $FORM = shift;
my $bbs = shift;
my $hold = shift;
my ($sthread,$sres,$flag,$result,@FILE);
my $dir = $pluspath.$bbs.'/'.$savedir;
#
# デコードする
#
require 'write.pl';
&decode(' 検索 ',$$FORM{'s'},\%FORM);
#
# エスケープ
#
my $keyword = $$FORM{'q'};
my $number = $$FORM{'no'};
my $target = $$FORM{'tg'};
my $thread = $$FORM{'tr'};
my $start = $$FORM{'st'};
$keyword =~ s/ / /g;
$keyword =~ s/ +/ /g;
$keyword =~ tr/ /\0/s;
#
# フォームチェック
#
if ($keyword eq '') {
&searcherror('検索ワードが入力されていません');
}
if ($number eq '' or $number !~ /[0-9]{1,3}/) {
$number = 20;
}
#
# 汚染チェック
#
if ($start and $start !~ m|^([0-9]*/[0-9]*)$|) {
&searcherror('不正なデータを受信しました');
}
#
# 変換
#
my @keylist = split(/\0/,$keyword);
#
# 負荷が上がりそうなことははねる
#
if (@keylist > 10) {
&searcherror('検索ワードが多すぎます');
}
foreach $k (@keylist) {
&searcherror('検索ワードは2byte以上指定してください') if (length($k) <= 1);
}
#
# 処理分岐
#
if (!$thread) {
#
# データファイル探索
#
opendir(DIR,$dir) or &searcherror('ディレクトリのオープンに失敗しました');
@FILE = sort{ (stat($dir.$b))[9] <=> (stat($dir.$a))[9] } grep { /\.dat$/ } readdir(DIR);
closedir(DIR);
} else {
#
# 汚染チェック
#
if ($thread =~ /\D/) {
&searcherror('不正なデータを受信しました');
}
if (-e $dir.$thread.'.dat') {
push(@FILE,$thread.'.dat');
}
}
#
# 始まり
#
if (!$start) {
$flag = 1;
} else {
($sthread,$sres) = split(/\//,$start);
}
#
# 一個ずつ
#
foreach (@FILE) {
#
# スレッド
#
my $threadno = $_+0;
my ($title,$resno);
#
# スキップチェック
#
if ($threadno == $sthread) {
$flag = 1;
}
#
# スキップ
#
if (!$flag) {
next;
}
#
# 読み込み
#
open(LOG,$dir.$_) or &searcherror($_.'のオープンに失敗しました');
#
# タイトル
#
$title = (split(/<>/,scalar()))[4];
seek(LOG,0,0);
#
# レススキップ
#
if ($threadno == $sthread) {
$resno = $sres;
while($sres--) {
;
}
}
#
# 総当り
#
while() {
#
# リセット
#
my ($ok,$tgword);
++$resno;
#
# 分割
#
my @TEMP = split(/<>/);
#
# 目標特定
#
if ($target eq 'nm') {
$tgword = $TEMP[0];
}
elsif ($target eq 'ml') {
$tgword = $TEMP[1];
}
elsif ($target eq 'ur') {
$tgword = $TEMP[5];
}
elsif ($target eq 'id') {
my $id;
if ($idsalt) {
if ($threeid ne '' and $TEMP[1] eq $threeid) {
$id = '???';
} else {
$TEMP[2] =~ m|\d+/(\d+)/(\d+)|;
$id = &idsum($1,$2,$TEMP[7]);
}
$tgword = $id;
}
$tgword .= $TEMP[2];
}
elsif ($target eq 'al') {
$tgword = $_;
}
elsif ($target eq 'tt') {
$tgword = $TEMP[4];
}
else {
$target = 'lg';
$tgword = $TEMP[3];
}
#
# 複数検索対応
#
my $match;
foreach $key (@keylist) {
my $l = length($key);
my $i = index($tgword,$key);
if ($i != -1) {
++$ok;
++$match;
$i += $l;
while (($i=index($tgword,$key,$i)) != -1) {
++$match;
$i += $l;
}
}
}
#
# or検索
#
if ($$FORM{'or'} and $ok > 0) {
++$result;
&srhtml(\@TEMP,\@keylist,$bbs,$match,$$FORM{'vw'},$title,$threadno,$resno,$target);
}
#
# and検索
#
elsif ($ok == @keylist) {
++$result;
&srhtml(\@TEMP,\@keylist,$bbs,$match,$$FORM{'vw'},$title,$threadno,$resno,$target);
}
#
# 終了判定
#
if ($result >= $number) {
close(LOG);
print '
';
©right;
}
#
# タイトル検索対応
#
if ($target eq 'tt') {
last;
}
}
#
# ファイル閉じ
#
close(LOG);
}
#
# ログの移動などによるエラー
#
if ($sthread and !$flag) {
&searcherror('ログが消されたか移動された可能性があります');
}
#
# 終了
#
if ($result == 0) {
&searcherror('マッチしませんでした');
}
}
;#
;# 結果表示html
;#
sub srhtml {
#
# 変数取得
#
my $TEMP = shift;
my $key = shift;
my $bbs = shift;
my $match = shift;
my $view = shift;
my $title = shift;
my $threadno = shift;
my $resno = shift;
my $target = shift;
#
# 全文表示か省略表示かで分岐
#
if ($view) {
print '';
print '';
print '';
print ''.$title.'';
print '(ヒット数:'.$match.')';
print ' | ';
&convertData($TEMP,'return'=>$pluspath,'link'=>$readcgi.'/'.$bbs.'/'.$threadno.'/','resno'=>$resno,'color'=>$search_nameclr,'count'=>$count,'print' => 0);
#
# 着色
#
if ($target eq 'lg' or $target eq 'al') {
&coloring(\$$TEMP[3],$key);
}
print ''.$resno.' ';
print '名前:'.$$TEMP[0].' '.$$TEMP[2].' '.$$TEMP[5];
print ' '.$$TEMP[3].' | ';
print '
|
';
} else {
print '';
}
}
;#
;# マッチした文字を強調表示する
;#
sub coloring {
#
# 変数取得
#
my $str = shift;
my $key = shift;
my @key = @$key;
return if (@key > 5);
my $r_str;
#
# タグを区切りにして配列に代入する
#
my @str = split(/(<[^>]*>)/,$$str);
$$str = '';
while(@str) {
my $tmp = shift(@str);
foreach $k (@key) {
my $l = length($k);
my $t;
while (($p=index($tmp,$k)) != -1) {
$t .= substr($tmp,0,$p);
$t .= ''.$k.'';
$tmp = substr($tmp,$p+$l);
}
$tmp = $t.$tmp;
}
$$str .= $tmp.shift(@str);
}
}
;#
;# エラー
;#
sub searcherror {
print '';
©right;
}