Re: Hoping for a working example of SFTP in PHP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



David,

No problem.

The $remoteDir variable should be in the format '%s/path/to/the/files/directory', sprintf will replace the %s with the $streamUrl.

You could also just use  $streamUrl . '/path/to/the/files/directory'; as well. If you only want to copy one single file, you can also use $streamUrl . '/path/to/the/file';  If this is the case, and you don't care if the file exists, I would suggest that you just use the ssh2_scp_send function instead of streams.

1) I put two different ways of copying files.  If you are using the stream "ssh2.sftp://"; copy just works on the stream.  If you want to avoid the $streamUrl stuff you can also just use the function ssh2_scp_send

ssh2_scp_send($connection, 'local-file', 'full-path-to-remote-file');

2) This works without a user password.  The passphrase is used to decrypt the key if it is encrypted.  Usually on shared hosts they require a passphrase when you create the ssh key.  I'm not sure what your situation is.  If you have control of the creation of keys, when you create one and just hit enter when it asks for a passphrase.

Eric

On 2/2/21 1:40 PM, David Spector wrote:

Dear R. Eric Wheeler,

Thank you! After several weeks of posting my question in several fora, you are the first to reply with an example that works. Thank you! I am so happy. After I have time to clean up the formatting and document it a bit more fully I plan to post it everywhere, since no one seemed to know how to make this simple and valuable example. I will give you credit, and you deserve it!

One minor problem: the file is uploaded to the document root instead of the $remoteDir directory. I can probably figure this out, but it would help if you correct my code. I may have messed something up.

Here is your code after I modified it to work in my environment. Note that I commented out your code to list the remote dir since it gave an error message and I don't need it anyway. If there are no errors detected, and it passes a simple test for successful upload once, I'm satisfied that the file was uploaded.

One question: what is the "copy" function there for? I don't think I need any files copied locally in order to upload a file.

One more question: can it work without knowing the user's password? I'm thinking of disabling passwords on my remote webserver, so access is by public/private keys only.

Thank you!

David

<?php declare(strict_types=1);
// From R. Eric Wheeler sikofitt@xxxxxxxxx

// Tested on
// PHP 7.4.14 (cli) (built: Jan  5 2021 15:12:29) ( ZTS Visual C++ 2017 x64 )
// Windows 10 Pro
// pecl ssh2 v1.2

// Remote server
// Gentoo GNU/Linux Base System release 2.7

error_reporting(E_ALL);
ini_set('display_errors', '1');

$c=GetConfigArr("secret.json");
extract($c);

file_put_contents(__DIR__.'/test.txt', 'worked!');

$host = $hostIP;
$port = (int)$securePort;

$connection = ssh2_connect($host, $port); // let libssh2 figure it out.

if(!is_resource($connection)) {
    exit('Connection failed.');
}

// Without the __DIR__ php will just try to get 'id_rsa' and will fail.
// if your keys are elsewhere __DIR__ should be changed to C:\path\to\your\files
$privateKey = __DIR__.'\w.key'; // id_rsa
$publicKey = __DIR__.'\w1.pub'; // id_rsa.pub
$username = $user;
$passphrase = $passphrase; // set this to passphrase if you have one.

if(false === ssh2_auth_pubkey_file($connection, $username, $publicKey, $privateKey, $passphrase)) {
    ssh2_disconnect($connection);
    exit('Authentication failed.');
}

$sftp = ssh2_sftp($connection);
$streamUrl = sprintf("ssh2.sftp://%d";, (int)$sftp);

$path = sprintf($remoteDir, $streamUrl);
$file = sprintf('%s/test.txt', $path);
$localFile = __DIR__ . '/test.txt';

if(!file_exists($file)) {
    if(true === copy($localFile, $file)) {
        print 'Successfully copied ' . $localFile . PHP_EOL;
    }
} else {
    print 'File exists' . PHP_EOL;
}

// using ssh2_scp_send, if all you need to do is upload a file.
// There doesn't seem to be another way to check if the file exists
// using just the ssh2 resource without using the ssh2.sftp stream wrapper.
// If you want to check if the file exists use ssh2_sftp_stat() it will
// return false if the file does not exist.
$file2 = 'test.txt';

$res = ssh2_scp_send($connection, $localFile, $file2);
if($res) {
    print 'Sent file ' . $file . PHP_EOL;
} else {
    print 'There was an error copying file to remote.' . PHP_EOL;
}

/*
// List contents of remote directory
$i = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);

while($i->valid()) {
    print $i->getPathname();
    if($i->isDir()) {
        print $i->getPath() . PHP_EOL;
    } else {
        print $i->getFilename() . PHP_EOL;
    }
    $i->next();
}
*/


// shutdown
unset($sftp); // If you don't unset $sftp ssh2_disconnect will throw a segfault.
ssh2_disconnect($connection);

function GetConfigArr($file)
    {
    global $pagesDir;
    $configStr=@file_get_contents($file);
    if ($configStr===false)
        exit("*** HMAC: Config file '$file' is missing from $pagesDir; please read ".             "file HMAC\Installation.txt for the steps to set up your HMAC website.");
    return json_decode($configStr,true);
    } // GetConfigArr
?>



[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux