* @version $Id: data2utf8.php,v 0.2 2005/06/08 23:46:00 upk Exp $ * @license http://opensource.org/licenses/gpl-license.php GNU Public License * @link http://jo1upk.blogdns.net/saito/ * * == 使用方法 == * 1. バックアップをとる * 2. PukiWiki Plus! I18N のファイルを展開する * 3. 2.で展開したところに、現在、稼動していた(EUC-JPの)データを上書きする * 4. 通常 PukiWiki を設定しているように DATA_HOME の定義 * 5. data2utf8.php.TXT を必要ならば data2utf8.php にリネームする * 6. 実行 * php -f data2utf8.php * * == ブラウザから実行する場合 == * 権限上の問題があるので、 * .htaccess などの定義を適宜変更する必要がある。 * 恐らく plugin ディレクトリなどでエラーが出るはず。 * 変換処理時のみ、.htaccess を消すなりして実行する。 * * == タイムアウトの場合 == * stage1 までの場合は、何度でも再実行できるようにしています。 * 以下の ini_set() の値を変更して反映される環境の場合は、適当に大きな値に * 変更して実行する方法もあります。 * * == 最後に == * 失敗しても、責任は取りかねますので、ご注意下さい。 * */ ini_set("max_execution_time", "360"); // デフォルトは、30秒。とりあえず 6分に設定。 ini_set("memory_limit", "32M"); // デフォルトは、8M。 /* ************************************************************************** * * 稼動条件の定義(各自必ず変更して利用下さい) * * ************************************************************************** */ define('DATA_HOME', ''); // pukiwiki.ini.php で定義している内容と異なる場合には、各自変更して下さい。 define('DATA_DIR', DATA_HOME . 'wiki/' ); // Latest wiki texts define('DIFF_DIR', DATA_HOME . 'diff/' ); // Latest diffs define('BACKUP_DIR', DATA_HOME . 'backup/' ); // Backups define('CACHE_DIR', DATA_HOME . 'cache/' ); // Some sort of caches define('UPLOAD_DIR', DATA_HOME . 'attach/' ); // Attached files and logs define('COUNTER_DIR', DATA_HOME . 'counter/' ); // Counter plugin's counts define('TRACKBACK_DIR', DATA_HOME . 'trackback/'); // TrackBack logs /* ************************************************************************** * * 変換処理の定義 * * ************************************************************************** */ $do_true = 1; // 変換処理実行 $do_false = 0; // 変換処理迂回 // PukiWiki Plus! I18N などを利用する場合には、0 にします。 $do_opt = 0; // オプション // pukiwiki.ini.php と同じ設定でOKです。 $do_backup = 1; // バックアップを実施している場合は 1 です。 $trackback = 1; // TrackBack で蓄積したファイルを変換するなら1 です。 $referer = 1; // Referer で蓄積したファイルを変換するなら1 です。 if (extension_loaded('zlib')) { define('BACKUP_EXT', '.gz'); } else { define('BACKUP_EXT', '.txt'); } // JCODE を利用する場合にのみ定義を有効にして下さい。 // ちなみに、ちゃんとしたテストはしていません。 // define('JCODE_DIR', ''); // define('JCODE_DIR', '/mnt/home/katsumi/pw/Plus!/jcode_1.35a/'); if (!defined('LOG_DIR')) { define('LOG_DIR', DATA_HOME . 'log/'); } // 存在していないディレクトリ(ロギングなど)を有効にしても、エラーを出さず終了 // します。あまり気にしないで結構です。 // 各種ディレクトリの定義リスト $config_dir = array( // 0:key 1:処理判定 2:ディレクトリ 3:拡張子 // 4:ファイル名変更 - 0:しない 1:する // 5:ファイル内容変更 - 0:しない 1:する array('diff', $do_true, DIFF_DIR, '.txt', 1,1), array('wiki', $do_true, DATA_DIR, '.txt', 1,1), array('counter', $do_true, COUNTER_DIR, '.count', 1,1), array('attach', $do_true, UPLOAD_DIR, '.log', 1,1), array('attach', $do_true, UPLOAD_DIR, '', 1,0), array('attach', $do_opt, UPLOAD_DIR . 'thumbnail/', '', 1,0), // img2 array('cache', $do_true, CACHE_DIR, '.ref', 1,1), array('cache', $do_true, CACHE_DIR, '.rel', 1,1), array('cache', $do_true, CACHE_DIR, '.tmp', 1,1), array('cache', $do_true, CACHE_DIR, '.dat', 0,1), array('cache', $do_true, CACHE_DIR, '.lite', 0,1), // amazon array('cache', $do_true, CACHE_DIR, '.tit', 0,1), // amazon array('cache', $do_true, CACHE_DIR, '.heavy', 0,1), // amazon // 現在の稼動状況に依存 array('backup', $do_backup, BACKUP_DIR, BACKUP_EXT, 1,1), array('trackback', $trackback, TRACKBACK_DIR, '.txt', 1,1), array('referer', $referer, TRACKBACK_DIR, '.ref', 1,0), // とりあえず、実行しない // array('cache', $do_opt, CACHE_DIR . 'html/', '.htm', 1,1), // showhtml // array('cache', $do_opt, CACHE_DIR . 'html/', '.lst', 1,1), // showhtml // array('cache', $do_opt, CACHE_DIR . 'html/', '', 1,0), // showhtml // array('log', $do_opt, LOG_DIR . 'browse/', '.txt', 1,1), // logging // array('log', $do_opt, LOG_DIR . 'download/', '.txt', 1,1), // do // array('log', $do_opt, LOG_DIR . 'update/', '.txt', 1,1), // do ); /* ************************************************************************** * * 実行の本体 * * ************************************************************************** */ /** * 文字コード変換処理 * PHPの素を利用するか、JCODEを利用するかを決定する。 */ if (defined('JCODE_DIR')) { require(JCODE_DIR . 'jcode.php'); function _euc2utf8($str) { return JcodeConvert($str, 1, 4); } } else { function _euc2utf8($x) { return mb_convert_encoding($x,'utf-8','EUC-JP'); } } $sub_dir = 'utf8_file/'; echo "
\n";
if (! stage_0() ) return;
if (! stage_1() ) return;
if (! stage_2() ) return;
echo "
\n"; /* ************************************************************************** * * 処理関数の定義 * * ************************************************************************** */ /** * 環境設定準備 * 所定の各ディレクトリに、処理用サブディレクトリを作成する */ function stage_0() { global $config_dir, $sub_dir; $sw = 0; echo "stage 0: start\n"; foreach($config_dir as $func) { if (!$func[1]) continue; if (! file_exists($func[2])) continue; // 存在していない場合 $dir = $func[2] . $sub_dir; if (file_exists($dir)) continue; if (mkdir($dir,0777)) { $sw = 1; echo "stage 0: makedir " . $dir . "\n"; } else { echo "stage 0: " . $func[0] . " - Permission denied.\n"; return 0; } } echo $sw ? "stage 0: complete\n" : "stage 0: Bypass\n"; return 1; } /** * ファイル名変更 * EUC-JP で生成されたファイルを UTF-8 に変換する。 * 拡張子が .php に関しては、ファイル名の変更を迂回する。 */ function stage_1() { global $config_dir, $sub_dir; $sw = 0; echo "stage 1: start\n"; foreach($config_dir as $func) { // 1:処理判定 if (!$func[1]) continue; if (! file_exists($func[2])) continue; // 存在していない場合 echo "stage 1: " . $func[0] . "(" . $func[3] . ") start\n"; // 4:ファイル名変更 - 0:しない 1:する if ($func[4]) { $func_name1 = 'get_existpages'; $func_name2 = 'pw_mv'; } else { $func_name1 = 'get_existfile'; $func_name2 = 'mv'; } // 2:ディレクトリ 3:拡張子 $files = $func_name1($func[2], $func[3]); foreach($files as $file => $name) { // 5:ファイル内容変更 - 0:しない 1:する if (! $func_name2($func[0], $func[5], $func[2], $func[2] . $sub_dir, $file)) return 0; $sw = 1; } } echo $sw ? "stage 1: complete\n" : "stage 1: Bypass\n"; return 1; } /** * 終止処理 * 元あった場所に戻す */ function stage_2() { global $config_dir, $sub_dir; $sw = 0; echo "stage 2: start\n"; foreach($config_dir as $func) { // 1:処理判定 if (!$func[1]) continue; if (! file_exists($func[2])) continue; // 存在していない場合 echo "stage 2: " . $func[0] . "(" . $func[3] . ") move start\n"; // 4:ファイル名変更 - 0:しない 1:する $func_name1 = ($func[4]) ? 'get_existpages' : 'get_existfile'; // 2:ディレクトリ 3:拡張子 $files = $func_name1($func[2].$sub_dir, $func[3]); // ファイルの取得 foreach($files as $file => $name) { // 5:ファイル内容変更 - 0:しない 1:する // mv($key, $conv, $olddir, $newdir, $filename) if (! mv($func[0], 0, $func[2].$sub_dir, $func[2], $file)) return 0; $sw = 1; } } foreach($config_dir as $func) { // 1:処理判定 if (!$func[1]) continue; if (! file_exists($func[2])) continue; // 存在していない場合 echo "stage 2: " . $func[0] . "(" . $func[3] . ") rmdir start\n"; @rmdir($func[2].$sub_dir); // 作業ディレクトリを消す } echo $sw ? "stage 2: complete\n" : "stage 2: Bypass\n"; return 1; } /** * ファイル名取得(単純ファイル名) */ function get_existfile($dir = DATA_HOME, $ext = '.php') { $aryret = array(); $pattern = '[\d\w\.]+'; if ($ext != '') $ext = preg_quote($ext, '/'); $pattern = '/^' . $pattern . $ext . '$/'; $dp = @opendir($dir) or die($dir . ' is not found or not readable.'); $matches = array(); while ($file = readdir($dp)){ if (preg_match($pattern, $file, $matches)){ $aryret[$file] = ""; } } closedir($dp); return $aryret; } /** * encode()されている文字を変換してファイルを移動する */ function pw_mv($key, $conv, $olddir, $newdir, $filename) { @list($file1, $ext) = explode('.', $filename); $ext = (empty($ext)) ? "" : "." . $ext; $oldname = $olddir . $filename; if ($key == 'attach') { @list($page, $file2) = explode('_', $file1); $utf8_page = _euc2utf8( decode($page) ); $utf8_file = _euc2utf8( decode($file2) ); $enc_name = encode($utf8_page) . "_" . encode($utf8_file) . $ext; $newname = $newdir . $enc_name; } else { $utf8_file = _euc2utf8( decode($file1) ); $enc_name = encode($utf8_file) . $ext; $newname = $newdir . $enc_name; } return _mv($key, $conv, $oldname, $newname); } /** * ファイルの単純移動 */ function mv($key, $conv, $olddir, $newdir, $filename) { $oldname = $olddir . $filename; $newname = $newdir . $filename; return _mv($key, $conv, $oldname, $newname); } /* * ファイルの単純移動 */ function _mv($key, $conv, $oldname, $newname) { // 5:ファイル内容変更 - 0:しない 1:する if (!$conv) { $rc = rename($oldname, $newname); if (!$rc) echo "_mv: RENAME ERROR! ". $oldname . "\n"; return $rc; } $rc = utf8_write($key, $oldname, $newname); if ($rc) { $rc = unlink($oldname); if (!$rc) echo "_mv: UNLINK ERROR! ". $oldname . "\n"; // 処理は続行 return 1; } else { if (!$rc) echo "_mv: CONVERT ERROR! ". $oldname . "\n"; return $rc; } } function utf8_write($key, $oldname, $newname) { @list($file1, $ext) = explode('.', $oldname); $oldname_time = @filemtime($oldname); // 最終更新日時の取得 if ($key == 'backup' && $ext == 'gz') { $sw_gz = 1; $f_open = 'gzopen'; $f_close = 'gzclose'; $f_file = 'gzfile'; $f_write = 'gzwrite'; } else { $sw_gz = 0; $f_open = 'fopen'; $f_close = 'fclose'; $f_file = 'file'; $f_write = 'fwrite'; } // showhtml用 $sw_lst = ($key == 'cache' && $ext == 'lst') ? 1 : 0; $data = $f_file($oldname); if (!($fp = $f_open($newname,'w'))) { echo "utf8_write: OPEN ERROR! ". $newname . "\n"; return 0; // ERROR } if (!$sw_gz) @flock($fp, LOCK_EX); foreach($data as $x) { if ($sw_lst) { @list($sh_file, $sh_time) = explode(' ', $x); @list($sh_body, $sh_ext) = explode('.', $sh_file); $wk = encode( _euc2utf8( decode($sh_body) ) ) . "." . $sh_ext . " " . $sh_time; } else { $wk = _euc2utf8($x); } $f_write($fp, $wk); } if (!$sw_gz) @flock($fp, LOCK_UN); @$f_close($fp); @touch($newname, $oldname_time); // 最終更新日時に戻す return 1; } /* ************************************************************************** * 本体関数 * * ************************************************************************** */ // 全ページ名を配列に function get_existpages($dir = DATA_DIR, $ext = '.txt') { $aryret = array(); $pattern = '^((?:[0-9A-F]{2})+)'; if ($ext != '') $pattern .= preg_quote($ext, '/') . '$'; $dp = @opendir($dir) or die($dir . ' is not found or not readable.'); $matches = array(); while ($file = readdir($dp)) { if (preg_match("/$pattern/", $file, $matches)) $aryret[$file] = decode($matches[1]); } closedir($dp); return $aryret; } // ページ名のエンコード function encode($key) { return ($key == '') ? '' : strtoupper(bin2hex($key)); // Equal to strtoupper(join('', unpack('H*0', $key))); // But PHP 4.3.10 says 'Warning: unpack(): Type H: outside of string in ...' } // ページ名のデコード function decode($key) { return ($key == '') ? '' : substr(pack('H*', '20202020' . $key), 4); } /* ************************************************************************** * * 定義終了 * * ************************************************************************** */ ?>