mirror of
https://codeberg.org/icewind/SMB.git
synced 2026-06-03 17:24:07 +02:00
move backends into their own namespace and add support for multiple auth methods
This commit is contained in:
parent
2280570d28
commit
29bdebad42
33 changed files with 752 additions and 377 deletions
85
src/AbstractServer.php
Normal file
85
src/AbstractServer.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
|
||||
|
||||
abstract class AbstractServer implements IServer {
|
||||
const LOCALE = 'en_US.UTF-8';
|
||||
|
||||
/**
|
||||
* @var string $host
|
||||
*/
|
||||
protected $host;
|
||||
|
||||
/**
|
||||
* @var IAuth $user
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\System
|
||||
*/
|
||||
protected $system;
|
||||
|
||||
/**
|
||||
* @var TimeZoneProvider
|
||||
*/
|
||||
protected $timezoneProvider;
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param IAuth $auth
|
||||
* @param System $system
|
||||
* @param TimeZoneProvider $timeZoneProvider
|
||||
*/
|
||||
public function __construct($host, IAuth $auth, System $system, TimeZoneProvider $timeZoneProvider) {
|
||||
$this->host = $host;
|
||||
$this->auth = $auth;
|
||||
$this->system = $system;
|
||||
$this->timezoneProvider = $timeZoneProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return IAuth
|
||||
*/
|
||||
public function getAuth() {
|
||||
return $this->auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* return string
|
||||
*/
|
||||
public function getHost() {
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeZone() {
|
||||
return $this->timezoneProvider->get();
|
||||
}
|
||||
|
||||
public function getSystem() {
|
||||
return $this->system;
|
||||
}
|
||||
}
|
||||
82
src/BasicAuth.php
Normal file
82
src/BasicAuth.php
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
|
||||
|
||||
class BasicAuth implements IAuth {
|
||||
/** @var string */
|
||||
private $username;
|
||||
/** @var string */
|
||||
private $workgroup;
|
||||
/** @var string */
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* BasicAuth constructor.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*/
|
||||
public function __construct($username, $password) {
|
||||
list($workgroup, $username) = $this->splitUser($username);
|
||||
$this->username = $username;
|
||||
$this->workgroup = $workgroup;
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split workgroup from username
|
||||
*
|
||||
* @param $user
|
||||
* @return string[] [$workgroup, $user]
|
||||
*/
|
||||
private function splitUser($user) {
|
||||
if (strpos($user, '/')) {
|
||||
return explode('/', $user, 2);
|
||||
} elseif (strpos($user, '\\')) {
|
||||
return explode('\\', $user);
|
||||
} else {
|
||||
return array(null, $user);
|
||||
}
|
||||
}
|
||||
|
||||
public function getUsername() {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function getWorkgroup() {
|
||||
return $this->workgroup;
|
||||
}
|
||||
|
||||
public function getPassword() {
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function getExtraCommandLineArguments() {
|
||||
return ($this->workgroup) ? '-W ' . escapeshellarg($this->workgroup) : '';
|
||||
}
|
||||
|
||||
public function setExtraSmbClientOptions($smbClientState) {
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
||||
53
src/IAuth.php
Normal file
53
src/IAuth.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
|
||||
interface IAuth {
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUsername();
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getWorkgroup();
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPassword();
|
||||
|
||||
/**
|
||||
* Any extra command line option for smbclient that are required
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExtraCommandLineArguments();
|
||||
|
||||
/**
|
||||
* Set any extra options for libsmbclient that are required
|
||||
*
|
||||
* @param resource $smbClientState
|
||||
*/
|
||||
public function setExtraSmbClientOptions($smbClientState);
|
||||
}
|
||||
|
|
@ -8,6 +8,19 @@
|
|||
namespace Icewind\SMB;
|
||||
|
||||
interface IFileInfo {
|
||||
/*
|
||||
* Mappings of the DOS mode bits, as returned by smbc_getxattr() when the
|
||||
* attribute name "system.dos_attr.mode" (or "system.dos_attr.*" or
|
||||
* "system.*") is specified.
|
||||
*/
|
||||
const MODE_READONLY = 0x01;
|
||||
const MODE_HIDDEN = 0x02;
|
||||
const MODE_SYSTEM = 0x04;
|
||||
const MODE_VOLUME_ID = 0x08;
|
||||
const MODE_DIRECTORY = 0x10;
|
||||
const MODE_ARCHIVE = 0x20;
|
||||
const MODE_NORMAL = 0x80;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
|
|
|||
64
src/IServer.php
Normal file
64
src/IServer.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
|
||||
interface IServer {
|
||||
/**
|
||||
* @return IAuth
|
||||
*/
|
||||
public function getAuth();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHost();
|
||||
|
||||
/**
|
||||
* @return \Icewind\SMB\IShare[]
|
||||
*
|
||||
* @throws \Icewind\SMB\Exception\AuthenticationException
|
||||
* @throws \Icewind\SMB\Exception\InvalidHostException
|
||||
*/
|
||||
public function listShares();
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return \Icewind\SMB\IShare
|
||||
*/
|
||||
public function getShare($name);
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeZone();
|
||||
|
||||
/**
|
||||
* @return System
|
||||
*/
|
||||
public function getSystem();
|
||||
|
||||
/**
|
||||
* @param System $system
|
||||
* @return bool
|
||||
*/
|
||||
public static function available(System $system);
|
||||
}
|
||||
49
src/KerberosAuth.php
Normal file
49
src/KerberosAuth.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
|
||||
/**
|
||||
* Use existing kerberos ticket to authenticate
|
||||
*/
|
||||
class KerberosAuth implements IAuth {
|
||||
public function getUsername() {
|
||||
return 'dummy';
|
||||
}
|
||||
|
||||
public function getWorkgroup() {
|
||||
return 'dummy';
|
||||
}
|
||||
|
||||
public function getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getExtraCommandLineArguments() {
|
||||
return '-k';
|
||||
}
|
||||
|
||||
public function setExtraSmbClientOptions($smbClientState) {
|
||||
smbclient_option_set($smbClientState, SMBCLIENT_OPT_USE_KERBEROS, true);
|
||||
smbclient_option_set($smbClientState, SMBCLIENT_OPT_FALLBACK_AFTER_KERBEROS, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,7 +5,9 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
use Icewind\SMB\IFileInfo;
|
||||
|
||||
class NativeFileInfo implements IFileInfo {
|
||||
const MODE_FILE = 0100000;
|
||||
|
|
@ -21,7 +23,7 @@ class NativeFileInfo implements IFileInfo {
|
|||
protected $name;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\NativeShare
|
||||
* @var NativeShare
|
||||
*/
|
||||
protected $share;
|
||||
|
||||
|
|
@ -36,7 +38,7 @@ class NativeFileInfo implements IFileInfo {
|
|||
protected $modeCache;
|
||||
|
||||
/**
|
||||
* @param \Icewind\SMB\NativeShare $share
|
||||
* @param NativeShare $share
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
* @param array $stat
|
||||
|
|
@ -113,7 +115,7 @@ class NativeFileInfo implements IFileInfo {
|
|||
*/
|
||||
public function isReadOnly() {
|
||||
$mode = $this->getMode();
|
||||
return (bool)($mode & FileInfo::MODE_READONLY);
|
||||
return (bool)($mode & IFileInfo::MODE_READONLY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -121,7 +123,7 @@ class NativeFileInfo implements IFileInfo {
|
|||
*/
|
||||
public function isHidden() {
|
||||
$mode = $this->getMode();
|
||||
return (bool)($mode & FileInfo::MODE_HIDDEN);
|
||||
return (bool)($mode & IFileInfo::MODE_HIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,7 +131,7 @@ class NativeFileInfo implements IFileInfo {
|
|||
*/
|
||||
public function isSystem() {
|
||||
$mode = $this->getMode();
|
||||
return (bool)($mode & FileInfo::MODE_SYSTEM);
|
||||
return (bool)($mode & IFileInfo::MODE_SYSTEM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -137,6 +139,6 @@ class NativeFileInfo implements IFileInfo {
|
|||
*/
|
||||
public function isArchived() {
|
||||
$mode = $this->getMode();
|
||||
return (bool)($mode & FileInfo::MODE_ARCHIVE);
|
||||
return (bool)($mode & IFileInfo::MODE_ARCHIVE);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
/**
|
||||
* Stream optimized for read only usage
|
||||
|
|
@ -38,7 +38,7 @@ class NativeReadStream extends NativeStream {
|
|||
* @return resource
|
||||
*/
|
||||
public static function wrap($state, $smbStream, $mode, $url) {
|
||||
stream_wrapper_register('nativesmb', '\Icewind\SMB\NativeReadStream');
|
||||
stream_wrapper_register('nativesmb', NativeReadStream::class);
|
||||
$context = stream_context_create(array(
|
||||
'nativesmb' => array(
|
||||
'state' => $state,
|
||||
|
|
@ -5,26 +5,32 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
class NativeServer extends Server {
|
||||
use Icewind\SMB\AbstractServer;
|
||||
use Icewind\SMB\IAuth;
|
||||
use Icewind\SMB\System;
|
||||
use Icewind\SMB\TimeZoneProvider;
|
||||
|
||||
class NativeServer extends AbstractServer {
|
||||
/**
|
||||
* @var \Icewind\SMB\NativeState
|
||||
* @var NativeState
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
* @param IAuth $auth
|
||||
* @param System $system
|
||||
* @param TimeZoneProvider $timeZoneProvider
|
||||
*/
|
||||
public function __construct($host, $user, $password) {
|
||||
parent::__construct($host, $user, $password);
|
||||
public function __construct($host, IAuth $auth, System $system, TimeZoneProvider $timeZoneProvider) {
|
||||
parent::__construct($host, $auth, $system, $timeZoneProvider);
|
||||
$this->state = new NativeState();
|
||||
}
|
||||
|
||||
protected function connect() {
|
||||
$this->state->init($this->getWorkgroup(), $this->getUser(), $this->getPassword());
|
||||
$this->state->init($this->getAuth());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,4 +58,14 @@ class NativeServer extends Server {
|
|||
public function getShare($name) {
|
||||
return new NativeShare($this, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the smbclient php extension is available
|
||||
*
|
||||
* @param System $system
|
||||
* @return bool
|
||||
*/
|
||||
public static function available(System $system) {
|
||||
return function_exists('smbclient_state_new');
|
||||
}
|
||||
}
|
||||
|
|
@ -5,14 +5,20 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
use Icewind\SMB\AbstractShare;
|
||||
use Icewind\SMB\Exception\DependencyException;
|
||||
use Icewind\SMB\Exception\InvalidPathException;
|
||||
use Icewind\SMB\Exception\InvalidResourceException;
|
||||
use Icewind\SMB\INotifyHandler;
|
||||
use Icewind\SMB\IServer;
|
||||
use Icewind\SMB\Wrapped\Server;
|
||||
use Icewind\SMB\Wrapped\Share;
|
||||
|
||||
class NativeShare extends AbstractShare {
|
||||
/**
|
||||
* @var Server $server
|
||||
* @var IServer $server
|
||||
*/
|
||||
private $server;
|
||||
|
||||
|
|
@ -22,12 +28,12 @@ class NativeShare extends AbstractShare {
|
|||
private $name;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\NativeState $state
|
||||
* @var NativeState $state
|
||||
*/
|
||||
private $state;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param IServer $server
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($server, $name) {
|
||||
|
|
@ -47,7 +53,7 @@ class NativeShare extends AbstractShare {
|
|||
}
|
||||
|
||||
$this->state = new NativeState();
|
||||
$this->state->init($this->server->getWorkgroup(), $this->server->getUser(), $this->server->getPassword());
|
||||
$this->state->init($this->server->getAuth());
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
|
|
@ -295,6 +301,9 @@ class NativeShare extends AbstractShare {
|
|||
public function notify($path) {
|
||||
// php-smbclient does support notify (https://github.com/eduardok/libsmbclient-php/issues/29)
|
||||
// so we use the smbclient based backend for this
|
||||
if (!Server::available($this->server->getSystem())) {
|
||||
throw new DependencyException('smbclient not found in path for notify command');
|
||||
}
|
||||
$share = new Share($this->server, $this->getName());
|
||||
return $share->notify($path);
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
use Icewind\SMB\Exception\AlreadyExistsException;
|
||||
use Icewind\SMB\Exception\ConnectionRefusedException;
|
||||
|
|
@ -20,6 +20,7 @@ use Icewind\SMB\Exception\NotEmptyException;
|
|||
use Icewind\SMB\Exception\NotFoundException;
|
||||
use Icewind\SMB\Exception\OutOfSpaceException;
|
||||
use Icewind\SMB\Exception\TimedOutException;
|
||||
use Icewind\SMB\IAuth;
|
||||
|
||||
/**
|
||||
* Low level wrapper for libsmbclient-php with error handling
|
||||
|
|
@ -63,7 +64,7 @@ class NativeState {
|
|||
protected function testResult($result, $uri) {
|
||||
if ($result === false or $result === null) {
|
||||
// smb://host/share/path
|
||||
if (is_string($uri)) {
|
||||
if (is_string($uri) && count(explode('/', $uri, 5)) > 4) {
|
||||
list(, , , , $path) = explode('/', $uri, 5);
|
||||
$path = '/' . $path;
|
||||
} else {
|
||||
|
|
@ -74,18 +75,17 @@ class NativeState {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $workGroup
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
* @param IAuth $auth
|
||||
* @return bool
|
||||
*/
|
||||
public function init($workGroup, $user, $password) {
|
||||
public function init(IAuth $auth) {
|
||||
if ($this->connected) {
|
||||
return true;
|
||||
}
|
||||
$this->state = smbclient_state_new();
|
||||
smbclient_option_set($this->state, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, false);
|
||||
$result = @smbclient_state_init($this->state, $workGroup, $user, $password);
|
||||
$auth->setExtraSmbClientOptions($this->state);
|
||||
$result = @smbclient_state_init($this->state, $auth->getWorkgroup(), $auth->getUsername(), $auth->getPassword());
|
||||
|
||||
$this->testResult($result, '');
|
||||
$this->connected = true;
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
use Icewind\SMB\Exception\Exception;
|
||||
use Icewind\SMB\Exception\InvalidRequestException;
|
||||
|
|
@ -18,7 +18,7 @@ class NativeStream implements File {
|
|||
public $context;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\NativeState
|
||||
* @var NativeState
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ class NativeStream implements File {
|
|||
* @return resource
|
||||
*/
|
||||
public static function wrap($state, $smbStream, $mode, $url) {
|
||||
stream_wrapper_register('nativesmb', '\Icewind\SMB\NativeStream');
|
||||
stream_wrapper_register('nativesmb', NativeStream::class);
|
||||
$context = stream_context_create(array(
|
||||
'nativesmb' => array(
|
||||
'state' => $state,
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Native;
|
||||
|
||||
/**
|
||||
* Stream optimized for write only usage
|
||||
|
|
@ -38,7 +38,7 @@ class NativeWriteStream extends NativeStream {
|
|||
* @return resource
|
||||
*/
|
||||
public static function wrap($state, $smbStream, $mode, $url) {
|
||||
stream_wrapper_register('nativesmb', '\Icewind\SMB\NativeWriteStream');
|
||||
stream_wrapper_register('nativesmb', NativeWriteStream::class);
|
||||
$context = stream_context_create(array(
|
||||
'nativesmb' => array(
|
||||
'state' => $state,
|
||||
166
src/Server.php
166
src/Server.php
|
|
@ -1,166 +0,0 @@
|
|||
<?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;
|
||||
|
||||
use Icewind\SMB\Exception\AuthenticationException;
|
||||
use Icewind\SMB\Exception\InvalidHostException;
|
||||
|
||||
class Server {
|
||||
const LOCALE = 'en_US.UTF-8';
|
||||
|
||||
/**
|
||||
* @var string $host
|
||||
*/
|
||||
protected $host;
|
||||
|
||||
/**
|
||||
* @var string $user
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* @var string $password
|
||||
*/
|
||||
protected $password;
|
||||
|
||||
/**
|
||||
* @var string $workgroup
|
||||
*/
|
||||
protected $workgroup;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\System
|
||||
*/
|
||||
private $system;
|
||||
|
||||
/**
|
||||
* @var TimeZoneProvider
|
||||
*/
|
||||
private $timezoneProvider;
|
||||
|
||||
/**
|
||||
* Check if the smbclient php extension is available
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function NativeAvailable() {
|
||||
return function_exists('smbclient_state_new');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
*/
|
||||
public function __construct($host, $user, $password) {
|
||||
$this->host = $host;
|
||||
list($workgroup, $user) = $this->splitUser($user);
|
||||
$this->user = $user;
|
||||
$this->workgroup = $workgroup;
|
||||
$this->password = $password;
|
||||
$this->system = new System();
|
||||
$this->timezoneProvider = new TimeZoneProvider($host, $this->system);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split workgroup from username
|
||||
*
|
||||
* @param $user
|
||||
* @return string[] [$workgroup, $user]
|
||||
*/
|
||||
public function splitUser($user) {
|
||||
if (strpos($user, '/')) {
|
||||
return explode('/', $user, 2);
|
||||
} elseif (strpos($user, '\\')) {
|
||||
return explode('\\', $user);
|
||||
} else {
|
||||
return array(null, $user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 string
|
||||
*/
|
||||
public function getWorkgroup() {
|
||||
return $this->workgroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Icewind\SMB\IShare[]
|
||||
*
|
||||
* @throws \Icewind\SMB\Exception\AuthenticationException
|
||||
* @throws \Icewind\SMB\Exception\InvalidHostException
|
||||
*/
|
||||
public function listShares() {
|
||||
$workgroupArgument = ($this->workgroup) ? ' -W ' . escapeshellarg($this->workgroup) : '';
|
||||
$command = sprintf('%s %s --authentication-file=%s -gL %s',
|
||||
$this->system->getSmbclientPath(),
|
||||
$workgroupArgument,
|
||||
System::getFD(3),
|
||||
escapeshellarg($this->getHost())
|
||||
);
|
||||
$connection = new RawConnection($command);
|
||||
$connection->writeAuthentication($this->getUser(), $this->getPassword());
|
||||
$connection->connect();
|
||||
$output = $connection->readAll();
|
||||
$parser = new Parser($this->timezoneProvider);
|
||||
|
||||
$parser->checkConnectionError($output[0]);
|
||||
|
||||
$shareNames = $parser->parseListShares($output);
|
||||
|
||||
$shares = array();
|
||||
foreach ($shareNames as $name => $description) {
|
||||
$shares[] = $this->getShare($name);
|
||||
}
|
||||
return $shares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return \Icewind\SMB\IShare
|
||||
*/
|
||||
public function getShare($name) {
|
||||
return new Share($this, $name, $this->system);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeZone() {
|
||||
return $this->timezoneProvider->get();
|
||||
}
|
||||
}
|
||||
64
src/ServerFactory.php
Normal file
64
src/ServerFactory.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
|
||||
|
||||
use Icewind\SMB\Exception\DependencyException;
|
||||
use Icewind\SMB\Native\NativeServer;
|
||||
use Icewind\SMB\Wrapped\Server;
|
||||
|
||||
class ServerFactory {
|
||||
const BACKENDS = [
|
||||
NativeServer::class,
|
||||
Server::class
|
||||
];
|
||||
|
||||
/** @var System|null */
|
||||
private $system = null;
|
||||
|
||||
/**
|
||||
* @param $host
|
||||
* @param IAuth $credentials
|
||||
* @return IServer
|
||||
* @throws DependencyException
|
||||
*/
|
||||
public function createServer($host, IAuth $credentials) {
|
||||
foreach (self::BACKENDS as $backend) {
|
||||
if (call_user_func("$backend::available", $this->getSystem())) {
|
||||
return new $backend($host, $credentials, $this->getSystem(), new TimeZoneProvider($host, $this->getSystem()));
|
||||
}
|
||||
}
|
||||
|
||||
throw new DependencyException('No valid backend available, ensure smbclient is in the path or php-smbclient is installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return System
|
||||
*/
|
||||
private function getSystem() {
|
||||
if (is_null($this->system)) {
|
||||
$this->system = new System();
|
||||
}
|
||||
|
||||
return $this->system;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
use Icewind\SMB\Exception\AuthenticationException;
|
||||
use Icewind\SMB\Exception\ConnectException;
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
class ErrorCodes {
|
||||
/**
|
||||
|
|
@ -5,22 +5,11 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
use Icewind\SMB\IFileInfo;
|
||||
|
||||
class FileInfo implements IFileInfo {
|
||||
/*
|
||||
* Mappings of the DOS mode bits, as returned by smbc_getxattr() when the
|
||||
* attribute name "system.dos_attr.mode" (or "system.dos_attr.*" or
|
||||
* "system.*") is specified.
|
||||
*/
|
||||
const MODE_READONLY = 0x01;
|
||||
const MODE_HIDDEN = 0x02;
|
||||
const MODE_SYSTEM = 0x04;
|
||||
const MODE_VOLUME_ID = 0x08;
|
||||
const MODE_DIRECTORY = 0x10;
|
||||
const MODE_ARCHIVE = 0x20;
|
||||
const MODE_NORMAL = 0x80;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -93,34 +82,34 @@ class FileInfo implements IFileInfo {
|
|||
* @return bool
|
||||
*/
|
||||
public function isDirectory() {
|
||||
return (bool)($this->mode & self::MODE_DIRECTORY);
|
||||
return (bool)($this->mode & IFileInfo::MODE_DIRECTORY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isReadOnly() {
|
||||
return (bool)($this->mode & self::MODE_READONLY);
|
||||
return (bool)($this->mode & IFileInfo::MODE_READONLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isHidden() {
|
||||
return (bool)($this->mode & self::MODE_HIDDEN);
|
||||
return (bool)($this->mode & IFileInfo::MODE_HIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSystem() {
|
||||
return (bool)($this->mode & self::MODE_SYSTEM);
|
||||
return (bool)($this->mode & IFileInfo::MODE_SYSTEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isArchived() {
|
||||
return (bool)($this->mode & self::MODE_ARCHIVE);
|
||||
return (bool)($this->mode & IFileInfo::MODE_ARCHIVE);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,11 +6,13 @@
|
|||
*
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
|
||||
use Icewind\SMB\Change;
|
||||
use Icewind\SMB\Exception\Exception;
|
||||
use Icewind\SMB\Exception\RevisionMismatchException;
|
||||
use Icewind\SMB\INotifyHandler;
|
||||
|
||||
class NotifyHandler implements INotifyHandler {
|
||||
/**
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
use Icewind\SMB\Exception\AccessDeniedException;
|
||||
use Icewind\SMB\Exception\AlreadyExistsException;
|
||||
|
|
@ -19,6 +19,7 @@ use Icewind\SMB\Exception\InvalidTypeException;
|
|||
use Icewind\SMB\Exception\NoLoginServerException;
|
||||
use Icewind\SMB\Exception\NotEmptyException;
|
||||
use Icewind\SMB\Exception\NotFoundException;
|
||||
use Icewind\SMB\TimeZoneProvider;
|
||||
|
||||
class Parser {
|
||||
const MSG_NOT_FOUND = 'Error opening local file ';
|
||||
|
|
@ -45,7 +46,7 @@ class Parser {
|
|||
];
|
||||
|
||||
/**
|
||||
* @param \Icewind\SMB\TimeZoneProvider $timeZoneProvider
|
||||
* @param TimeZoneProvider $timeZoneProvider
|
||||
*/
|
||||
public function __construct(TimeZoneProvider $timeZoneProvider) {
|
||||
$this->timeZoneProvider = $timeZoneProvider;
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
use Icewind\SMB\Exception\ConnectException;
|
||||
use Icewind\SMB\Exception\ConnectionException;
|
||||
70
src/Wrapped/Server.php
Normal file
70
src/Wrapped/Server.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?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\Wrapped;
|
||||
|
||||
use Icewind\SMB\AbstractServer;
|
||||
use Icewind\SMB\System;
|
||||
|
||||
class Server extends AbstractServer {
|
||||
/**
|
||||
* Check if the smbclient php extension is available
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function available(System $system) {
|
||||
return $system->getSmbclientPath();
|
||||
}
|
||||
|
||||
private function getAuthFileArgument() {
|
||||
if ($this->getAuth()->getUsername()) {
|
||||
return '--authentication-file=' . System::getFD(3);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Icewind\SMB\IShare[]
|
||||
*
|
||||
* @throws \Icewind\SMB\Exception\AuthenticationException
|
||||
* @throws \Icewind\SMB\Exception\InvalidHostException
|
||||
*/
|
||||
public function listShares() {
|
||||
$command = sprintf('%s %s %s -L %s',
|
||||
$this->system->getSmbclientPath(),
|
||||
$this->getAuthFileArgument(),
|
||||
$this->getAuth()->getExtraCommandLineArguments(),
|
||||
escapeshellarg('//' . $this->getHost())
|
||||
);
|
||||
$connection = new RawConnection($command);
|
||||
$connection->writeAuthentication($this->getAuth()->getUsername(), $this->getAuth()->getPassword());
|
||||
$connection->connect();
|
||||
$output = $connection->readAll();
|
||||
$parser = new Parser($this->timezoneProvider);
|
||||
|
||||
if (isset($output[0])) {
|
||||
$parser->checkConnectionError($output[0]);
|
||||
}
|
||||
|
||||
$shareNames = $parser->parseListShares($output);
|
||||
|
||||
$shares = array();
|
||||
foreach ($shareNames as $name => $description) {
|
||||
$shares[] = $this->getShare($name);
|
||||
}
|
||||
return $shares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return \Icewind\SMB\IShare
|
||||
*/
|
||||
public function getShare($name) {
|
||||
return new Share($this, $name, $this->system);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,18 +5,23 @@
|
|||
* http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Icewind\SMB;
|
||||
namespace Icewind\SMB\Wrapped;
|
||||
|
||||
use Icewind\SMB\AbstractShare;
|
||||
use Icewind\SMB\Exception\ConnectionException;
|
||||
use Icewind\SMB\Exception\DependencyException;
|
||||
use Icewind\SMB\Exception\FileInUseException;
|
||||
use Icewind\SMB\Exception\InvalidTypeException;
|
||||
use Icewind\SMB\Exception\NotFoundException;
|
||||
use Icewind\SMB\INotifyHandler;
|
||||
use Icewind\SMB\IServer;
|
||||
use Icewind\SMB\System;
|
||||
use Icewind\SMB\TimeZoneProvider;
|
||||
use Icewind\Streams\CallbackWrapper;
|
||||
|
||||
class Share extends AbstractShare {
|
||||
/**
|
||||
* @var Server $server
|
||||
* @var IServer $server
|
||||
*/
|
||||
private $server;
|
||||
|
||||
|
|
@ -31,21 +36,21 @@ class Share extends AbstractShare {
|
|||
public $connection;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\Parser
|
||||
* @var Parser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
/**
|
||||
* @var \Icewind\SMB\System
|
||||
* @var System
|
||||
*/
|
||||
private $system;
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param IServer $server
|
||||
* @param string $name
|
||||
* @param System $system
|
||||
*/
|
||||
public function __construct($server, $name, System $system = null) {
|
||||
public function __construct(IServer $server, $name, System $system = null) {
|
||||
parent::__construct();
|
||||
$this->server = $server;
|
||||
$this->name = $name;
|
||||
|
|
@ -53,21 +58,24 @@ class Share extends AbstractShare {
|
|||
$this->parser = new Parser(new TimeZoneProvider($this->server->getHost(), $this->system));
|
||||
}
|
||||
|
||||
protected function getConnection() {
|
||||
$workgroupArgument = ($this->server->getWorkgroup()) ? ' -W ' . escapeshellarg($this->server->getWorkgroup()) : '';
|
||||
$smbClientPath = $this->system->getSmbclientPath();
|
||||
if (!$smbClientPath) {
|
||||
throw new DependencyException('Can\'t find smbclient binary in path');
|
||||
private function getAuthFileArgument() {
|
||||
if ($this->server->getAuth()->getUsername()) {
|
||||
return '--authentication-file=' . System::getFD(3);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
$command = sprintf('%s%s %s --authentication-file=%s %s',
|
||||
}
|
||||
|
||||
protected function getConnection() {
|
||||
$command = sprintf('%s%s %s %s %s',
|
||||
$this->system->hasStdBuf() ? 'stdbuf -o0 ' : '',
|
||||
$this->system->getSmbclientPath(),
|
||||
$workgroupArgument,
|
||||
System::getFD(3),
|
||||
$this->getAuthFileArgument(),
|
||||
$this->server->getAuth()->getExtraCommandLineArguments(),
|
||||
escapeshellarg('//' . $this->server->getHost() . '/' . $this->name)
|
||||
);
|
||||
$connection = new Connection($command, $this->parser);
|
||||
$connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
|
||||
$connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword());
|
||||
$connection->connect();
|
||||
if (!$connection->isValid()) {
|
||||
throw new ConnectionException($connection->readLine());
|
||||
Loading…
Add table
Add a link
Reference in a new issue