2016-12-01 2 views
4

私は、SFTP接続を使ってファイルをダウンロードするアプリを持っています。PHP 7 SSH2.SFTP stat()bug work around

PHPの警告:ファイルサイズを():それは次のようにそんなにPHP 7に私が手にエラーがあり、PHP 5.6で正常に働いていたstatにssh2.sftpに失敗しました...

私のコードがあります次のように:

public function retrieveFiles($downloadTargetFolder,$remoteFolder = '.') { 

      $fileCount = 0; 

       echo "\nSftpFetcher retrieveFiles\n"; 

     $con = ssh2_connect($this->host,$this->port) or die("Couldn't connect\n"); 
     if($this->pubKeyFile){ 
       $isAuth = ssh2_auth_pubkey_file($con, $this->user, $this->pubKeyFile, $this->privKeyFile); 
     } else { 
       $isAuth = ssh2_auth_password($con, $this->user, $this->pass); 
     }; 


     if ($isAuth) { 

       $sftp = ssh2_sftp($con); 
       $rd = "ssh2.sftp://{$sftp}{$remoteFolder}"; 

       if (!$dir = opendir($rd)) { 
         echo "\nCould not open the remote directory\n"; 
       } else { 
         $files = array(); 
           while (false != ($file = readdir($dir))) { 
            if ($file == "." || $file == "..") 
             continue; 
            $files[] = $file; 
           } 

         if (is_array($files)) { 
          foreach ($files as $remoteFile) { 
               echo "\ncheck file: $remoteFile vs filter: " . $this->filter."\n"; 
           if ($this->filter !== null && strpos($remoteFile,$this->filter) === false) { 
            continue; 
           } 
               echo "file matched\n"; 
           $localFile = $downloadTargetFolder . DIRECTORY_SEPARATOR . basename($remoteFile); 


           //$result = ftp_get($con,$localFile,$remoteFile,FTP_BINARY); 
           $result = true; 
           // Remote stream 
           if (!$remoteStream = @fopen($rd."/".$remoteFile, 'r')) { 
             echo "Unable to open the remote file $remoteFolder/$remoteFile\n"; 
             $return = false; 
           } else { 
             // Local stream 
             if (!$localStream = @fopen($localFile, 'w')) { 
               echo "Unable to open the local file $localFile\n"; 
               $return = false; 
             } else { 
               // Write from our remote stream to our local stream 

               $read = 0; 
               $fileSize = filesize($rd."/".$remoteFile); 
               while ($read < $fileSize && ($buffer = fread($remoteStream, $fileSize - $read))) { 
                 $read += strlen($buffer); 
                 if (fwrite($localStream, $buffer) === FALSE) { 
                   echo "Unable to write the local file $localFile\n"; 
                   $return = false; 
                   break; 
                 } 
               } 


               echo "File retrieved"; 
               // Close 
               fclose($localStream); 
               fclose($remoteStream); 

             } 

           } 

           if ($result) { 
            $fileCount++; 
           } 
          } 
         } 

         ssh2_exec($con, 'exit'); 
         unset($con); 
       } 

     } else { 
       echo "Error authenticating the user ".$this->user."\n"; 
     } 

      return $fileCount; 

    } 
} 

いくつかの研究の後、私はSTATとの問題が(そこがわかった):

http://dougal.gunters.org/blog/2016/01/18/wordpress-php7-and-updates-via-php-ssh2/ https://bugs.php.net/bug.php?id=71376

私の質問

私の現在のコードを与えられた私はSFTP経由でダウンロードできるようにする回避策はありますか代わりに使用することをお勧めすることができます別のライブラリの誰かがありますか?

私のPHPのバージョン: PHPの7.0.8-0ubuntu0.16.04.3(CLI)(NTS)

答えて

6

PHP ssh2.sftp opendir/readdir fixを引用し、

代わりにストリームパスとして"ssh2.sftp://$sftp"を使用するのは、$のSFTPを変換しますのような整数に変換する:"ssh2.sftp://" . intval($sftp) . "/"。それはうまくいくでしょう。

次のように変更された理由は次のとおりです。

PHP 5.6.28(と明らかに7.0.13)が$のSFTPリソースの文字列補間を引き起こしている、URLの解析にセキュリティ修正を導入ハンドルをnoにすると有効なURLとして認識されなくなります。その結果、opendir()、readdir()などはPHP文字列にアップグレードした後に、パス文字列で$ sftpリソースを使用すると失敗します。私の知る他のライブラリについては

...唯一の他のライブラリはlibssh2のための一種のエミュレータを持っているphpseclib、次のとおりです。

https://github.com/phpseclib/libssh2-compatibility-layer

「エミュレータ」は確かに改善することができること〜によってtho。 composer.jsonファイルのように追加する必要があります。

+0

これでうまくいき、あなたの答えがその日に保存されました。ありがとう! – Revent

+0

ありがとうございます:) osのアップデート、PHP 5.6、intvalがこのトリックをやった後、この問題が奇妙に起こりました。今私は多くの人とは対照的に、問題に1時間しか過ぎませんでした。 –