PEAR::Archive_Zipの実装

phpでzipアーカイブを操作するPEARライブラリ、Archive_Zip(beta)。なかなか便利なんですが、ディレクトリを圧縮しようとしたら無限ループが発生してWebサーバが落ちました。使用バージョンはArchive_Zip 0.1.1(beta)。CentOS4.4で、php5.1.6と4.4.6で確認。

require_once 'Archive/Zip.php';
$zip =& new Archive_Zip($zipName);
$zip->create($dirname);

ほんとにこれだけで死亡。add()でやっても死亡。エラーを表示してみると、/home/user/data/../../../../… みたいな感じで親階層へのリンクが無限ループしている模様。Archive_Zipのエラーが出てるあたりを確かめてみると、

1208|  // ----- Read the directory for files and sub-directories
1209|   $p_hdir = opendir($p_filename);
1210|   $p_hitem = readdir($p_hdir); // '.' directory
1211|   $p_hitem = readdir($p_hdir); // '..' directory
1212|  while ($p_hitem = readdir($p_hdir))

こんな感じでディレクトリを回す前に、. と .. をスキップする予定になっているようです。

ところがウチの環境だと、. と .. が先頭じゃなくて途中で出てきてスキップできずに地雷を踏む、という挙動になってしまったようです。何故先頭じゃないのかは知らないけど、先頭にあると決め打ちする実装もいかがなものかと。

で、最初にスキップせずに、ループ内で . と .. をスキップするようにしてみたら、今度はディレクトリ内のファイルがアーカイブに登録されないという症状が。

この時点で面倒になったので調査打ち切り。ディレクトリじゃなくてファイルの一覧を投げてやった場合は正しく動作するので、ディレクトリを再帰的にたどって自前でファイル名の一覧を生成して、それをArchive_Zipに投げて終了としました。

このパッケージ自体、2005年11月に今のbetaが上がってから進展が無い上にドキュメントも整備されてないので、騙し騙しやっていくぐらいがいい付き合い方なのかなー