徐々に思い出してきました.
http://www.suzuka-ct.ac.jp/mech/moodle/mod/wiki/view.php?id=320&page=view/lib%2Fmoodlelib.php%2Fzip%E9%96%A2%E9%80%A3
こちらの"(3) unzip_cleanfilename(): 6285行近辺"のところに書いてある内容が関係していそうです.
function unzip_cleanfilename ($p_event, &$p_header) {
//This function is used as callback in unzip_file() function
//to clean illegal characters for given platform and to prevent directory traversal.
//Produces the same result as info-zip unzip.
// (FS_CONVERTER):ZIP/UNZIP/LISTZIPの際のヘッダー情報に含まれるファイル名をカレント文字セットに変換する
// (FS_CONVERTER):unzipする際に日本語ファイル名/フォルダ名中の'\'が'/'に変換されて文字化けする問題の対策
// (FS_CONVERTER):一旦,UTF-8に変換してから処理を行い,再びファイルシステムの文字コードに戻す.
$p_header['filename'] = zipitem2currentCharset($p_header['filename']); // (FS_CONVERTER)
$p_header['filename'] = ereg_replace('
:cntrl:',
, $p_header['filename']); //strip control chars first!
$p_header['filename'] = ereg_replace('\.\.+', , $p_header['filename']); //directory traversal protection
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$p_header['filename'] = ereg_replace('[:*"?<>|]', '_', $p_header['filename']); //replace illegal chars
$p_header['filename'] = ereg_replace('^([a-zA-Z])_', '\1:', $p_header['filename']); //repair drive letter
} else {
//Add filtering for other systems here
// BSD: none (tested)
// Linux: ??
// MacosX: ??
}
$p_header['filename'] = cleardoubleslashes($p_header['filename']); //normalize the slashes/backslashes
$p_header['filename'] = convert2fsCharset($p_header['filename'], 'UTF-8'); // (FS_CONVERTER) (ADD)
return 1;
}
一つ目の赤い行が重要で,2つめの赤い行(convert2fsCharset())はOSのファイルシステムがUTF-8に対応している(Windows以外ですね)ならば不要なはずです.
なお,zipitem2currentCharset($p_header['filename'])は自作の関数で,fs_converter.phpに含まれている以下の関数です.
function zipitem2currentCharset($str)
{
$encoding = mb_detect_encoding($str, 'auto');
$str = mb_convert_encoding($str, 'UTF-8', $encoding);
return $str;
}
あら,fs_moodle固有の機能を取り除いたらシンプルな関数になってしまいましたね.では,これをそのまま組み込んで,以下のように.
function unzip_cleanfilename ($p_event, &$p_header) {
//This function is used as callback in unzip_file() function
//to clean illegal characters for given platform and to prevent directory traversal.
//Produces the same result as info-zip unzip.
$p_header['filename'] = mb_convert_encoding($p_header['filename'], 'UTF-8', 'auto'); // (ADD)
$p_header['filename'] = ereg_replace(':cntrl:', '', $p_header['filename']); //strip control chars first!
$p_header['filename'] = ereg_replace('\.\.+', '', $p_header['filename']); //directory traversal protection
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$p_header['filename'] = ereg_replace('[:*"?<>|]', '_', $p_header['filename']); //replace illegal chars
$p_header['filename'] = ereg_replace('^([a-zA-Z])_', '\1:', $p_header['filename']); //repair drive letter
} else {
//Add filtering for other systems here
// BSD: none (tested)
// Linux: ??
// MacosX: ??
}
$p_header['filename'] = cleardoubleslashes($p_header['filename']); //normalize the slashes/backslashes
return 1;
}