libzipの組み込み
今回は、ZIPファイルの読み込み用のネイティブライブラリとしてlibzipを組み込みます。libzipとは、PHPでのZip関数、ZipArchiveクラスを実装しているライブラリと同様です。しかし現在、PHPのZip機能は古いバージョンを想定されているために、libzipの新しい機能が使えません。
特にパスワード付きZIPファイルの読み込みは必要になる場合があるものの、PHPで標準で備えていないので、このサンプルを通じて、libzipでパスワード付きZIPファイルを読めるサンプルを作成します。
libzipのインストール
PHPでは、libzipはPHPのソースに含まれており、共有としては使いにくい部分があります。また、他のライブラリに影響を与えないように、ここでは、ソースコードからインストールします。
$ wget http://www.nih.at/libzip/libzip-0.11.1.tar.gz $ tar xvfz libzip-0.11.1.tar.gz $ cd libzip-0.11.1 $ sudo -s # ./configure; make; make install
これで、/usr/local/にlibzipがインストールされました。
pkg-configの確認
pkg-configとは、ライブラリをコンパイル、リンクする際のオプション設定を取得するプログラムです。さまざまなライブラリがpkg-config形式に対応しており、ライブラリを組み込む際に便利なので、このpkg-configを利用することを前提にconfig.m4ファイルを編集します。
先ほどインストールしたlibzip用のpkg-configのファイルは/usr/local/lib/pkgconfig/libzip.pcにインストールされます。しかし、デフォルトでは、pkg-configはこのファイルを検索しません。そこで、PKG_CONFIG_PATH=/usr/local/lib/pkgconfigの環境変数を設定します。
また、pkg-configを利用することで、他の利用者がコンパイルする場合にはシステムでインストールされている場所を探し出し、環境に依存しないビルド環境を設定することも容易です。以下のように、pkg-configが正常にlibzipを認識できているか確認します。
$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig $ pkg-config --modversion libzip 0.11.1
バージョン番号が合っていれば問題ありません。もし、違うバージョンが表示された場合には、すでにインストールされているlibzipを参照していますので、PKG_CONFIG_PATHのサーチパスの順番や、正しくパスが設定されているかなど確認してください。
config.m4を変更する
config.m4ファイルは、configureファイルを作成するための設定です。今回は、すでにインストールされていることが前提なので、比較的簡単な記述ですみます。
if test "$PHP_PZIP" != "no"; then AC_MSG_CHECKING(for pkg-config) if test ! -f "$PKG_CONFIG"; then PKG_CONFIG=`which pkg-config` //……(1) fi PHP_NEW_EXTENSION(pzip, pzip.c pzip_file.c pzip_entry.c pzip_stream.c,$ext_shared) PHP_SUBST(PZIP_SHARED_LIBADD) if test -f "$PKG_CONFIG"; then AC_MSG_RESULT(found pkg-config) if $PKG_CONFIG --exists libzip; then // ……(2) AC_MSG_RESULT(pzip : found libzip) ZIP_LIBS=`$PKG_CONFIG --libs libzip` // ……(3) ZIP_INCS=`$PKG_CONFIG --cflags-only-I libzip` // ……(4) AC_MSG_RESULT(libzip includes : $ZIP_INCS) // ……(5) AC_MSG_RESULT(libzip links : $ZIP_LIBS) PZIP_LIBS="$LDFLAGS $ZIP_LIBS" // ……(6) PZIP_INCS="$CFLAGS $ZIP_INCS" // ……(7) PHP_EVAL_INCLINE($PZIP_INCS) // ……(8) PHP_EVAL_LIBLINE($PZIP_LIBS, PZIP_SHARED_LIBADD) // ……(9) else AC_MSG_RESULT(not found libzip) fi fi fi
(1)では、pkg-configの場所を確認しています。次に(2)で、libzipがpkg-configで見つかった場合の処理の処理です。(3)では、リンク時のオプションの取得、(4)では、コンパイル時に必要なincludeするファイルのパスを取得します。(5)のようにAC_MSG_RESULTで、それまでの設定をconfigure時に出力できますので、デバッグ時などに利用できます。また、(6)、(7)ではすでにリンク時のオプションやinclude時のオプションが登録されている場合がありますので、それらを含めた形で再度、変数を作成します。次に、エクステンションのコンパイル時のincludeパスの指定を(8)のPHP_EVAL_INCLINEマクロで行い、(9)のPHP_EVAL_LIBLINEマクロでリンク時のオプションを設定します。
実際に利用する関数の紹介
上記の設定が完了すると、libzipが提供している関数を利用できます。ここで、実際に今回のサンプルで利用する関数の一覧を紹介します。
関数名 | 説明 | 利用しているソース |
---|---|---|
zip_open | ZIPファイルをオープンするときに関数 | pzip_file.c |
zip_close | ZIPファイルをクローズするときに関数 | pzip_file.c |
zip_get_num_files |
ZIPファイルの中にいくつのエントリー(ファイル)が 含まれているかの数を取得する関数 |
pzip_file.c |
zip_discard | zip_openで取得したメモリを解放するための関数 | pzip_file.c |
zip_stat | ZIPファイルのエントリー情報をファイル名から取得する関数 | pzip_file.c |
zip_stat_index |
ZIPファイルのエントリー情報を インデックス(何番目)から取得する関数 |
pzip_file.c |
zip_fopen_index |
ZIPファイル内のファイルディスクリプタを インデックスから取得する関数 |
pzip_file.c |
zip_fopen_index_encrypted |
ZIPファイル内の暗号化されたファイルの ファイルディスクリプタをインデックスから取得する関数 |
pzip_file.c |
zip_fread |
zip_fopen_xxxxxで取得したファイルディスクリプタから データを読みこむ関数 |
pzip_stream.c |