PHP+cURLでFTP接続し、CWDすると失敗することがある

諸所の理由でPHP+cURLでFTPダウンロードしてたのですが、
サーバ環境によってはCWDがうまいこといかないみたい;;

なぜか。

詳細ログをとってFTPコマンドのやり取りを解析してみた。

実行したソースコード

PHP:
  1. <?php
  2.  
  3. //ftp接続設定
  4. $baseUrl = “ftp://hoge:foobar@127.0.0.1/”;
  5. $path = “/var/www/html/index.html”;
  6.  
  7. //テンポラリファイル準備
  8. $fp = tmpfile();
  9. $fpe = tmpfile();
  10.  
  11. //curlに設定をセット
  12. $options = array(
  13. CURLOPT_QUOTE => array(“CWD “ . dirname($path)),
  14. CURLOPT_URL => $baseUrl . basename($path),
  15. CURLOPT_FILE => $fp,
  16. CURLOPT_VERBOSE => true,
  17. CURLOPT_STDERR => $fpe,
  18. );
  19.  
  20. //curl実行
  21. $ch = curl_init();
  22. curl_setopt_array($ch, $options);
  23. curl_exec($ch);
  24. curl_close($ch);
  25.  
  26. fclose($fp);
  27.  
  28. //ログ表示
  29. rewind($fpe);
  30. echo stream_get_contents($fpe);

成功するパターン

1度目の接続

* About to connect() to 127.0.0.1 port 21 (#0)
* Trying 127.0.0.1... * connected
* Connected to 127.0.0.1 (127.0.0.1) port 21 (#0)
< 220 ProFTPD 1.3.3 Server (ProFTPD) [127.0.0.1] > USER hoge
< 331 Password required for foo. > PASS foobar
< 230 User foo logged in. > PWD
< 257 "/home/hoge" is current directory. * Entry path is '/home/hoge' > CWD /var/www/html
< 250 CWD command successful
...

2度目の接続

* Re-using existing connection! (#0) with host 127.0.0.1
* Connected to 127.0.0.1 (127.0.0.1) port 21 (#0)
* Request has same path as previous transfer
> CWD /var/www/html
< 250 CWD command successful
...

失敗するパターン

1度目の接続

* About to connect() to 127.0.0.1 port 21
* Trying 127.0.0.1... * connected
* Connected to 127.0.0.1 (127.0.0.1) port 21
< 220 ProFTPD 1.3.3 Server (ProFTPD) [127.0.0.1] > USER hoge
< 331 Password required for foo. > PASS foobar
< 230 User foo logged in. > PWD
< 257 "/home/hoge" is current directory. * Entry path is '/home/hoge' > CWD /var/www/html
< 250 CWD command successful
...

2度目の接続

* Re-using existing connection! (#0) with host 127.0.0.1
* Connected to 127.0.0.1 (127.0.0.1) port 21
> CWD /var/www/html
< 250 CWD command successful > CWD /home/hoge
< 250 CWD command successful
...

ログ見て、一目瞭然っすね。
CURLOPT_QUOTEでせっかくCWDしたのに、こいつ、ホームディレクトリに再度CWDしてやがる・・・・!!
どおりでダウンロードできないわけね。

解決策探したけれど、中々解決できなかったので妥協して下記のようにした。

PHP:
  1. $options = array(
  2. CURLOPT_QUOTE => array(“CWD “ . dirname($path)),
  3. CURLOPT_URL => $baseUrl . basename($path),
  4. CURLOPT_FILE => $fp,
  5. CURLOPT_FRESH_CONNECT => true,
  6. );

CURLOPT_FRESH_CONNECTをtrueにすると、接続を保持せず再接続するみたい。
新規接続時はCWDが正常に動くので、とりあえずこれで。

とはいえ何度もログインしてて非常に美しくないので、もし解決策知ってる方がいたら教えてください!><

参考
PHP + cURL : さくらインターネットの FTPES でダウンロード

手動でACPIマルチプロセッサのHALをいれなおす

ネットブックのデュアルブート化の際、誤ってHALを削除してしまうという大失態を犯し、
以降通常のhal.dllでしか起動しなくなってしまいました。
Atomはマルチプロセッサとして動作するので、そのようにHALを入れなおす必要があります。
今回はその修復メモ。
続きを読む

Redmineのアカウントを使って、Subversionの認証を行う on debian lenny

むちゃくちゃつまづきどころが多かったのでメモ。

mod_auth_mysqlのインストール

普通にコマンド入力してインストールします

www@admin:~$ sudo apt-get install libapache2-mod-auth-mysql

問題が、mod_auth_mysql.so が mod_auth_basic.so より先に読み込めないと、以下のエラーが出ちゃいます。

pcfg_openfile() called with NULL filename

ということで名前を変えて先に起動するようにセット

www@admin:~$ sudo cp /etc/apache2/mods-available/auth_mysql.load /etc/apache2/mods-available/auth_00mysql.load

各種モジュール有効化

www@admin:~$ sudo a2enmod auth_00mysql auth_basic auth_digest

で、設定したいsvnのconfに以下のように記述

<Location "/svn">
DAV svn
SVNParentPath /var/www/svn
     <LimitExcept GET PROPFIND OPTIONS REPORT>
       Auth_MySQL                      On
       Auth_MySQL_Socket               /var/run/mysqld/mysqld.sock
       Auth_MySQL_Host                 localhost
       Auth_MySQL_User                 [redmineのデータベースユーザ名]
       Auth_MySQL_Password             [redmineのデータベースパスワード]
       Auth_MySQL_DB                   [redmineのデータベース名]
       Auth_MySQL_Password_Table       users
       Auth_MySQL_Username_Field       login
       Auth_MySQL_Password_Field       hashed_password
       Auth_MySQL_Encryption_Types     SHA1Sum
       Auth_MySQL_Empty_Passwords      Off
       AuthType Basic
       AuthName "Authorization Realm"
       Require valid-user
     </LimitExcept>
</Location>

AuthMySQLのパラメータ名が違うのと、Encryption_TypesがSHA1Sumなのがコツ。
なんでsha1じゃねーんだ。。ヽ(`Д´)ノウワーン

パラメータ違うと、

Invalid command 'AuthMySQLEnable', perhaps misspelled or defined by a module not included in the server configuration

って出るし、SHA1Sumじゃないと

Unsupported encryption type: sha1

って出る。分かるかい!ヽ(`Д´)ノウワーン

ということで、

www@admin:~$ sudo /etc/init.d/apache2 reload

して無事にsvnが動くのでした。。疲れた。。

参考サイト:
Subversion+Apache からredmineの認証を使う
うにっくすさんの覚え書き – Apache2 – MySQL認証