2010年9月8日水曜日

「PHP 5.3.x で推奨されない機能」にひっかかって Uber_Uploader が動かなくなった

追記)2017/6に,FreeBSD で fine-uploader を使ってみた(その1)というのを書いた。 そこでは fine-uploader という JavaScript のライブラリを使ったファイルのアップローダーについて書いている。 Uber Uploader はすでに古く更新されていないので,fine-uploader など新しいアップロードライブラリを使うことをお薦めする。
追記)2011/8時点での Uber-Uploader の最新版についてはUber-Uploader 6.8.2 の使い方(その1)で述べているので,参考にしてみて欲しい。

個人で細々と web site を運用している。そこで結構重宝してるのが,Uber_Uploader というソフト。以前,web へのファイルのアップロードの進捗状況がわかるようなアップローダーが欲しくていろいろ調べて,uber_uploaderを使った,という感じのことをこのブログに書いた(cgiとutf8とphpとjs)。その時は,Uber Uploaderのバージョン 6.5 を使っていた。その後バージョンアップがなされ,今はバージョン 6.8.2 になっている。バージョン 6.5 から 6.8.2 になるまでに,途中で結構大きな構造の変更がなされ,見た感じはちょっと違ったものになっている。どちらも使えるようになっているが,今日の話題はバージョンの違いではなくて,uber_uploader がうまく働かなくなってしまった話題(以下の現象はバージョンが 6.5 か 6.8.2 かに関係なく発生した)
 web site は,古いノートマシンを使って運用している。われながらかなり危険なことをしてるなぁ,と思っているが,なにせ先立つモノがないと…。OSはFreeBSDを使っている。サーバーに入れてるバージョンは FreeBSD 8.0 にしている。FreeBSD の場合,いろいろなアプリケーションソフトは ports というシステムで管理されている。アプリケーションのアップデートをする場合は portupgrade というアプリケーションを使ってやると,勝手にアップデートしてくれる。めんどくさいので,よく portupgrade -a (全てアップデート対象ならアップデートするという設定)を実行している。多くの場合は特に問題はないのだが,これをやると時々サーバーの動作がおかしくなる時がある。
 この間も portupgrade -a をすると,emacs を使った時の感触が違っていた。どうもカーソルの動きがおかしい。どうやら,emacs のバージョンが22から23に上がり,内部の文字コードが utf8 になったために起こる現象みたいだった。これは,PuTTY の設定で UTF-8 を使う,とするとなんとかそれっぽく動くようになった。
 他にも apache や perl がバージョンアップするといろいろとトラブルに見舞われたりする。Perl の場合は影響が大きく,いろいろなものが動かなくなってしまったりする。それなら portupgrade -a を使わずに一個一個 upgrade すればよさそうなものだが,これが結構数が多くて,めんどくさいからついつい portupgrade -a をしてしまう…


 で,やっと今回の本題に入ろう。今回は portupgrade -a をしたら,急に uber_uploader が働かなくなってしまった。どうなったかというと,
(1) サイトの上の方に「 date 関数は危険だから気をつけろ」みたいなメッセージがいっぱい出てきた。
(2) (1) のメッセージを無視すると,アップロードできそうになるのだが,アップロードボタンを押しても,うんともすんとも言わず,ブラウザのステータス欄に「完了」と出て終わる。かと言って,ファイルはアップロードされていない。普通なら,アップロードボタンを押すと,ファイルをアップロードする様子(進捗状況)が棒グラフで出るはずなのに,何も出ず,ただただ止まってしまう。
 と,こんな感じになってしまった。エラー表示が出ても,ファイルがアップロードさえできればいいのだが,ファイルがアップロードされない,というので困ってしまった。この二つを解決するのに数日かかってしまった。その顛末を書こう。

 その前に,最終的に何が問題だったかを書いておくと,
(a) /usr/local/etc/php.ini の中で
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ; Error handling and logging ;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   display_errors = On
 としていたため,エラーや警告があるとメッセージを出すために,ルーチンが止まってしまった。

(b) エラーや警告がなければよいのだが,今回は2つ警告があった。
 以下の2つの警告のメッセージを表示しようとしたのがルーチンが止まった直接の原因だった。
 (b-1) mktime関数を引数をなしで使っていた(mktime()としていた)ため,非推奨の警告
 (b-2) タイムゾーンを指定しないでdate関数を使ったために,非推奨の警告

(c) 調べているうちに判明したが,以下の2つの非推奨の設定をしていた。
 (c-1) register_long_arrays
 (c-2) magic_quotes_gpc

さて,どういう風になったかを書いていこう。Uber_Uploader がうまく働かない,というのがわかったのは,同窓会で写真を撮ってもらったのが始まり。その写真を送ってもらうのに,100 MBぐらいあるからアップローダーで転送してもらおう,と考えた。友達に頼むと,まずはデジカメのケーブルが見つからないから,写真をコンピュータに落とせない,と言ってきた。それは向こうの問題だからいいのだが,やっとケーブルが見つかって,さぁ,写真をアップロードしようと思ったら,エラーでうまくいかない,とのことだった。よくあるのが必須項目を入力してない,とか,exeやwordのファイルなどのように転送できない拡張子を持ったものをアップロードしようとした,などのミス。ということで,また友達がミスをしたのかと思っていた。ところがいろいろ指示をしてもうまくアップロードできない。で,仕方ないので自分でテストに適当なファイルをアップロードしようと思ったら,おかしなメッセージがでるし,アップロードできない,という現象に遭遇して,その時初めて Uber_Uploader が働いていない,というのに気づいた。今回はこちらのミスだったのだが,しばらく友達を疑ってしまった…。いやぁ,申し訳ない。

 で,Uber_Uploader がうまく働かない,というのがわかったのだが,何が原因でそうなったかが最初は全然わからなかった。まず,Uber_UploaderAJAX で書かれていて,phpcgi (結局は perl) ,apache を使った複合システムで,どこに問題があるのかがとてもわかりにくい。それで困ってしまった。とりあえず,最近 Uber_Uploader のルーチンをいじってないので,原因として考えられたのが portupgrade によって,どれかのルーチンのバージョンが上がったことに起因するトラブルだった。可能性があるのは phpPerlが怪しい。そこでいろいろ調べてみた。
 まずは,date関数がよくない,みたいに書いてあったので,エラーを出したルーチンのdate関数を使っている部分を探してみたところ,とりあえず必要なさげな部分だったので,そこをコメントアウトしてみた。すると,とりあえずはdate関数がよくない,ってエラーメッセージはでなくなった。まずは一安心。しかし,もっと深刻なアップロードができない,ってのは全然わからなかった。そこで次に /var/log/httpd-error.log のチェック。そこにあった見慣れないエラーはというと,
<font color=#ff0000><br />
<b>Warning</b>:  Directive 'register_long_arrays' is deprecated in PHP 5.3 and greater in <b>Unknown</b> on line <b>0</b><br />
</font><font color=#ff0000><br />
<b>Warning</b>:  Directive 'magic_quotes_gpc' is deprecated in PHP 5.3 and greater in <b>Unknown</b> on line <b>0</b><br />
</font><font color=#ff0000><br />
これがいっぱい出ている。とりあえず php のバージョンが上がったために出てきたエラーみたいだった。しかし,どうも警告レベルで,それがあってもファイルがアップロードできない,という直接の原因ではなさそうだった…。でも,まぁ,気になるので最初に調べてみた。

いろいろ検索をしていると日本PHPユーザー会のサイトを見ると,PHP 5.3.x で推奨されない機能というページがあった。そこには,「register_long_arrays」と「magic_quotes_gpc」がPHP 5.3では推奨されない,と書いてあった。どうやら上記の警告メッセージは「非推奨になったパラメータを使っているぞ」という警告みたいだった。そこで,/usr/local/etc/php.ini の中でそれらの設定を「Off」またはナシにしておいた。
; Whether or not to register the old-style input arrays, HTTP_GET_VARS
; and friends.  If you're not using them, it's recommended to turn them off,
; for performance reasons.
;;register_long_arrays = On
register_long_arrays = Off

; Magic quotes for incoming GET/POST/Cookie data.
;;magic_quotes_gpc = On
magic_quotes_gpc = Off

さらに,/usr/local/etc/php.ini を見ていると,
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
display_errors = On  (← ここを off に変更した)
というのを発見した。
なんじゃこりゃ?
なんでエラーメッセージを書こうとするの?
そのせいで,サイトがファイルのアップロードを実行せずに止まったんやぁ!!!
で,このエラー表示パラメータをOFFにしておいた。

これでよし。うまくいくはず,と思ったのだが,折角設定ファイルを変えたのにまだ警告メッセージが消えない…なんで??? 実は,php のパラメータを変えたら,apache を再起動しないといけなかった…。再起動したらちゃんと警告メッセージは消えてくれた。

さて,エラー表示を出さないように php.ini のパラメータを変えたが,肝心のアップロードできない,というのは未解決だった。php.iniをいじった後でapache を再起動し忘れてた時に,ブラウザに表示されるエラーメッセージや,ブラウザのエラーコンソール,/var/log/httpd-error.log などを見ていたのだが,そこにmktimedate('r') という言葉を見つけた。どうもそれらの関数を「使うな」とか「危険」と書いてある。そこで先程の日本PHPユーザー会のサイトのPHP 5.2.x から PHP 5.3.x への移行というページのPHP 5.3.x で推奨されない機能を見てみた。すると,
is_dst を mktime() に渡すこと。 かわりにタイムゾーン処理用の新しい関数を使用します。
という文があった。なんのこっちゃ?と思ったが,どうやら mktime の引数を空で使ってはいけないみたい。mktime() としたい時には,代わりに time() を使えと書いてあった。確かに Uber_Uploaderubr_link_upload.php の中で「$now_time = mktime();」として使ってある。そこで,このmktime() の代わりに time() を使うようにしてみた。するとちゃんとアップロードするようになった!!我ながらよく頑張った!!

さらに date 関数についても日本PHPユーザー会のサイトで検索してみた。するとdateという関数のリファレンスページが出てきた。その「エラー / 例外」というところに,
すべての日付/時刻関数は、有効なタイムゾーンが設定されていない場合に E_NOTICE を発生させます。
また、システム設定のタイムゾーンあるいは環境変数 TZ を使用した場合には E_STRICT あるいは E_WARNING を発生させます。
date_default_timezone_set() も参照ください。
と書いてあった。そこで,date_default_timezone_setを見てみた。どうやら,この date_default_timezone_set関数timezone を指定しないで date 関数を使うと警告がでるみたい。今回みたいに警告も表示する,ってしてると,そこでルーチンが止まってしまってトラブルが起こったみたい。具体的には,php ルーチンのはじめの方に
date_default_timezone_set('Asia/Tokyo');
と書くか,あるいは /usr/local/etc/php.ini の中で,
[Date]
; Defines the default timezone used by the date functions
date.timezone = 'Asia/Tokyo'
とタイムゾーンを設定する必要がある。タイムゾーンに設定できる文字列はサポートされるタイムゾーンのリストに書いてあった。Uber Uploader のルーチンを極力いじらないで済ますには,/usr/local/etc/php.ini をいじる方が楽だとおもう。最終的に php.ini を変更したら date 関数に関するエラーも消えた…。よかった,これでアップローダーが復活した。

それにしても,アプリケーションのアップデートは怖いなぁ…

0 件のコメント: