update icewind/smb to 1.0.4

This commit is contained in:
Robin Appelman 2015-08-17 16:31:29 +02:00
parent e76fc1cf38
commit 5514a133de
11 changed files with 99 additions and 43 deletions

View File

@ -6,7 +6,7 @@
"vendor-dir": "."
},
"require": {
"icewind/smb": "1.0.3",
"icewind/smb": "1.0.4",
"icewind/streams": "0.2"
}
}

View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "2c7c72fe357eb667fbd9921bad770ecd",
"hash": "5c612406bc1235075305b09a5d6996a9",
"packages": [
{
"name": "icewind/smb",
"version": "v1.0.3",
"version": "v1.0.4",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/SMB.git",
"reference": "33ab10cc4d5c3e48cba3a074b5f9fc67590cd032"
"reference": "9277bd20262a01b38a33cc7356e98055f2262d32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/33ab10cc4d5c3e48cba3a074b5f9fc67590cd032",
"reference": "33ab10cc4d5c3e48cba3a074b5f9fc67590cd032",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/9277bd20262a01b38a33cc7356e98055f2262d32",
"reference": "9277bd20262a01b38a33cc7356e98055f2262d32",
"shasum": ""
},
"require": {
@ -45,7 +45,7 @@
}
],
"description": "php wrapper for smbclient and libsmbclient-php",
"time": "2015-08-13 14:19:03"
"time": "2015-08-17 14:20:38"
},
{
"name": "icewind/streams",

View File

@ -43,17 +43,17 @@
},
{
"name": "icewind/smb",
"version": "v1.0.3",
"version_normalized": "1.0.3.0",
"version": "v1.0.4",
"version_normalized": "1.0.4.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/SMB.git",
"reference": "33ab10cc4d5c3e48cba3a074b5f9fc67590cd032"
"reference": "9277bd20262a01b38a33cc7356e98055f2262d32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/33ab10cc4d5c3e48cba3a074b5f9fc67590cd032",
"reference": "33ab10cc4d5c3e48cba3a074b5f9fc67590cd032",
"url": "https://api.github.com/repos/icewind1991/SMB/zipball/9277bd20262a01b38a33cc7356e98055f2262d32",
"reference": "9277bd20262a01b38a33cc7356e98055f2262d32",
"shasum": ""
},
"require": {
@ -63,7 +63,7 @@
"require-dev": {
"satooshi/php-coveralls": "dev-master"
},
"time": "2015-08-13 14:19:03",
"time": "2015-08-17 14:20:38",
"type": "library",
"installation-source": "source",
"autoload": {

View File

@ -0,0 +1,26 @@
<?php
/**
* Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Licensed under the MIT license:
* http://opensource.org/licenses/MIT
*/
namespace Icewind\SMB;
use Icewind\SMB\Exception\InvalidPathException;
abstract class AbstractShare implements IShare {
private $forbiddenCharacters;
public function __construct() {
$this->forbiddenCharacters = array('?', '<', '>', ':', '*', '|', '"', chr(0), "\n", "\r");
}
protected function verifyPath($path) {
foreach ($this->forbiddenCharacters as $char) {
if (strpos($path, $char) !== false) {
throw new InvalidPathException('Invalid path, "' . $char . '" is not allowed');
}
}
}
}

View File

@ -8,8 +8,10 @@
namespace Icewind\SMB;
use Icewind\SMB\Exception\AuthenticationException;
use Icewind\SMB\Exception\ConnectException;
use Icewind\SMB\Exception\ConnectionException;
use Icewind\SMB\Exception\InvalidHostException;
use Icewind\SMB\Exception\NoLoginServerException;
class Connection extends RawConnection {
const DELIMITER = 'smb:';
@ -26,18 +28,25 @@ class Connection extends RawConnection {
/**
* get all unprocessed output from smbclient until the next prompt
*
* @throws ConnectionException
* @return string
* @throws AuthenticationException
* @throws ConnectException
* @throws ConnectionException
* @throws InvalidHostException
* @throws NoLoginServerException
*/
public function read() {
if (!$this->isValid()) {
throw new ConnectionException();
throw new ConnectionException('Connection not valid');
}
$line = $this->readLine(); //first line is prompt
$this->checkConnectionError($line);
$output = array();
$line = $this->readLine();
if ($line === false) {
throw new ConnectException('Unknown error');
}
$length = mb_strlen(self::DELIMITER);
while (mb_substr($line, 0, $length) !== self::DELIMITER) { //next prompt functions as delimiter
$output[] .= $line;
@ -52,20 +61,24 @@ class Connection extends RawConnection {
* @param $line
* @throws AuthenticationException
* @throws InvalidHostException
* @throws NoLoginServerException
*/
private function checkConnectionError($line) {
$line = rtrim($line, ')');
if (substr($line, -23) === ErrorCodes::LogonFailure) {
throw new AuthenticationException();
throw new AuthenticationException('Invalid login');
}
if (substr($line, -26) === ErrorCodes::BadHostName) {
throw new InvalidHostException();
throw new InvalidHostException('Invalid hostname');
}
if (substr($line, -22) === ErrorCodes::Unsuccessful) {
throw new InvalidHostException();
throw new InvalidHostException('Connection unsuccessful');
}
if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
throw new InvalidHostException();
throw new InvalidHostException('Connection refused');
}
if (substr($line, -26) === ErrorCodes::NoLogonServers) {
throw new NoLoginServerException('No login server');
}
}

View File

@ -15,6 +15,7 @@ class ErrorCodes {
const BadHostName = 'NT_STATUS_BAD_NETWORK_NAME';
const Unsuccessful = 'NT_STATUS_UNSUCCESSFUL';
const ConnectionRefused = 'NT_STATUS_CONNECTION_REFUSED';
const NoLogonServers = 'NT_STATUS_NO_LOGON_SERVERS';
const PathNotFound = 'NT_STATUS_OBJECT_PATH_NOT_FOUND';
const NoSuchFile = 'NT_STATUS_NO_SUCH_FILE';

View File

@ -0,0 +1,10 @@
<?php
/**
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Licensed under the MIT license:
* http://opensource.org/licenses/MIT
*/
namespace Icewind\SMB\Exception;
class InvalidPathException extends InvalidRequestException {}

View File

@ -0,0 +1,10 @@
<?php
/**
* Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
* This file is licensed under the Licensed under the MIT license:
* http://opensource.org/licenses/MIT
*/
namespace Icewind\SMB\Exception;
class NoLoginServerException extends ConnectException {}

View File

@ -7,7 +7,7 @@
namespace Icewind\SMB;
class NativeShare implements IShare {
class NativeShare extends AbstractShare {
/**
* @var Server $server
*/
@ -28,6 +28,7 @@ class NativeShare implements IShare {
* @param string $name
*/
public function __construct($server, $name) {
parent::__construct();
$this->server = $server;
$this->name = $name;
$this->state = new NativeState();
@ -56,6 +57,7 @@ class NativeShare implements IShare {
}
private function buildUrl($path) {
$this->verifyPath($path);
$url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name);
if ($path) {
$path = trim($path, '/');

View File

@ -68,7 +68,7 @@ class Server {
} elseif (strpos($user, '\\')) {
return explode('\\', $user);
} else {
return [null, $user];
return array(null, $user);
}
}

View File

@ -7,17 +7,13 @@
namespace Icewind\SMB;
use Icewind\SMB\Exception\AccessDeniedException;
use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\ConnectionException;
use Icewind\SMB\Exception\Exception;
use Icewind\SMB\Exception\FileInUseException;
use Icewind\SMB\Exception\InvalidTypeException;
use Icewind\SMB\Exception\NotEmptyException;
use Icewind\SMB\Exception\NotFoundException;
use Icewind\Streams\CallbackWrapper;
class Share implements IShare {
class Share extends AbstractShare {
/**
* @var Server $server
*/
@ -43,6 +39,7 @@ class Share implements IShare {
* @param string $name
*/
public function __construct($server, $name) {
parent::__construct();
$this->server = $server;
$this->name = $name;
$this->parser = new Parser(new TimeZoneProvider($this->server->getHost()));
@ -58,11 +55,10 @@ class Share implements IShare {
return;
}
$workgroupArgument = ($this->server->getWorkgroup()) ? ' -W ' . escapeshellarg($this->server->getWorkgroup()) : '';
$command = sprintf('%s %s --authentication-file=/proc/self/fd/3 //%s/%s',
$command = sprintf('%s %s --authentication-file=/proc/self/fd/3 %s',
Server::CLIENT,
$workgroupArgument,
$this->server->getHost(),
$this->name
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
);
$this->connection = new Connection($command);
$this->connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
@ -258,20 +254,18 @@ class Share implements IShare {
*/
public function read($source) {
$source = $this->escapePath($source);
// close the single quote, open a double quote where we put the single quote...
$source = str_replace('\'', '\'"\'"\'', $source);
// 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
$workgroupArgument = ($this->server->getWorkgroup()) ? ' -W ' . escapeshellarg($this->server->getWorkgroup()) : '';
$command = sprintf('%s %s --authentication-file=/proc/self/fd/3 //%s/%s -c \'get %s /proc/self/fd/5\'',
$command = sprintf('%s %s --authentication-file=/proc/self/fd/3 %s',
Server::CLIENT,
$workgroupArgument,
$this->server->getHost(),
$this->name,
$source
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
);
$connection = new Connection($command);
$connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
$connection->write('get ' . $source . ' /proc/self/fd/5');
$connection->write('exit');
$fh = $connection->getFileOutputStream();
stream_context_set_option($fh, 'file', 'connection', $connection);
return $fh;
@ -288,25 +282,24 @@ class Share implements IShare {
*/
public function write($target) {
$target = $this->escapePath($target);
// close the single quote, open a double quote where we put the single quote...
$target = str_replace('\'', '\'"\'"\'', $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
$workgroupArgument = ($this->server->getWorkgroup()) ? ' -W ' . escapeshellarg($this->server->getWorkgroup()) : '';
$command = sprintf('%s %s --authentication-file=/proc/self/fd/3 //%s/%s -c \'put /proc/self/fd/4 %s\'',
$command = sprintf('%s %s --authentication-file=/proc/self/fd/3 %s',
Server::CLIENT,
$workgroupArgument,
$this->server->getHost(),
$this->name,
$target
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
);
$connection = new RawConnection($command);
$connection = new Connection($command);
$connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
$fh = $connection->getFileInputStream();
$connection->write('put /proc/self/fd/4 ' . $target);
$connection->write('exit');
// 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) {
return CallbackWrapper::wrap($fh, null, null, function () use ($connection, $target) {
$connection->close(false); // dont terminate, give the upload some time
});
}
@ -384,6 +377,7 @@ class Share implements IShare {
* @return string
*/
protected function escapePath($path) {
$this->verifyPath($path);
if ($path === '/') {
$path = '';
}