0

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.

gprobst
  • 11
  • 1
  • 2
    Try to enable [debug messages](https://stackoverflow.com/questions/845021/how-can-i-get-useful-error-messages-in-php) – Luuk Nov 11 '22 at 18:42
  • Is the PHP version the only difference? Are both versions running on the same machine? What did you try to do to debug the code? We cannot debug it for you. – Martin Prikryl Nov 11 '22 at 18:55
  • 1
    As a first step, I would remove all those `@` suppressors. If the script isn’t working as it should, there’s a good chance they are hiding useful warnings and notices that could indicate where the problem(s) could be. – rickdenhaan Nov 11 '22 at 19:01
  • 1
    Are both PHP installations configured the exact same way? Are the same extensions enabled on both (particularly `ssh2`)? – kmoser Nov 11 '22 at 22:55
  • They are set up similarly but not exactly the same. The 7.4 has SSH2 v1.2, while the 8.1 has SSH2 v1.3. – gprobst Nov 11 '22 at 23:08
  • @gprobst That sounds like a possible culprit. – kmoser Nov 11 '22 at 23:59
  • Please do not post information in comments. Edit everything into your question, as if you were posting it all together from the very beginning. – Martin Prikryl Nov 12 '22 at 15:46
  • 1
    Did you check the settings of [allow url fopen](https://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen) on both servers to see if it is disallowed on the 8.1 server? – gview Nov 26 '22 at 19:41

1 Answers1

0

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.