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
?>