Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new SMB storage backend #4770

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bc276ae
new smb storage backend
icewind1991 Jun 7, 2013
a85d38d
Merge branch 'master' into smb
icewind1991 Jul 4, 2013
aad2304
smb: fix stat behaviour
icewind1991 Jul 4, 2013
a77119f
disable external storage tests
icewind1991 Jul 4, 2013
37f4c55
merge master into smb
icewind1991 Sep 6, 2013
88e5712
add smb wrapper to 3rdparty
icewind1991 Sep 8, 2013
a73d058
smb: fix share mtime
icewind1991 Sep 8, 2013
8a8110b
use ===
icewind1991 Sep 8, 2013
1db7e7b
fix accidental comment
icewind1991 Sep 8, 2013
1770fdc
fixing typo
DeepDiver1975 Sep 9, 2013
5141028
merge master into smb
icewind1991 Nov 26, 2013
5c4eb85
Merge branch 'master' into smb
icewind1991 Dec 17, 2013
5812a5b
Update SMB streamwrapper
icewind1991 Dec 17, 2013
8631534
Fix rename not returning a result, unlink not working on folders and …
icewind1991 Dec 17, 2013
bd781d7
Merge branch 'smb' of github.com:owncloud/core into smb
icewind1991 Dec 17, 2013
8079a9c
check if the file exists for isReadable and isUpdatable
icewind1991 Dec 17, 2013
a2764ab
Merge branch 'master' into smb
icewind1991 Dec 19, 2013
be3a5c6
Merge branch 'master' into smb
icewind1991 Jan 3, 2014
d7f160c
Merge branch 'master' into smb
icewind1991 Jan 14, 2014
6beee91
merge 3rdparty submodule
icewind1991 Jan 14, 2014
d515aa2
merge master into smb
icewind1991 Jan 30, 2014
d7fdbc8
Merge branch 'master' into smb
icewind1991 Feb 4, 2014
538961f
Fix parsing smb dir result
icewind1991 Feb 5, 2014
a674726
Merge branch 'master' into smb
icewind1991 Feb 25, 2014
80f4e68
update smb library
icewind1991 Feb 25, 2014
48e8e8a
merge master into smb
icewind1991 Mar 26, 2014
8cd05d7
merge master into smb
icewind1991 Apr 7, 2014
5baec0f
use PSR style autoloading for smb
icewind1991 Apr 7, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions apps/files_external/3rdparty/smb/Icewind/SMB/Connection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <[email protected]>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace Icewind\SMB;

class Connection extends RawConnection {
const DELIMITER = 'smb:';

/**
* send input to smbclient
*
* @param string $input
*/
public function write($input) {
parent::write($input . PHP_EOL);
}

/**
* get all unprocessed output from smbclient until the next prompt
*
* @throws ConnectionError
* @return string
*/
public function read() {
if (!$this->isValid()) {
throw new ConnectionError();
}
$line = $this->readLine(); //first line is prompt
$this->checkConnectionError($line);

$output = array();
$line = $this->readLine();
$length = strlen(self::DELIMITER);
while (substr($line, 0, $length) !== self::DELIMITER) { //next prompt functions as delimiter
$output[] .= $line;
$line = parent::read();
}
return $output;
}

/**
* read a single line of unprocessed output
*
* @return string
*/
public function readLine() {
return parent::read();
}

/**
* check if the first line holds a connection failure
*
* @param $line
* @throws AuthenticationException
* @throws InvalidHostException
*/
private function checkConnectionError($line) {
$line = rtrim($line, ')');
if (substr($line, -23) === ErrorCodes::LogonFailure) {
throw new AuthenticationException();
}
if (substr($line, -26) === ErrorCodes::BadHostName) {
throw new InvalidHostException();
}
if (substr($line, -22) === ErrorCodes::Unsuccessful) {
throw new InvalidHostException();
}
if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
throw new InvalidHostException();
}
}

public function close() {
$this->write('close' . PHP_EOL);
}

public function __destruct() {
$this->close();
parent::__destruct();
}
}
52 changes: 52 additions & 0 deletions apps/files_external/3rdparty/smb/Icewind/SMB/ErrorCodes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* Copyright (c) 2012 Robin Appelman <[email protected]>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace Icewind\SMB;

class NotFoundException extends \Exception {
}

class AlreadyExistsException extends \Exception {
}

class NotEmptyException extends \Exception {
}

class ConnectionError extends \Exception {
}

class AuthenticationException extends \Exception {
}

class InvalidHostException extends \Exception {
}

class AccessDeniedException extends \Exception {
}

class InvalidTypeException extends \Exception {
}

class ErrorCodes {
/**
* connection errors
*/
const LogonFailure = 'NT_STATUS_LOGON_FAILURE';
const BadHostName = 'NT_STATUS_BAD_NETWORK_NAME';
const Unsuccessful = 'NT_STATUS_UNSUCCESSFUL';
const ConnectionRefused = 'NT_STATUS_CONNECTION_REFUSED';

const PathNotFound = 'NT_STATUS_OBJECT_PATH_NOT_FOUND';
const NoSuchFile = 'NT_STATUS_NO_SUCH_FILE';
const ObjectNotFound = 'NT_STATUS_OBJECT_NAME_NOT_FOUND';
const NameCollision = 'NT_STATUS_OBJECT_NAME_COLLISION';
const AccessDenied = 'NT_STATUS_ACCESS_DENIED';
const DirectoryNotEmpty = 'NT_STATUS_DIRECTORY_NOT_EMPTY';
const FileIsADirectory = 'NT_STATUS_FILE_IS_A_DIRECTORY';
const NotADirectory = 'NT_STATUS_NOT_A_DIRECTORY';
}
92 changes: 92 additions & 0 deletions apps/files_external/3rdparty/smb/Icewind/SMB/RawConnection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <[email protected]>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace Icewind\SMB;

class RawConnection {
/**
* @var resource[] $pipes
*
* $pipes[0] holds STDIN for smbclient
* $pipes[1] holds STDOUT for smbclient
*/
private $pipes;

/**
* @var resource $process
*/
private $process;


public function __construct($command) {
$descriptorSpec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array('file', '/dev/null', 'w')
);
setlocale(LC_ALL, Server::LOCALE);
$this->process = proc_open($command, $descriptorSpec, $this->pipes, null, array(
'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!!
'LC_ALL' => Server::LOCALE
));
if (!$this->isValid()) {
throw new ConnectionError();
}
}

/**
* check if the connection is still active
*
* @return bool
*/
public function isValid() {
if (is_resource($this->process)) {
$status = proc_get_status($this->process);
return $status['running'];
} else {
return false;
}
}

/**
* send input to the process
*
* @param string $input
*/
public function write($input) {
fwrite($this->pipes[0], $input);
fflush($this->pipes[0]);
}

/**
* read a line of output
*
* @return string
*/
public function read() {
return trim(fgets($this->pipes[1]));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. trim() on binary data?

}

/**
* get all output until the process closes
*
* @return array
*/
public function readAll() {
$output = array();
while ($line = $this->read()) {
$output[] = $line;
}
return $output;
}

public function __destruct() {
proc_terminate($this->process);
proc_close($this->process);
}
}
134 changes: 134 additions & 0 deletions apps/files_external/3rdparty/smb/Icewind/SMB/Server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?php
/**
* Copyright (c) 2013 Robin Appelman <[email protected]>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/

namespace Icewind\SMB;

class Server {
const CLIENT = 'smbclient';
const LOCALE = 'en_US.UTF-8';

/**
* @var string $host
*/
private $host;

/**
* @var string $user
*/
private $user;

/**
* @var string $password
*/
private $password;

/**
* @param string $host
* @param string $user
* @param string $password
*/
public function __construct($host, $user, $password) {
$this->host = $host;
$this->user = $user;
$this->password = $password;
}

/**
* @return string
*/
public function getAuthString() {
return $this->user . '%' . $this->password;
}

/**
* @return string
*/
public function getUser() {
return $this->user;
}

/**
* @return string
*/
public function getPassword() {
return $this->password;
}

/**
* return string
*/
public function getHost() {
return $this->host;
}

/**
* @return Share[]
* @throws \Icewind\SMB\AuthenticationException
* @throws \Icewind\SMB\InvalidHostException
*/
public function listShares() {
$user = escapeshellarg($this->getUser());
$command = self::CLIENT . ' -U ' . $user . ' ' . '-gL ' . escapeshellarg($this->getHost());
$connection = new RawConnection($command);
$connection->write($this->getPassword() . PHP_EOL);
$output = $connection->readAll();

$line = $output[0];

// disregard password prompt
if (substr($line, 0, 6) == 'Enter ' and count($output) > 1) {
$line = $output[1];
}

$line = rtrim($line, ')');
if (substr($line, -23) === ErrorCodes::LogonFailure) {
throw new AuthenticationException();
}
if (substr($line, -26) === ErrorCodes::BadHostName) {
throw new InvalidHostException();
}
if (substr($line, -22) === ErrorCodes::Unsuccessful) {
throw new InvalidHostException();
}
if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
throw new InvalidHostException();
}

$shareNames = array();
foreach ($output as $line) {
if (strpos($line, '|')) {
list($type, $name, $description) = explode('|', $line);
if (strtolower($type) === 'disk') {
$shareNames[$name] = $description;
}
}
}

$shares = array();
foreach ($shareNames as $name => $description) {
$shares[] = $this->getShare($name);
}
return $shares;
}

/**
* @param string $name
* @return Share
*/
public function getShare($name) {
return new Share($this, $name);
}

/**
* @return string
*/
public function getTimeZone() {
$command = 'net time zone -S ' . escapeshellarg($this->getHost());
return exec($command);
}
}
Loading