0

I'm currently attempting to use PHP to transfer small files between our server and a remote FTPS (FTP over SSL) server. I'm the standard fair to get this done, ie, file_put_contents, file_get_contents, etc... with the following stream context:

stream_context_create(array('ftp' => array('overwrite' => true), 'ssl' => array('allow_self_signed' => true)))

I'm passing this context stream using the following code. It can connect to the FTPS server just fine, but when it comes to creating the remote file, the file itself completely empty. Empty as in 0 for the file size.

    if(false === file_exists($localFile))
    {
        throw new Exception("Local file, {$localFile}, does not exist.");
    }

    if(false === $localFileContents = file_get_contents($localFile))
    {
        throw new Exception("Could not open Local file, {$localFile}.");
    }

    if(false === file_put_contents("{$this->url}{$remoteFile}", $localFileContents, FILE_APPEND, $this->context))
    {
        throw new Exception("Could not write to remote file, {$remoteFile}.");
    }

The remote file location, ie $this->url, is in the following format: "ftps://{user}:{pass}@{host}:{port}"

We're currently using Windows/Apache setup, so I can't use ftp_ssl_connect() without compiling our own PHP binaries. We couldn't go this route anyhow as it's a major change in our environment.

halfer
  • 19,824
  • 17
  • 99
  • 186
Wilhelm Murdoch
  • 1,806
  • 1
  • 22
  • 42

3 Answers3

1

Just a correction to the code in the selected answer:

Lines 11 and 12 should read:

    CURLOPT_URL => $remoteDir,
    CURLOPT_RETURNTRANSFER => 1
halfer
  • 19,824
  • 17
  • 99
  • 186
A. Genedy
  • 578
  • 4
  • 11
1

The PHP FTP/FTPS Documentations says:

Note: Appending
As of PHP 5.0.0 files may be appended via the ftp:// URL wrapper. In prior versions, attempting to append to a file via ftp:// will result in failure.

Are you sure you are using PHP >= 5.0.0. Or you can try it with FILE_TEXT flag instead of FILE_APPEND.

shamittomar
  • 46,210
  • 12
  • 74
  • 78
1

I've just had to do something very similiar.

I found the solution here: http://www.php.net/manual/en/function.curl-setopt.php#90988

I ended up wrapping it in a class thusly:

class ftps {

    /**
     * @param string $remoteDir Fully quantified path to the directory, eg ftp://foo:bar@blergh.com/directory/
     */
    public function ls($remoteDir) {

        $connection = $this->initConnection();

        curl_setopt_array($connection, array(
            CURLOPT_URL => $remoteDir,
            CURLOPT_RETURNTRANSFER => 1
        ));

        $result = curl_exec($connection);

        $this->finishConnection($connection);

        return explode("\n", $result);

    }

    private function initConnection()
    {
        $connection = curl_init();

        curl_setopt_array($connection, array(
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_FTP_SSL => CURLFTPSSL_TRY
        ));

        return $connection;
    }

    private function finishConnection(&$connection)
    {
        curl_close($connection);
        unset($connection);
    }

}
Drew
  • 1,687
  • 5
  • 25
  • 46
  • Never, ever do this. By disabling peer and host verification you completely invalidate the encryption because anyone who cares to can use a MitM attack to read your transfer. If you're going to disable verification in this manner just don't bother using SSL/TLS. –  Feb 19 '14 at 12:39
  • Agreed. It would mostly invalidate the point of SSL if you can't tell that your traffic is not being intercepted. Do you know how you could overcome the OPs problem if you don't have control over the remote server? I'd be super keen to know. – Drew Feb 19 '14 at 20:47
  • It's impossible to know without seeing the OP's actual code. The snippet posted is incomplete. It also fails to verify the peer in its stream context so it's no safer than disabling verification using curl. –  Feb 19 '14 at 20:49