mirror of
https://codeberg.org/icewind/SMB.git
synced 2026-06-03 17:24:07 +02:00
Also add Share::getWrite to non native shares
This commit is contained in:
parent
7c2393afb0
commit
89d73346f2
7 changed files with 112 additions and 35 deletions
|
|
@ -10,7 +10,8 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require" : {
|
"require" : {
|
||||||
"php": ">=5.3"
|
"php": ">=5.3",
|
||||||
|
"icewind/streams": "0.1.x"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"satooshi/php-coveralls" : "dev-master"
|
"satooshi/php-coveralls" : "dev-master"
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,10 @@ class Connection extends RawConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close() {
|
public function close($terminate = true) {
|
||||||
if (is_resource($this->getInputStream())) {
|
if (is_resource($this->getInputStream())) {
|
||||||
$this->write('close' . PHP_EOL);
|
$this->write('close' . PHP_EOL);
|
||||||
}
|
}
|
||||||
}
|
parent::close($terminate);
|
||||||
|
|
||||||
public function __destruct() {
|
|
||||||
$this->close();
|
|
||||||
parent::__destruct();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,4 +93,12 @@ interface IShare {
|
||||||
* @return resource a read only stream with the contents of the remote file
|
* @return resource a read only stream with the contents of the remote file
|
||||||
*/
|
*/
|
||||||
public function read($source);
|
public function read($source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a writable stream to a remote file
|
||||||
|
*
|
||||||
|
* @param string $target
|
||||||
|
* @return resource a write only stream to upload a remote file
|
||||||
|
*/
|
||||||
|
public function write($target);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ class RawConnection {
|
||||||
* @param string $input
|
* @param string $input
|
||||||
*/
|
*/
|
||||||
public function write($input) {
|
public function write($input) {
|
||||||
fwrite($this->pipes[0], $input);
|
fwrite($this->getInputStream(), $input);
|
||||||
fflush($this->pipes[0]);
|
fflush($this->getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,7 +72,7 @@ class RawConnection {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function read() {
|
public function read() {
|
||||||
return trim(fgets($this->pipes[1]));
|
return trim(fgets($this->getOutputStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -88,12 +88,28 @@ class RawConnection {
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getInputStream() {
|
||||||
|
return $this->pipes[0];
|
||||||
|
}
|
||||||
|
|
||||||
public function getOutputStream() {
|
public function getOutputStream() {
|
||||||
return $this->pipes[1];
|
return $this->pipes[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInputStream() {
|
public function getErrorStream() {
|
||||||
return $this->pipes[0];
|
return $this->pipes[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthStream() {
|
||||||
|
return $this->pipes[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFileInputStream() {
|
||||||
|
return $this->pipes[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFileOutputStream() {
|
||||||
|
return $this->pipes[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeAuthentication($user, $password) {
|
public function writeAuthentication($user, $password) {
|
||||||
|
|
@ -101,16 +117,25 @@ class RawConnection {
|
||||||
? "username=$user"
|
? "username=$user"
|
||||||
: "username=$user\npassword=$password";
|
: "username=$user\npassword=$password";
|
||||||
|
|
||||||
if (fwrite($this->pipes[3], $auth) === false) {
|
if (fwrite($this->getAuthStream(), $auth) === false) {
|
||||||
fclose($this->pipes[3]);
|
fclose($this->getAuthStream());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose($this->pipes[3]);
|
fclose($this->getAuthStream());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function close($terminate = true) {
|
||||||
|
if (!is_resource($this->process)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($terminate) {
|
||||||
proc_terminate($this->process);
|
proc_terminate($this->process);
|
||||||
|
}
|
||||||
proc_close($this->process);
|
proc_close($this->process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
namespace Icewind\SMB;
|
namespace Icewind\SMB;
|
||||||
|
|
||||||
|
use Icewind\Streams\CallbackWrapper;
|
||||||
|
|
||||||
class Share implements IShare {
|
class Share implements IShare {
|
||||||
/**
|
/**
|
||||||
* @var Server $server
|
* @var Server $server
|
||||||
|
|
@ -22,7 +24,7 @@ class Share implements IShare {
|
||||||
/**
|
/**
|
||||||
* @var Connection $connection
|
* @var Connection $connection
|
||||||
*/
|
*/
|
||||||
private $connection;
|
public $connection;
|
||||||
|
|
||||||
private $serverTimezone;
|
private $serverTimezone;
|
||||||
|
|
||||||
|
|
@ -203,25 +205,68 @@ class Share implements IShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a readable stream top a remote file
|
* Open a readable stream to a remote file
|
||||||
*
|
*
|
||||||
* @param string $source
|
* @param string $source
|
||||||
* @return resource a read only stream with the contents of the remote file
|
* @return resource a read only stream with the contents of the remote file
|
||||||
*/
|
*/
|
||||||
public function read($source) {
|
public function read($source) {
|
||||||
$source = $this->escapePath($source);
|
$source = $this->escapePath($source);
|
||||||
// since we do binary transfer over STDOUT we create a new connection
|
// since returned stream is closed by the caller we need to create a new instance
|
||||||
|
// since we can't re-use the same file descriptor over multiple calls
|
||||||
$command = Server::CLIENT . ' --authentication-file=/proc/self/fd/3' .
|
$command = Server::CLIENT . ' --authentication-file=/proc/self/fd/3' .
|
||||||
' //' . $this->server->getHost() . '/' . $this->name
|
' //' . $this->server->getHost() . '/' . $this->name
|
||||||
. ' -c \'get ' . $source . ' -\'';
|
. ' -c \'get ' . $source . ' /proc/self/fd/5\'';
|
||||||
$connection = new Connection($command);
|
$connection = new Connection($command);
|
||||||
$connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
|
$connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
|
||||||
$fh = $connection->getOutputStream();
|
$fh = $connection->getFileOutputStream();
|
||||||
//save the connection as context of the stream to prevent it going out of scope and cleaning up the resource
|
//save the connection as context of the stream to prevent it going out of scope and cleaning up the resource
|
||||||
stream_context_set_option($fh, 'file', 'connection', $connection);
|
stream_context_set_option($fh, 'file', 'connection', $connection);
|
||||||
return $fh;
|
return $fh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a writable stream to a remote file
|
||||||
|
*
|
||||||
|
* @param string $target
|
||||||
|
* @return resource a write only stream to upload a remote file
|
||||||
|
*/
|
||||||
|
public function write($target) {
|
||||||
|
$target = $this->escapePath($target);
|
||||||
|
// since returned stream is closed by the caller we need to create a new instance
|
||||||
|
// since we can't re-use the same file descriptor over multiple calls
|
||||||
|
$command = Server::CLIENT . ' --authentication-file=/proc/self/fd/3' .
|
||||||
|
' //' . $this->server->getHost() . '/' . $this->name
|
||||||
|
. ' -c \'put /proc/self/fd/4 ' . $target . '\'';
|
||||||
|
$connection = new RawConnection($command);
|
||||||
|
$connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
|
||||||
|
$fh = $connection->getFileInputStream();
|
||||||
|
|
||||||
|
// use a close callback to ensure the upload is finished before continuing
|
||||||
|
// this also serves as a way to keep the connection in scope
|
||||||
|
return CallbackWrapper::wrap($fh, null, null, function () use ($connection) {
|
||||||
|
$connection->close(false); // dont terminate, give the upload some time
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resource $source
|
||||||
|
* @param callable $callback
|
||||||
|
* @return resource
|
||||||
|
*/
|
||||||
|
protected function addCloseCallback($source, $callback) {
|
||||||
|
$context = stream_context_create(array(
|
||||||
|
'callback' => array(
|
||||||
|
'source' => $source,
|
||||||
|
'close' => $callback
|
||||||
|
)
|
||||||
|
));
|
||||||
|
stream_wrapper_register('callback', '\Icewind\Streams\CallbackWrapper');
|
||||||
|
$stream = fopen('callback://', 'r+', false, $context);
|
||||||
|
stream_wrapper_unregister('callback');
|
||||||
|
return $stream;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $command
|
* @param string $command
|
||||||
* @return array
|
* @return array
|
||||||
|
|
|
||||||
|
|
@ -68,17 +68,6 @@ class NativeStream extends \PHPUnit_Framework_TestCase {
|
||||||
$this->assertEquals(120, ftell($fh));
|
$this->assertEquals(120, ftell($fh));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testWrite() {
|
|
||||||
$fh = $this->share->write($this->root . '/foobar');
|
|
||||||
fwrite($fh, 'qwerty');
|
|
||||||
fclose($fh);
|
|
||||||
|
|
||||||
$tmpFile1 = tempnam('/tmp', 'smb_test_');
|
|
||||||
$this->share->get($this->root . '/foobar', $tmpFile1);
|
|
||||||
$this->assertEquals('qwerty', file_get_contents($tmpFile1));
|
|
||||||
unlink($tmpFile1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testStat() {
|
public function testStat() {
|
||||||
$sourceFile = $this->getTextFile();
|
$sourceFile = $this->getTextFile();
|
||||||
$this->share->put($sourceFile, $this->root . '/foobar');
|
$this->share->put($sourceFile, $this->root . '/foobar');
|
||||||
|
|
|
||||||
|
|
@ -298,4 +298,17 @@ class Share extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
$this->assertEquals(file_get_contents($sourceFile), $content);
|
$this->assertEquals(file_get_contents($sourceFile), $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testWriteStream() {
|
||||||
|
$fh = $this->share->write($this->root . '/foobar', 'qwerty');
|
||||||
|
fwrite($fh, 'qwerty');
|
||||||
|
fclose($fh);
|
||||||
|
// sleep(5);
|
||||||
|
|
||||||
|
|
||||||
|
$tmpFile1 = tempnam('/tmp', 'smb_test_');
|
||||||
|
$this->share->get($this->root . '/foobar', $tmpFile1);
|
||||||
|
$this->assertEquals('qwerty', file_get_contents($tmpFile1));
|
||||||
|
unlink($tmpFile1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue