mirror of
https://codeberg.org/icewind/SMB.git
synced 2026-06-03 17:24:07 +02:00
initial commit
This commit is contained in:
commit
e324e70050
21 changed files with 1410 additions and 0 deletions
19
src/autoload.php
Normal file
19
src/autoload.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* 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) {
|
||||
if (substr($class, 0, 4) == 'SMB\\') {
|
||||
$class = strtolower($class);
|
||||
$file = str_replace('\\', '/', substr($class, 4));
|
||||
include $file . '.php';
|
||||
}
|
||||
});
|
||||
61
src/command/command.php
Normal file
61
src/command/command.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
abstract class Command {
|
||||
const CLIENT = 'smbclient';
|
||||
|
||||
/**
|
||||
* @var \SMB\Connection $connection
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* @param \SMB\Connection $connection
|
||||
*/
|
||||
public function __construct($connection) {
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $command
|
||||
* @return array
|
||||
*/
|
||||
protected function execute($command) {
|
||||
$auth = $this->escape($this->connection->getAuthString());
|
||||
$command = self::CLIENT . ' -N -U ' . $auth . ' ' . $command . ' 2> /dev/null';
|
||||
exec($command, $output);
|
||||
return $output;
|
||||
}
|
||||
|
||||
abstract public function run($arguments);
|
||||
|
||||
/**
|
||||
* @param array $lines
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function parseOutput($lines);
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function escape($string) {
|
||||
return escapeshellarg($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public function escapePath($path) {
|
||||
$path = str_replace('/', '\\', $path);
|
||||
return '"' . trim(escapeshellarg($path), "'") . '"';
|
||||
}
|
||||
}
|
||||
36
src/command/del.php
Normal file
36
src/command/del.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Del extends Simple {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'del';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
if (count($lines) === 0) {
|
||||
return true;
|
||||
} else {
|
||||
list($error,) = explode(' ', $lines[0]);
|
||||
switch ($error) {
|
||||
case 'NT_STATUS_OBJECT_PATH_NOT_FOUND':
|
||||
case 'NT_STATUS_OBJECT_NAME_NOT_FOUND':
|
||||
case 'NT_STATUS_NO_SUCH_FILE':
|
||||
throw new \SMB\NotFoundException();
|
||||
default:
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/command/dir.php
Normal file
47
src/command/dir.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Dir extends Simple {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'cd';
|
||||
}
|
||||
|
||||
public function run($arguments) {
|
||||
$arguments['postfix']=' ; dir';
|
||||
return parent::run($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return array
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
//last line is used space
|
||||
array_pop($lines);
|
||||
$content = array();
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if ($line) {
|
||||
list($name, $meta) = explode(" ", $line, 2);
|
||||
if ($name !== '.' and $name !== '..') {
|
||||
list($type, $meta) = explode(" ", trim($meta), 2);
|
||||
list($size, $time) = explode(" ", trim($meta), 2);
|
||||
$content[$name] = array(
|
||||
'size' => intval(trim($size)),
|
||||
'type' => ($type === 'D') ? 'dir' : 'file',
|
||||
'time' => strtotime($time)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
30
src/command/double.php
Normal file
30
src/command/double.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
/**
|
||||
* run a command with two path parameter
|
||||
*/
|
||||
abstract class Double extends Command {
|
||||
/**
|
||||
* @var string $command
|
||||
*/
|
||||
protected $command;
|
||||
|
||||
public function run($arguments) {
|
||||
$path1 = $this->escapePath($arguments['path1']);
|
||||
$path2 = $this->escapePath($arguments['path2']);
|
||||
$share = $arguments['share'];
|
||||
$postFix = (isset($arguments['postfix'])) ? $arguments['postfix'] : '';
|
||||
$cmd = $this->escape('//' . $this->connection->getHost() . '/' . $share);
|
||||
$cmd .= " -c '" . $this->command . ' ' . $path1 . ' ' . $path2 . $postFix . "'";
|
||||
$output = $this->execute($cmd);
|
||||
return $this->parseOutput($output);
|
||||
}
|
||||
}
|
||||
46
src/command/get.php
Normal file
46
src/command/get.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Get extends Command {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'get';
|
||||
}
|
||||
|
||||
public function run($arguments) {
|
||||
$path1 = $this->escapePath($arguments['path1']);
|
||||
$path2 = $this->escape($arguments['path2']); //seccond path is local, needs different escaping
|
||||
$share = $arguments['share'];
|
||||
$postFix = (isset($arguments['postfix'])) ? $arguments['postfix'] : '';
|
||||
$cmd = $this->escape('//' . $this->connection->getHost() . '/' . $share);
|
||||
$cmd .= " -c '" . $this->command . ' ' . $path1 . ' ' . $path2 . $postFix . "'";
|
||||
$output = $this->execute($cmd);
|
||||
return $this->parseOutput($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
if (count($lines) === 0) {
|
||||
return true;
|
||||
} else {
|
||||
list($error,) = explode(' ', $lines[0]);
|
||||
switch ($error) {
|
||||
case 'NT_STATUS_OBJECT_PATH_NOT_FOUND':
|
||||
case 'NT_STATUS_OBJECT_NAME_NOT_FOUND':
|
||||
throw new \SMB\NotFoundException();
|
||||
default:
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/command/listshares.php
Normal file
33
src/command/listshares.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class ListShares extends Command {
|
||||
public function run($arguments) {
|
||||
$output = $this->execute('-gL ' . $this->escape($this->connection->getHost()));
|
||||
return $this->parseOutput($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return array
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
$shares = array();
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, '|')) {
|
||||
list($type, $name, $description) = explode('|', $line);
|
||||
if (strtolower($type) === 'disk') {
|
||||
$shares[$name] = $description;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $shares;
|
||||
}
|
||||
}
|
||||
37
src/command/mkdir.php
Normal file
37
src/command/mkdir.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Mkdir extends Simple {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'mkdir';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
if (count($lines) ===0) {
|
||||
return true;
|
||||
} else {
|
||||
list($error,) = explode(' ', $lines[0]);
|
||||
switch ($error) {
|
||||
case 'NT_STATUS_OBJECT_PATH_NOT_FOUND':
|
||||
case 'NT_STATUS_OBJECT_NAME_NOT_FOUND':
|
||||
throw new \SMB\NotFoundException();
|
||||
case 'NT_STATUS_OBJECT_NAME_COLLISION':
|
||||
throw new \SMB\AlreadyExistsException();
|
||||
default:
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/command/put.php
Normal file
49
src/command/put.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Put extends Command {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'put';
|
||||
}
|
||||
|
||||
public function run($arguments) {
|
||||
$path1 = $this->escape($arguments['path1']); //first path is local, needs different escaping
|
||||
$path2 = $this->escapePath($arguments['path2']);
|
||||
$share = $arguments['share'];
|
||||
$postFix = (isset($arguments['postfix'])) ? $arguments['postfix'] : '';
|
||||
$cmd = $this->escape('//' . $this->connection->getHost() . '/' . $share);
|
||||
$cmd .= " -c '" . $this->command . ' ' . $path1 . ' ' . $path2 . $postFix . "'";
|
||||
$output = $this->execute($cmd);
|
||||
return $this->parseOutput($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
if (count($lines) === 0) {
|
||||
return true;
|
||||
} else {
|
||||
if (strpos($lines[0], 'does not exist')) {
|
||||
throw new \SMB\NotFoundException();
|
||||
}
|
||||
list($error,) = explode(' ', $lines[0]);
|
||||
switch ($error) {
|
||||
case 'NT_STATUS_OBJECT_PATH_NOT_FOUND':
|
||||
case 'NT_STATUS_OBJECT_NAME_NOT_FOUND':
|
||||
throw new \SMB\NotFoundException();
|
||||
default:
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/command/rename.php
Normal file
35
src/command/rename.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Rename extends Double {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'rename';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
if (count($lines) === 0) {
|
||||
return true;
|
||||
} else {
|
||||
list($error,) = explode(' ', $lines[0]);
|
||||
switch ($error) {
|
||||
case 'NT_STATUS_OBJECT_PATH_NOT_FOUND':
|
||||
case 'NT_STATUS_OBJECT_NAME_NOT_FOUND':
|
||||
throw new \SMB\NotFoundException();
|
||||
default:
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/command/rmdir.php
Normal file
37
src/command/rmdir.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
class Rmdir extends Simple {
|
||||
public function __construct($connection) {
|
||||
parent::__construct($connection);
|
||||
$this->command = 'rmdir';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lines
|
||||
* @return bool
|
||||
*/
|
||||
protected function parseOutput($lines) {
|
||||
if (count($lines) === 0) {
|
||||
return true;
|
||||
} else {
|
||||
list($error,) = explode(' ', $lines[0]);
|
||||
switch ($error) {
|
||||
case 'NT_STATUS_OBJECT_PATH_NOT_FOUND':
|
||||
case 'NT_STATUS_OBJECT_NAME_NOT_FOUND':
|
||||
throw new \SMB\NotFoundException();
|
||||
case 'NT_STATUS_DIRECTORY_NOT_EMPTY':
|
||||
throw new \SMB\NotEmptyException();
|
||||
default:
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/command/simple.php
Normal file
29
src/command/simple.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB\Command;
|
||||
|
||||
/**
|
||||
* run a command with one path parameter
|
||||
*/
|
||||
abstract class Simple extends Command {
|
||||
/**
|
||||
* @var string $command
|
||||
*/
|
||||
protected $command;
|
||||
|
||||
public function run($arguments) {
|
||||
$path = $this->escapePath($arguments['path']);
|
||||
$share = $arguments['share'];
|
||||
$postFix = (isset($arguments['postfix'])) ? $arguments['postfix'] : '';
|
||||
$cmd = $this->escape('//' . $this->connection->getHost() . '/' . $share);
|
||||
$cmd .= " -c '" . $this->command . ' ' . $path . $postFix . "'";
|
||||
$output = $this->execute($cmd);
|
||||
return $this->parseOutput($output);
|
||||
}
|
||||
}
|
||||
72
src/connection.php
Normal file
72
src/connection.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB;
|
||||
|
||||
class Connection {
|
||||
/**
|
||||
* @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 getHost() {
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Share[]
|
||||
*/
|
||||
public function listShares() {
|
||||
$cmd = new Command\ListShares($this);
|
||||
$shareNames = $cmd->run(null);
|
||||
$shares = array();
|
||||
foreach ($shareNames as $name => $description) {
|
||||
$shares[] = new Share($this, $name);
|
||||
}
|
||||
return $shares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return Share
|
||||
*/
|
||||
public function getShare($name) {
|
||||
return new Share($this, $name);
|
||||
}
|
||||
}
|
||||
18
src/errors.php
Normal file
18
src/errors.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* 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 {
|
||||
}
|
||||
|
||||
class AlreadyExistsException extends \Exception {
|
||||
}
|
||||
|
||||
class NotEmptyException extends \Exception {
|
||||
}
|
||||
103
src/share.php
Normal file
103
src/share.php
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace SMB;
|
||||
|
||||
class Share {
|
||||
/**
|
||||
* @var Connection $connection
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* @var string $name
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @param Connection $connection
|
||||
* @param string $share
|
||||
*/
|
||||
public function __construct($connection, $name) {
|
||||
$this->connection = $connection;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the content of a remote folder
|
||||
*
|
||||
* @param $path
|
||||
* @return array
|
||||
*/
|
||||
public function dir($path) {
|
||||
return (new Command\Dir($this->connection))->run(array('path' => $path, 'share' => $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a folder on the share
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function mkdir($path) {
|
||||
return (new Command\Mkdir($this->connection))->run(array('path' => $path, 'share' => $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a folder on the share
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function rmdir($path) {
|
||||
return (new Command\Rmdir($this->connection))->run(array('path' => $path, 'share' => $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file on the share
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function del($path) {
|
||||
return (new Command\Del($this->connection))->run(array('path' => $path, 'share' => $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a remote file
|
||||
*
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
* @return bool
|
||||
*/
|
||||
public function rename($from, $to) {
|
||||
return (new Command\Rename($this->connection))->run(array('path1' => $from, 'path2' => $to, 'share' => $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a local file
|
||||
*
|
||||
* @param string $source local file
|
||||
* @param string $target remove file
|
||||
* @return bool
|
||||
*/
|
||||
public function put($source, $target) {
|
||||
return (new Command\Put($this->connection))->run(array('path1' => $source, 'path2' => $target, 'share' => $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a remote file
|
||||
*
|
||||
* @param string $source remove file
|
||||
* @param string $target local file
|
||||
* @return bool
|
||||
*/
|
||||
public function get($source, $target) {
|
||||
return (new Command\Get($this->connection))->run(array('path1' => $source, 'path2' => $target, 'share' => $this->name));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue