PHP5.2.8, 5.2.9

PHP5.2.8, 5.2.9

by Tatsuya Shirai -
Number of replies: 8

 そろそろMoodle2.0の調査を始めようかと思います.

 そのためにはPHPを5.2.8にバージョンアップしなくてはなりません.ところが気づけばPHPは5.2.9にバージョンアップしてしまい,本家のDownloadには存在しません.

 ところが5.2.8から5.2.9にマイナーバージョンアップを行った過程で,関数の互換性が失われたとの情報もあります.
http://d.hatena.ne.jp/hnw/20090228

 どうでしょうか,Moodleは影響を受けないでしょうか.既にPHP5.2.9にバージョンアップをした方はいるでしょうか? 特に問題は無いでしょうか?


array_unique()関数自体はかなり多くの箇所で用いられていますねぇ.

Maximum rating: -
In reply to Tatsuya Shirai

Re: PHP5.2.8, 5.2.9

by Tatsuya Shirai -

 moodle.orgで公開しているWindows用パッケージ(xampp, Moodle2.0)のPHPを使えば良いことに気づきました.Apacheは2.2.11(これはwww.apache.orgのミラーサイトから入手したインストーラーパッケージ)とPHP5.2.8にバージョンアップ完了しました.

 なお,Windows用パッケージに同梱されているeAccelerator.dllはPHP5.2.8用のものでは無いようです.Apacheの起動に失敗しました.他のサイトで公開されているコンパイル済みのDLLをダウンロードしてPHP/extフォルダに上書きしたらApacheが起動するようになりましたので.紛らわしい.

In reply to Tatsuya Shirai

Re: PHP5.2.8, 5.2.9

by Tatsuya Shirai -

 デフォルトのphp.iniでは,php_pdf.dllをextensionで読み込む設定になっているのに,php_pdf.dllが同梱されていません.PECLのWindowsバイナリの配布元が一時的に閉鎖中のようですが,なんとかhttp://jp2.php.net/get/pecl-5.2.6-Win32.zip/from/a/mirrorにてPHP5.2.6用がダウンロードできるようです.

 ところがこの中にphp_pdf.dllは含まれておらず,代わりにphp_pdflib.dllが含まれている.変更になったのだろうか? 調べたが情報が無い.上記URLの5.2.6を5.2.5に変えてPHP5.2.5用のPECLバイナリをダウンロードしたところ,こちらにはphp_pdf.dllが入っていた.これで良いのか? よく分からないので,自己責任で判断して下さい.とりあえず私は5.2.5用のphp_pdf.dllをphp/extにコピーしてみましたが...

In reply to Tatsuya Shirai

escapeshellarg()の挙動がPHP5.2.8でおかしい?

by Tatsuya Shirai -

 先週末にPHPを5.2.0から5.2.8にアップデートしたら,急にバックアップに失敗するようになりました.全てではなく4つのコースのみです.そのうちの一つは少なくともここしばらくは誰もコースに入っていないと思われる動きの少ないコースです.でも,まぁ,そういうこともあるかな?程度に軽く考えていました.

 それとは別件で,Wikiのエクスポートを久しぶりに使ったらzip書庫の作成に失敗しました.そして調査を進めて行くと,どうやらバックアップの失敗も同じzip書庫の作成に失敗していることが原因のようであることが分かってきました.

 近頃はpclzipライブラリではなく,外部のzipプログラムを使っています.これを試しにpclzipを使うように,$CFG->zipを空に設定してみたところ,バックアップもエクスポートも成功します.内部と外部のzip手順の違いを調べて行く過程で,escapeshellarg()関数の挙動がおかしいことに気付きました.

 以下に簡単に再現するコードを示します.


<?php
$str = "情処応用";
echo $str."<br />";
for ($i = 0; $i < strlen($str); $i++) echo  "[".bin2hex($str[$i])."]";
echo "<br/>";
$str = escapeshellarg($str);
echo $str."<br />";
for ($i = 0; $i < strlen($str); $i++) echo  "[".bin2hex($str[$i])."]";
echo "<br/>";
?>


マルチバイト文字はシフトJISではなくUTF-8です.PHP5.2.8(Windows/32bit)の実行結果は,


情処応用
[e6][83][85][e5][87][a6][e5][bf][9c][e7][94][a8]
"��処応用"
[22][e6][83][e5][87][a6][e5][bf][9c][e7][94][a8][22]


 0x85が1個,消えています.両端をシングルクオートではなくダブルクオート(0x22)で括るのはWindows的には正しい動作です.これをPHP5.2.5(Windows/32bit)で実行すると,


情処応用
[e6][83][85][e5][87][a6][e5][bf][9c][e7][94][a8]
"情処応用"
[22][e6][83][85][e5][87][a6][e5][bf][9c][e7][94][a8][22]


と出力されます.もちろん,二つのWindowsの環境が完全に一致している訳ではありません.php.iniもhttpd.confも違います.ただ,いままで問題なく動いていた側のPCが,PHPを5.2.8に変えただけで異常な症状を示しましたので,やはりPHP5.2.8を疑いたくなります.Webで情報を探しましたが,該当する報告は見当たりませんので,当方の環境だけなのかも知れませんが...どなたかLinuxの環境でPHP5.2.8(あるいはPHP5.2.9)を実行可能な方,先に示したコードを実行して結果を教えて頂けないでしょうか.

 なお,escapeshellarg()にまつわるトラブルの中に,ロケールの問題を挙げている方もいました.

setlocale(LC_ALL, 'ja_JP.UTF-8');

で改善したという報告(この現象とは別の現象です)があったので試してみましたが,効果はありませんでした.

#2時間くらい悩んでしまいました...

#あ,もちろん,Windows環境のPHP5.2.8や5.2.9,あるいはPHP5.2.6, 5.2.7での動作報告もお待ちしております.

In reply to Tatsuya Shirai

Re: escapeshellarg()の挙動がPHP5.2.8でおかしい?

by Tatsuya Shirai -

 ちなみに,escapeshellarg()がどのような挙動をする関数なのか,よく分かっていません.

 なお,いまescapeshellarg()をescapeshellcmd()関数に変えても同じく0x85が欠落することを確認しました.なんで...

 escapeshellcmd()は”#&;`|*?~<>^()[]{}$\\x0A および \xFF については、その文字の前にバックスラッシュが 追加されます。' および " は、対になっていない場合にのみエスケープされます。Windows では、 これらの文字に加えて % がスペースに置き換えられます。 "とのことです.

 追加されたり置き換えられるのであって削除されるものでは無いですし,0x85はANKではない(だからだとは思うが)ので関係ない.

 ちなみにWindowsの場合は引数やプログラム名に半角空白を含むとそこで区切られてしまうので(内部コマンドcdは大丈夫),パスはダブルクオートで括ります.そしてダブルクオートはファイル名に使えない文字(\ / : * ? " < > |)に含まれるのでファイル名には含まれていません.したがって単に両側をダブルクオートで囲うだけで良い.とりあえずはそういう逃げ方もあるのだが...

In reply to Tatsuya Shirai

Re: escapeshellarg()の挙動がPHP5.2.8でおかしい?

by Tatsuya Shirai -

 とりあえず,Windows環境の私が幸せになれるように,fs_moodleは対策を行いました.いまのところ好調です.

 fs_moodleでは,OSの種類に応じてfs関数と名付けた関数をライブラリとして用意しています.
 今回はfunction escapeshellarg()に対して,fs_escapeshellarg()を作成しました.至って簡単に,Windowsの場合は,

    function fs_escapeshellarg($path)
    {
        if (strpos($path, ' ')) return "\"$path\"";
        return $path;
    }

が読み込まれ,Windows以外は,

    function fs_escapeshellarg($path)
    {
        return escapeshellarg($path);
    }

が読み込まれます.そのままですね.
 PHP5.2.5より後のバージョンのLinuxでもescapeshellarg()がおかしな挙動を示すバージョンがあるならばこの関数に独自のescapeshellarg()を実装します.

申し訳ありませんが,引き続き,テスト用のコードの実行結果のご報告をお待ちしております.

In reply to Tatsuya Shirai

Re: escapeshellarg()の挙動がPHP5.2.8でおかしい?

by Tatsuya Shirai -

    function fs_escapeshellarg($path)
    {
        if (strpos($path, ' ')) return "\"$path\"";
        return $path;
    }

これは不十分な実装でしたね.当方の環境(Windows + fs_moodle)で外部zipコマンドを利用して'+'や'&'をファイル名に含むファイルやフォルダを引数としてzip書庫の作成を行うと失敗する現象が確認されました.なんでかんでもダブルクウォートで括るという選択肢もあったのですが,そこをケチったのがいけなかったのか? いまのところは,

    function fs_escapeshellarg($path)
    {
        if (strpos($path, ' ')) return "\"$path\"";
        if (strpos($path, '+')) return "\"$path\"";
        if (strpos($path, '&')) return "\"$path\"";
        return $path;
    }

という消極的な対策(ファイル名にダブルクウォートは許していないので)で改善しましたが,どうしたものでしょうか.


http://php.plus-server.net/function.escapeshellcmd.html

escapeshellarg()の説明ではあまり詳しく書かれていなかったので.%を半角スペースに置き換える操作はescapeshellarg()でも行っていることを確認しました.でも,それをやると今度は%をファイル名に含むファイル名を引数に渡して正しく動かないと思うのですけれども...?

In reply to Tatsuya Shirai

MySQLのアップグレード

by Tatsuya Shirai -

 PHPとApacheのアップグレードだけでお茶を濁そうとしていたのですが,phpMyAdminがMySQLのバージョンが低いので致命的な問題を生じる恐れがあると脅かしてくるようになったのでMySQLも5.1.32にアップグレードしました.

 いままではxamppliteパッケージでインストールしたMySQLを使い続けていたのですが,これを機に本家からWindows用のバイナリをフルパッケージでダウンロードしました.

 MySQLを停止して現状のMySQLのフォルダをリネームし,新しくダウンロードしてきたzipパッケージをいままでと同じMySQLという名前でxamppliteフォルダの下に展開しました.インストーラパッケージですと,データベースをAll usersの領域にしか作成できない(後から変更できるのだと思いますが)ようでしたので,ZIPパッケージを用いました.

 dataフォルダをコピーしてサービスに登録済みのmysqlを起動したのですが,エラーが出て起動しません.ハマりましたね.いくつか気付いたところを記録しておきます.

1.mysqldのバイナリの名前が変わっている.
 以前のパッケージではNT系用と95系用とでmysqldの名前が違ったようで,サービスにはmysqld-nt.exeが登録されていました.どうやらいまはmysqld.exeで統一されたようですね.mysqld-nt.exeなどbinフォルダ内に存在しないので起動しなくて当然です.サービスを手動で削除し,mysqld --installでサービス登録し直しました.でも,これだけでもダメでした.

2.my.ini.cnfという罠
 Windowsは拡張子cnfを特別なもの(短縮ダイヤル)として扱っているようで,全ての拡張子を表示する設定にしても表示されない.前々から気持ちが悪かったので,my.iniという名前に変えてエディタで開いたところ,ファイル名がmy.ini.cnfとりネームされていることに気付く.新たにmy.iniというファイルを作成し,my.ini.cnfの中身を全てコピーして呪縛から逃れる.

3.正しい設定ファイルを参照するようにサービスを登録
 先にmysqld --install でサービス登録した時,設定ファイルを指定して居なかったので,かなり昔にWINDOWSフォルダに作成したmy.cnfファイルを参照していたようです.これを今回,更新したmy.iniを参照するように,mysqld --install mysql --defaults-file=C:\xampplite\mysql\my.ini と登録することで,サービスとして起動するmysqlに正しい設定ファイルを見に行くように指定する.でも,システムエラー 1067 が発生してサービスは起動しません.

4.謎の設定”skip-bdb"
 dataフォルダ内のエラーログ(*.err)を見てみると,skip-bdbなどというコマンドは無いというエラーが記録されていました.my.ini内にあったこの記述を#でコメントアウトするとサービスが正常に起動しました.

4.mysql_upgradeを行おう
 phpMyAdminでデータベースのテーブルを参照するとエラーが発生する.同じくエラーログを見ると"Please use mysql_upgrade to fix this error."とある.MySQLのバージョンが上がっているのでシステム側のデータベースのテーブルを更新する必要があるのですね.知らなかった.mysql_upgrade -p でログインしてadminのパスワードを入力するとデータベースのアップグレードが行われて,正常にテーブルを見ることができるようになりました.気持ちが悪いのでdataフォルダのコピーからやり直しています.

とりあえずこれで今のところはOKです.あ,ちなみにWindowsの場合はbasedirやtmpdir, datadirのパス区切りに\を使ってはいけません./を使いましょう.私はこれにも気付かずにエラーを連発しました.