#!/usr/local/bin/perl5
#↑環境に応じて修正の事
#bbs data convert script 2004/11/9-10 abfuku
# Akihiro Katoh氏(WebSite消失)製 TreeTypeBBSから
# りゅういち氏(http://www.cj-c.com/)製 ChildTree掲示板(以下cbbs)へ
# 文書データを変換移行するスクリプト。
# article.dat 及び tree.dat の存在するディレクトリに当cgiを配置。
# (拡張子は.cgiへ・Ascii転送・実行属性追加)
# そして当cgiを一回実行(適当な端末からブラウザ表示)させれば、
# cbbs用データcbbs.datを同一ディレクトリに出力。あとはcbbs側に移動の事。
# 無保証・Noサポート・自己責任でどーぞ
$olddat = "article.dat"; #変更していた場合はここも適時修正
$oldtree = "tree.dat"; #同上
$outdat = "cbbs.dat";
print "Content-type: text/html\n\n";
print "
\n";
print '';
print "\nconvert result\n\n";
print "$olddat & $oldtree -> 変換開始
\n";
open (FP,"<$olddat"); #旧文書情報は最初に一括読み込み
while(){
chop;
($num,$renum,$time,$email,$hp,$name,$title,$comment,$r_h,$cou) = split(/<>/);
$hashart{$num} = $_; #$hashart{} はGlobal利用
$maxnum = $num if($num > $maxnum); #最終文書
}
close(FP);
open(OFP,">$outdat"); #OFPはGlobal利用
print OFP "$maxnum<><><><><><><><><>$maxnum<><><><><>\n";
print "最終文書番号:$maxnum
\n
\n";
#以下 Tree情報を基に Main Loop
open(FP,"<$oldtree");
while(){
# $_=;
chop $_;
$OneLine=substr($_,1); #最初の1文字は省く
#以下、1Tree分の処理
$TreeLevel=0;
$RootNo=int($OneLine);
print "【Tree:$RootNo 処理開始】
\n";
$ResCnt=-1;
while ($OneLine ne ""){ #文字がなくなるまで続ける
$Temp=substr($OneLine,0,1); #1文字調査
if ($Temp eq "("){
$TreeLevel += 1; #「(」なら階層を上げる
$OneLine=substr($OneLine,1); #1文字処理済み
}
elsif ($Temp eq ")"){
$TreeLevel -= 1; #「)」なら階層を下げる
$OneLine=substr($OneLine,1); #1文字処理済み
}
else{ #カッコでない場合はレス番号一つ分処理
$ResCnt+=1;
$TreeInfoNO{$ResCnt}=int($OneLine);
$TreeInfoLV{$ResCnt}=$TreeLevel;
while (substr($OneLine,0,1) =~ /[0-9]/){ #数字を捨てる
$OneLine=substr($OneLine,1); #数字1文字をSkip
}
}
}
#1行分の情報収集終了、以下降順に出力
for($i=$ResCnt;$i>=0;$i=$i-1){
&conv1mes($RootNo,$TreeInfoNO{$i},$TreeInfoLV{$i});
}
}
close(FP);
close(OFP);
print "
\n変換終了 -> $outdat
\n";
print "\n";
#終了
sub conv1mes{
local($RootNo,$MesNo,$LV) = @_;
#引数:$RootNo=Target文書のTreeRoot、$MesNo=Target文書、$LV=その階層
#この情報を基にOFPへ1文書分を変換出力する
#旧文書情報を入手
local($num,$renum,$time,$email,$hp,$name,$title,$comment,$r_h,$fix);
($num,$renum,$time,$email,$hp,$name,$title,$comment,$r_h,$fix)
= split(/<>/,$hashart{$MesNo});
#パラメータ一部修正
if ($LV==0) {$RootNo=0;} #ルート文書の場合はルート指定は0
$LV=$LV * 15 ; #cbbsの仕様にて、階層は15の倍数で表現
if (substr($hp,0,7) eq "http://"){
$hp = substr($hp,7); #WebURLの http:// は省く
}
$r_h.="::1::||||:||||||::"; #IP以外のcbbs用個人情報カラム追加
$comment =~ s/\
/\
/go; #
→
へ
#日付の文字表記変換
local($sec,$min,$hour,$mday,$mon,$year,$wday,$week,$date);
($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime($time);
$year=$year+1900;
$mon++;
if($mon < 10){$mon ="0$mon"; }
if($mday < 10){$mday="0$mday";}
if($hour < 10){$hour="0$hour";}
if($min < 10){$min ="0$min"; }
if($sec < 10){$sec ="0$sec"; }
$week=('Sun','Mon','Tue','Wed','Thu','Fri','Sat') [$wday];
$date="$year\/$mon\/$mday\($week\) $hour\:$min\:$sec";
#cbbs形式で出力
print "NO:$MesNo Level:$LV RootNo:$RootNo Subject:$title
\n";
print OFP "$MesNo<>$date<>$name<>$email<>$title<>$comment<>$hp<>$LV<><>";
print OFP "$RootNo<><>$r_h<>$time<><>\n";
}
#以下参考:両掲示板のデータフォーマット調査結果
#
# 【CBBS】 cbbs.dat 1行1発言、パラメータは<>で区切る
# 一行目のみ、最終発言番号情報 (要らないかも?)
# n<><><><><><><><><>n<><><><><>
#
# 二行目以下
# 1.番号
# 2.投稿日(文字列表記)
# 3.名前
# 4.メアド
# 5.Subject
# 6.本文 (改行は
)※
が大文字だとレス引用が正しく動作せず
# 7.WebURL(http://は省略)
# 8.ルートを0階層とみなし、階層数*15(2階層なら30・10階層なら150)
# 9.Null (というか不明・以下同様)
# 10.属するTreeのルート文書番号(ルート発言は0)
# 11.削除キー(暗号化済み)
# 12.IP+"::1::||||:||||||::" (追加値はcbbs特有の個人情報)
# 13.投稿日(Unix日付型)
# 14.Null
# 15.Null (この後には区切り文字<>は付かない)
#
# Tree単位では新しい順。各Treeの中では、新しい枝の末端
#(見た目上はTree内で下の文書)から逆回帰的(?)に並ぶ。
# 常に枝先→親の順番となり、各Treeの中でRootが最後となる。
# ある行に対して、その後ろで階層値-15のものが親文書となる。
# ※同じTreeの文書群は常に一まとめ
#
# (例1)
# 1−2-4
# └3
# ↓
# 3<>〜中略〜<>15<><>1〜後略〜
# 4<>〜中略〜<>30<><>1〜後略〜
# 2<>〜中略〜<>15<><>1〜後略〜
# 1<>〜中略〜<>0<><>0〜後略〜
#
# (例2)
# 1−2
# └3-4
# ↓
# 4<>〜中略〜<>30<><>1〜後略〜
# 3<>〜中略〜<>15<><>1〜後略〜
# 2<>〜中略〜<>15<><>1〜後略〜
# 1<>〜中略〜<>0<><>0〜後略〜
#
# 【旧TreeBBS(Akihiro Katoh氏制作版)】
# article.dat 1行1発言、パラメータは<>で区切る
#
# 1.番号
# 2.直属の親文書番号(ルートの場合は0)
# 3.投稿日(UNIX日付型)
# 4.メアド
# 5.WebURL(http://付き)
# 6.名前
# 7.Subject
# 8.本文 (改行は
)※こちらは
が大文字な点に注意
# 9.IP
# 10.0 (用途不明)
#
# こちらのファイルはおおよそ作成順に並び、複数Treeの文書が様々に混在。
# 一応、上記の情報のみでTreeの構成は可能であるものの、検索性が悪く処理が
# 重くなる事から、別途ツリー情報収納ファイルが存在。
#
# tree.dat 1行1Tree。
#
# 各番号は"("で区切り、同時に1階層下げる扱いとなる。
# 階層が上がる場合は")"追加。2階層以上上がる場合もその都度複数記述。
# ルートから回帰的に各枝へ進行、同一階層はカッコでくくられる形になる。
# (1Tree内の出現順はcbbsと逆になる)
#
# (例1)
# 1−2-4
# └3
# ↓
# (1(2(4())3))
#
# (例2)
# 1−2
# └3-4
# ↓
# (1(2()3(4())))
#