Script that works with PHP 7.4 is returing fopen error with SSH2 in PHP 8.1

549 Views Asked by At

I use the script below (in conjunction with a cron job) to SFTP an XML file generated on a public website to an FTP server. It works as expected in PHP 7.4, but when I try to run it in PHP 8.1.16, it seems to be in constant state of loading/running and never completes or returns an error.

UPDATE: I've made some changes based on suggestions in the comments, and seem to have it narrowed down to an issue with fopen.

    ini_set('display_startup_errors', 1);
    ini_set('display_errors', 1);
    error_reporting(-1);

    $file = "MYTempFiles/myXML.xml";
    $returnFile = file_put_contents($file, file_get_contents('https://www.example.com/myXML'), LOCK_EX);
    $sftpFile = "/username/myXML.xml";
    if($returnFile === false) {
      die('<p class="center">There was an error processing the XML file.</p>');
    }
    else {
      echo "<p>$returnFile bytes written to file.</p>";
      echo "\r\n<p>request-" . time()."</p>";
    }

    $sftp_server = "sftp.example.com";
    $sftp_userpass = "example_pwd";
    $sftp_username = "example_username";
    $sftp_port ="2245";

    class SFTPConnection
    {
        private $connection;
        private $sftp;

        public function __construct($host, $port)
        {
            $this->connection = ssh2_connect($host, $port);
            if (! $this->connection)
                throw new Exception("Could not connect to $host on port $port.");
        }

        public function login($username, $password)
        {
            if (! ssh2_auth_password($this->connection, $username, $password))
                throw new Exception("Could not authenticate with username $username " .
                                    "and password $password.");

            $this->sftp = ssh2_sftp($this->connection);
            if (! $this->sftp)
                throw new Exception("Could not initialize SFTP subsystem.");
        }

        public function uploadFile($local_file, $remote_file)
        {
            $sftp = $this->sftp;
            $sftp = (int)$sftp;   
            $stream = fopen("ssh2.sftp://$sftp$remote_file", 'w');
              
            if (! $stream)
                throw new Exception("Could not open file: $remote_file");

            $data_to_send = file_get_contents($local_file);
            if ($data_to_send === false)
                throw new Exception("Could not open local file: $local_file.");

            if (fwrite($stream, $data_to_send) === false)
                throw new Exception("Could not send data from file: $local_file.");

            fclose($stream);
        }
    }

    try
    {
        $mySftp = new SFTPConnection($sftp_server, $sftp_port);
        $mySftp->login($sftp_username, $sftp_userpass);
        $mySftp->uploadFile($file, $sftpFile);
    }
    catch (Exception $e)
    {
        echo $e->getMessage() . "\n";
    }

I've compared the phpinfo for both instances of PHP looking for a difference that might result in the script not working as expected, but I didn't see anything obvious. Without getting any kind of error, I'm not really sure where else to try to troubleshoot.

I've checked to make sure the connection is good, and there are no issues there.

After following the advice to add message debugging, and removing all the @ suppressor I originally had, I'm now getting the following warnings.

Warning: fopen(): Unable to open ssh2.sftp://6/username/myXML.xml on remote host in /filepath_goes_here/sftp-xml-file.php on line 51

Warning: fopen(ssh2.sftp://6/username/myXML.xml): Failed to open stream: operation failed in /filepath_goes_here/sftp-xml-file.php on line 51
Could not open file: /username/myXML.xml

I had originally been running SSH2 v1.2 on PHP 7.4, while the 8.1 instance had SSH2 v1.3.1. I have since updated to SSH2 v1.3.1 on the PHP 7.4 instance, and it still works without any issues on 7.4 but returns the fopen errors on 8.1.

I have confirmed that allow_url_fopen is set to "on" for the 8.1 instance.

1

There are 1 best solutions below

0
On

I just had a similar issue when moving from a server running PHP 7.0.33 to one running 8.1.16 In my case I was getting a Permission denied error:

fopen(../../dataroot/data/today/relations.txt): Failed to open stream:

On both servers the script was being run by the same account with identical properties. I checked the fopen status etc was the same on both servers and that the permissions for the entire dirctory tree were identical on both servers.

I finally found that I needed to have world execute permission on every directory in the path for php to be able to read the txt file. On the php 7 server I had world read privelege on the dataroot and data directories and execute on the today directory.

I'm not an expert in linux or php so may have missed something along the way but I searched high and low for possible answers and found none.