diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json index b0267ba343..72335c8d89 100644 --- a/apps/files_external/3rdparty/composer.json +++ b/apps/files_external/3rdparty/composer.json @@ -8,7 +8,7 @@ "classmap-authoritative": true }, "require": { - "icewind/smb": "1.0.8", + "icewind/smb": "1.1.0", "icewind/streams": "0.4" } } diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock index 13931ad757..7161ae19a2 100644 --- a/apps/files_external/3rdparty/composer.lock +++ b/apps/files_external/3rdparty/composer.lock @@ -4,21 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1671a5ec7bef407432d42775f898dc34", - "content-hash": "9d995f0d55bee8a3b344a3c685e7b4a4", + "hash": "8de0823d3d0a167ee24450a111cb67b9", + "content-hash": "6733058865c1765823b31cfbb24552e1", "packages": [ { "name": "icewind/smb", - "version": "v1.0.8", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/icewind1991/SMB.git", - "reference": "764f3fc793a904eb937d619ad097fb076ff199cd" + "reference": "822f924967c68228555cea84ea44765f8e85c601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/icewind1991/SMB/zipball/764f3fc793a904eb937d619ad097fb076ff199cd", - "reference": "764f3fc793a904eb937d619ad097fb076ff199cd", + "url": "https://api.github.com/repos/icewind1991/SMB/zipball/822f924967c68228555cea84ea44765f8e85c601", + "reference": "822f924967c68228555cea84ea44765f8e85c601", "shasum": "" }, "require": { @@ -47,7 +47,7 @@ } ], "description": "php wrapper for smbclient and libsmbclient-php", - "time": "2016-03-17 13:29:58" + "time": "2016-04-26 13:26:39" }, { "name": "icewind/streams", diff --git a/apps/files_external/3rdparty/composer/LICENSE b/apps/files_external/3rdparty/composer/LICENSE index c8d57af8b2..1a28124886 100644 --- a/apps/files_external/3rdparty/composer/LICENSE +++ b/apps/files_external/3rdparty/composer/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2015 Nils Adermann, Jordi Boggiano +Copyright (c) 2016 Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json index 48f8c555c3..31c602de3c 100644 --- a/apps/files_external/3rdparty/composer/installed.json +++ b/apps/files_external/3rdparty/composer/installed.json @@ -44,17 +44,17 @@ }, { "name": "icewind/smb", - "version": "v1.0.8", - "version_normalized": "1.0.8.0", + "version": "v1.1.0", + "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/icewind1991/SMB.git", - "reference": "764f3fc793a904eb937d619ad097fb076ff199cd" + "reference": "822f924967c68228555cea84ea44765f8e85c601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/icewind1991/SMB/zipball/764f3fc793a904eb937d619ad097fb076ff199cd", - "reference": "764f3fc793a904eb937d619ad097fb076ff199cd", + "url": "https://api.github.com/repos/icewind1991/SMB/zipball/822f924967c68228555cea84ea44765f8e85c601", + "reference": "822f924967c68228555cea84ea44765f8e85c601", "shasum": "" }, "require": { @@ -65,7 +65,7 @@ "phpunit/phpunit": "^4.8", "satooshi/php-coveralls": "v1.0.0" }, - "time": "2016-03-17 13:29:58", + "time": "2016-04-26 13:26:39", "type": "library", "installation-source": "source", "autoload": { diff --git a/apps/files_external/3rdparty/icewind/smb/src/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Connection.php index f48dcb766e..d24cdc1f6d 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Connection.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Connection.php @@ -15,6 +15,7 @@ use Icewind\SMB\Exception\NoLoginServerException; class Connection extends RawConnection { const DELIMITER = 'smb:'; + const DELIMITER_LENGTH = 4; /** * send input to smbclient @@ -28,6 +29,7 @@ class Connection extends RawConnection { /** * get all unprocessed output from smbclient until the next prompt * + * @param callable $callback (optional) callback to call for every line read * @return string * @throws AuthenticationException * @throws ConnectException @@ -35,7 +37,7 @@ class Connection extends RawConnection { * @throws InvalidHostException * @throws NoLoginServerException */ - public function read() { + public function read(callable $callback = null) { if (!$this->isValid()) { throw new ConnectionException('Connection not valid'); } @@ -45,25 +47,49 @@ class Connection extends RawConnection { $output = array(); $line = $this->readLine(); if ($line === false) { - if ($promptLine) { //maybe we have some error we missed on the previous line - throw new ConnectException('Unknown error (' . $promptLine . ')'); - } else { - $error = $this->readError(); // maybe something on stderr - if ($error) { - throw new ConnectException('Unknown error (' . $error . ')'); - } else { - throw new ConnectException('Unknown error'); - } - } + $this->unknownError($promptLine); } - $length = mb_strlen(self::DELIMITER); - while (mb_substr($line, 0, $length) !== self::DELIMITER) { //next prompt functions as delimiter - $output[] .= $line; + while (!$this->isPrompt($line)) { //next prompt functions as delimiter + if (is_callable($callback)) { + $result = $callback($line); + if ($result === false) { // allow the callback to close the connection for infinite running commands + $this->close(true); + } + } else { + $output[] .= $line; + } $line = $this->readLine(); } return $output; } + /** + * Check + * + * @param $line + * @return bool + */ + private function isPrompt($line) { + return mb_substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER || $line === false; + } + + /** + * @param string $promptLine (optional) prompt line that might contain some info about the error + * @throws ConnectException + */ + private function unknownError($promptLine = '') { + if ($promptLine) { //maybe we have some error we missed on the previous line + throw new ConnectException('Unknown error (' . $promptLine . ')'); + } else { + $error = $this->readError(); // maybe something on stderr + if ($error) { + throw new ConnectException('Unknown error (' . $error . ')'); + } else { + throw new ConnectException('Unknown error'); + } + } + } + /** * check if the first line holds a connection failure * diff --git a/apps/files_external/3rdparty/icewind/smb/src/IShare.php b/apps/files_external/3rdparty/icewind/smb/src/IShare.php index 4851e9de05..4042315133 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/IShare.php +++ b/apps/files_external/3rdparty/icewind/smb/src/IShare.php @@ -8,6 +8,17 @@ namespace Icewind\SMB; interface IShare { + // https://msdn.microsoft.com/en-us/library/dn392331.aspx + const NOTIFY_ADDED = 1; + const NOTIFY_REMOVED = 2; + const NOTIFY_MODIFIED = 3; + const NOTIFY_RENAMED_OLD = 4; + const NOTIFY_RENAMED_NEW = 5; + const NOTIFY_ADDED_STREAM = 6; + const NOTIFY_REMOVED_STREAM = 7; + const NOTIFY_MODIFIED_STREAM = 8; + const NOTIFY_REMOVED_BY_DELETE = 9; + /** * Get the name of the share * @@ -131,4 +142,11 @@ interface IShare { * @return mixed */ public function setMode($path, $mode); + + /** + * @param string $path + * @param callable $callback callable which will be called for each received change + * @return mixed + */ + public function notify($path, callable $callback); } diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php index 27d975514a..51e16d1841 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php +++ b/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php @@ -301,6 +301,18 @@ class NativeShare extends AbstractShare { return $this->setAttribute($path, 'system.dos_attr.mode', $mode); } + /** + * @param string $path + * @param callable $callback callable which will be called for each received change + * @return mixed + */ + public function notify($path, callable $callback) { + // php-smbclient does support notify (https://github.com/eduardok/libsmbclient-php/issues/29) + // so we use the smbclient based backend for this + $share = new Share($this->server, $this->getName()); + $share->notify($path, $callback); + } + public function __destruct() { unset($this->state); } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Share.php b/apps/files_external/3rdparty/icewind/smb/src/Share.php index 694bd30bd0..21f8fe5b13 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Share.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Share.php @@ -51,6 +51,22 @@ 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()) : ''; + $command = sprintf('stdbuf -o0 %s %s --authentication-file=%s %s', + $this->system->getSmbclientPath(), + $workgroupArgument, + System::getFD(3), + escapeshellarg('//' . $this->server->getHost() . '/' . $this->name) + ); + $connection = new Connection($command); + $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword()); + if (!$connection->isValid()) { + throw new ConnectionException(); + } + return $connection; + } + /** * @throws \Icewind\SMB\Exception\ConnectionException * @throws \Icewind\SMB\Exception\AuthenticationException @@ -60,18 +76,7 @@ class Share extends AbstractShare { if ($this->connection and $this->connection->isValid()) { return; } - $workgroupArgument = ($this->server->getWorkgroup()) ? ' -W ' . escapeshellarg($this->server->getWorkgroup()) : ''; - $command = sprintf('%s %s --authentication-file=%s %s', - $this->system->getSmbclientPath(), - $workgroupArgument, - System::getFD(3), - escapeshellarg('//' . $this->server->getHost() . '/' . $this->name) - ); - $this->connection = new Connection($command); - $this->connection->writeAuthentication($this->server->getUser(), $this->server->getPassword()); - if (!$this->connection->isValid()) { - throw new ConnectionException(); - } + $this->connection = $this->getConnection(); } protected function reconnect() { @@ -344,6 +349,26 @@ class Share extends AbstractShare { return $this->parseOutput($output, $path); } + /** + * @param string $path + * @param callable $callback callable which will be called for each received change + * @return mixed + */ + public function notify($path, callable $callback) { + $connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process + $command = 'notify ' . $this->escapePath($path); + $connection->write($command . PHP_EOL); + $connection->read(function ($line) use ($callback, $path) { + $code = (int)substr($line, 0, 4); + $subPath = substr($line, 5); + if ($path === '') { + return $callback($code, $subPath); + } else { + return $callback($code, $path . '/' . $subPath); + } + }); + } + /** * @param string $command * @return array @@ -370,7 +395,7 @@ class Share extends AbstractShare { * @return bool */ protected function parseOutput($lines, $path = '') { - $this->parser->checkForError($lines, $path); + return $this->parser->checkForError($lines, $path); } /**