#!/usr/bin/perl
###############################################################################
#
# ::FreeStyleWiki
#
# Wiki::DatabaseStorage 移行スクリプト
#
###############################################################################
BEGIN {
if(exists $ENV{MOD_PERL}){
# カレントディレクトリの変更
chdir($ENV{FSWIKI_HOME});
}
}
#==============================================================================
# モジュールのインクルード
#==============================================================================
use Cwd;
use lib ('./dev','./lib');
use strict;
use CGI2;
use Wiki;
use Util;
use Jcode;
use HTML::Template;
# これをやらないとApache::Registoryで動かない
if(exists $ENV{MOD_PERL}){
eval("use Digest::Perl::MD5;");
eval("use plugin::core::Diff;");
eval("use plugin::pdf::PDFMaker;");
&Jcode::load_module("Jcode::Unicode");
}
#==============================================================================
# CGIとWikiのインスタンス化
#==============================================================================
my $cgi = CGI2->new();
my $wiki = Wiki->new($cgi,'setup.dat');
# ストレージをデフォルトに変更する
$wiki->{"storage"}->finalize();
$wiki->{"storage"} = Wiki::DefaultStorage->new($wiki);
# スクリプト名の上書き
$wiki->config("script_name","wikidb.cgi");
# データベース作成用のインスタンス生成
my $wikidb = Wiki::DB->new();
eval {
# Session用ディレクトリはFarmでも共通に使用する
$wiki->config('session_dir',$wiki->config('log_dir'));
#==============================================================================
# Farmとして動作する場合
#==============================================================================
my $path_info = $cgi->path_info();
my $path_count = 0;
if(length($path_info) > 0){
# PATH_INFOの最後が/だったら/なしのURLに転送する
if($path_info =~ m|/$|) {
$path_info =~ s|/$||;
$wiki->redirectURL($cgi->url().$path_info);
}
$path_info =~ m([^/]+)$>;
$wiki->config('script_name', $1);
$wiki->config('data_dir' , $wiki->config('data_dir' ).$path_info);
$wiki->config('config_dir' , $wiki->config('config_dir').$path_info);
$wiki->config('backup_dir' , $wiki->config('backup_dir').$path_info);
$wiki->config('log_dir' , $wiki->config('log_dir' ).$path_info);
}
#==============================================================================
# 設定を反映(もうちょっとスマートにやりたいね)
#==============================================================================
my $config = &Util::load_config_hash($wiki,$wiki->config('config_file'));
foreach my $key (keys(%$config)){
$wiki->config($key,$config->{$key});
}
# キャッシュの設定を反映
my $cache_config = &Util::load_config_hash($wiki,'cache.dat');
$wiki->config('use_cache' ,$cache_config->{use_cache});
$wiki->config('no_cache' ,$cache_config->{no_cache});
$wiki->config('remove_cache',$cache_config->{remove_cache});
#==============================================================================
# タイムアウトしているセッションを破棄
#==============================================================================
$cgi->remove_session($wiki);
#==============================================================================
# ユーザ情報の読み込み
#==============================================================================
my $users = &Util::load_config_hash($wiki,$wiki->config('userdat_file'));
foreach my $id (keys(%$users)){
my ($pass,$type) = split(/\t/,$users->{$id});
$wiki->add_user($id,$pass,$type);
}
#==============================================================================
# プラグインのインストールと初期化
#==============================================================================
# 最低限のプラグインのみインストールする
my @plugins = split(/,/,"admin,core,info");
my $plugin_error = '';
foreach(sort(@plugins)){
$plugin_error .= $wiki->install_plugin($_);
}
# プラグインごとの初期化処理を起動
$wiki->do_hook("initialize");
#==============================================================================
# アクションハンドラの呼び出し
#==============================================================================
my ($action, $content);
$action = $cgi->param("action");
$action = (!defined($action))?"LOGIN":$action;
my $login = $wiki->get_login_info();
# 未ログインの場合はログイン処理を行う。
if ( !defined($login) ) {
$action = "LOGIN";
$content = $wiki->call_handler($action);
}
# ログアウト時はログイン画面に戻す
elsif( $action eq "LOGIN" && defined($cgi->param('logout')) ) {
$content = $wiki->call_handler($action);
$wiki->redirectURL($wiki->config('script_name')."?action=LOGIN");
}
# 管理者でない場合はログアウト処理を行う。
elsif( $login->{type} != 0 ) {
$action = "LOGIN";
$cgi->param('logout','1');
$wiki->call_handler($action);
$cgi->param('logout',"");
$wiki->{'login_info'} = undef;
$content = "
管理者でログインしてください。
";
$content .= $wiki->call_handler($action);
}
# 管理者ログイン時は移行画面を表示する
else {
if ( $action eq "MAKEDB" ){
$content .= $wikidb->make_db($wiki);
}
else {
$content .= "".$wikidb->get_logout_form($wiki)."\n
\n";
$content .= $wikidb->get_db_config_form($wiki)."\n";
$content .= $wikidb->get_db_cmd_form($wiki);
}
}
# プラグインのインストールに失敗した場合
$content .= $plugin_error . $content if $plugin_error ne '';
#==============================================================================
# レスポンス
#==============================================================================
# ページのタイトルを決定
my $title = "Wiki Database Storage 作成ツール";
my $output = "";
my $tmpl = $wikidb->get_template($wiki);
my $template = HTML::Template->new(
scalarref => \$tmpl,
die_on_bad_params => 0,
loop_context_vars => 1,
global_vars => 1);
$template->param(TITLE => $title, CONTENTS => $content);
$output = $template->output();
#------------------------------------------------------------------------------
# 出力処理
#------------------------------------------------------------------------------
# ヘッダの出力
print "Content-Type: text/html;charset=EUC-JP\n";
print "Pragma: no-cache\n";
print "Cache-Control: no-cache\n\n";
# HTMLの出力
print $output;
};
my $msg = $@;
$ENV{'PATH_INFO'} = undef;
$wiki->_process_before_exit();
if($msg && index($msg, 'safe_die')<0){
$msg = Util::escapeHTML($msg);
print "Content-Type: text/html\n\n";
print "Software Error ";
print "Software Error: $msg
";
}
1;
package Wiki::DB;
use File::Path;
use DBI;
use strict;
#==============================================================================
# コンストラクタ
#==============================================================================
sub new {
my $class = shift;
my $self = {};
return bless $self,$class;
}
sub get_template {
my $self = shift;
my $wiki = shift;
return <<__EOD__;
__EOD__
}
sub get_logout_form {
my $self = shift;
my $wiki = shift;
my $script = $wiki->config('script_name');
return <<__EOD__;
__EOD__
}
sub get_db_config_form {
my $self = shift;
my $wiki = shift;
my $script = $wiki->config('script_name');
my $driver = $wiki->{config}->{db_driver};
my $drh = DBI->installed_versions($driver);
return <<__EOD__;
データベースの操作
データベース接続への設定は以下のようになっています。
設定項目 設定値
DBI $drh->{'DBI'}
DBドライバ $wiki->{config}->{db_driver} - $drh->{'DBD::'.$driver}
DBディレクトリ $wiki->{config}->{db_dir}
DB名 $wiki->{config}->{db_name}
DBユーザー $wiki->{config}->{db_user}
DBパスワード $wiki->{config}->{db_pass}
__EOD__
}
sub get_db_cmd_form {
my $self = shift;
my $wiki = shift;
my $script = $wiki->config('script_name');
return <<__EOD__;
__EOD__
}
sub make_db {
my $self = shift;
my $wiki = shift;
my $html = "";
eval {
my $wikifarm = $self->get_wikifarm_instance($wiki, $wiki->get_CGI()->param('farm'));
if (defined($wikifarm)){
if (! -d $wiki->config('db_dir').$wikifarm->get_CGI->path_info() ) {
mkpath($wiki->config('db_dir').$wikifarm->get_CGI->path_info());
}
$html .= $self->db_transition($wikifarm);
} else {
return "Wikiインスタンスの作成に失敗しました。"
}
$wikifarm->_process_before_exit();
};
if($@){
return $html." $@";
}
return $html." "."正常に終了しました。";
}
sub db_transition {
my $self = shift;
my $wiki = shift;
my $hDB = shift;
my ($sql,$hst,$hst1,$hst2) = undef;
my $html = "";
$html .= "\n";
my $pathinfo = $wiki->get_CGI->path_info();
my $dbname = $wiki->config('db_dir').$pathinfo."/".$wiki->config('db_name');
$html .= "データベース接続[dbi:".$wiki->config('db_driver').":dbname=".$dbname."]";
$hDB = DBI->connect("dbi:".$wiki->config('db_driver').":dbname=".$dbname,"","",{PrintError=>0});
if (!$hDB) { $html .= " NG - ".$DBI::errstr." \n"; }; $html .= " OK\n";
eval {
$sql = {
# Drop
data_drp => "DROP TABLE data_tbl",
backup_drp => "DROP TABLE backup_tbl",
attr_drp => "DROP TABLE attr_tbl",
access_drp => "DROP TABLE access_tbl",
data_drp_idx_1 => "DROP INDEX data_idx_1",
backup_drp_idx_1 => "DROP INDEX backup_idx_1",
attr_drp_idx_1 => "DROP INDEX attr_idx_1",
attr_drp_idx_2 => "DROP INDEX attr_idx_2",
access_drp_idx_1 => "DROP INDEX access_idx_1",
access_drp_idx_2 => "DROP INDEX access_idx_2",
# Table
data_tbl => "CREATE TABLE data_tbl (page text, source text, lastmodified bigint)",
backup_tbl => "CREATE TABLE backup_tbl (page text, source text, lastmodified bigint)",
attr_tbl => "CREATE TABLE attr_tbl (page text, key text, val text, lastmodified bigint)",
access_tbl => "CREATE TABLE access_tbl (page text, datetime text, remote_addr text, referer text, user_agent text, lastmodified bigint)",
# Index
data_idx_1 => "CREATE UNIQUE INDEX data_idx_1 ON data_tbl (page)",
backup_idx_1 => "CREATE UNIQUE INDEX backup_idx_1 ON backup_tbl (page, lastmodified DESC)",
attr_idx_1 => "CREATE UNIQUE INDEX attr_idx_1 ON attr_tbl (page, key)",
attr_idx_2 => "CREATE UNIQUE INDEX attr_idx_2 ON attr_tbl (key, page)",
access_idx_1 => "CREATE INDEX access_idx_1 ON access_tbl (lastmodified DESC)",
access_idx_2 => "CREATE INDEX access_idx_2 ON access_tbl (page, datetime DESC)",
# Insert
data_ins => "INSERT INTO data_tbl VALUES(?, ?, ?)",
backup_ins => "INSERT INTO backup_tbl VALUES(?, ?, ?)",
attr_ins => "INSERT INTO attr_tbl VALUES(?, ?, ?, ?)",
};
# インデックス/テーブルの削除
$hst = $hDB->do($sql->{data_drp_idx1});
$hst = $hDB->do($sql->{backup_drp_idx1});
$hst = $hDB->do($sql->{attr_drp_idx1});
$hst = $hDB->do($sql->{attr_drp_idx2});
$hst = $hDB->do($sql->{access_drp_idx1});
$hst = $hDB->do($sql->{access_drp_idx2});
$hst = $hDB->do($sql->{data_drp});
$hst = $hDB->do($sql->{backup_drp});
$hst = $hDB->do($sql->{attr_drp});
$hst = $hDB->do($sql->{access_drp});
# ページ情報テーブル/インデックス
$html .= "".$sql->{data_tbl}; $hst = $hDB->do($sql->{data_tbl}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
$html .= "".$sql->{data_idx_1}; $hst = $hDB->do($sql->{data_idx_1}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
# バックアップ用テーブル/インデックス
$html .= "".$sql->{backup_tbl}; $hst = $hDB->do($sql->{backup_tbl}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
$html .= "".$sql->{backup_idx_1}; $hst = $hDB->do($sql->{backup_idx_1}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
# ページ属性テーブル/インデックス
$html .= "".$sql->{attr_tbl}; $hst = $hDB->do($sql->{attr_tbl}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
$html .= "".$sql->{attr_idx_1}; $hst = $hDB->do($sql->{attr_idx_1}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
$html .= "".$sql->{attr_idx_2}; $hst = $hDB->do($sql->{attr_idx_2}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
# アクセスログ・テーブル/インデックス
$html .= "".$sql->{access_tbl}; $hst = $hDB->do($sql->{access_tbl}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
$html .= "".$sql->{access_idx_1}; $hst = $hDB->do($sql->{access_idx_1}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
$html .= "".$sql->{access_idx_2}; $hst = $hDB->do($sql->{access_idx_2}); if (!$hst) { $html .= " NG - ".$DBI::errstr." \n"; die; }; $html .= " OK\n";
my @list = $wiki->get_page_list({-sort => 'name'});
$html .= "ページ数:".$#list;
$hst1 = $hDB->prepare($sql->{data_ins});
die "$DBI::errstr " if (!$hst1);
$hst2 = $hDB->prepare($sql->{attr_ins});
die "$DBI::errstr " if (!$hst2);
foreach my $page (@list) {
# ページの登録
$hst1->execute($page, $wiki->get_page($page), $wiki->get_last_modified2($page) );
# ページ・レベルの登録
my $level = $wiki->get_page_level($page);
$hst2->execute($page, "page_level", $level, time() ) if ( $level > 0 );
# 凍結情報の登録
my $freeze = $wiki->is_freeze($page);
$hst2->execute($page, "freeze", $freeze, time() ) if ( $freeze > 0 );
# # タイトル情報の登録
# my @title = grep(/^{{title .+}}$/, split(/\n/,$wiki->get_page($page)));
# if ( $#title >= 0 ) {
# $title[0] =~ s/{{title (.+)}}$/$1/;
# $hst2->execute($page, "title", $title[0], time());
# }
}
$html .= " OK ";
}; # eval
if ($@) {
$html .= " エラーが発生しました。 - $@";
}
$hst1->finish() if ($hst1);
$hst2->finish() if ($hst2);
if ($hDB) {
$hDB->disconnect();
}
$html .= " \n";
return $html;
}
#===========================================================
# 指定された WikiFarm 環境のインスタンスを生成します。
# ここで指定する $farm は絶対パスである必要があります。
# この関数は farmlink から流用しています。
#===========================================================
sub get_wikifarm_instance {
my $self = shift;
my $rwiki = shift;
my $farm = shift;
# WikiFarm キャッシュから取得する
my $wiki = undef;
# InterWikiとKeyword情報のバックアップ
my $interwiki = $Wiki::Parser::interwiki;
my $keyword = $Wiki::Parser::keyword;
#-----------------------------------------------------------
# WikiFarm用のwikiインスタンス作成
#-----------------------------------------------------------
eval {
my $cgi = CGI2->new();
# ルートWikiへの相対パスの取得
my $relative_path = $cgi->path_info();
$relative_path =~ s/[^\/]*//g;
$relative_path =~ s/\//..\//g;
# PATH_INFOの上書き
$cgi->path_info($farm);
# pageの上書き
$cgi->param('page',"#farmlink");
$wiki = Wiki->new($cgi,'setup.dat');
# ストレージをデフォルトに変更する
$wiki->{"storage"}->finalize();
$wiki->{"storage"} = Wiki::DefaultStorage->new($wiki);
# 子Wiki呼出情報の引継ぎ
$wiki->{farmlink} = $rwiki->{farmlink};
# Session用ディレクトリはFarmでも共通に使用する
$wiki->config('session_dir',$wiki->config('log_dir'));
# Farmとして動作する設定
my $path_count = 0;
$wiki->config('script_name', $relative_path.$wiki->config('script_name').$farm);
$wiki->config('data_dir' , $wiki->config('data_dir' ).$farm);
$wiki->config('config_dir' , $wiki->config('config_dir').$farm);
$wiki->config('backup_dir' , $wiki->config('backup_dir').$farm);
$wiki->config('log_dir' , $wiki->config('log_dir' ).$farm);
if(!($wiki->config('theme_uri') =~ /^(\/|http:|https:|ftp:)/)){
my @paths = split(/\//,$farm);
$path_count = $#paths;
for(my $i=0;$i<$path_count;$i++){
$wiki->config('theme_uri','../'.$wiki->config('theme_uri'));
}
}
# 設定を反映
my $config = &Util::load_config_hash($wiki,$wiki->config('config_file'));
foreach my $key (keys(%$config)){
$wiki->config($key,$config->{$key});
}
# 個別に設定が必要なものだけ上書き
$wiki->config('css' ,$wiki->config('theme_uri')."/".$config->{theme}."/".$config->{theme}.".css");
$wiki->config('site_tmpl' ,$wiki->config('tmpl_dir')."/site/".$config->{site_tmpl_theme}."/".$config->{site_tmpl_theme}.".tmpl");
$wiki->config('site_handyphone_tmpl' ,$wiki->config('tmpl_dir')."/site/".$config->{site_tmpl_theme}."/".$config->{site_tmpl_theme}."_handyphone.tmpl");
# キャッシュの設定を反映
my $cache_config = &Util::load_config_hash($wiki,'cache.dat');
$wiki->config('use_cache' ,$cache_config->{use_cache});
$wiki->config('no_cache' ,$cache_config->{no_cache});
$wiki->config('remove_cache',$cache_config->{remove_cache});
# InterWikiとKeyword情報の再作成
$Wiki::Parser::interwiki = Wiki::InterWiki->new($wiki);
$Wiki::Parser::keyword = Wiki::Keyword->new($wiki,$Wiki::Parser::interwiki);
# InterWikiとKeyword情報の保管
$wiki->{interwiki} = $Wiki::Parser::interwiki;
$wiki->{keyword} = $Wiki::Parser::keyword;
# プラグインのインストールと初期化
### my @plugins = split(/\n/,&Util::load_config_text($wiki,$wiki->config('plugin_file')));
# 最低限のプラグインのみインストールする
my @plugins = split(/,/,"admin,core,info");
my $plugin_error = '';
foreach(sort(@plugins)){
$plugin_error .= $wiki->install_plugin($_);
}
# プラグインごとの初期化処理を起動
$wiki->do_hook("initialize");
};
# InterWikiとKeyword情報のレストア
$Wiki::Parser::interwiki = $interwiki;
$Wiki::Parser::keyword = $keyword;
if ( defined($wiki) ) {
# Wiki インスタンスのキャッシュ登録
$rwiki->{wikifarm}->{$farm} = $wiki;
# Wiki インスタンスのキャッシュ情報の引継ぎ
$wiki->{wikifarm} = $rwiki->{wikifarm};
}
return $wiki;
}
1;