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 9 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
19 changes: 19 additions & 0 deletions apps/files_external/3rdparty/smb/autoload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?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.
*/

set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__);

require_once 'errors.php';

spl_autoload_register(function ($class) {
Copy link

Choose a reason for hiding this comment

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

Can't this be done in a more automatic-autoload-approach, i.e. without registering your own autoloader?

if (substr($class, 0, 4) == 'SMB\\') {
$class = strtolower($class);
$file = str_replace('\\', '/', substr($class, 4));
include __DIR__ . '/' . $file . '.php';
}
});
61 changes: 61 additions & 0 deletions apps/files_external/3rdparty/smb/cachingshare.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?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 SMB;

/**
* Class CachingShare
*
* caches metadata from share
*
* @package SMB
*/
class CachingShare extends Share {
private $dirCache = array();

private function clear($path = null) {
if (is_null($path)) {
$this->dirCache = array();
} else {
unset($this->dirCache[$path]);
}
}

public function dir($path) {
if (!isset($this->dirCache[$path])) {
$this->dirCache[$path] = parent::dir($path);
}
return $this->dirCache[$path];
}

public function mkdir($path) {
$this->clear(dirname($path));
return parent::mkdir($path);
}

public function rmdir($path) {
$this->clear(dirname($path));
return parent::rmdir($path);
}

public function del($path) {
$this->clear(dirname($path));
return parent::del($path);
}

public function put($source, $target) {
$this->clear(dirname($target));
return parent::put($source, $target);
}

public function rename($from, $to) {
$this->clear(dirname($from));
$this->clear(dirname($to));
return parent::rename($from, $to);
}
}
77 changes: 77 additions & 0 deletions apps/files_external/3rdparty/smb/connection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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 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 untill the next prompt
*
* @throws ConnectionError
* @return array
*/
public function read() {
if (!$this->isValid()) {
throw new ConnectionError();
}
$line = parent::read(); //first line is prompt
$this->checkConnectionError($line);

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

/**
* 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/errors.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 SMB;

class NotFoundException extends \Exception {
Copy link

Choose a reason for hiding this comment

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

Are these exceptions all required? Maybe some of the SPL exceptions could be reused. http://www.php.net/manual/en/spl.exceptions.php

}

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';
Copy link

Choose a reason for hiding this comment

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

I'm not sure I see how these constants are useful. Why not use the string constants verbatim?

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/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 SMB;

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

Choose a reason for hiding this comment

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

Shouldn't these be available to subclasses? Personally, I think that the number of proper use-cases of private is just as limited as the number of use-cases for static.


/**
* @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')
Copy link

Choose a reason for hiding this comment

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

This seems to indicate this is a client for unix only, which is okay. I also remember discussing that on Windows native mounts and local storage should be used, which is okay, but it should be documented in the class description (or even checked).

);
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 array
*/
public function read() {
return trim(fgets($this->pipes[1]));
}

/**
* 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);
}
}
Loading